diff --git a/Tests/LibC/TestWchar.cpp b/Tests/LibC/TestWchar.cpp index 2e42de40570..4ac72825045 100644 --- a/Tests/LibC/TestWchar.cpp +++ b/Tests/LibC/TestWchar.cpp @@ -364,6 +364,32 @@ TEST_CASE(wcsrtombs) EXPECT_EQ(src, nullptr); } +TEST_CASE(wcsnrtombs) +{ + mbstate_t state = {}; + const wchar_t good_chars[] = { L'\U0001F41E', L'\U0001F41E', L'\0' }; + const wchar_t* src; + size_t ret = 0; + + // Convert nothing. + src = good_chars; + ret = wcsnrtombs(nullptr, &src, 0, 0, &state); + EXPECT_EQ(ret, 0ul); + EXPECT_EQ(src, good_chars); + + // Convert one wide char. + src = good_chars; + ret = wcsnrtombs(nullptr, &src, 1, 0, &state); + EXPECT_EQ(ret, 4ul); + EXPECT_EQ(src, good_chars + 1); + + // Encounter a null character. + src = good_chars; + ret = wcsnrtombs(nullptr, &src, 4, 0, &state); + EXPECT_EQ(ret, 8ul); + EXPECT_EQ(src, nullptr); +} + TEST_CASE(mbsrtowcs) { mbstate_t state = {}; diff --git a/Userland/Libraries/LibC/wchar.cpp b/Userland/Libraries/LibC/wchar.cpp index d42c15cbf0e..e2cea8ea61c 100644 --- a/Userland/Libraries/LibC/wchar.cpp +++ b/Userland/Libraries/LibC/wchar.cpp @@ -488,7 +488,7 @@ int wcwidth(wchar_t wc) return 1; } -size_t wcsrtombs(char* dest, const wchar_t** src, size_t len, mbstate_t* ps) +size_t wcsnrtombs(char* dest, const wchar_t** src, size_t nwc, size_t len, mbstate_t* ps) { static mbstate_t _anonymous_state = {}; @@ -496,7 +496,8 @@ size_t wcsrtombs(char* dest, const wchar_t** src, size_t len, mbstate_t* ps) ps = &_anonymous_state; size_t written = 0; - while (true) { + size_t read = 0; + while (read < nwc) { size_t ret = 0; char buf[MB_LEN_MAX]; @@ -526,8 +527,11 @@ size_t wcsrtombs(char* dest, const wchar_t** src, size_t len, mbstate_t* ps) } *src += 1; + read += 1; written += ret; } + + return written; } size_t mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* ps) @@ -573,10 +577,15 @@ int wmemcmp(const wchar_t* s1, const wchar_t* s2, size_t n) return 0; } -size_t wcsnrtombs(char*, const wchar_t**, size_t, size_t, mbstate_t*) +size_t wcsrtombs(char* dest, const wchar_t** src, size_t len, mbstate_t* ps) { - dbgln("FIXME: Implement wcsnrtombs()"); - TODO(); + static mbstate_t anonymous_state = {}; + + if (ps == nullptr) + ps = &anonymous_state; + + // SIZE_MAX is as close as we are going to get to "unlimited". + return wcsnrtombs(dest, src, SIZE_MAX, len, ps); } size_t mbsnrtowcs(wchar_t*, const char**, size_t, size_t, mbstate_t*)