diff options
-rw-r--r-- | include/cru/win/string.hpp | 14 | ||||
-rw-r--r-- | src/win/string.cpp | 40 | ||||
-rw-r--r-- | test/win/string.cpp | 27 |
3 files changed, 76 insertions, 5 deletions
diff --git a/include/cru/win/string.hpp b/include/cru/win/string.hpp index 75395052..3fdadbf8 100644 --- a/include/cru/win/string.hpp +++ b/include/cru/win/string.hpp @@ -60,9 +60,10 @@ class Utf8Iterator : public Object { }; class Utf16Iterator : public Object { - static_assert(sizeof(wchar_t) == 2, - "Emmm, according to my knowledge, wchar_t should be 2-length on " - "Windows. If not, Utf16 will be broken."); + static_assert( + sizeof(wchar_t) == 2, + "Emmm, according to my knowledge, wchar_t should be 2-length on " + "Windows. If not, Utf16 will be broken."); public: Utf16Iterator(const std::wstring_view& string) : string_(string) {} @@ -86,4 +87,11 @@ class Utf16Iterator : public Object { std::wstring_view string_; int position_ = 0; }; + +int IndexUtf8ToUtf16(const std::string_view& utf8_string, int utf8_index, + const std::wstring_view& utf16_string); + +int IndexUtf16ToUtf8(const std::wstring_view& utf16_string, int utf16_index, + const std::string_view& utf8_string); + } // namespace cru::platform::win diff --git a/src/win/string.cpp b/src/win/string.cpp index c8b0ca87..fb9811eb 100644 --- a/src/win/string.cpp +++ b/src/win/string.cpp @@ -143,4 +143,44 @@ CodePoint Utf16Iterator::Next() { } } +int IndexUtf8ToUtf16(const std::string_view& utf8_string, int utf8_index, + const std::wstring_view& utf16_string) { + if (utf8_index >= static_cast<int>(utf8_string.length())) + return static_cast<int>(utf16_string.length()); + + int cp_index = 0; + Utf8Iterator iter{utf8_string}; + while (iter.CurrentPosition() <= utf8_index) { + iter.Next(); + cp_index++; + } + + Utf16Iterator result_iter{utf16_string}; + for (int i = 0; i < cp_index - 1; i++) { + if (result_iter.Next() == k_code_point_end) break; + } + + return result_iter.CurrentPosition(); +} + +int IndexUtf16ToUtf8(const std::wstring_view& utf16_string, int utf16_index, + const std::string_view& utf8_string) { + if (utf16_index >= static_cast<int>(utf16_string.length())) + return static_cast<int>(utf8_string.length()); + + int cp_index = 0; + Utf16Iterator iter{utf16_string}; + while (iter.CurrentPosition() <= utf16_index) { + iter.Next(); + cp_index++; + } + + Utf8Iterator result_iter{utf8_string}; + for (int i = 0; i < cp_index - 1; i++) { + if (result_iter.Next() == k_code_point_end) break; + } + + return result_iter.CurrentPosition(); +} + } // namespace cru::platform::win diff --git a/test/win/string.cpp b/test/win/string.cpp index 4e25f8c0..3864b987 100644 --- a/test/win/string.cpp +++ b/test/win/string.cpp @@ -4,7 +4,7 @@ using cru::platform::win::k_code_point_end; -TEST(WinString, Utf8ShouldWork) { +TEST(WinString, Utf8Iterator) { using cru::platform::win::Utf8Iterator; std::string_view text = "aπ你🤣!"; Utf8Iterator i{text}; @@ -16,7 +16,7 @@ TEST(WinString, Utf8ShouldWork) { ASSERT_EQ(i.Next(), k_code_point_end); } -TEST(WinString, Utf16ShouldWork) { +TEST(WinString, Utf16Iterator) { using cru::platform::win::Utf16Iterator; std::wstring_view text = L"aπ你🤣!"; Utf16Iterator i{text}; @@ -28,3 +28,26 @@ TEST(WinString, Utf16ShouldWork) { ASSERT_EQ(i.Next(), k_code_point_end); } +TEST(WinString, IndexUtf8ToUtf16) { + using cru::platform::win::IndexUtf8ToUtf16; + std::string_view utf8_string = "aπ你🤣!"; + std::wstring_view utf16_string = L"aπ你🤣!"; + ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 0, utf16_string), 0); + ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 1, utf16_string), 1); + ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 3, utf16_string), 2); + ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 6, utf16_string), 3); + ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 10, utf16_string), 5); + ASSERT_EQ(IndexUtf8ToUtf16(utf8_string, 11, utf16_string), 6); +} + +TEST(WinString, IndexUtf16ToUtf8) { + using cru::platform::win::IndexUtf16ToUtf8; + std::string_view utf8_string = "aπ你🤣!"; + std::wstring_view utf16_string = L"aπ你🤣!"; + ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 0, utf8_string), 0); + ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 1, utf8_string), 1); + ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 2, utf8_string), 3); + ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 3, utf8_string), 6); + ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 5, utf8_string), 10); + ASSERT_EQ(IndexUtf16ToUtf8(utf16_string, 6, utf8_string), 11); +} |