diff options
-rw-r--r-- | include/cru/common/String.hpp | 61 | ||||
-rw-r--r-- | src/common/String.cpp | 32 |
2 files changed, 59 insertions, 34 deletions
diff --git a/include/cru/common/String.hpp b/include/cru/common/String.hpp index ed3deb4c..f407cb60 100644 --- a/include/cru/common/String.hpp +++ b/include/cru/common/String.hpp @@ -12,6 +12,7 @@ #include <limits> #include <stdexcept> #include <string> +#include <string_view> #include <system_error> #include <type_traits> #include <vector> @@ -21,20 +22,36 @@ class StringView; class CRU_BASE_API String { public: + using value_type = std::uint16_t; + using size_type = Index; + using difference_type = Index; + using reference = std::uint16_t&; + using const_reference = const std::uint16_t&; + using pointer = std::uint16_t*; + using const_pointer = const std::uint16_t*; + using iterator = std::uint16_t*; + using const_iterator = const std::uint16_t*; + using reverse_iterator = std::reverse_iterator<iterator>; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + + public: + static String FromUtf8(const char* str); + static String FromUtf8(const char* str, Index size); static String FromUtf8(std::string_view str) { return FromUtf8(str.data(), str.size()); } - static String FromUtf8(const char* str, Index size); - static String FromUtf16(const std::uint16_t* str) { return String(str); } - static String FromUtf16(const std::uint16_t* str, Index size) { - return String(str, size); + static String FromUtf16(const char16_t* str) { + return String(reinterpret_cast<const_pointer>(str)); } - - static String FromUtf16(const char16_t* str) { return String(str); } static String FromUtf16(const char16_t* str, Index size) { - return String(str, size); + return String(reinterpret_cast<const_pointer>(str), size); } + static String FromUtf16(std::u16string_view str) { + return FromUtf16(str.data(), str.size()); + } + + static inline String From(StringView str); // Never use this if you don't know what this mean! static String FromBuffer(std::uint16_t* buffer, Index size, Index capacity) { @@ -49,30 +66,14 @@ class CRU_BASE_API String { #endif public: - using value_type = std::uint16_t; - using size_type = Index; - using difference_type = Index; - using reference = std::uint16_t&; - using const_reference = const std::uint16_t&; - using pointer = std::uint16_t*; - using const_pointer = const std::uint16_t*; - using iterator = std::uint16_t*; - using const_iterator = const std::uint16_t*; - using reverse_iterator = std::reverse_iterator<iterator>; - using const_reverse_iterator = std::reverse_iterator<const_iterator>; - - public: String() = default; - explicit String(const std::uint16_t* str); - String(const std::uint16_t* str, Index size); - - explicit String(const char16_t* str); - String(const char16_t* str, Index size); - String(const std::u16string_view& str) : String(str.data(), str.size()) {} + explicit String(const_pointer str); + String(const_pointer str, size_type size); template <Index size> - constexpr String(const char16_t (&str)[size]) : String(str, size) {} + String(const char16_t (&str)[size]) + : String(reinterpret_cast<const_pointer>(str), size) {} template <typename Iter> String(Iter start, Iter end) { @@ -81,8 +82,7 @@ class CRU_BASE_API String { } } - String(const std::initializer_list<std::uint16_t>& l) - : String(l.begin(), l.end()) {} + String(std::initializer_list<value_type> l) : String(l.begin(), l.end()) {} #ifdef CRU_PLATFORM_WINDOWS String(const wchar_t* str); @@ -112,6 +112,7 @@ class CRU_BASE_API String { void resize(Index new_size); void reserve(Index new_capacity); + void shrink_to_fit(); std::uint16_t& front() { return this->operator[](0); } const std::uint16_t& front() const { return this->operator[](0); } @@ -369,6 +370,8 @@ inline String::iterator String::insert(const_iterator pos, StringView str) { inline void String::append(StringView str) { this->append(str.data(), str.size()); } + +inline String String::From(StringView str) { return str.ToString(); } } // namespace cru template <> diff --git a/src/common/String.cpp b/src/common/String.cpp index 3d3e4a3c..092ba406 100644 --- a/src/common/String.cpp +++ b/src/common/String.cpp @@ -9,8 +9,12 @@ #include <string_view> namespace cru { +String String::FromUtf8(const char* str) { + return FromUtf16(cru::ToUtf16(std::string_view(str))); +} + String String::FromUtf8(const char* str, Index size) { - return String{cru::ToUtf16(std::string_view(str, size))}; + return FromUtf16(cru::ToUtf16(std::string_view(str, size))); } std::uint16_t String::kEmptyBuffer[1] = {0}; @@ -25,6 +29,7 @@ Index GetStrSize(const C* str) { } String::String(const std::uint16_t* str) : String(str, GetStrSize(str)) {} + String::String(const std::uint16_t* str, Index size) { this->buffer_ = new std::uint16_t[size + 1]; std::memcpy(this->buffer_, str, size * sizeof(char16_t)); @@ -33,10 +38,6 @@ String::String(const std::uint16_t* str, Index size) { this->capacity_ = size; } -String::String(const char16_t* str) : String(str, GetStrSize(str)) {} -String::String(const char16_t* str, Index size) - : String(reinterpret_cast<const std::uint16_t*>(str), size) {} - #ifdef CRU_PLATFORM_WINDOWS String::String(const wchar_t* str) : String(str, GetStrSize(str)) {} String::String(const wchar_t* str, Index size) @@ -125,7 +126,24 @@ void String::resize(Index new_size) { } } +void String::shrink_to_fit() { + if (capacity_ == size_) return; + if (size_ == 0) { + delete[] buffer_; + buffer_ = kEmptyBuffer; + size_ = 0; + capacity_ = 0; + } else { + auto new_buffer = new value_type[size_ + 1]; + std::memcpy(new_buffer, buffer_, sizeof(value_type) * size_); + delete[] buffer_; + buffer_ = new_buffer; + capacity_ = size_; + } +} + void String::reserve(Index new_capacity) { + Expects(new_capacity >= 0); if (new_capacity <= this->capacity_) return; if (new_capacity > 0) { std::uint16_t* new_buffer = new std::uint16_t[new_capacity + 1]; @@ -141,6 +159,8 @@ void String::reserve(Index new_capacity) { String::iterator String::insert(const_iterator pos, const std::uint16_t* str, Index size) { + Expects(pos >= cbegin() && pos <= cend()); + std::vector<std::uint16_t> backup_buffer; if (str >= buffer_ && str < buffer_ + size_) { backup_buffer.resize(size); @@ -174,6 +194,8 @@ String::iterator String::insert(const_iterator pos, const std::uint16_t* str, } String::iterator String::erase(const_iterator start, const_iterator end) { + Expects(buffer_ <= start && start <= end && end <= buffer_ + size_); + Index new_size = size_ - (end - start); auto s = const_cast<iterator>(start); |