diff options
-rw-r--r-- | include/cru/common/Format.hpp | 3 | ||||
-rw-r--r-- | include/cru/common/String.hpp | 68 | ||||
-rw-r--r-- | include/cru/common/StringUtil.hpp | 36 | ||||
-rw-r--r-- | include/cru/xml/XmlNode.hpp | 1 | ||||
-rw-r--r-- | src/common/String.cpp | 304 | ||||
-rw-r--r-- | src/common/StringUtil.cpp | 28 | ||||
-rw-r--r-- | src/ui/mapper/PointMapper.cpp | 4 | ||||
-rw-r--r-- | test/common/StringTest.cpp | 41 | ||||
-rw-r--r-- | test/common/StringUtilTest.cpp | 17 |
9 files changed, 276 insertions, 226 deletions
diff --git a/include/cru/common/Format.hpp b/include/cru/common/Format.hpp index c2fd2e09..1ad71262 100644 --- a/include/cru/common/Format.hpp +++ b/include/cru/common/Format.hpp @@ -2,7 +2,8 @@ #include "Exception.hpp" #include "String.hpp" -#include "cru/common/Base.hpp" + +#include <charconv> namespace cru { inline String ToString(bool value) { diff --git a/include/cru/common/String.hpp b/include/cru/common/String.hpp index dac81e8d..1d660623 100644 --- a/include/cru/common/String.hpp +++ b/include/cru/common/String.hpp @@ -5,18 +5,10 @@ #include "StringUtil.hpp" #include <double-conversion/double-conversion.h> -#include <algorithm> -#include <array> -#include <charconv> #include <initializer_list> #include <iterator> -#include <limits> -#include <stdexcept> #include <string> #include <string_view> -#include <system_error> -#include <tuple> -#include <type_traits> #include <vector> namespace cru { @@ -24,9 +16,6 @@ class StringView; class CRU_BASE_API String { public: - static double_conversion::StringToDoubleConverter - kDefaultStringToDoubleConverter; - using value_type = char16_t; using size_type = Index; using difference_type = Index; @@ -181,24 +170,21 @@ class CRU_BASE_API String { return String(this->buffer_ + start, size); } - public: String& operator+=(value_type value) { this->append(value); return *this; } String& operator+=(StringView other); + public: operator std::u16string_view() const { return std::u16string_view(data(), size()); } + StringView View() const; + public: Index Find(value_type value, Index start = 0) const; - - String& TrimStart(); - String& TrimEnd(); - String& Trim(); - std::vector<String> Split(value_type separator, bool remove_space_line = false) const; std::vector<String> SplitToLines(bool remove_space_line = false) const; @@ -206,6 +192,10 @@ class CRU_BASE_API String { bool StartWith(StringView str) const; bool EndWith(StringView str) const; + String& TrimStart(); + String& TrimEnd(); + String& Trim(); + public: void AppendCodePoint(CodePoint code_point); @@ -218,6 +208,11 @@ class CRU_BASE_API String { Range RangeFromCodeUnitToCodePoint(Range code_unit_range) const; Range RangeFromCodePointToCodeUnit(Range code_point_range) const; + float ParseToFloat(Index* processed_characters_count = nullptr) const; + double ParseToDouble(Index* processed_characters_count = nullptr) const; + std::vector<float> ParseToFloatList(value_type separator = u' ') const; + std::vector<double> ParseToDoubleList(value_type separator = u' ') const; + #ifdef CRU_PLATFORM_WINDOWS const wchar_t* WinCStr() const { return reinterpret_cast<const wchar_t*>(c_str()); @@ -231,11 +226,6 @@ class CRU_BASE_API String { int Compare(const String& other) const; - float ParseToFloat(Index* processed_characters_count = nullptr) const; - double ParseToDouble(Index* processed_characters_count = nullptr) const; - std::vector<float> ParseToFloatList(value_type separator = u' '); - std::vector<double> ParseToDoubleList(value_type separator = u' '); - private: static char16_t kEmptyBuffer[1]; @@ -247,6 +237,9 @@ class CRU_BASE_API String { class CRU_BASE_API StringView { public: + static double_conversion::StringToDoubleConverter + kDefaultStringToDoubleConverter; + using value_type = char16_t; using size_type = Index; using difference_type = Index; @@ -307,16 +300,39 @@ class CRU_BASE_API StringView { StringView substr(Index pos); StringView substr(Index pos, Index size); - int Compare(const StringView& other) const; - - String ToString() const { return String(ptr_, size_); } - value_type operator[](Index index) const { return ptr_[index]; } operator std::u16string_view() const { return std::u16string_view(data(), size()); } + public: + int Compare(const StringView& other) const; + + String ToString() const { return String(ptr_, size_); } + + Utf16CodePointIterator CodePointIterator() const { + return Utf16CodePointIterator(ptr_, size_); + } + + Index Find(value_type value, Index start = 0) const; + std::vector<String> Split(value_type separator, + bool remove_space_line = false) const; + std::vector<String> SplitToLines(bool remove_space_line = false) const; + + bool StartWith(StringView str) const; + bool EndWith(StringView str) const; + + Index IndexFromCodeUnitToCodePoint(Index code_unit_index) const; + Index IndexFromCodePointToCodeUnit(Index code_point_index) const; + Range RangeFromCodeUnitToCodePoint(Range code_unit_range) const; + Range RangeFromCodePointToCodeUnit(Range code_point_range) const; + + float ParseToFloat(Index* processed_characters_count = nullptr) const; + double ParseToDouble(Index* processed_characters_count = nullptr) const; + std::vector<float> ParseToFloatList(value_type separator = u' ') const; + std::vector<double> ParseToDoubleList(value_type separator = u' ') const; + std::string ToUtf8() const; private: diff --git a/include/cru/common/StringUtil.hpp b/include/cru/common/StringUtil.hpp index 2d53fc2b..c840960d 100644 --- a/include/cru/common/StringUtil.hpp +++ b/include/cru/common/StringUtil.hpp @@ -2,9 +2,6 @@ #include "Base.hpp" #include <functional> -#include <stdexcept> -#include <string> -#include <string_view> namespace cru { using CodePoint = std::int32_t; @@ -118,9 +115,6 @@ using Utf8CodePointIterator = CodePointIterator<char, &Utf8NextCodePoint>; using Utf16CodePointIterator = CodePointIterator<char16_t, &Utf16NextCodePoint>; -void CRU_BASE_API Utf8EncodeCodePointAppend(CodePoint code_point, - std::string& str); - namespace details { template <typename UInt, int number_of_bit, typename ReturnType> inline std::enable_if_t<std::is_unsigned_v<UInt>, ReturnType> ExtractBits( @@ -129,18 +123,18 @@ inline std::enable_if_t<std::is_unsigned_v<UInt>, ReturnType> ExtractBits( } } // namespace details -template <typename TAppend> -bool Utf8EncodeCodePointAppendWithFunc(CodePoint code_point, TAppend&& append) { - auto write_continue_byte = [&append](std::uint8_t byte6) { - append((1u << 7) + (((1u << 6) - 1) & byte6)); +template <typename TStr> +bool Utf8EncodeCodePointAppend(CodePoint code_point, TStr& str) { + auto write_continue_byte = [&str](std::uint8_t byte6) { + str.push_back((1u << 7) + (((1u << 6) - 1) & byte6)); }; if (code_point >= 0 && code_point <= 0x007F) { - append(static_cast<char>(code_point)); + str.push_back(static_cast<char>(code_point)); return true; } else if (code_point >= 0x0080 && code_point <= 0x07FF) { std::uint32_t unsigned_code_point = code_point; - append( + str.push_back( static_cast<char>(details::ExtractBits<std::uint32_t, 5, std::uint8_t>( (unsigned_code_point >> 6)) + 0b11000000)); @@ -149,7 +143,7 @@ bool Utf8EncodeCodePointAppendWithFunc(CodePoint code_point, TAppend&& append) { return true; } else if (code_point >= 0x0800 && code_point <= 0xFFFF) { std::uint32_t unsigned_code_point = code_point; - append( + str.push_back( static_cast<char>(details::ExtractBits<std::uint32_t, 4, std::uint8_t>( (unsigned_code_point >> (6 * 2))) + 0b11100000)); @@ -160,7 +154,7 @@ bool Utf8EncodeCodePointAppendWithFunc(CodePoint code_point, TAppend&& append) { return true; } else if (code_point >= 0x10000 && code_point <= 0x10FFFF) { std::uint32_t unsigned_code_point = code_point; - append( + str.push_back( static_cast<char>(details::ExtractBits<std::uint32_t, 3, std::uint8_t>( (unsigned_code_point >> (6 * 3))) + 0b11110000)); @@ -176,19 +170,18 @@ bool Utf8EncodeCodePointAppendWithFunc(CodePoint code_point, TAppend&& append) { } } -template <typename TAppend> -bool Utf16EncodeCodePointAppendWithFunc(CodePoint code_point, - TAppend&& append) { +template <typename TStr> +bool Utf16EncodeCodePointAppend(CodePoint code_point, TStr& str) { if ((code_point >= 0 && code_point <= 0xD7FF) || (code_point >= 0xE000 && code_point <= 0xFFFF)) { - append(static_cast<char16_t>(code_point)); + str.push_back(static_cast<char16_t>(code_point)); return true; } else if (code_point >= 0x10000 && code_point <= 0x10FFFF) { std::uint32_t u = code_point - 0x10000; - append(static_cast<char16_t>( + str.push_back(static_cast<char16_t>( details::ExtractBits<std::uint32_t, 10, std::uint32_t>(u >> 10) + 0xD800u)); - append(static_cast<char16_t>( + str.push_back(static_cast<char16_t>( details::ExtractBits<std::uint32_t, 10, std::uint32_t>(u) + 0xDC00u)); return true; } else { @@ -196,9 +189,6 @@ bool Utf16EncodeCodePointAppendWithFunc(CodePoint code_point, } } -std::string CRU_BASE_API ToUtf8(const char16_t* ptr, Index size); -std::u16string CRU_BASE_API ToUtf16(const char* s, Index size); - // If given s is not a valid utf16 string, return value is UD. bool CRU_BASE_API Utf16IsValidInsertPosition(const char16_t* ptr, Index size, Index position); diff --git a/include/cru/xml/XmlNode.hpp b/include/cru/xml/XmlNode.hpp index 0972037a..71753410 100644 --- a/include/cru/xml/XmlNode.hpp +++ b/include/cru/xml/XmlNode.hpp @@ -5,6 +5,7 @@ #include "cru/common/String.hpp" #include <algorithm> +#include <optional> #include <unordered_map> #include <vector> diff --git a/src/common/String.cpp b/src/common/String.cpp index 3721eed3..24fb4071 100644 --- a/src/common/String.cpp +++ b/src/common/String.cpp @@ -11,14 +11,6 @@ #include <string_view> namespace cru { -double_conversion::StringToDoubleConverter - String::kDefaultStringToDoubleConverter( - double_conversion::StringToDoubleConverter::ALLOW_LEADING_SPACES | - double_conversion::StringToDoubleConverter::ALLOW_TRAILING_SPACES | - double_conversion::StringToDoubleConverter:: - ALLOW_CASE_INSENSIBILITY, - 0.0, NAN, "infinity", "nan"); - template <typename C> Index GetStrSize(const C* str) { Index i = 0; @@ -29,11 +21,16 @@ Index GetStrSize(const C* str) { } String String::FromUtf8(const char* str) { - return FromUtf16(cru::ToUtf16(str, GetStrSize(str))); + return FromUtf8(str, GetStrSize(str)); } String String::FromUtf8(const char* str, Index size) { - return FromUtf16(cru::ToUtf16(str, size)); + String result; + Utf8CodePointIterator iter(str, size); + for (auto cp : iter) { + Utf16EncodeCodePointAppend(cp, result); + } + return result; } char16_t String::kEmptyBuffer[1] = {0}; @@ -190,6 +187,7 @@ String::iterator String::insert(const_iterator pos, const_iterator str, } Index index = pos - cbegin(); + Index new_size = size_ + size; if (new_size > capacity_) { auto new_capacity = capacity_; @@ -229,15 +227,32 @@ String::iterator String::erase(const_iterator start, const_iterator end) { return s; } +String& String::operator+=(StringView other) { + append(other); + return *this; +} + +StringView String::View() const { return *this; } + Index String::Find(value_type value, Index start) const { - Expects(start >= 0 && start <= size_); + return View().Find(value, start); +} - for (Index i = start; i < size_; ++i) { - if (buffer_[i] == value) return i; - } - return -1; +std::vector<String> String::Split(value_type separator, + bool remove_space_line) const { + return View().Split(separator, remove_space_line); } +std::vector<String> String::SplitToLines(bool remove_space_line) const { + return View().SplitToLines(remove_space_line); +} + +bool String::StartWith(StringView str) const { return View().StartWith(str); } + +bool String::EndWith(StringView str) const { return View().EndWith(str); } + +std::string String::ToUtf8() const { return View().ToUtf8(); } + String& String::TrimStart() { if (size_ == 0) return *this; @@ -270,8 +285,132 @@ String& String::Trim() { return *this; } -std::vector<String> String::Split(value_type separator, - bool remove_space_line) const { +void String::AppendCodePoint(CodePoint code_point) { + if (Utf16EncodeCodePointAppend(code_point, *this)) { + throw TextEncodeException(u"Code point out of range."); + } +} + +Index String::IndexFromCodeUnitToCodePoint(Index code_unit_index) const { + return View().IndexFromCodeUnitToCodePoint(code_unit_index); +} + +Index String::IndexFromCodePointToCodeUnit(Index code_point_index) const { + return View().IndexFromCodePointToCodeUnit(code_point_index); +} + +Range String::RangeFromCodeUnitToCodePoint(Range code_unit_range) const { + return View().RangeFromCodeUnitToCodePoint(code_unit_range); +} + +Range String::RangeFromCodePointToCodeUnit(Range code_point_range) const { + return View().RangeFromCodePointToCodeUnit(code_point_range); +} + +float String::ParseToFloat(Index* processed_characters_count) const { + return View().ParseToFloat(processed_characters_count); +} + +double String::ParseToDouble(Index* processed_characters_count) const { + return View().ParseToDouble(processed_characters_count); +} + +std::vector<float> String::ParseToFloatList(value_type separator) const { + return View().ParseToFloatList(separator); +} + +std::vector<double> String::ParseToDoubleList(value_type separator) const { + return View().ParseToDoubleList(separator); +} + +namespace { +inline int Compare(char16_t left, char16_t right) { + if (left < right) return -1; + if (left > right) return 1; + return 0; +} +} // namespace + +int String::Compare(const String& other) const { + const_iterator i1 = cbegin(); + const_iterator i2 = other.cbegin(); + + const_iterator end1 = cend(); + const_iterator end2 = other.cend(); + + while (i1 != end1 && i2 != end2) { + int r = cru::Compare(*i1, *i2); + if (r != 0) return r; + i1++; + i2++; + } + + if (i1 == end1) { + if (i2 == end2) { + return 0; + } else { + return -1; + } + } else { + return 1; + } +} + +double_conversion::StringToDoubleConverter + StringView::kDefaultStringToDoubleConverter( + double_conversion::StringToDoubleConverter::ALLOW_LEADING_SPACES | + double_conversion::StringToDoubleConverter::ALLOW_TRAILING_SPACES | + double_conversion::StringToDoubleConverter:: + ALLOW_CASE_INSENSIBILITY, + 0.0, NAN, "infinity", "nan"); + +int StringView::Compare(const StringView& other) const { + const_iterator i1 = cbegin(); + const_iterator i2 = other.cbegin(); + + const_iterator end1 = cend(); + const_iterator end2 = other.cend(); + + while (i1 != end1 && i2 != end2) { + int r = cru::Compare(*i1, *i2); + if (r != 0) return r; + i1++; + i2++; + } + + if (i1 == end1) { + if (i2 == end2) { + return 0; + } else { + return -1; + } + } else { + return 1; + } +} + +StringView StringView::substr(Index pos) { + Expects(pos >= 0 && pos < size_); + return StringView(ptr_ + pos, size_ - pos); +} + +StringView StringView::substr(Index pos, Index size) { + Expects(pos >= 0 && pos < size_); + + return StringView(ptr_ + pos, std::min(size, size_ - pos)); +} + +Index StringView::Find(value_type value, Index start) const { + Expects(start >= 0 && start <= size_); + + for (Index i = start; i < size_; ++i) { + if (ptr_[i] == value) return i; + } + return -1; +} + +std::vector<String> StringView::Split(value_type separator, + bool remove_space_line) const { std::vector<String> result; if (size_ == 0) return result; @@ -279,11 +418,11 @@ std::vector<String> String::Split(value_type separator, Index line_start = 0; Index line_end = 0; while (line_end < size_) { - if (buffer_[line_end] == separator) { + if (ptr_[line_end] == separator) { if (remove_space_line) { bool add = false; for (Index i = line_start; i < line_end; i++) { - if (!IsWhitespace(buffer_[i])) { + if (!IsWhitespace(ptr_[i])) { add = true; break; } @@ -302,7 +441,7 @@ std::vector<String> String::Split(value_type separator, if (remove_space_line) { bool add = false; for (Index i = line_start; i < size_; i++) { - if (!IsWhitespace(buffer_[i])) { + if (!IsWhitespace(ptr_[i])) { add = true; break; } @@ -315,30 +454,21 @@ std::vector<String> String::Split(value_type separator, return result; } -std::vector<String> String::SplitToLines(bool remove_space_line) const { +std::vector<String> StringView::SplitToLines(bool remove_space_line) const { return Split(u'\n', remove_space_line); } -bool String::StartWith(StringView str) const { +bool StringView::StartWith(StringView str) const { if (str.size() > size_) return false; - return std::memcmp(str.data(), buffer_, str.size()) == 0; + return std::memcmp(str.data(), ptr_, str.size()) == 0; } -bool String::EndWith(StringView str) const { +bool StringView::EndWith(StringView str) const { if (str.size() > size_) return false; - return std::memcmp(str.data(), buffer_ + size_ - str.size(), str.size()) == 0; + return std::memcmp(str.data(), ptr_ + size_ - str.size(), str.size()) == 0; } -std::string String::ToUtf8() const { return cru::ToUtf8(buffer_, size_); } - -void String::AppendCodePoint(CodePoint code_point) { - if (!Utf16EncodeCodePointAppendWithFunc( - code_point, [this](char16_t c) { this->push_back(c); })) { - throw TextEncodeException(u"Code point out of range."); - } -} - -Index String::IndexFromCodeUnitToCodePoint(Index code_unit_index) const { +Index StringView::IndexFromCodeUnitToCodePoint(Index code_unit_index) const { auto iter = CodePointIterator(); Index result = 0; while (iter.GetPosition() < code_unit_index && !iter.IsPastEnd()) { @@ -348,7 +478,7 @@ Index String::IndexFromCodeUnitToCodePoint(Index code_unit_index) const { return result; } -Index String::IndexFromCodePointToCodeUnit(Index code_point_index) const { +Index StringView::IndexFromCodePointToCodeUnit(Index code_point_index) const { auto iter = CodePointIterator(); Index cpi = 0; while (cpi < code_point_index && !iter.IsPastEnd()) { @@ -358,106 +488,51 @@ Index String::IndexFromCodePointToCodeUnit(Index code_point_index) const { return iter.GetPosition(); } -Range String::RangeFromCodeUnitToCodePoint(Range code_unit_range) const { +Range StringView::RangeFromCodeUnitToCodePoint(Range code_unit_range) const { return Range::FromTwoSides( IndexFromCodeUnitToCodePoint(code_unit_range.GetStart()), IndexFromCodeUnitToCodePoint(code_unit_range.GetEnd())); } -Range String::RangeFromCodePointToCodeUnit(Range code_point_range) const { +Range StringView::RangeFromCodePointToCodeUnit(Range code_point_range) const { return Range::FromTwoSides( IndexFromCodePointToCodeUnit(code_point_range.GetStart()), IndexFromCodePointToCodeUnit(code_point_range.GetEnd())); } -String& String::operator+=(StringView other) { - append(other); - return *this; -} - -namespace { -inline int Compare(char16_t left, char16_t right) { - if (left < right) return -1; - if (left > right) return 1; - return 0; -} -} // namespace - -int String::Compare(const String& other) const { - const_iterator i1 = cbegin(); - const_iterator i2 = other.cbegin(); - - const_iterator end1 = cend(); - const_iterator end2 = other.cend(); - - while (i1 != end1 && i2 != end2) { - int r = cru::Compare(*i1, *i2); - if (r != 0) return r; - i1++; - i2++; - } - - if (i1 == end1) { - if (i2 == end2) { - return 0; - } else { - return -1; - } - } else { - return 1; - } -} - -int StringView::Compare(const StringView& other) const { - const_iterator i1 = cbegin(); - const_iterator i2 = other.cbegin(); - - const_iterator end1 = cend(); - const_iterator end2 = other.cend(); - - while (i1 != end1 && i2 != end2) { - int r = cru::Compare(*i1, *i2); - if (r != 0) return r; - i1++; - i2++; - } - - if (i1 == end1) { - if (i2 == end2) { - return 0; - } else { - return -1; - } - } else { - return 1; +std::string StringView::ToUtf8() const { + std::string result; + for (auto cp : CodePointIterator()) { + Utf8EncodeCodePointAppend(cp, result); } + return result; } -float String::ParseToFloat(Index* processed_characters_count) const { +float StringView::ParseToFloat(Index* processed_characters_count) const { int pcc; auto result = kDefaultStringToDoubleConverter.StringToFloat( - reinterpret_cast<const uc16*>(buffer_), static_cast<int>(size_), &pcc); + reinterpret_cast<const uc16*>(ptr_), static_cast<int>(size_), &pcc); if (processed_characters_count != nullptr) { *processed_characters_count = pcc; } return result; } -double String::ParseToDouble(Index* processed_characters_count) const { +double StringView::ParseToDouble(Index* processed_characters_count) const { int pcc; auto result = kDefaultStringToDoubleConverter.StringToDouble( - reinterpret_cast<const uc16*>(buffer_), static_cast<int>(size_), &pcc); + reinterpret_cast<const uc16*>(ptr_), static_cast<int>(size_), &pcc); if (processed_characters_count != nullptr) { *processed_characters_count = pcc; } return result; } -std::vector<float> String::ParseToFloatList(value_type separator) { +std::vector<float> StringView::ParseToFloatList(value_type separator) const { std::vector<float> result; - auto list = Split(separator); + auto list = Split(separator, true); for (auto& item : list) { - auto value = ParseToFloat(); + auto value = item.ParseToFloat(); if (std::isnan(value)) { throw Exception(u"Invalid double value."); } @@ -466,11 +541,11 @@ std::vector<float> String::ParseToFloatList(value_type separator) { return result; } -std::vector<double> String::ParseToDoubleList(value_type separator) { +std::vector<double> StringView::ParseToDoubleList(value_type separator) const { std::vector<double> result; - auto list = Split(separator); + auto list = Split(separator, true); for (auto& item : list) { - auto value = ParseToDouble(); + auto value = item.ParseToDouble(); if (std::isnan(value)) { throw Exception(u"Invalid double value."); } @@ -479,19 +554,6 @@ std::vector<double> String::ParseToDoubleList(value_type separator) { return result; } -StringView StringView::substr(Index pos) { - Expects(pos >= 0 && pos < size_); - return StringView(ptr_ + pos, size_ - pos); -} - -StringView StringView::substr(Index pos, Index size) { - Expects(pos >= 0 && pos < size_); - - return StringView(ptr_ + pos, std::min(size, size_ - pos)); -} - -std::string StringView::ToUtf8() const { return cru::ToUtf8(ptr_, size_); } - String ToLower(StringView s) { String result; for (auto c : s) result.push_back(ToLower(c)); diff --git a/src/common/StringUtil.cpp b/src/common/StringUtil.cpp index 1f5f6150..2bec815d 100644 --- a/src/common/StringUtil.cpp +++ b/src/common/StringUtil.cpp @@ -149,34 +149,6 @@ CodePoint Utf16PreviousCodePoint(const char16_t* ptr, Index size, Index current, return result; } -void Utf8EncodeCodePointAppend(CodePoint code_point, std::string& str) { - if (!Utf8EncodeCodePointAppendWithFunc(code_point, - [&str](char c) { str.push_back(c); })) - throw TextEncodeException(u"Code point out of range."); -} - -void Utf16EncodeCodePointAppend(CodePoint code_point, std::u16string& str) { - if (!Utf16EncodeCodePointAppendWithFunc( - code_point, [&str](char16_t c) { str.push_back(c); })) - throw TextEncodeException(u"Code point out of range."); -} - -std::string ToUtf8(const char16_t* ptr, Index size) { - std::string result; - for (CodePoint cp : Utf16CodePointIterator(ptr, size)) { - Utf8EncodeCodePointAppend(cp, result); - } - return result; -} - -std::u16string ToUtf16(const char* ptr, Index size) { - std::u16string result; - for (CodePoint cp : Utf8CodePointIterator(ptr, size)) { - Utf16EncodeCodePointAppend(cp, result); - } - return result; -} - bool Utf16IsValidInsertPosition(const char16_t* ptr, Index size, Index position) { if (position < 0) return false; diff --git a/src/ui/mapper/PointMapper.cpp b/src/ui/mapper/PointMapper.cpp index abd586a4..59a7b187 100644 --- a/src/ui/mapper/PointMapper.cpp +++ b/src/ui/mapper/PointMapper.cpp @@ -1,3 +1,5 @@ #include "cru/ui/mapper/PointMapper.hpp" -namespace cru::ui::mapper {} +namespace cru::ui::mapper { + +} diff --git a/test/common/StringTest.cpp b/test/common/StringTest.cpp index 737a93ad..0a60e729 100644 --- a/test/common/StringTest.cpp +++ b/test/common/StringTest.cpp @@ -70,14 +70,35 @@ TEST(String, SplitToLinesRemoveSpaceLine) { ASSERT_EQ(lines[2], String(u"ghi")); } -TEST(String, ParseToFloat) { - using cru::String; - ASSERT_EQ(String(u"3.14159").ParseToDouble(), 3.14159); - ASSERT_EQ(String(u" 3.14159").ParseToDouble(), 3.14159); - ASSERT_EQ(String(u" 3.14159 ").ParseToDouble(), 3.14159); - - cru::Index processed_char_count = 0; - ASSERT_EQ(String(u" 3.14159 garbege").ParseToDouble(&processed_char_count), - 3.14159); - ASSERT_EQ(processed_char_count, 9); +TEST(StringView, ToUtf8) { + using cru::StringView; + StringView utf16_text = u"aπ你🤣!"; + std::string_view utf8_text = "aπ你🤣!"; + + ASSERT_EQ(utf16_text.ToUtf8(), utf8_text); +} + +TEST(String, FromUtf8) { + std::u16string_view utf16_text = u"aπ你🤣!"; + std::string_view utf8_text = "aπ你🤣!"; + + ASSERT_EQ(cru::String::FromUtf8(utf8_text), utf16_text); +} + +TEST(StringView, ParseToDouble) { + using cru::StringView; + ASSERT_EQ(StringView(u"3.14159").ParseToDouble(), 3.14159); + ASSERT_EQ(StringView(u" 3.14159").ParseToDouble(), 3.14159); + ASSERT_EQ(StringView(u" 3.14159 ").ParseToDouble(), 3.14159); +} + +TEST(String, ParseToDoubleList) { + using cru::StringView; + + auto list = StringView(u" 1.23 2.34 3.45 ").ParseToDoubleList(); + + ASSERT_EQ(list.size(), 3); + ASSERT_EQ(list[0], 1.23); + ASSERT_EQ(list[1], 2.34); + ASSERT_EQ(list[2], 3.45); } diff --git a/test/common/StringUtilTest.cpp b/test/common/StringUtilTest.cpp index 5e1753b8..0fc63685 100644 --- a/test/common/StringUtilTest.cpp +++ b/test/common/StringUtilTest.cpp @@ -1,3 +1,4 @@ +#include "cru/common/String.hpp" #include "cru/common/StringUtil.hpp" #include <gtest/gtest.h> @@ -91,22 +92,6 @@ TEST(StringUtil, Utf16CodePointIterator) { ASSERT_EQ(code_points, expected_code_points); } -TEST(StringUtil, ToUtf8) { - using cru::ToUtf8; - std::u16string_view utf16_text = u"aπ你🤣!"; - std::string_view utf8_text = "aπ你🤣!"; - - ASSERT_EQ(ToUtf8(utf16_text.data(), utf16_text.size()), utf8_text); -} - -TEST(StringUtil, ToUtf16) { - using cru::ToUtf16; - std::u16string_view utf16_text = u"aπ你🤣!"; - std::string_view utf8_text = "aπ你🤣!"; - - ASSERT_EQ(ToUtf16(utf8_text.data(), utf8_text.size()), utf16_text); -} - // TEST(WinString, IndexUtf8ToUtf16) { // using cru::platform::win::IndexUtf8ToUtf16; // std::string_view utf8_string = "aπ你🤣!"; |