Browse Source

LibC: Implement wcsnrtombs

Tim Schumacher 3 years ago
parent
commit
552ae77f0d
2 changed files with 40 additions and 5 deletions
  1. 26 0
      Tests/LibC/TestWchar.cpp
  2. 14 5
      Userland/Libraries/LibC/wchar.cpp

+ 26 - 0
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 = {};

+ 14 - 5
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*)