aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/common/String.hpp61
-rw-r--r--src/common/String.cpp32
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);