LibC: Fix locale handling in wcrtomb and mbrtowc
This commit is contained in:
parent
cdcd226b1a
commit
7ff7a4aa87
|
@ -28,18 +28,28 @@ size_t wcrtomb(char* __restrict s, wchar_t ws, mbstate_t* __restrict ps)
|
||||||
{
|
{
|
||||||
(void)ps;
|
(void)ps;
|
||||||
|
|
||||||
// ws == '\0' doesn't seem to apply to UTF8?
|
// ws == '\0' doesn't seem to apply to UTF8/ASCII?
|
||||||
|
|
||||||
if (s == nullptr)
|
if (s == nullptr)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!BAN::UTF8::from_codepoints(&ws, 1, s))
|
switch (__getlocale(LC_CTYPE))
|
||||||
{
|
{
|
||||||
errno = EILSEQ;
|
case locale_t::LOCALE_INVALID:
|
||||||
return -1;
|
ASSERT_NOT_REACHED();
|
||||||
|
case locale_t::LOCALE_POSIX:
|
||||||
|
if (ws > 0x7F)
|
||||||
|
break;
|
||||||
|
*s = ws;
|
||||||
|
return 1;
|
||||||
|
case locale_t::LOCALE_UTF8:
|
||||||
|
if (!BAN::UTF8::from_codepoints(&ws, 1, s))
|
||||||
|
break;
|
||||||
|
return BAN::UTF8::byte_length(s[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return BAN::UTF8::byte_length(s[0]);
|
errno = EILSEQ;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t mbrtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n, mbstate_t* __restrict ps)
|
size_t mbrtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n, mbstate_t* __restrict ps)
|
||||||
|
@ -49,17 +59,46 @@ size_t mbrtowc(wchar_t* __restrict pwc, const char* __restrict s, size_t n, mbst
|
||||||
if (s == nullptr)
|
if (s == nullptr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const auto bytes = BAN::UTF8::byte_length(*s);
|
const auto locale = __getlocale(LC_CTYPE);
|
||||||
if (bytes == BAN::UTF8::invalid)
|
|
||||||
|
size_t bytes = -1;
|
||||||
|
switch (locale)
|
||||||
|
{
|
||||||
|
case locale_t::LOCALE_INVALID:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
case locale_t::LOCALE_POSIX:
|
||||||
|
bytes = 1;
|
||||||
|
break;
|
||||||
|
case locale_t::LOCALE_UTF8:
|
||||||
|
if (auto b = BAN::UTF8::byte_length(s[0]); b != BAN::UTF8::invalid)
|
||||||
|
bytes = b;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes == static_cast<size_t>(-1))
|
||||||
{
|
{
|
||||||
errno = EILSEQ;
|
errno = EILSEQ;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n < bytes)
|
if (n < bytes)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
const auto codepoint = BAN::UTF8::to_codepoint(s);
|
wchar_t codepoint = WEOF;
|
||||||
if (codepoint == BAN::UTF8::invalid)
|
switch (locale)
|
||||||
|
{
|
||||||
|
case locale_t::LOCALE_INVALID:
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
case locale_t::LOCALE_POSIX:
|
||||||
|
codepoint = s[0];
|
||||||
|
break;
|
||||||
|
case locale_t::LOCALE_UTF8:
|
||||||
|
if (auto cp = BAN::UTF8::to_codepoint(s); cp != BAN::UTF8::invalid)
|
||||||
|
codepoint = cp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (codepoint == WEOF)
|
||||||
{
|
{
|
||||||
errno = EILSEQ;
|
errno = EILSEQ;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in New Issue