mirror of
https://github.com/tfussell/xlnt.git
synced 2024-03-22 13:11:17 +08:00
finish up custom string class implementation
This commit is contained in:
parent
4919e7ea00
commit
7b5246f9dd
|
@ -29,7 +29,7 @@
|
||||||
#include <xlnt/cell/types.hpp>
|
#include <xlnt/cell/types.hpp>
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
@ -412,7 +412,7 @@ private:
|
||||||
/// </summary>
|
/// </summary>
|
||||||
inline std::ostream &operator<<(std::ostream &stream, const xlnt::cell &cell)
|
inline std::ostream &operator<<(std::ostream &stream, const xlnt::cell &cell)
|
||||||
{
|
{
|
||||||
return stream << cell.to_string();
|
return stream << std::string(cell.to_string().data());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include <xlnt/cell/types.hpp>
|
#include <xlnt/cell/types.hpp>
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
// We might want to change these types for various optimizations in the future
|
// We might want to change these types for various optimizations in the future
|
||||||
// so use typedefs.
|
// so use typedefs.
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
// @author: see AUTHORS file
|
// @author: see AUTHORS file
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/datetime.hpp>
|
#include <xlnt/utils/datetime.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
// Note: this comes from https://github.com/tfussell/miniz-cpp
|
// Note: this comes from https://github.com/tfussell/miniz-cpp
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include <xlnt/cell/comment.hpp>
|
#include <xlnt/cell/comment.hpp>
|
||||||
#include <xlnt/worksheet/worksheet.hpp>
|
#include <xlnt/worksheet/worksheet.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
#include <xlnt/packaging/zip_file.hpp>
|
#include <xlnt/packaging/zip_file.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
#include <xlnt/workbook/workbook.hpp>
|
#include <xlnt/workbook/workbook.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
#include <xlnt/worksheet/worksheet.hpp>
|
#include <xlnt/worksheet/worksheet.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
namespace detail { struct xml_document_impl; }
|
namespace detail { struct xml_document_impl; }
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
namespace detail { struct xml_node_impl; }
|
namespace detail { struct xml_node_impl; }
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/hash_combine.hpp>
|
#include <xlnt/utils/hash_combine.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#include <xlnt/utils/hash_combine.hpp>
|
#include <xlnt/utils/hash_combine.hpp>
|
||||||
#include <xlnt/styles/side.hpp>
|
#include <xlnt/styles/side.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include <xlnt/utils/hash_combine.hpp>
|
#include <xlnt/utils/hash_combine.hpp>
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#include <xlnt/styles/color.hpp>
|
#include <xlnt/styles/color.hpp>
|
||||||
#include <xlnt/utils/hash_combine.hpp>
|
#include <xlnt/utils/hash_combine.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include <xlnt/utils/hash_combine.hpp>
|
#include <xlnt/utils/hash_combine.hpp>
|
||||||
#include <xlnt/styles/color.hpp>
|
#include <xlnt/styles/color.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include <xlnt/styles/style.hpp>
|
#include <xlnt/styles/style.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/hash_combine.hpp>
|
#include <xlnt/utils/hash_combine.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
#include <xlnt/styles/color.hpp>
|
#include <xlnt/styles/color.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include <xlnt/styles/number_format.hpp>
|
#include <xlnt/styles/number_format.hpp>
|
||||||
#include <xlnt/styles/protection.hpp>
|
#include <xlnt/styles/protection.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
|
|
||||||
#include <xlnt/cell/types.hpp>
|
#include <xlnt/cell/types.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ class XLNT_CLASS cell_coordinates_exception
|
||||||
class XLNT_CLASS illegal_character_error
|
class XLNT_CLASS illegal_character_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
illegal_character_error(char c);
|
illegal_character_error(utf32_char c);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -1,139 +1,87 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iostream>
|
#include <unordered_map>
|
||||||
#include <iterator>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#ifdef XLNT_STD_STRING
|
||||||
|
#include <string>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class iter_range
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
iter_range(T begin_iter, T end_iter) : begin_(begin_iter), end_(end_iter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
T begin() { return begin_; }
|
||||||
|
T end() { return end_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
T begin_;
|
||||||
|
T end_;
|
||||||
|
};
|
||||||
|
|
||||||
|
using utf_mb_narrow_char = char;
|
||||||
|
using utf_mb_narrow_string = utf_mb_narrow_char[];
|
||||||
|
using utf_mb_wide_char = wchar_t;
|
||||||
|
using utf_mb_wide_string = utf_mb_wide_char[];
|
||||||
|
using utf8_char = char;
|
||||||
|
using utf8_string = utf8_char[];
|
||||||
|
using utf16_char = char16_t;
|
||||||
|
using utf16_string = utf16_char[];
|
||||||
|
using utf32_char = char32_t;
|
||||||
|
using utf32_string = utf32_char[];
|
||||||
|
|
||||||
class XLNT_CLASS string
|
class XLNT_CLASS string
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using value_type = std::uint32_t;
|
using code_point = utf32_char;
|
||||||
using reference = value_type &;
|
using reference = code_point &;
|
||||||
using const_reference = value_type &;
|
using const_reference = const code_point &;
|
||||||
using pointer = value_type *;
|
using pointer = code_point *;
|
||||||
using const_pointer = const pointer;
|
using const_pointer = const code_point *;
|
||||||
using byte = char;
|
using byte = char;
|
||||||
using byte_pointer = byte *;
|
using byte_pointer = byte *;
|
||||||
using const_byte_pointer = const byte *;
|
using const_byte_pointer = const byte *;
|
||||||
using difference_type = std::ptrdiff_t;
|
using difference_type = std::ptrdiff_t;
|
||||||
using size_type = std::size_t;
|
using size_type = std::size_t;
|
||||||
|
|
||||||
using utf_mb_narrow_char = char;
|
class const_iterator;
|
||||||
using utf_mb_narrow_string = utf_mb_narrow_char[];
|
|
||||||
using utf_mb_wide_char = wchar_t;
|
|
||||||
using utf_mb_wide_string = utf_mb_wide_char[];
|
|
||||||
using utf8_char = char;
|
|
||||||
using utf8_string = utf8_char[];
|
|
||||||
using utf16_char = char16_t;
|
|
||||||
using utf16_string = utf16_char[];
|
|
||||||
using utf32_char = char32_t;
|
|
||||||
using utf32_string = utf32_char[];
|
|
||||||
|
|
||||||
class code_point
|
class iterator : public std::iterator<std::bidirectional_iterator_tag, code_point>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
code_point(byte_pointer data, size_type index, size_type end)
|
iterator(string *parent, size_type index);
|
||||||
: data_(data),
|
|
||||||
index_(index),
|
|
||||||
end_(end)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
code_point(const_byte_pointer data, size_type index, size_type end)
|
iterator(const iterator &other);
|
||||||
: data_(const_cast<byte_pointer>(data)),
|
|
||||||
index_(index),
|
|
||||||
end_(end)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
code_point &operator=(utf32_char value);
|
code_point operator*();
|
||||||
|
|
||||||
code_point &operator=(const code_point &value)
|
bool operator==(const iterator &other) const;
|
||||||
{
|
|
||||||
return *this = value.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(char rhs) const;
|
bool operator!=(const iterator &other) const { return !(*this == other); }
|
||||||
bool operator!=(char rhs) const;
|
|
||||||
bool operator<(char rhs) const;
|
|
||||||
bool operator<=(char rhs) const;
|
|
||||||
bool operator>(char rhs) const;
|
|
||||||
bool operator>=(char rhs) const;
|
|
||||||
|
|
||||||
utf32_char get() const;
|
difference_type operator-(const iterator &other) const;
|
||||||
|
|
||||||
byte_pointer data_;
|
iterator &operator+=(int offset) { return *this = *this + offset; }
|
||||||
size_type index_;
|
|
||||||
size_type end_;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <bool is_const = true>
|
iterator &operator-=(int offset) { return *this = *this - offset; }
|
||||||
class common_iterator : public std::iterator<std::bidirectional_iterator_tag, value_type>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
common_iterator(byte_pointer data, size_type index, size_type length)
|
|
||||||
: current_(data, index, length)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator(const_byte_pointer data, size_type index, size_type length)
|
iterator operator+(int offset);
|
||||||
: current_(data, index, length)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator(const common_iterator<false> &other)
|
iterator operator-(int offset) { return *this + (-1 * offset); }
|
||||||
: current_(other.current_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator(const common_iterator<true> &other)
|
iterator &operator--();
|
||||||
: current_(other.current_)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
code_point &operator*()
|
iterator operator--(int)
|
||||||
{
|
|
||||||
return current_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const common_iterator &other) const
|
|
||||||
{
|
|
||||||
return current_.data_ == other.current_.data_ && current_.index_ == other.current_.index_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator!=(const common_iterator &other) const
|
|
||||||
{
|
|
||||||
return !(*this == other);
|
|
||||||
}
|
|
||||||
|
|
||||||
difference_type operator-(const common_iterator &other) const
|
|
||||||
{
|
|
||||||
return current_.index_ - other.current_.index_;
|
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator operator+(size_type offset)
|
|
||||||
{
|
|
||||||
common_iterator copy = *this;
|
|
||||||
size_type end = std::max<size_type>(0, std::min<size_type>(current_.end_, current_.index_ + offset));
|
|
||||||
|
|
||||||
while (copy.current_.index_ != end)
|
|
||||||
{
|
|
||||||
end < copy.current_.index_ ? --copy : ++copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
common_iterator &operator--();
|
|
||||||
|
|
||||||
common_iterator operator--(int)
|
|
||||||
{
|
{
|
||||||
iterator old = *this;
|
iterator old = *this;
|
||||||
--*this;
|
--*this;
|
||||||
|
@ -141,40 +89,80 @@ public:
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
common_iterator &operator++();
|
iterator &operator++();
|
||||||
|
|
||||||
common_iterator operator++(int)
|
iterator operator++(int)
|
||||||
{
|
{
|
||||||
common_iterator old = *this;
|
iterator old = *this;
|
||||||
++*this;
|
++*this;
|
||||||
|
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class common_iterator<true>;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
code_point current_;
|
friend class const_iterator;
|
||||||
|
|
||||||
|
string *parent_;
|
||||||
|
size_type index_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class const_iterator : public std::iterator<std::bidirectional_iterator_tag, code_point>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const_iterator(const string *parent, size_type index);
|
||||||
|
|
||||||
|
const_iterator(const string::iterator &other);
|
||||||
|
|
||||||
|
const_iterator(const const_iterator &other);
|
||||||
|
|
||||||
|
const code_point operator*() const;
|
||||||
|
|
||||||
|
bool operator==(const const_iterator &other) const;
|
||||||
|
|
||||||
|
bool operator!=(const const_iterator &other) const { return !(*this == other); }
|
||||||
|
|
||||||
|
difference_type operator-(const const_iterator &other) const;
|
||||||
|
|
||||||
|
const_iterator &operator+=(int offset);
|
||||||
|
|
||||||
|
const_iterator &operator-=(int offset) { return *this += -offset; }
|
||||||
|
|
||||||
|
const_iterator operator+(int offset);
|
||||||
|
|
||||||
|
const_iterator operator-(int offset) { return *this + (-1 * offset); }
|
||||||
|
|
||||||
|
const_iterator &operator--();
|
||||||
|
|
||||||
|
const_iterator operator--(int)
|
||||||
|
{
|
||||||
|
const_iterator old = *this;
|
||||||
|
--*this;
|
||||||
|
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator &operator++();
|
||||||
|
|
||||||
|
const_iterator operator++(int)
|
||||||
|
{
|
||||||
|
const_iterator old = *this;
|
||||||
|
++*this;
|
||||||
|
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const string *parent_;
|
||||||
|
size_type index_;
|
||||||
};
|
};
|
||||||
|
|
||||||
using iterator = common_iterator<false>;
|
|
||||||
using const_iterator = common_iterator<true>;
|
|
||||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
static const size_type npos = -1;
|
static const size_type npos = -1;
|
||||||
|
|
||||||
static string from(std::int8_t i);
|
template<typename T>
|
||||||
static string from(std::int16_t i);
|
static string from(T value);
|
||||||
static string from(std::int32_t i);
|
|
||||||
static string from(std::int64_t i);
|
|
||||||
static string from(std::uint8_t i);
|
|
||||||
static string from(std::uint16_t i);
|
|
||||||
static string from(std::uint32_t i);
|
|
||||||
static string from(std::uint64_t i);
|
|
||||||
static string from(float i);
|
|
||||||
static string from(double i);
|
|
||||||
static string from(long double i);
|
|
||||||
|
|
||||||
string();
|
string();
|
||||||
string(string &&str);
|
string(string &&str);
|
||||||
|
@ -182,6 +170,10 @@ public:
|
||||||
string(const string &str, size_type offset);
|
string(const string &str, size_type offset);
|
||||||
string(const string &str, size_type offset, size_type len);
|
string(const string &str, size_type offset, size_type len);
|
||||||
|
|
||||||
|
#ifdef XLNT_STD_STRING
|
||||||
|
string(const std::string &str);
|
||||||
|
#endif
|
||||||
|
|
||||||
string(const utf_mb_wide_string str);
|
string(const utf_mb_wide_string str);
|
||||||
string(const utf8_string str);
|
string(const utf8_string str);
|
||||||
string(const utf16_string str);
|
string(const utf16_string str);
|
||||||
|
@ -199,8 +191,8 @@ public:
|
||||||
|
|
||||||
~string();
|
~string();
|
||||||
|
|
||||||
size_type length() const { return length_; }
|
size_type length() const;
|
||||||
size_type bytes() const;
|
size_type num_bytes() const;
|
||||||
|
|
||||||
bool empty() const { return length() == 0; }
|
bool empty() const { return length() == 0; }
|
||||||
|
|
||||||
|
@ -210,35 +202,33 @@ public:
|
||||||
string substr(size_type offset) const;
|
string substr(size_type offset) const;
|
||||||
string substr(size_type offset, size_type len) const;
|
string substr(size_type offset, size_type len) const;
|
||||||
|
|
||||||
code_point back();
|
code_point back() const;
|
||||||
const code_point back() const;
|
code_point front() const;
|
||||||
code_point front();
|
|
||||||
const code_point front() const;
|
|
||||||
|
|
||||||
size_type find(code_point c) const;
|
|
||||||
size_type find(char c) const;
|
size_type find(char c) const;
|
||||||
size_type find(string str) const;
|
size_type find(code_point c) const;
|
||||||
|
size_type find(const string &str) const;
|
||||||
|
|
||||||
size_type find(code_point c, size_type offset) const;
|
|
||||||
size_type find(char c, size_type offset) const;
|
size_type find(char c, size_type offset) const;
|
||||||
size_type find(string str, size_type offset) const;
|
size_type find(code_point c, size_type offset) const;
|
||||||
|
size_type find(const string &str, size_type offset) const;
|
||||||
|
|
||||||
size_type find_last_of(code_point c) const;
|
|
||||||
size_type find_last_of(char c) const;
|
size_type find_last_of(char c) const;
|
||||||
size_type find_last_of(string str) const;
|
size_type find_last_of(code_point c) const;
|
||||||
|
size_type find_last_of(const string &str) const;
|
||||||
|
|
||||||
size_type find_last_of(code_point c, size_type offset) const;
|
|
||||||
size_type find_last_of(char c, size_type offset) const;
|
size_type find_last_of(char c, size_type offset) const;
|
||||||
size_type find_last_of(string str, size_type offset) const;
|
size_type find_last_of(code_point c, size_type offset) const;
|
||||||
|
size_type find_last_of(const string &str, size_type offset) const;
|
||||||
|
|
||||||
size_type find_first_of(string str) const;
|
size_type find_first_of(const string &str) const;
|
||||||
size_type find_first_of(string str, size_type offset) const;
|
size_type find_first_of(const string &str, size_type offset) const;
|
||||||
|
|
||||||
size_type find_first_not_of(string str) const;
|
size_type find_first_not_of(const string &str) const;
|
||||||
size_type find_first_not_of(string str, size_type offset) const;
|
size_type find_first_not_of(const string &str, size_type offset) const;
|
||||||
|
|
||||||
size_type find_last_not_of(string str) const;
|
size_type find_last_not_of(const string &str) const;
|
||||||
size_type find_last_not_of(string str, size_type offset) const;
|
size_type find_last_not_of(const string &str, size_type offset) const;
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
@ -247,7 +237,7 @@ public:
|
||||||
|
|
||||||
int to_hex() const;
|
int to_hex() const;
|
||||||
|
|
||||||
void remove(code_point iter);
|
void erase(size_type index);
|
||||||
|
|
||||||
iterator begin();
|
iterator begin();
|
||||||
const_iterator begin() const { return cbegin(); }
|
const_iterator begin() const { return cbegin(); }
|
||||||
|
@ -263,12 +253,13 @@ public:
|
||||||
|
|
||||||
string &operator=(string rhs);
|
string &operator=(string rhs);
|
||||||
|
|
||||||
void append(char c);
|
void append(utf_mb_narrow_char c);
|
||||||
void append(wchar_t c);
|
void append(utf_mb_wide_char c);
|
||||||
void append(char16_t c);
|
void append(utf16_char c);
|
||||||
void append(char32_t c);
|
|
||||||
void append(string str);
|
|
||||||
void append(code_point c);
|
void append(code_point c);
|
||||||
|
void append(const string &str);
|
||||||
|
|
||||||
|
void replace(size_type index, utf32_char c);
|
||||||
|
|
||||||
code_point at(size_type index);
|
code_point at(size_type index);
|
||||||
const code_point at(size_type index) const;
|
const code_point at(size_type index) const;
|
||||||
|
@ -297,8 +288,8 @@ public:
|
||||||
private:
|
private:
|
||||||
explicit string(size_type initial_size);
|
explicit string(size_type initial_size);
|
||||||
|
|
||||||
size_type length_;
|
|
||||||
std::vector<byte> *data_;
|
std::vector<byte> *data_;
|
||||||
|
std::unordered_map<size_type, size_type> *code_point_byte_offsets_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
|
|
||||||
#include <xlnt/packaging/relationship.hpp>
|
#include <xlnt/packaging/relationship.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <xlnt/worksheet/major_order.hpp>
|
#include <xlnt/worksheet/major_order.hpp>
|
||||||
#include <xlnt/worksheet/worksheet.hpp>
|
#include <xlnt/worksheet/worksheet.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
// @author: see AUTHORS file
|
// @author: see AUTHORS file
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
// @author: see AUTHORS file
|
// @author: see AUTHORS file
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
// @author: see AUTHORS file
|
// @author: see AUTHORS file
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
// @author: see AUTHORS file
|
// @author: see AUTHORS file
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include <xlnt/worksheet/range_reference.hpp>
|
#include <xlnt/worksheet/range_reference.hpp>
|
||||||
#include <xlnt/worksheet/worksheet.hpp>
|
#include <xlnt/worksheet/worksheet.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
#include <xlnt/cell/cell_reference.hpp>
|
#include <xlnt/cell/cell_reference.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
// @author: see AUTHORS file
|
// @author: see AUTHORS file
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
// @author: see AUTHORS file
|
// @author: see AUTHORS file
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <xlnt/utils/string.hpp>
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
// @author: see AUTHORS file
|
// @author: see AUTHORS file
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
#include <xlnt/packaging/relationship.hpp>
|
#include <xlnt/packaging/relationship.hpp>
|
||||||
#include <xlnt/worksheet/page_setup.hpp>
|
#include <xlnt/worksheet/page_setup.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
// @author: see AUTHORS file
|
// @author: see AUTHORS file
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
#include <xlnt/cell/cell.hpp>
|
#include <xlnt/cell/cell.hpp>
|
||||||
#include <xlnt/cell/cell_reference.hpp>
|
#include <xlnt/cell/cell_reference.hpp>
|
||||||
|
|
|
@ -56,18 +56,25 @@ enum class limit_style
|
||||||
/// </summary>
|
/// </summary>
|
||||||
const limit_style LimitStyle = limit_style::openpyxl;
|
const limit_style LimitStyle = limit_style::openpyxl;
|
||||||
|
|
||||||
// If no API is defined, assume default
|
#ifndef XLNT_API
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#if !defined(XLNT_API) && defined(SHARED)
|
#ifdef XLNT_SHARED
|
||||||
#ifdef XLNT_EXPORT
|
#ifdef XLNT_EXPORT
|
||||||
#define XLNT_API __declspec(dllexport)
|
#define XLNT_API __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
#define XLNT_API __declspec(dllimport)
|
#define XLNT_API __declspec(dllimport)
|
||||||
#endif
|
#endif // XLNT_EXPORT
|
||||||
|
#endif // XLNT_SHARED
|
||||||
#else
|
#else
|
||||||
#define XLNT_API
|
#define XLNT_API
|
||||||
#endif
|
#endif // _MSC_VER
|
||||||
#endif
|
#endif // XLNT_API
|
||||||
|
|
||||||
|
#ifndef XLNT_STD_STRING
|
||||||
|
#ifndef XLNT_SHARED
|
||||||
|
#define XLNT_STD_STRING
|
||||||
|
#endif // XLNT_SHARED
|
||||||
|
#endif // XLNT_STD_STRING
|
||||||
|
|
||||||
// If no API for classes is defined, assume default
|
// If no API for classes is defined, assume default
|
||||||
#ifndef XLNT_CLASS
|
#ifndef XLNT_CLASS
|
||||||
|
|
|
@ -144,7 +144,7 @@ bool is_valid_color(const xlnt::string &color)
|
||||||
|
|
||||||
for (std::size_t i = 0; i < color.length(); i++)
|
for (std::size_t i = 0; i < color.length(); i++)
|
||||||
{
|
{
|
||||||
if (std::toupper(color[i].get()) != std::toupper(other[i].get()))
|
if (std::toupper(color[i]) != std::toupper(other[i]))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -335,7 +335,7 @@ bool is_valid_locale(const xlnt::string &locale_string)
|
||||||
|
|
||||||
for (auto c : country)
|
for (auto c : country)
|
||||||
{
|
{
|
||||||
if (!is_hex(static_cast<char>(std::toupper(c.get()))))
|
if (!is_hex(static_cast<char>(std::toupper(c))))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -699,12 +699,12 @@ xlnt::string format_section(long double number, const section &format, xlnt::cal
|
||||||
|
|
||||||
if (decimal_pos != xlnt::string::npos)
|
if (decimal_pos != xlnt::string::npos)
|
||||||
{
|
{
|
||||||
result[decimal_pos] = ',';
|
result.replace(decimal_pos, U',');
|
||||||
decimal_pos += 3;
|
decimal_pos += 3;
|
||||||
|
|
||||||
while (decimal_pos < result.length())
|
while (decimal_pos < result.length())
|
||||||
{
|
{
|
||||||
result.remove(result.back());
|
result.erase(result.length());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1071,7 +1071,7 @@ bool cell::has_hyperlink() const
|
||||||
|
|
||||||
void cell::set_hyperlink(const string &hyperlink)
|
void cell::set_hyperlink(const string &hyperlink)
|
||||||
{
|
{
|
||||||
if (hyperlink.length() == 0 || hyperlink.find(':') == std::string::npos)
|
if (hyperlink.length() == 0 || hyperlink.find(':') == xlnt::string::npos)
|
||||||
{
|
{
|
||||||
throw data_type_exception();
|
throw data_type_exception();
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,70 +89,52 @@ std::pair<string, row_t> cell_reference::split_reference(const string &reference
|
||||||
absolute_column = false;
|
absolute_column = false;
|
||||||
absolute_row = false;
|
absolute_row = false;
|
||||||
|
|
||||||
// Convert a coordinate string like 'B12' to a tuple ('B', 12)
|
auto is_alpha = [](string::code_point c)
|
||||||
bool column_part = true;
|
{
|
||||||
|
return (c >= U'A' && c <= U'Z') || (c >= U'a' && c <= U'z');
|
||||||
|
};
|
||||||
|
|
||||||
string column_string;
|
auto upper_ref_string = reference_string.to_upper();
|
||||||
|
auto iter = upper_ref_string.begin();
|
||||||
|
auto end = upper_ref_string.end();
|
||||||
|
|
||||||
for (auto character : reference_string)
|
while(iter != end && (is_alpha(*iter) || *iter == U'$'))
|
||||||
{
|
{
|
||||||
auto upper = std::toupper(character.get(), std::locale::classic());
|
++iter;
|
||||||
|
|
||||||
if (std::isalpha(character.get(), std::locale::classic()))
|
|
||||||
{
|
|
||||||
if (column_part)
|
|
||||||
{
|
|
||||||
column_string.append(upper);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw cell_coordinates_exception(reference_string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (character == '$')
|
|
||||||
{
|
|
||||||
if (column_part)
|
|
||||||
{
|
|
||||||
if (column_string.empty())
|
|
||||||
{
|
|
||||||
column_string.append(upper);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
column_part = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (column_part)
|
|
||||||
{
|
|
||||||
column_part = false;
|
|
||||||
}
|
|
||||||
else if (!std::isdigit(character.get(), std::locale::classic()))
|
|
||||||
{
|
|
||||||
throw cell_coordinates_exception(reference_string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string row_string = reference_string.substr(column_string.length());
|
string column_string(upper_ref_string.begin(), iter);
|
||||||
|
|
||||||
if (row_string.length() == 0)
|
if (column_string.length() > 1 && column_string.front() == '$')
|
||||||
{
|
|
||||||
throw cell_coordinates_exception(reference_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (column_string[0] == '$')
|
|
||||||
{
|
|
||||||
absolute_row = true;
|
|
||||||
column_string = column_string.substr(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (row_string[0] == '$')
|
|
||||||
{
|
{
|
||||||
absolute_column = true;
|
absolute_column = true;
|
||||||
row_string = row_string.substr(1);
|
column_string.erase(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (column_string.length() > 1 && column_string.back() == '$')
|
||||||
|
{
|
||||||
|
absolute_row = true;
|
||||||
|
column_string.erase(column_string.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
string row_string(iter, end);
|
||||||
|
|
||||||
|
auto is_digit = [](string::code_point c)
|
||||||
|
{
|
||||||
|
return (c >= U'0' && c <= U'9');
|
||||||
|
};
|
||||||
|
|
||||||
|
for(auto c : row_string)
|
||||||
|
{
|
||||||
|
if(!is_digit(c))
|
||||||
|
{
|
||||||
|
throw cell_coordinates_exception(reference_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (column_string.length() == 0 || row_string.length() == 0)
|
||||||
|
{
|
||||||
|
throw cell_coordinates_exception(reference_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { column_string, row_string.to<row_t>() };
|
return { column_string, row_string.to<row_t>() };
|
||||||
|
|
|
@ -257,7 +257,7 @@ public:
|
||||||
TS_ASSERT_THROWS(cell.set_value(str), xlnt::illegal_character_error);
|
TS_ASSERT_THROWS(cell.set_value(str), xlnt::illegal_character_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
cell.set_value(xlnt::string("\33"));
|
cell.set_value(xlnt::string("\41")); // !
|
||||||
cell.set_value(xlnt::string("\t")); // Tab
|
cell.set_value(xlnt::string("\t")); // Tab
|
||||||
cell.set_value(xlnt::string("\n")); // Newline
|
cell.set_value(xlnt::string("\n")); // Newline
|
||||||
cell.set_value(xlnt::string("\r")); // Carriage return
|
cell.set_value(xlnt::string("\r")); // Carriage return
|
||||||
|
@ -361,7 +361,7 @@ public:
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
unsigned char pound = 163;
|
unsigned char pound = 163;
|
||||||
auto test_string = "Compount Value (" + std::string(pound) + ")";
|
auto test_string = "Compount Value (" + xlnt::string(pound) + ")";
|
||||||
auto ws = wb.create_sheet();
|
auto ws = wb.create_sheet();
|
||||||
cell = ws[xlnt::cell_reference("A1")];
|
cell = ws[xlnt::cell_reference("A1")];
|
||||||
TS_ASSERT_THROWS(cell.check_string(test_string), xlnt::unicode_decode_error);
|
TS_ASSERT_THROWS(cell.check_string(test_string), xlnt::unicode_decode_error);
|
||||||
|
|
|
@ -17,14 +17,23 @@ column_t::index_t column_t::column_index_from_string(const string &column_string
|
||||||
column_t::index_t column_index = 0;
|
column_t::index_t column_index = 0;
|
||||||
int place = 1;
|
int place = 1;
|
||||||
|
|
||||||
|
auto is_alpha = [](string::code_point c)
|
||||||
|
{
|
||||||
|
return (c >= U'A' && c <= U'Z') || (c >= U'a' && c <= U'z');
|
||||||
|
};
|
||||||
|
|
||||||
|
auto column_string_upper = column_string.to_upper();
|
||||||
|
|
||||||
for (int i = static_cast<int>(column_string.length()) - 1; i >= 0; i--)
|
for (int i = static_cast<int>(column_string.length()) - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (!std::isalpha(column_string[static_cast<std::size_t>(i)].get(), std::locale::classic()))
|
auto index = static_cast<std::size_t>(i);
|
||||||
|
|
||||||
|
if (!is_alpha(column_string[index]))
|
||||||
{
|
{
|
||||||
throw column_string_index_exception();
|
throw column_string_index_exception();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto char_index = std::toupper(column_string[static_cast<std::size_t>(i)].get(), std::locale::classic()) - U'A';
|
auto char_index = column_string_upper[index] - U'A';
|
||||||
|
|
||||||
column_index += static_cast<column_t::index_t>((char_index + 1) * place);
|
column_index += static_cast<column_t::index_t>((char_index + 1) * place);
|
||||||
place *= 26;
|
place *= 26;
|
||||||
|
|
|
@ -30,11 +30,11 @@ xlnt::string check_string(xlnt::string s)
|
||||||
s = s.substr(0, 32767); // max string length in Excel
|
s = s.substr(0, 32767); // max string length in Excel
|
||||||
}
|
}
|
||||||
|
|
||||||
for (xlnt::string::code_point c : s)
|
for (auto c : s)
|
||||||
{
|
{
|
||||||
if (c >= 0 && (c <= 8 || c == 11 || c == 12 || (c >= 14 && c <= 31)))
|
if (c <= 8 || c == 11 || c == 12 || (c >= 14 && c <= 31))
|
||||||
{
|
{
|
||||||
throw xlnt::illegal_character_error(0);
|
throw xlnt::illegal_character_error(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,49 @@ std::pair<bool, long double> cast_percentage(const xlnt::string &s)
|
||||||
std::pair<bool, xlnt::time> cast_time(const xlnt::string &s)
|
std::pair<bool, xlnt::time> cast_time(const xlnt::string &s)
|
||||||
{
|
{
|
||||||
xlnt::time result;
|
xlnt::time result;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto last_colon = s.find_last_of(':');
|
||||||
|
|
||||||
|
if (last_colon == xlnt::string::npos)
|
||||||
|
{
|
||||||
return { false, result };
|
return { false, result };
|
||||||
|
}
|
||||||
|
|
||||||
|
double seconds = s.substr(last_colon + 1).to<double>();
|
||||||
|
result.second = static_cast<int>(seconds);
|
||||||
|
result.microsecond = static_cast<int>((seconds - static_cast<double>(result.second)) * 1e6);
|
||||||
|
|
||||||
|
auto first_colon = s.find(':');
|
||||||
|
|
||||||
|
if (first_colon == last_colon)
|
||||||
|
{
|
||||||
|
auto decimal_pos = s.find('.');
|
||||||
|
|
||||||
|
if (decimal_pos != xlnt::string::npos)
|
||||||
|
{
|
||||||
|
result.minute = s.substr(0, first_colon).to<int>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.hour = s.substr(0, first_colon).to<int>();
|
||||||
|
result.minute = result.second;
|
||||||
|
result.second = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.hour = s.substr(0, first_colon).to<int>();
|
||||||
|
result.minute = s.substr(first_colon + 1, last_colon - first_colon - 1).to<int>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::invalid_argument)
|
||||||
|
{
|
||||||
|
return { false, result };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { true, result };
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <xlnt/cell/comment.hpp>
|
#include <xlnt/cell/comment.hpp>
|
||||||
|
#include <xlnt/utils/string.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include <detail/constants.hpp>
|
#include <detail/constants.hpp>
|
||||||
|
|
||||||
#include "xlnt_config.hpp"
|
#include <xlnt/xlnt_config.hpp>
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
|
|
|
@ -289,7 +289,7 @@ void zip_file::append_comment()
|
||||||
auto comment_length = std::min(static_cast<uint16_t>(comment.length()), std::numeric_limits<uint16_t>::max());
|
auto comment_length = std::min(static_cast<uint16_t>(comment.length()), std::numeric_limits<uint16_t>::max());
|
||||||
buffer_[buffer_.size() - 2] = static_cast<char>(comment_length);
|
buffer_[buffer_.size() - 2] = static_cast<char>(comment_length);
|
||||||
buffer_[buffer_.size() - 1] = static_cast<char>(comment_length >> 8);
|
buffer_[buffer_.size() - 1] = static_cast<char>(comment_length >> 8);
|
||||||
std::copy(comment.data(), comment.data() + comment.bytes(), std::back_inserter(buffer_));
|
std::copy(comment.data(), comment.data() + comment.num_bytes(), std::back_inserter(buffer_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,7 @@ xml_document workbook_serializer::write_workbook() const
|
||||||
sheet_index_string = sheet_index_string.substr(sheet_index_string.find_last_of('/'));
|
sheet_index_string = sheet_index_string.substr(sheet_index_string.find_last_of('/'));
|
||||||
auto iter = sheet_index_string.end();
|
auto iter = sheet_index_string.end();
|
||||||
--iter;
|
--iter;
|
||||||
while (isdigit((*iter).get()))
|
while (isdigit(*iter))
|
||||||
--iter;
|
--iter;
|
||||||
auto first_digit = iter - sheet_index_string.begin();
|
auto first_digit = iter - sheet_index_string.begin();
|
||||||
sheet_index_string = sheet_index_string.substr(static_cast<string::size_type>(first_digit + 1));
|
sheet_index_string = sheet_index_string.substr(static_cast<string::size_type>(first_digit + 1));
|
||||||
|
|
|
@ -34,7 +34,7 @@ cell_coordinates_exception::cell_coordinates_exception(const string &coord_strin
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
illegal_character_error::illegal_character_error(char c)
|
illegal_character_error::illegal_character_error(xlnt::utf32_char c)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
//TODO: make this conditional on XLNT_STD_STRING once std::sto* functions are replaced
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <utf8.h>
|
#include <utf8.h>
|
||||||
|
@ -12,7 +15,7 @@
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::size_t count_bytes(const T *arr)
|
std::size_t string_length(const T *arr)
|
||||||
{
|
{
|
||||||
std::size_t i = 0;
|
std::size_t i = 0;
|
||||||
|
|
||||||
|
@ -24,153 +27,229 @@ std::size_t count_bytes(const T *arr)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xlnt::string::code_point to_upper(xlnt::string::code_point p)
|
||||||
|
{
|
||||||
|
if(p >= U'a' && p <= U'z')
|
||||||
|
{
|
||||||
|
return U'A' + p - U'a';
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
xlnt::string::code_point to_lower(xlnt::string::code_point p)
|
||||||
|
{
|
||||||
|
if(p >= U'A' && p <= U'Z')
|
||||||
|
{
|
||||||
|
return U'a' + p - U'A';
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace xlnt {
|
namespace xlnt {
|
||||||
|
|
||||||
bool string::code_point::operator==(char rhs) const
|
template<>
|
||||||
{
|
|
||||||
return get() == rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool string::code_point::operator!=(char rhs) const
|
|
||||||
{
|
|
||||||
return get() != rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool string::code_point::operator<(char rhs) const
|
|
||||||
{
|
|
||||||
return char(get()) < rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool string::code_point::operator<=(char rhs) const
|
|
||||||
{
|
|
||||||
return char(get()) <= rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool string::code_point::operator>(char rhs) const
|
|
||||||
{
|
|
||||||
return char(get()) > rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool string::code_point::operator>=(char rhs) const
|
|
||||||
{
|
|
||||||
return char(get()) >= rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
string string::from(std::int8_t i)
|
string string::from(std::int8_t i)
|
||||||
{
|
{
|
||||||
return string(std::to_string(i).c_str());
|
return string(std::to_string(i).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
string string::from(std::int16_t i)
|
string string::from(std::int16_t i)
|
||||||
{
|
{
|
||||||
return string(std::to_string(i).c_str());
|
return string(std::to_string(i).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
string string::from(std::int32_t i)
|
string string::from(std::int32_t i)
|
||||||
{
|
{
|
||||||
return string(std::to_string(i).c_str());
|
return string(std::to_string(i).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
string string::from(std::int64_t i)
|
string string::from(std::int64_t i)
|
||||||
{
|
{
|
||||||
return string(std::to_string(i).c_str());
|
return string(std::to_string(i).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
string string::from(std::uint8_t i)
|
string string::from(std::uint8_t i)
|
||||||
{
|
{
|
||||||
return string(std::to_string(i).c_str());
|
return string(std::to_string(i).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
string string::from(std::uint16_t i)
|
string string::from(std::uint16_t i)
|
||||||
{
|
{
|
||||||
return string(std::to_string(i).c_str());
|
return string(std::to_string(i).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
string string::from(std::uint32_t i)
|
string string::from(std::uint32_t i)
|
||||||
{
|
{
|
||||||
return string(std::to_string(i).c_str());
|
return string(std::to_string(i).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
string string::from(std::uint64_t i)
|
string string::from(std::uint64_t i)
|
||||||
{
|
{
|
||||||
return string(std::to_string(i).c_str());
|
return string(std::to_string(i).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
string string::from(std::size_t i)
|
||||||
|
{
|
||||||
|
return string(std::to_string(i).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
string string::from(float i)
|
string string::from(float i)
|
||||||
{
|
{
|
||||||
return string(std::to_string(i).c_str());
|
return string(std::to_string(i).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
string string::from(double i)
|
string string::from(double i)
|
||||||
{
|
{
|
||||||
return string(std::to_string(i).c_str());
|
return string(std::to_string(i).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
string string::from(long double i)
|
string string::from(long double i)
|
||||||
{
|
{
|
||||||
return string(std::to_string(i).c_str());
|
return string(std::to_string(i).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
string::code_point &string::code_point::operator=(string::utf32_char value)
|
#ifdef XLNT_STD_STRING
|
||||||
{
|
|
||||||
utf8::append(value, data_ + index_);
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
string::utf32_char string::code_point::get() const
|
|
||||||
{
|
|
||||||
return utf8::peek_next(data_ + index_, data_ + end_);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
xlnt::string::common_iterator<false> &xlnt::string::common_iterator<false>::operator--()
|
string string::from(const std::string &s)
|
||||||
{
|
{
|
||||||
auto iter = current_.data_ + current_.index_;
|
return string(s.data());
|
||||||
utf8::prior(iter, current_.data_);
|
}
|
||||||
current_.index_ = iter - current_.data_;
|
#endif
|
||||||
|
|
||||||
|
xlnt::string::iterator::iterator(xlnt::string *parent, size_type index)
|
||||||
|
: parent_(parent),
|
||||||
|
index_(index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
xlnt::string::iterator::iterator(const xlnt::string::iterator &other)
|
||||||
|
: parent_(other.parent_),
|
||||||
|
index_(other.index_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
string::code_point xlnt::string::iterator::operator*()
|
||||||
|
{
|
||||||
|
return parent_->at(index_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool xlnt::string::iterator::operator==(const iterator &other) const
|
||||||
|
{
|
||||||
|
return parent_ == other.parent_ && index_ == other.index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
string::difference_type string::iterator::operator-(const iterator &other) const
|
||||||
|
{
|
||||||
|
return index_ - other.index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
xlnt::string::const_iterator::const_iterator(const xlnt::string *parent, size_type index)
|
||||||
|
: parent_(parent),
|
||||||
|
index_(index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
xlnt::string::const_iterator::const_iterator(const xlnt::string::iterator &other)
|
||||||
|
: parent_(other.parent_),
|
||||||
|
index_(other.index_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
xlnt::string::const_iterator::const_iterator(const xlnt::string::const_iterator &other)
|
||||||
|
: parent_(other.parent_),
|
||||||
|
index_(other.index_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
string::difference_type string::const_iterator::operator-(const const_iterator &other) const
|
||||||
|
{
|
||||||
|
return index_ - other.index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string::code_point xlnt::string::const_iterator::operator*() const
|
||||||
|
{
|
||||||
|
return parent_->at(index_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool xlnt::string::const_iterator::operator==(const const_iterator &other) const
|
||||||
|
{
|
||||||
|
return parent_ == other.parent_ && index_ == other.index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
xlnt::string::iterator &xlnt::string::iterator::operator--()
|
||||||
|
{
|
||||||
|
return *this -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xlnt::string::const_iterator &xlnt::string::const_iterator::operator--()
|
||||||
|
{
|
||||||
|
return *this -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xlnt::string::iterator &xlnt::string::iterator::operator++()
|
||||||
|
{
|
||||||
|
return *this += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
xlnt::string::const_iterator &xlnt::string::const_iterator::operator++()
|
||||||
|
{
|
||||||
|
return *this += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string::const_iterator &string::const_iterator::operator+=(int offset)
|
||||||
|
{
|
||||||
|
auto new_index = index_ + offset;
|
||||||
|
new_index = std::max<int>(0, std::min<int>(parent_->length(), new_index));
|
||||||
|
index_ = static_cast<std::size_t>(new_index);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
xlnt::string::iterator xlnt::string::iterator::operator+(int offset)
|
||||||
xlnt::string::common_iterator<true> &xlnt::string::common_iterator<true>::operator--()
|
|
||||||
{
|
{
|
||||||
auto iter = current_.data_ + current_.index_;
|
iterator copy = *this;
|
||||||
utf8::prior(iter, current_.data_);
|
|
||||||
current_.index_ = iter - current_.data_;
|
|
||||||
|
|
||||||
return *this;
|
auto new_index = index_ + offset;
|
||||||
|
new_index = std::max<int>(0, std::min<int>(parent_->length(), new_index));
|
||||||
|
copy.index_ = static_cast<std::size_t>(new_index);
|
||||||
|
|
||||||
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
xlnt::string::const_iterator xlnt::string::const_iterator::operator+(int offset)
|
||||||
xlnt::string::common_iterator<false> &xlnt::string::common_iterator<false>::operator++()
|
|
||||||
{
|
{
|
||||||
auto iter = current_.data_ + current_.index_;
|
const_iterator copy = *this;
|
||||||
utf8::advance(iter, 1, current_.data_ + current_.end_);
|
|
||||||
current_.index_ = iter - current_.data_;
|
|
||||||
|
|
||||||
return *this;
|
auto new_index = index_ + offset;
|
||||||
}
|
new_index = std::max<int>(0, std::min<int>(parent_->length(), new_index));
|
||||||
|
copy.index_ = static_cast<std::size_t>(new_index);
|
||||||
|
|
||||||
template<>
|
return copy;
|
||||||
xlnt::string::common_iterator<true> &xlnt::string::common_iterator<true>::operator++()
|
|
||||||
{
|
|
||||||
auto iter = current_.data_ + current_.index_;
|
|
||||||
utf8::advance(iter, 1, current_.data_ + current_.end_);
|
|
||||||
current_.index_ = iter - current_.data_;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string::string(size_type initial_size)
|
string::string(size_type initial_size)
|
||||||
: length_(0),
|
: data_(new std::vector<char>),
|
||||||
data_(new std::vector<char>)
|
code_point_byte_offsets_(new std::unordered_map<size_type, size_type>)
|
||||||
{
|
{
|
||||||
data_->resize(initial_size + 1);
|
data_->resize(initial_size + 1);
|
||||||
data_->back() = '\0';
|
data_->back() = '\0';
|
||||||
|
|
||||||
|
code_point_byte_offsets_->insert({0, 0});
|
||||||
}
|
}
|
||||||
|
|
||||||
string::string() : string(size_type(0))
|
string::string() : string(size_type(0))
|
||||||
|
@ -182,7 +261,9 @@ string::string(string &&str) : string()
|
||||||
swap(*this, str);
|
swap(*this, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
string::string(const string &str) : string(str, 0)
|
string::string(const string &str)
|
||||||
|
: data_(new std::vector<char>(*str.data_)),
|
||||||
|
code_point_byte_offsets_(new std::unordered_map<size_type, size_type>(*str.code_point_byte_offsets_))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,58 +273,100 @@ string::string(const string &str, size_type offset) : string(str, offset, str.le
|
||||||
|
|
||||||
string::string(const string &str, size_type offset, size_type len) : string()
|
string::string(const string &str, size_type offset, size_type len) : string()
|
||||||
{
|
{
|
||||||
*this = str.substr(offset, len);
|
auto part = str.substr(offset, len);
|
||||||
|
|
||||||
|
*data_ = *part.data_;
|
||||||
|
*code_point_byte_offsets_ = *part.code_point_byte_offsets_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef XLNT_STD_STRING
|
||||||
|
string::string(const std::string &str) : string(str.data())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
string::string(const utf_mb_wide_string str) : string()
|
string::string(const utf_mb_wide_string str) : string()
|
||||||
{
|
{
|
||||||
data_->clear();
|
auto iter = str;
|
||||||
utf8::utf16to8(str, str + count_bytes(str), std::back_inserter(*data_));
|
|
||||||
data_->push_back('\0');
|
|
||||||
|
|
||||||
length_ = utf8::distance(data(), data() + data_->size() - 1);
|
while(*iter != '\0')
|
||||||
|
{
|
||||||
|
append(*iter);
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string::string(const utf8_string str) : string()
|
string::string(const utf8_string str) : string()
|
||||||
{
|
{
|
||||||
data_->clear();
|
auto start = str;
|
||||||
std::copy(str, str + count_bytes(str), std::back_inserter(*data_));
|
auto end = str;
|
||||||
data_->push_back('\0');
|
|
||||||
|
|
||||||
length_ = utf8::distance(data(), data() + data_->size() - 1);
|
while(*end != '\0')
|
||||||
|
{
|
||||||
|
++end;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iter = start;
|
||||||
|
|
||||||
|
while(iter != end)
|
||||||
|
{
|
||||||
|
append((utf32_char)utf8::next(iter, end));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string::string(const utf16_string str) : string()
|
string::string(const utf16_string str) : string()
|
||||||
{
|
{
|
||||||
data_->clear();
|
auto iter = str;
|
||||||
utf8::utf16to8(str, str + count_bytes(str), std::back_inserter(*data_));
|
|
||||||
data_->push_back('\0');
|
|
||||||
|
|
||||||
length_ = utf8::distance(data(), data() + data_->size() - 1);
|
while(*iter != '\0')
|
||||||
|
{
|
||||||
|
append(*iter);
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string::string(const utf32_string str) : string()
|
string::string(const utf32_string str) : string()
|
||||||
{
|
{
|
||||||
data_->clear();
|
auto iter = str;
|
||||||
utf8::utf32to8(str, str + count_bytes(str), std::back_inserter(*data_));
|
|
||||||
data_->push_back('\0');
|
|
||||||
|
|
||||||
length_ = utf8::distance(data(), data() + data_->size() - 1);
|
while(*iter != '\0')
|
||||||
|
{
|
||||||
|
append(*iter);
|
||||||
|
iter++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string::~string()
|
string::~string()
|
||||||
{
|
{
|
||||||
delete data_;
|
delete data_;
|
||||||
|
data_ = nullptr;
|
||||||
|
delete code_point_byte_offsets_;
|
||||||
|
code_point_byte_offsets_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
string string::to_upper() const
|
string string::to_upper() const
|
||||||
{
|
{
|
||||||
return *this;
|
string upper;
|
||||||
|
|
||||||
|
for(auto c : *this)
|
||||||
|
{
|
||||||
|
upper.append(::to_upper(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
return upper;
|
||||||
}
|
}
|
||||||
|
|
||||||
string string::to_lower() const
|
string string::to_lower() const
|
||||||
{
|
{
|
||||||
return *this;
|
|
||||||
|
string lower;
|
||||||
|
|
||||||
|
for(auto c : *this)
|
||||||
|
{
|
||||||
|
lower.append(::to_lower(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
return lower;
|
||||||
}
|
}
|
||||||
|
|
||||||
string string::substr(size_type offset) const
|
string string::substr(size_type offset) const
|
||||||
|
@ -253,37 +376,22 @@ string string::substr(size_type offset) const
|
||||||
|
|
||||||
string string::substr(size_type offset, size_type len) const
|
string string::substr(size_type offset, size_type len) const
|
||||||
{
|
{
|
||||||
auto iter = begin() + offset;
|
if(len != npos && offset + len < length())
|
||||||
size_type i = 0;
|
|
||||||
string result;
|
|
||||||
|
|
||||||
while (i++ < len && iter != end())
|
|
||||||
{
|
{
|
||||||
result.append(*iter);
|
return string(begin() + offset, begin() + (offset + len));
|
||||||
++iter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return string(begin() + offset, end());
|
||||||
}
|
}
|
||||||
|
|
||||||
string::code_point string::back()
|
string::code_point string::back() const
|
||||||
{
|
{
|
||||||
return *(begin() + length_ + -1);
|
return at(length() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const string::code_point string::back() const
|
string::code_point string::front() const
|
||||||
{
|
{
|
||||||
return *(begin() + length_ + -1);
|
return at(0);
|
||||||
}
|
|
||||||
|
|
||||||
string::code_point string::front()
|
|
||||||
{
|
|
||||||
return *begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
const string::code_point string::front() const
|
|
||||||
{
|
|
||||||
return *begin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type string::find(code_point c) const
|
string::size_type string::find(code_point c) const
|
||||||
|
@ -296,7 +404,7 @@ string::size_type string::find(char c) const
|
||||||
return find(c, 0);
|
return find(c, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type string::find(string str) const
|
string::size_type string::find(const string &str) const
|
||||||
{
|
{
|
||||||
return find(str, 0);
|
return find(str, 0);
|
||||||
}
|
}
|
||||||
|
@ -305,24 +413,6 @@ string::size_type string::find(code_point c, size_type offset) const
|
||||||
{
|
{
|
||||||
auto iter = begin() + offset;
|
auto iter = begin() + offset;
|
||||||
|
|
||||||
while (iter != end())
|
|
||||||
{
|
|
||||||
if ((*iter).get() == c.get())
|
|
||||||
{
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
++iter;
|
|
||||||
offset++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return npos;
|
|
||||||
}
|
|
||||||
|
|
||||||
string::size_type string::find(char c, size_type offset) const
|
|
||||||
{
|
|
||||||
auto iter = begin() + offset;
|
|
||||||
|
|
||||||
while (iter != end())
|
while (iter != end())
|
||||||
{
|
{
|
||||||
if (*iter == c)
|
if (*iter == c)
|
||||||
|
@ -337,9 +427,24 @@ string::size_type string::find(char c, size_type offset) const
|
||||||
return npos;
|
return npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type string::find(string str, size_type offset) const
|
string::size_type string::find(char c, size_type offset) const
|
||||||
{
|
{
|
||||||
return 0;
|
return find(static_cast<code_point>(c), offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
string::size_type string::find(const string &str, size_type offset) const
|
||||||
|
{
|
||||||
|
while (offset < length() - str.length())
|
||||||
|
{
|
||||||
|
if (substr(offset, str.length()) == str)
|
||||||
|
{
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type string::find_last_of(code_point c) const
|
string::size_type string::find_last_of(code_point c) const
|
||||||
|
@ -352,60 +457,124 @@ string::size_type string::find_last_of(char c) const
|
||||||
return find_last_of(c, 0);
|
return find_last_of(c, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type string::find_last_of(string str) const
|
string::size_type string::find_last_of(const string &str) const
|
||||||
{
|
{
|
||||||
return find_last_of(str, 0);
|
return find_last_of(str, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type string::find_last_of(code_point c, size_type offset) const
|
string::size_type string::find_last_of(code_point c, size_type offset) const
|
||||||
{
|
{
|
||||||
return 0;
|
auto stop = begin() + offset;
|
||||||
|
auto iter = end() - 1;
|
||||||
|
|
||||||
|
while (iter != stop)
|
||||||
|
{
|
||||||
|
if (*iter == c)
|
||||||
|
{
|
||||||
|
return iter - begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
--iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *stop == c ? offset : npos;
|
||||||
}
|
}
|
||||||
string::size_type string::find_last_of(char c, size_type offset) const
|
string::size_type string::find_last_of(char c, size_type offset) const
|
||||||
{
|
{
|
||||||
return 0;
|
return find_last_of(static_cast<code_point>(c), offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type string::find_last_of(string str, size_type offset) const
|
string::size_type string::find_last_of(const string &str, size_type offset) const
|
||||||
{
|
{
|
||||||
return 0;
|
auto stop = begin() + offset;
|
||||||
|
auto iter = end() - 1;
|
||||||
|
|
||||||
|
while (iter != stop)
|
||||||
|
{
|
||||||
|
if(str.find(*iter) != npos)
|
||||||
|
{
|
||||||
|
return iter - begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
--iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type string::find_first_of(string str) const
|
string::size_type string::find_first_of(const string &str) const
|
||||||
{
|
{
|
||||||
return find_first_of(str, 0);
|
return find_first_of(str, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type string::find_first_of(string str, size_type offset) const
|
string::size_type string::find_first_of(const string &str, size_type offset) const
|
||||||
{
|
{
|
||||||
return 0;
|
auto iter = begin() + offset;
|
||||||
|
|
||||||
|
while (iter != end())
|
||||||
|
{
|
||||||
|
if(str.find(*iter) != npos)
|
||||||
|
{
|
||||||
|
return iter - begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type string::find_first_not_of(string str) const
|
string::size_type string::find_first_not_of(const string &str) const
|
||||||
{
|
{
|
||||||
return find_first_not_of(str, 0);
|
return find_first_not_of(str, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type string::find_first_not_of(string str, size_type offset) const
|
string::size_type string::find_first_not_of(const string &str, size_type offset) const
|
||||||
{
|
{
|
||||||
return 0;
|
auto iter = begin() + offset;
|
||||||
|
|
||||||
|
while (iter != end())
|
||||||
|
{
|
||||||
|
if(str.find(*iter) == npos)
|
||||||
|
{
|
||||||
|
return iter - begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type string::find_last_not_of(string str) const
|
string::size_type string::find_last_not_of(const string &str) const
|
||||||
{
|
{
|
||||||
return find_last_not_of(str, 0);
|
return find_last_not_of(str, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
string::size_type string::find_last_not_of(string str, size_type offset) const
|
string::size_type string::find_last_not_of(const string &str, size_type offset) const
|
||||||
{
|
{
|
||||||
return 0;
|
auto stop = begin() + offset;
|
||||||
|
auto iter = end() - 1;
|
||||||
|
|
||||||
|
while (iter != stop)
|
||||||
|
{
|
||||||
|
if(str.find(*iter) == npos)
|
||||||
|
{
|
||||||
|
return iter - begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
--iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void string::clear()
|
void string::clear()
|
||||||
{
|
{
|
||||||
length_ = 0;
|
|
||||||
data_->clear();
|
data_->clear();
|
||||||
data_->push_back('\0');
|
data_->push_back('\0');
|
||||||
|
code_point_byte_offsets_->clear();
|
||||||
|
code_point_byte_offsets_->insert({0, 0});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
@ -432,14 +601,40 @@ long double string::to() const
|
||||||
return std::stold(std::string(data()));
|
return std::stold(std::string(data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
double string::to() const
|
||||||
|
{
|
||||||
|
return std::stod(std::string(data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef XLNT_STD_STRING
|
||||||
|
template<>
|
||||||
|
std::string string::to() const
|
||||||
|
{
|
||||||
|
return std::string(data());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int string::to_hex() const
|
int string::to_hex() const
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void string::remove(code_point iter)
|
void string::erase(size_type index)
|
||||||
{
|
{
|
||||||
|
auto start = code_point_byte_offsets_->at(index);
|
||||||
|
auto next_start = code_point_byte_offsets_->at(index + 1);
|
||||||
|
|
||||||
|
data_->erase(data_->begin() + start, data_->begin() + next_start);
|
||||||
|
|
||||||
|
auto code_point_bytes = next_start - start;
|
||||||
|
|
||||||
|
for(size_type i = index + 1; i < length(); i++)
|
||||||
|
{
|
||||||
|
code_point_byte_offsets_->at(i) = code_point_byte_offsets_->at(i + 1) - code_point_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
code_point_byte_offsets_->erase(code_point_byte_offsets_->find(length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
string &string::operator=(string rhs)
|
string &string::operator=(string rhs)
|
||||||
|
@ -451,22 +646,22 @@ string &string::operator=(string rhs)
|
||||||
|
|
||||||
string::iterator string::begin()
|
string::iterator string::begin()
|
||||||
{
|
{
|
||||||
return iterator(data(), 0, length_);
|
return iterator(this, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
string::const_iterator string::cbegin() const
|
string::const_iterator string::cbegin() const
|
||||||
{
|
{
|
||||||
return const_iterator(data(), 0, length_);
|
return const_iterator(this, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
string::iterator string::end()
|
string::iterator string::end()
|
||||||
{
|
{
|
||||||
return iterator(data(), length_, length_);
|
return iterator(this, length());
|
||||||
}
|
}
|
||||||
|
|
||||||
string::const_iterator string::cend() const
|
string::const_iterator string::cend() const
|
||||||
{
|
{
|
||||||
return const_iterator(data(), length_, length_);
|
return const_iterator(this, length());
|
||||||
}
|
}
|
||||||
|
|
||||||
string::byte_pointer string::data()
|
string::byte_pointer string::data()
|
||||||
|
@ -485,7 +680,7 @@ std::size_t string::hash() const
|
||||||
return hasher(std::string(data()));
|
return hasher(std::string(data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t string::bytes() const
|
std::size_t string::num_bytes() const
|
||||||
{
|
{
|
||||||
return data_->size();
|
return data_->size();
|
||||||
}
|
}
|
||||||
|
@ -495,37 +690,67 @@ void string::append(char c)
|
||||||
data_->back() = c;
|
data_->back() = c;
|
||||||
data_->push_back('\0');
|
data_->push_back('\0');
|
||||||
|
|
||||||
length_++;
|
code_point_byte_offsets_->insert({length() + 1, num_bytes() - 1});
|
||||||
}
|
}
|
||||||
|
|
||||||
void string::append(wchar_t c)
|
void string::append(wchar_t c)
|
||||||
{
|
{
|
||||||
|
if(c < 128)
|
||||||
|
{
|
||||||
|
append(static_cast<char>(c));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
data_->pop_back();
|
data_->pop_back();
|
||||||
utf8::utf16to8(&c, &c + 1, std::back_inserter(*data_));
|
|
||||||
|
std::array<char, 4> utf8_encoded {{0}};
|
||||||
|
auto end = utf8::utf16to8(&c, &c + 1, utf8_encoded.begin());
|
||||||
|
std::copy(utf8_encoded.begin(), end, std::back_inserter(*data_));
|
||||||
|
|
||||||
data_->push_back('\0');
|
data_->push_back('\0');
|
||||||
|
|
||||||
length_++;
|
code_point_byte_offsets_->insert({length() + 1, num_bytes() - 1});
|
||||||
}
|
}
|
||||||
|
|
||||||
void string::append(char16_t c)
|
void string::append(char16_t c)
|
||||||
{
|
{
|
||||||
|
if(c < 128)
|
||||||
|
{
|
||||||
|
append(static_cast<char>(c));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
data_->pop_back();
|
data_->pop_back();
|
||||||
utf8::utf16to8(&c, &c + 1, std::back_inserter(*data_));
|
|
||||||
|
std::array<char, 4> utf8_encoded {{0}};
|
||||||
|
auto end = utf8::utf16to8(&c, &c + 1, utf8_encoded.begin());
|
||||||
|
std::copy(utf8_encoded.begin(), end, std::back_inserter(*data_));
|
||||||
|
|
||||||
data_->push_back('\0');
|
data_->push_back('\0');
|
||||||
|
|
||||||
length_++;
|
code_point_byte_offsets_->insert({length() + 1, num_bytes() - 1});
|
||||||
}
|
}
|
||||||
|
|
||||||
void string::append(char32_t c)
|
void string::append(code_point c)
|
||||||
{
|
{
|
||||||
|
if(c < 128)
|
||||||
|
{
|
||||||
|
append(static_cast<char>(c));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
data_->pop_back();
|
data_->pop_back();
|
||||||
utf8::utf32to8(&c, &c + 1, std::back_inserter(*data_));
|
|
||||||
|
std::array<char, 4> utf8_encoded {{0}};
|
||||||
|
auto end = utf8::utf32to8(&c, &c + 1, utf8_encoded.begin());
|
||||||
|
std::copy(utf8_encoded.begin(), end, std::back_inserter(*data_));
|
||||||
|
|
||||||
data_->push_back('\0');
|
data_->push_back('\0');
|
||||||
|
|
||||||
length_++;
|
code_point_byte_offsets_->insert({length() + 1, num_bytes() - 1});
|
||||||
}
|
}
|
||||||
|
|
||||||
void string::append(string str)
|
void string::append(const string &str)
|
||||||
{
|
{
|
||||||
for (auto c : str)
|
for (auto c : str)
|
||||||
{
|
{
|
||||||
|
@ -533,19 +758,61 @@ void string::append(string str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void string::append(code_point c)
|
void string::replace(size_type index, utf32_char value)
|
||||||
{
|
{
|
||||||
append(c.get());
|
std::array<byte, 4> encoded = {{0}};
|
||||||
|
auto encoded_end = utf8::utf32to8(&value, &value + 1, encoded.begin());
|
||||||
|
auto encoded_len = encoded_end - encoded.begin();
|
||||||
|
|
||||||
|
auto data_start = code_point_byte_offsets_->at(index);
|
||||||
|
auto data_end = code_point_byte_offsets_->at(index + 1);
|
||||||
|
|
||||||
|
auto previous_len = data_end - data_start;
|
||||||
|
int difference = encoded_len - previous_len;
|
||||||
|
|
||||||
|
if(difference < 0)
|
||||||
|
{
|
||||||
|
data_->erase(data_->begin() + data_end + difference, data_->begin() + data_end);
|
||||||
|
}
|
||||||
|
else if(difference > 0)
|
||||||
|
{
|
||||||
|
data_->insert(data_->begin() + data_start, difference, '\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
for(std::size_t i = index + 1; i < code_point_byte_offsets_->size(); i++)
|
||||||
|
{
|
||||||
|
code_point_byte_offsets_->at(i) += difference;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iter = encoded.begin();
|
||||||
|
auto data_iter = data_->begin() + data_start;
|
||||||
|
|
||||||
|
while(iter != encoded_end)
|
||||||
|
{
|
||||||
|
*data_iter = *iter;
|
||||||
|
++data_iter;
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string::code_point string::at(size_type index)
|
string::code_point string::at(size_type index)
|
||||||
{
|
{
|
||||||
return *(begin() + index);
|
if(index == length())
|
||||||
|
{
|
||||||
|
return U'\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return utf8::peek_next(data_->begin() + code_point_byte_offsets_->at(index), data_->end());
|
||||||
}
|
}
|
||||||
|
|
||||||
const string::code_point string::at(size_type index) const
|
const string::code_point string::at(size_type index) const
|
||||||
{
|
{
|
||||||
return *(begin() + index);
|
if(index == length())
|
||||||
|
{
|
||||||
|
return U'\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return utf8::peek_next(data_->begin() + code_point_byte_offsets_->at(index), data_->end());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool string::operator==(const_byte_pointer str) const
|
bool string::operator==(const_byte_pointer str) const
|
||||||
|
@ -562,7 +829,7 @@ bool string::operator==(const string &str) const
|
||||||
|
|
||||||
while (left_iter != end() && right_iter != str.end())
|
while (left_iter != end() && right_iter != str.end())
|
||||||
{
|
{
|
||||||
if ((*left_iter).get() != (*right_iter).get())
|
if (*left_iter != *right_iter)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -603,8 +870,8 @@ void swap(string &left, string &right)
|
||||||
{
|
{
|
||||||
using std::swap;
|
using std::swap;
|
||||||
|
|
||||||
swap(left.length_, right.length_);
|
|
||||||
swap(left.data_, right.data_);
|
swap(left.data_, right.data_);
|
||||||
|
swap(left.code_point_byte_offsets_, right.code_point_byte_offsets_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream &operator<<(std::ostream &left, string &right)
|
std::ostream &operator<<(std::ostream &left, string &right)
|
||||||
|
@ -631,4 +898,9 @@ bool string::operator<(const string &other) const
|
||||||
return std::string(data()) < std::string(other.data());
|
return std::string(data()) < std::string(other.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string::size_type string::length() const
|
||||||
|
{
|
||||||
|
return code_point_byte_offsets_->size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace xlnt
|
} // namespace xlnt
|
||||||
|
|
|
@ -27,7 +27,8 @@ std::vector<xlnt::string> split_string(const xlnt::string &string, char delim)
|
||||||
separator_index = string.find(delim, previous_index);
|
separator_index = string.find(delim, previous_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
split.push_back(string.substr(previous_index));
|
auto part = string.substr(previous_index);
|
||||||
|
split.push_back(part);
|
||||||
|
|
||||||
return split;
|
return split;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,9 +47,9 @@ public:
|
||||||
{
|
{
|
||||||
xlnt::workbook wb;
|
xlnt::workbook wb;
|
||||||
auto new_sheet = wb.create_sheet();
|
auto new_sheet = wb.create_sheet();
|
||||||
std::string title = "my sheet";
|
xlnt::string title = "my sheet";
|
||||||
new_sheet.set_title(title.c_str());
|
new_sheet.set_title(title);
|
||||||
auto found_sheet = wb.get_sheet_by_name(title.c_str());
|
auto found_sheet = wb.get_sheet_by_name(title);
|
||||||
TS_ASSERT_EQUALS(new_sheet, found_sheet);
|
TS_ASSERT_EQUALS(new_sheet, found_sheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,9 +120,9 @@ public:
|
||||||
{
|
{
|
||||||
xlnt::workbook wb;
|
xlnt::workbook wb;
|
||||||
auto new_sheet = wb.create_sheet();
|
auto new_sheet = wb.create_sheet();
|
||||||
std::string title = "my sheet";
|
xlnt::string title = "my sheet";
|
||||||
new_sheet.set_title(title.c_str());
|
new_sheet.set_title(title);
|
||||||
auto found_sheet = wb.get_sheet_by_name(title.c_str());
|
auto found_sheet = wb.get_sheet_by_name(title);
|
||||||
TS_ASSERT_EQUALS(new_sheet, found_sheet);
|
TS_ASSERT_EQUALS(new_sheet, found_sheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -351,7 +351,7 @@ std::size_t workbook::index_from_ws_filename(const string &ws_filename)
|
||||||
sheet_index_string = sheet_index_string.substr(sheet_index_string.find_last_of('/'));
|
sheet_index_string = sheet_index_string.substr(sheet_index_string.find_last_of('/'));
|
||||||
auto iter = sheet_index_string.end();
|
auto iter = sheet_index_string.end();
|
||||||
--iter;
|
--iter;
|
||||||
while (isdigit((*iter).get()))
|
while (isdigit((*iter)))
|
||||||
--iter;
|
--iter;
|
||||||
auto first_digit = static_cast<std::size_t>(iter - sheet_index_string.begin());
|
auto first_digit = static_cast<std::size_t>(iter - sheet_index_string.begin());
|
||||||
sheet_index_string = sheet_index_string.substr(first_digit + 1);
|
sheet_index_string = sheet_index_string.substr(first_digit + 1);
|
||||||
|
@ -388,9 +388,9 @@ worksheet workbook::create_sheet(const string &title)
|
||||||
throw sheet_title_exception(title);
|
throw sheet_title_exception(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::find_if(title.data(), title.data() + title.bytes(), [](char c) {
|
if (std::find_if(title.data(), title.data() + title.num_bytes(), [](char c) {
|
||||||
return c == '*' || c == ':' || c == '/' || c == '\\' || c == '?' || c == '[' || c == ']';
|
return c == '*' || c == ':' || c == '/' || c == '\\' || c == '?' || c == '[' || c == ']';
|
||||||
}) != title.data() + title.bytes())
|
}) != title.data() + title.num_bytes())
|
||||||
{
|
{
|
||||||
throw sheet_title_exception(title);
|
throw sheet_title_exception(title);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ string sheet_protection::hash_password(const string &plaintext_password)
|
||||||
{
|
{
|
||||||
int password = 0x0000;
|
int password = 0x0000;
|
||||||
|
|
||||||
for (int i = 1; i <= plaintext_password.bytes(); i++)
|
for (int i = 1; i <= plaintext_password.num_bytes(); i++)
|
||||||
{
|
{
|
||||||
char character = plaintext_password.data()[i - 1];
|
char character = plaintext_password.data()[i - 1];
|
||||||
int value = character << i;
|
int value = character << i;
|
||||||
|
@ -33,13 +33,13 @@ string sheet_protection::hash_password(const string &plaintext_password)
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
password ^= plaintext_password.bytes();
|
password ^= plaintext_password.num_bytes();
|
||||||
password ^= 0xCE4B;
|
password ^= 0xCE4B;
|
||||||
|
|
||||||
string hashed = int_to_hex(password);
|
string hashed = int_to_hex(password);
|
||||||
auto iter = hashed.data();
|
auto iter = hashed.data();
|
||||||
|
|
||||||
while (iter != hashed.data() + hashed.bytes())
|
while (iter != hashed.data() + hashed.num_bytes())
|
||||||
{
|
{
|
||||||
*iter = std::toupper(*iter, std::locale::classic());
|
*iter = std::toupper(*iter, std::locale::classic());
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,13 +55,13 @@ public:
|
||||||
return compare_xml(expected_xml.get_root(), observed.get_root());
|
return compare_xml(expected_xml.get_root(), observed.get_root());
|
||||||
}
|
}
|
||||||
|
|
||||||
static comparison_result compare_xml(const std::string &left_contents, const std::string &right_contents)
|
static comparison_result compare_xml(const xlnt::string &left_contents, const xlnt::string &right_contents)
|
||||||
{
|
{
|
||||||
xlnt::xml_document left_xml;
|
xlnt::xml_document left_xml;
|
||||||
left_xml.from_string(left_contents.c_str());
|
left_xml.from_string(left_contents.data());
|
||||||
|
|
||||||
xlnt::xml_document right_xml;
|
xlnt::xml_document right_xml;
|
||||||
right_xml.from_string(right_contents.c_str());
|
right_xml.from_string(right_contents.data());
|
||||||
|
|
||||||
return compare_xml(left_xml.get_root(), right_xml.get_root());
|
return compare_xml(left_xml.get_root(), right_xml.get_root());
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,7 @@ public:
|
||||||
|
|
||||||
if (_NSGetExecutablePath(path.data(), &size) == 0)
|
if (_NSGetExecutablePath(path.data(), &size) == 0)
|
||||||
{
|
{
|
||||||
return std::string(path.begin(), std::find(path.begin(), path.end(), '\0') - 9);
|
return xlnt::string(path.begin(), std::find(path.begin(), path.end(), '\0') - 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::runtime_error("buffer too small, " + std::to_string(path.size()) + ", should be: " + std::to_string(size));
|
throw std::runtime_error("buffer too small, " + std::to_string(path.size()) + ", should be: " + std::to_string(size));
|
||||||
|
@ -126,7 +126,7 @@ public:
|
||||||
{
|
{
|
||||||
struct stat fileAtt;
|
struct stat fileAtt;
|
||||||
|
|
||||||
if (stat(path.c_str(), &fileAtt) == 0)
|
if (stat(path.data(), &fileAtt) == 0)
|
||||||
{
|
{
|
||||||
return S_ISREG(fileAtt.st_mode);
|
return S_ISREG(fileAtt.st_mode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
class TemporaryDirectory
|
class TemporaryDirectory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::string CreateTemporaryFilename()
|
static xlnt::string CreateTemporaryFilename()
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
std::array<TCHAR, MAX_PATH> buffer;
|
std::array<TCHAR, MAX_PATH> buffer;
|
||||||
|
@ -24,7 +24,7 @@ public:
|
||||||
{
|
{
|
||||||
throw std::runtime_error("GetTempPath failed");
|
throw std::runtime_error("GetTempPath failed");
|
||||||
}
|
}
|
||||||
std::string directory(buffer.begin(), buffer.begin() + result);
|
xlnt::string directory(buffer.begin(), buffer.begin() + result);
|
||||||
return PathHelper::WindowsToUniversalPath(directory + "xlnt");
|
return PathHelper::WindowsToUniversalPath(directory + "xlnt");
|
||||||
#else
|
#else
|
||||||
return "/tmp/xlsx";
|
return "/tmp/xlsx";
|
||||||
|
@ -41,8 +41,8 @@ public:
|
||||||
remove(filename_.c_str());
|
remove(filename_.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetFilename() const { return filename_; }
|
xlnt::string GetFilename() const { return filename_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::string filename_;
|
const xlnt::string filename_;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user