Skip to content
This repository has been archived by the owner on Nov 29, 2024. It is now read-only.

Commit

Permalink
string: add recoding from UTF-16 to UTF-32
Browse files Browse the repository at this point in the history
I know there are system functions for this (and libiconv), but this is
so trivial and quick in our implementation.
  • Loading branch information
rozmansi committed Sep 27, 2024
1 parent da11495 commit 5675f8b
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 1 deletion.
11 changes: 11 additions & 0 deletions UnitTests/compat.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ namespace Assert
throw std::runtime_error("not equal");
}

inline void AreEqual(const char32_t* a, const char32_t* b)
{
#ifdef _WIN32
if (stdex::strcmp(a, b) != 0)
throw std::runtime_error("not equal");
#else
if (wcscmp(reinterpret_cast<const wchar_t*>(a), reinterpret_cast<const wchar_t*>(b)) != 0)
throw std::runtime_error("not equal");
#endif
}

template <class T>
void AreNotEqual(const T& a, const T& b)
{
Expand Down
1 change: 1 addition & 0 deletions UnitTests/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ int main(int, const char *[])
UnitTests::stream::file_stat();
UnitTests::stream::open_close();
UnitTests::stream::replicator();
UnitTests::string::strncpy();
UnitTests::string::sprintf();
UnitTests::unicode::charset_encoder();
UnitTests::unicode::normalize();
Expand Down
1 change: 1 addition & 0 deletions UnitTests/pch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ namespace UnitTests
TEST_CLASS(string)
{
public:
TEST_METHOD(strncpy);
TEST_METHOD(sprintf);
};

Expand Down
7 changes: 7 additions & 0 deletions UnitTests/string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework;

namespace UnitTests
{
void string::strncpy()
{
stdex::utf32_t tmp[0x100];
stdex::strncpy(tmp, u"This is a 🐔Test🐮.");
Assert::AreEqual(reinterpret_cast<const stdex::utf32_t*>(U"This is a 🐔Test🐮."), tmp);
}

void string::sprintf()
{
stdex::locale locale(stdex::create_locale(LC_ALL, "en_US.UTF-8"));
Expand Down
51 changes: 50 additions & 1 deletion include/stdex/string.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*
/*
SPDX-License-Identifier: MIT
Copyright © 2016-2024 Amebis
*/
Expand Down Expand Up @@ -1636,6 +1636,26 @@ namespace stdex
}
}

///
/// Recode UTF-16 zero-terminated string to UTF-32
///
/// \param[in] dst Destination string
/// \param[in] src Source string
///
/// \return Number of code units excluding zero terminator in the dst string after the operation.
///
inline size_t strcpy(
_Out_ _Post_maybez_ utf32_t* dst,
_In_z_ const utf16_t* src)
{
stdex_assert(dst);
stdex_assert(src);
for (size_t j = 0, i = 0; ; ++j, ++i) {
if ((dst[j] = (is_surrogate_pair(&src[i]) ? surrogate_pair_to_ucs4(&src[i++]) : static_cast<utf32_t>(src[i]))) == 0)
return j;
}
}

///
/// Copy zero-terminated string
///
Expand Down Expand Up @@ -1690,6 +1710,35 @@ namespace stdex
}
}

///
/// Recode UTF-16 zero-terminated string to UTF-32
///
/// \param[in] dst Destination string
/// \param[in] count_dst Destination string code unit count limit
/// \param[in] src Source string
/// \param[in] count_src Source string code unit count limit
///
/// \return Number of code units excluding zero terminator in the dst string after the operation.
///
inline size_t strncpy(
_Out_writes_(count_dst) _Post_maybez_ utf32_t* dst, _In_ size_t count_dst,
_In_reads_or_z_opt_(count_src) const utf16_t* src, _In_ size_t count_src)
{
stdex_assert(dst || !count_dst);
stdex_assert(src || !count_src);
for (size_t j = 0, i = 0; ; ++j, ++i)
{
if (j >= count_dst)
return j;
if (i >= count_src) {
dst[j] = 0;
return j;
}
if ((dst[j] = (i + 1 < count_src && is_surrogate_pair(&src[i]) ? surrogate_pair_to_ucs4(&src[i++]) : static_cast<utf32_t>(src[i]))) == 0)
return j;
}
}

///
/// Copy zero-terminated string
///
Expand Down

0 comments on commit 5675f8b

Please sign in to comment.