mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-06 17:06:31 +00:00
LibC: Implement mbsrtowcs
This commit is contained in:
parent
b0babd062e
commit
420bdccf0b
|
@ -363,3 +363,54 @@ TEST_CASE(wcsrtombs)
|
|||
EXPECT_EQ(memcmp(buf, "\xf0\x9f\x90\x9e\xf0\x9f\x90\x9e", 9), 0);
|
||||
EXPECT_EQ(src, nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE(mbsrtowcs)
|
||||
{
|
||||
mbstate_t state = {};
|
||||
wchar_t buf[4];
|
||||
const char good_chars[] = "\xf0\x9f\x90\x9e\xf0\x9f\x90\x9e";
|
||||
const char bad_chars[] = "\xf0\x9f\x90\x9e\xf0\xff\x90\x9e";
|
||||
const char* src;
|
||||
size_t ret = 0;
|
||||
|
||||
// Convert normal and valid multibyte sequences.
|
||||
src = good_chars;
|
||||
ret = mbsrtowcs(buf, &src, 3, &state);
|
||||
EXPECT_EQ(ret, 2ul);
|
||||
EXPECT_EQ(buf[0], L'\U0001F41E');
|
||||
EXPECT_EQ(buf[1], L'\U0001F41E');
|
||||
EXPECT_EQ(buf[2], L'\0');
|
||||
EXPECT_EQ(src, nullptr);
|
||||
EXPECT_NE(mbsinit(&state), 0);
|
||||
|
||||
// Stop on invalid multibyte sequences.
|
||||
src = bad_chars;
|
||||
ret = mbsrtowcs(buf, &src, 3, &state);
|
||||
EXPECT_EQ(ret, -1ul);
|
||||
EXPECT_EQ(buf[0], L'\U0001F41E');
|
||||
EXPECT_EQ(errno, EILSEQ);
|
||||
EXPECT_EQ(src, bad_chars + 4);
|
||||
|
||||
// Valid sequence but not enough space.
|
||||
src = good_chars;
|
||||
ret = mbsrtowcs(buf, &src, 1, &state);
|
||||
EXPECT_EQ(ret, 1ul);
|
||||
EXPECT_EQ(buf[0], L'\U0001F41E');
|
||||
EXPECT_EQ(src, good_chars + 4);
|
||||
|
||||
// Try a conversion with no destination and too short length.
|
||||
src = good_chars;
|
||||
ret = mbsrtowcs(nullptr, &src, 1, &state);
|
||||
EXPECT_EQ(ret, 2ul);
|
||||
EXPECT_EQ(src, nullptr);
|
||||
EXPECT_NE(mbsinit(&state), 0);
|
||||
|
||||
// Try a conversion using the internal anonymous state.
|
||||
src = good_chars;
|
||||
ret = mbsrtowcs(buf, &src, 3, nullptr);
|
||||
EXPECT_EQ(ret, 2ul);
|
||||
EXPECT_EQ(buf[0], L'\U0001F41E');
|
||||
EXPECT_EQ(buf[1], L'\U0001F41E');
|
||||
EXPECT_EQ(buf[2], L'\0');
|
||||
EXPECT_EQ(src, nullptr);
|
||||
}
|
||||
|
|
|
@ -505,4 +505,38 @@ size_t wcsrtombs(char* dest, const wchar_t** src, size_t len, mbstate_t* ps)
|
|||
written += ret;
|
||||
}
|
||||
}
|
||||
|
||||
size_t mbsrtowcs(wchar_t* dst, const char** src, size_t len, mbstate_t* ps)
|
||||
{
|
||||
static mbstate_t _anonymous_state = {};
|
||||
|
||||
if (ps == nullptr)
|
||||
ps = &_anonymous_state;
|
||||
|
||||
size_t written = 0;
|
||||
while (written < len || !dst) {
|
||||
// Convert next multibyte to wchar.
|
||||
size_t ret = mbrtowc(dst, *src, MB_LEN_MAX, ps);
|
||||
|
||||
// Multibyte sequence is invalid.
|
||||
if (ret == -1ul) {
|
||||
errno = EILSEQ;
|
||||
return (size_t)-1;
|
||||
}
|
||||
|
||||
// Null byte has been reached.
|
||||
if (**src == '\0') {
|
||||
*src = nullptr;
|
||||
return written;
|
||||
}
|
||||
|
||||
*src += ret;
|
||||
written += 1;
|
||||
if (dst)
|
||||
dst += 1;
|
||||
}
|
||||
|
||||
// If we are here, we have written `len` wchars, but not reached the null byte.
|
||||
return written;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,5 +57,6 @@ long double wcstold(const wchar_t*, wchar_t**);
|
|||
int swprintf(wchar_t*, size_t, const wchar_t*, ...);
|
||||
int wcwidth(wchar_t);
|
||||
size_t wcsrtombs(char*, const wchar_t**, size_t, mbstate_t*);
|
||||
size_t mbsrtowcs(wchar_t*, const char**, size_t, mbstate_t*);
|
||||
|
||||
__END_DECLS
|
||||
|
|
Loading…
Reference in a new issue