mirror of
https://github.com/fluencelabs/musl
synced 2025-06-02 01:21:34 +00:00
when wcsrtombs stopped due to hitting zero remaining space in the output buffer, it was wrongly clearing the position pointer as if it had completed the conversion successfully. this commit rearranges the code somewhat to make a clear separation between the cases of ending due to running out of output buffer space, and ending due to reaching the end of input or an illegal sequence in the input. the new branches have been arranged with the hope of optimizing more common cases, too.
62 lines
1.0 KiB
C
62 lines
1.0 KiB
C
/*
|
|
* This code was written by Rich Felker in 2010; no copyright is claimed.
|
|
* This code is in the public domain. Attribution is appreciated but
|
|
* unnecessary.
|
|
*/
|
|
|
|
#include <wchar.h>
|
|
|
|
size_t wcsrtombs(char *restrict s, const wchar_t **restrict ws, size_t n, mbstate_t *restrict st)
|
|
{
|
|
const wchar_t *ws2;
|
|
char buf[4];
|
|
size_t N = n, l;
|
|
if (!s) {
|
|
for (n=0, ws2=*ws; *ws2; ws2++) {
|
|
if (*ws2 >= 0x80u) {
|
|
l = wcrtomb(buf, *ws2, 0);
|
|
if (!(l+1)) return -1;
|
|
n += l;
|
|
} else n++;
|
|
}
|
|
return n;
|
|
}
|
|
while (n>=4) {
|
|
if (**ws-1u >= 0x7fu) {
|
|
if (!**ws) {
|
|
*s = 0;
|
|
*ws = 0;
|
|
return N-n;
|
|
}
|
|
l = wcrtomb(s, **ws, 0);
|
|
if (!(l+1)) return -1;
|
|
s += l;
|
|
n -= l;
|
|
} else {
|
|
*s++ = **ws;
|
|
n--;
|
|
}
|
|
(*ws)++;
|
|
}
|
|
while (n) {
|
|
if (**ws-1u >= 0x7fu) {
|
|
if (!**ws) {
|
|
*s = 0;
|
|
*ws = 0;
|
|
return N-n;
|
|
}
|
|
l = wcrtomb(buf, **ws, 0);
|
|
if (!(l+1)) return -1;
|
|
if (l>n) return N-n;
|
|
wcrtomb(s, **ws, 0);
|
|
s += l;
|
|
n -= l;
|
|
} else {
|
|
*s++ = **ws;
|
|
n--;
|
|
}
|
|
(*ws)++;
|
|
}
|
|
return N;
|
|
}
|