// // This file is basically OpenBSD's citrus_utf8.c but rewritten to not require a // 12-byte mbstate_t so we're backwards-compatible with our LP32 ABI where // mbstate_t was only 4 bytes. // // The state is the UTF-8 sequence. We only support <= 4-bytes sequences so LP32 // mbstate_t already has enough space (out of the 4 available bytes we only // need 3 since we should never need to store the entire sequence in the // intermediary state). // // The C standard leaves the conversion state undefined after a bad conversion. // To avoid unexpected failures due to the possible use of the internal private // state we always reset the conversion state when encountering illegal // sequences. // // We also implement the POSIX interface directly rather than being accessed via // function pointers. //
// Our wchar_t is UTF-32. return mbrtoc32(reinterpret_cast<char32_t*>(pwc), s, n, state);
}
size_t mbsnrtowcs(wchar_t* dst, constchar** src, size_t nmc, size_t len, mbstate_t* ps) { static mbstate_t __private_state;
mbstate_t* state = (ps == nullptr) ? &__private_state : ps;
size_t i, o, r;
// The fast paths in the loops below are not safe if an ASCII // character appears as anything but the first byte of a // multibyte sequence. Check now to avoid doing it in the loops. if (nmc > 0 && mbstate_bytes_so_far(state) > 0 && static_cast<uint8_t>((*src)[0]) < 0x80) { return mbstate_reset_and_return_illegal(EILSEQ, state);
}
// Measure only? if (dst == nullptr) { for (i = o = 0; i < nmc; i += r, o++) { if (static_cast<uint8_t>((*src)[i]) < 0x80) { // Fast path for plain ASCII characters. if ((*src)[i] == '\0') { return mbstate_reset_and_return(o, state);
}
r = 1;
} else {
r = mbrtowc(nullptr, *src + i, nmc - i, state); if (r == BIONIC_MULTIBYTE_RESULT_ILLEGAL_SEQUENCE) { return mbstate_reset_and_return_illegal(EILSEQ, state);
} if (r == BIONIC_MULTIBYTE_RESULT_INCOMPLETE_SEQUENCE) { return mbstate_reset_and_return_illegal(EILSEQ, state);
} if (r == 0) { return mbstate_reset_and_return(o, state);
}
}
} return mbstate_reset_and_return(o, state);
}
// Actually convert, updating `dst` and `src`. for (i = o = 0; i < nmc && o < len; i += r, o++) { if (static_cast<uint8_t>((*src)[i]) < 0x80) { // Fast path for plain ASCII characters.
dst[o] = (*src)[i];
r = 1; if ((*src)[i] == '\0') {
*src = nullptr; return mbstate_reset_and_return(o, state);
}
} else {
r = mbrtowc(dst + o, *src + i, nmc - i, state); if (r == BIONIC_MULTIBYTE_RESULT_ILLEGAL_SEQUENCE) {
*src += i; return mbstate_reset_and_return_illegal(EILSEQ, state);
} if (r == BIONIC_MULTIBYTE_RESULT_INCOMPLETE_SEQUENCE) {
*src += nmc; return mbstate_reset_and_return_illegal(EILSEQ, state);
} if (r == 0) {
*src = nullptr; return mbstate_reset_and_return(o, state);
}
}
}
*src += i; return mbstate_reset_and_return(o, state);
}
if (!mbstate_is_initial(state)) { return mbstate_reset_and_return_illegal(EILSEQ, state);
}
char buf[MB_LEN_MAX];
size_t i, o, r; if (dst == nullptr) { for (i = o = 0; i < nwc; i++, o += r) { wchar_t wc = (*src)[i]; if (static_cast<uint32_t>(wc) < 0x80) { // Fast path for plain ASCII characters. if (wc == 0) { return o;
}
r = 1;
} else {
r = wcrtomb(buf, wc, state); if (r == BIONIC_MULTIBYTE_RESULT_ILLEGAL_SEQUENCE) { return r;
}
}
} return o;
}
for (i = o = 0; i < nwc && o < len; i++, o += r) { wchar_t wc = (*src)[i]; if (static_cast<uint32_t>(wc) < 0x80) { // Fast path for plain ASCII characters.
dst[o] = wc; if (wc == 0) {
*src = nullptr; return o;
}
r = 1;
} elseif (len - o >= sizeof(buf)) { // Enough space to translate in-place.
r = wcrtomb(dst + o, wc, state); if (r == BIONIC_MULTIBYTE_RESULT_ILLEGAL_SEQUENCE) {
*src += i; return r;
}
} else { // May not be enough space; use temp buffer.
r = wcrtomb(buf, wc, state); if (r == BIONIC_MULTIBYTE_RESULT_ILLEGAL_SEQUENCE) {
*src += i; return r;
} if (r > len - o) { break;
}
memcpy(dst + o, buf, r);
}
}
*src += i; return o;
}
wchar_t* wcsdup(constwchar_t* s) {
size_t n = wcslen(s) + 1; wchar_t* result = static_cast<wchar_t*>(malloc(n * sizeof(wchar_t))); if (result != nullptr) {
wmemcpy(result, s, n);
} return result;
}
// Currently only ARM64 and x86-64 have a psimd wmemchr(), // but even those fall back to this for misaligned pointers. #ifdefined(__aarch64__) || defined(__x86_64__) #define wmemchr __wmemchr_misaligned extern"C" #endif wchar_t* wmemchr(constwchar_t* s, wchar_t c, size_t n) { for (size_t i = 0; i < n; i++) { if (s[i] == c) { returnconst_cast<wchar_t*>(&s[i]);
}
} return nullptr;
} #undef wmemchr
wchar_t* wmemset(wchar_t* s, wchar_t c, size_t n) { // Unicode characters are 21 bits, so there's only one value we can pass to memset(). // Luckily, that's the only value that actually matters. if (c == 0) [[likely]] {
memset(s, 0, n * sizeof(wchar_t));
} else { for (size_t i = 0; i < n; i++) s[i] = c;
} return s;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-06-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.