1*c9945492SAndroid Build Coastguard Worker #include <stdlib.h> 2*c9945492SAndroid Build Coastguard Worker #include <wchar.h> 3*c9945492SAndroid Build Coastguard Worker #include <errno.h> 4*c9945492SAndroid Build Coastguard Worker #include "internal.h" 5*c9945492SAndroid Build Coastguard Worker mbrtowc(wchar_t * restrict wc,const char * restrict src,size_t n,mbstate_t * restrict st)6*c9945492SAndroid Build Coastguard Workersize_t mbrtowc(wchar_t *restrict wc, const char *restrict src, size_t n, mbstate_t *restrict st) 7*c9945492SAndroid Build Coastguard Worker { 8*c9945492SAndroid Build Coastguard Worker static unsigned internal_state; 9*c9945492SAndroid Build Coastguard Worker unsigned c; 10*c9945492SAndroid Build Coastguard Worker const unsigned char *s = (const void *)src; 11*c9945492SAndroid Build Coastguard Worker const size_t N = n; 12*c9945492SAndroid Build Coastguard Worker wchar_t dummy; 13*c9945492SAndroid Build Coastguard Worker 14*c9945492SAndroid Build Coastguard Worker if (!st) st = (void *)&internal_state; 15*c9945492SAndroid Build Coastguard Worker c = *(unsigned *)st; 16*c9945492SAndroid Build Coastguard Worker 17*c9945492SAndroid Build Coastguard Worker if (!s) { 18*c9945492SAndroid Build Coastguard Worker if (c) goto ilseq; 19*c9945492SAndroid Build Coastguard Worker return 0; 20*c9945492SAndroid Build Coastguard Worker } else if (!wc) wc = &dummy; 21*c9945492SAndroid Build Coastguard Worker 22*c9945492SAndroid Build Coastguard Worker if (!n) return -2; 23*c9945492SAndroid Build Coastguard Worker if (!c) { 24*c9945492SAndroid Build Coastguard Worker if (*s < 0x80) return !!(*wc = *s); 25*c9945492SAndroid Build Coastguard Worker if (MB_CUR_MAX==1) return (*wc = CODEUNIT(*s)), 1; 26*c9945492SAndroid Build Coastguard Worker if (*s-SA > SB-SA) goto ilseq; 27*c9945492SAndroid Build Coastguard Worker c = bittab[*s++-SA]; n--; 28*c9945492SAndroid Build Coastguard Worker } 29*c9945492SAndroid Build Coastguard Worker 30*c9945492SAndroid Build Coastguard Worker if (n) { 31*c9945492SAndroid Build Coastguard Worker if (OOB(c,*s)) goto ilseq; 32*c9945492SAndroid Build Coastguard Worker loop: 33*c9945492SAndroid Build Coastguard Worker c = c<<6 | *s++-0x80; n--; 34*c9945492SAndroid Build Coastguard Worker if (!(c&(1U<<31))) { 35*c9945492SAndroid Build Coastguard Worker *(unsigned *)st = 0; 36*c9945492SAndroid Build Coastguard Worker *wc = c; 37*c9945492SAndroid Build Coastguard Worker return N-n; 38*c9945492SAndroid Build Coastguard Worker } 39*c9945492SAndroid Build Coastguard Worker if (n) { 40*c9945492SAndroid Build Coastguard Worker if (*s-0x80u >= 0x40) goto ilseq; 41*c9945492SAndroid Build Coastguard Worker goto loop; 42*c9945492SAndroid Build Coastguard Worker } 43*c9945492SAndroid Build Coastguard Worker } 44*c9945492SAndroid Build Coastguard Worker 45*c9945492SAndroid Build Coastguard Worker *(unsigned *)st = c; 46*c9945492SAndroid Build Coastguard Worker return -2; 47*c9945492SAndroid Build Coastguard Worker ilseq: 48*c9945492SAndroid Build Coastguard Worker *(unsigned *)st = 0; 49*c9945492SAndroid Build Coastguard Worker errno = EILSEQ; 50*c9945492SAndroid Build Coastguard Worker return -1; 51*c9945492SAndroid Build Coastguard Worker } 52