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 mbtowc(wchar_t * restrict wc,const char * restrict src,size_t n)6*c9945492SAndroid Build Coastguard Workerint mbtowc(wchar_t *restrict wc, const char *restrict src, size_t n) 7*c9945492SAndroid Build Coastguard Worker { 8*c9945492SAndroid Build Coastguard Worker unsigned c; 9*c9945492SAndroid Build Coastguard Worker const unsigned char *s = (const void *)src; 10*c9945492SAndroid Build Coastguard Worker wchar_t dummy; 11*c9945492SAndroid Build Coastguard Worker 12*c9945492SAndroid Build Coastguard Worker if (!s) return 0; 13*c9945492SAndroid Build Coastguard Worker if (!n) goto ilseq; 14*c9945492SAndroid Build Coastguard Worker if (!wc) wc = &dummy; 15*c9945492SAndroid Build Coastguard Worker 16*c9945492SAndroid Build Coastguard Worker if (*s < 0x80) return !!(*wc = *s); 17*c9945492SAndroid Build Coastguard Worker if (MB_CUR_MAX==1) return (*wc = CODEUNIT(*s)), 1; 18*c9945492SAndroid Build Coastguard Worker if (*s-SA > SB-SA) goto ilseq; 19*c9945492SAndroid Build Coastguard Worker c = bittab[*s++-SA]; 20*c9945492SAndroid Build Coastguard Worker 21*c9945492SAndroid Build Coastguard Worker /* Avoid excessive checks against n: If shifting the state n-1 22*c9945492SAndroid Build Coastguard Worker * times does not clear the high bit, then the value of n is 23*c9945492SAndroid Build Coastguard Worker * insufficient to read a character */ 24*c9945492SAndroid Build Coastguard Worker if (n<4 && ((c<<(6*n-6)) & (1U<<31))) goto ilseq; 25*c9945492SAndroid Build Coastguard Worker 26*c9945492SAndroid Build Coastguard Worker if (OOB(c,*s)) goto ilseq; 27*c9945492SAndroid Build Coastguard Worker c = c<<6 | *s++-0x80; 28*c9945492SAndroid Build Coastguard Worker if (!(c&(1U<<31))) { 29*c9945492SAndroid Build Coastguard Worker *wc = c; 30*c9945492SAndroid Build Coastguard Worker return 2; 31*c9945492SAndroid Build Coastguard Worker } 32*c9945492SAndroid Build Coastguard Worker 33*c9945492SAndroid Build Coastguard Worker if (*s-0x80u >= 0x40) goto ilseq; 34*c9945492SAndroid Build Coastguard Worker c = c<<6 | *s++-0x80; 35*c9945492SAndroid Build Coastguard Worker if (!(c&(1U<<31))) { 36*c9945492SAndroid Build Coastguard Worker *wc = c; 37*c9945492SAndroid Build Coastguard Worker return 3; 38*c9945492SAndroid Build Coastguard Worker } 39*c9945492SAndroid Build Coastguard Worker 40*c9945492SAndroid Build Coastguard Worker if (*s-0x80u >= 0x40) goto ilseq; 41*c9945492SAndroid Build Coastguard Worker *wc = c<<6 | *s++-0x80; 42*c9945492SAndroid Build Coastguard Worker return 4; 43*c9945492SAndroid Build Coastguard Worker 44*c9945492SAndroid Build Coastguard Worker ilseq: 45*c9945492SAndroid Build Coastguard Worker errno = EILSEQ; 46*c9945492SAndroid Build Coastguard Worker return -1; 47*c9945492SAndroid Build Coastguard Worker } 48