blob: 26da8d60b24537f77def964fd93dbd31d059fe52 [file] [log] [blame]
#include "internal.h"
#include <errno.h>
#include <stdlib.h>
#include <wchar.h>
size_t mbrtowc(wchar_t* restrict wc, const char* restrict src, size_t n, mbstate_t* restrict st) {
static unsigned internal_state;
unsigned c;
const unsigned char* s = (const void*)src;
const unsigned N = n;
wchar_t dummy;
if (!st)
st = (void*)&internal_state;
c = *(unsigned*)st;
if (!s) {
if (c)
goto ilseq;
return 0;
} else if (!wc)
wc = &dummy;
if (!n)
return -2;
if (!c) {
if (*s < 0x80)
return !!(*wc = *s);
if (MB_CUR_MAX == 1)
return (*wc = CODEUNIT(*s)), 1;
if (*s - SA > SB - SA)
goto ilseq;
c = bittab[*s++ - SA];
n--;
}
if (n) {
if (OOB(c, *s))
goto ilseq;
loop:
c = c << 6 | (*s++ - 0x80);
n--;
if (!(c & (1U << 31))) {
*(unsigned*)st = 0;
*wc = c;
return N - n;
}
if (n) {
if (*s - 0x80u >= 0x40)
goto ilseq;
goto loop;
}
}
*(unsigned*)st = c;
return -2;
ilseq:
*(unsigned*)st = 0;
errno = EILSEQ;
return -1;
}