luna: Make Utf8StringEncoder short-circuit instead of failing when hitting the length limit
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-01-14 12:07:08 +01:00
parent e3ef29e80d
commit d0600f5714
Signed by: apio
GPG Key ID: B8A7D06E42258954

View File

@ -2,8 +2,6 @@
#include <luna/CString.h> #include <luna/CString.h>
#include <luna/Utf8.h> #include <luna/Utf8.h>
// FIXME: Not enough space for a sequence is not an error. (mbstowcs(3) and wcstombs(3), case 2 when buf is not NULL)
static_assert(WCHAR_MAX > 0x10ffff); static_assert(WCHAR_MAX > 0x10ffff);
static Result<usize> utf8_char_length(char c) static Result<usize> utf8_char_length(char c)
@ -32,31 +30,31 @@ static inline usize wide_char_length_as_utf8_unchecked(wchar_t c)
return 4; return 4;
} }
static Result<void> encode_wide_char_as_utf8(wchar_t c, char* result, usize& len) static Result<bool> encode_wide_char_as_utf8(wchar_t c, char* result, usize& len)
{ {
const usize utf8_len = TRY(wide_char_length_as_utf8(c)); const usize utf8_len = TRY(wide_char_length_as_utf8(c));
if (utf8_len > len) { return err(EILSEQ); } if (utf8_len > len) { return false; } // Not enough space
u8* buf = (u8*)result; u8* buf = (u8*)result;
if (len == 1) if (len == 1)
{ {
buf[0] = c & 0x7f; buf[0] = c & 0x7f;
return {}; return true;
} }
if (len == 2) if (len == 2)
{ {
buf[0] = 0b11000000 | ((c & 0x7c0) >> 6); buf[0] = 0b11000000 | ((c & 0x7c0) >> 6);
buf[1] = 0b10000000 | (c & 0x3f); buf[1] = 0b10000000 | (c & 0x3f);
return {}; return true;
} }
if (len == 3) if (len == 3)
{ {
buf[0] = 0b11100000 | ((c & 0xf000) >> 12); buf[0] = 0b11100000 | ((c & 0xf000) >> 12);
buf[1] = 0b10000000 | ((c & 0xfc0) >> 6); buf[1] = 0b10000000 | ((c & 0xfc0) >> 6);
buf[2] = 0b10000000 | (c & 0x3f); buf[2] = 0b10000000 | (c & 0x3f);
return {}; return true;
} }
if (len == 4) if (len == 4)
{ {
@ -64,7 +62,7 @@ static Result<void> encode_wide_char_as_utf8(wchar_t c, char* result, usize& len
buf[1] = 0b10000000 | ((c & 0x3f000) >> 12); buf[1] = 0b10000000 | ((c & 0x3f000) >> 12);
buf[2] = 0b10000000 | ((c & 0xfc0) >> 6); buf[2] = 0b10000000 | ((c & 0xfc0) >> 6);
buf[3] = 0b10000000 | (c & 0x3f); buf[3] = 0b10000000 | (c & 0x3f);
return {}; return true;
} }
unreachable(); unreachable();
@ -197,7 +195,8 @@ Result<usize> Utf8StringEncoder::encode(char* buf, usize max) const
while (*it && max > 1) while (*it && max > 1)
{ {
usize len = max - 1; usize len = max - 1;
TRY(encode_wide_char_as_utf8(*it, buf, len)); bool ok = TRY(encode_wide_char_as_utf8(*it, buf, len));
if (!ok) break;
buf += len; buf += len;
max -= len; max -= len;
it++; it++;