1*c9945492SAndroid Build Coastguard Worker #include <stdint.h> 2*c9945492SAndroid Build Coastguard Worker #include <wchar.h> 3*c9945492SAndroid Build Coastguard Worker #include <errno.h> 4*c9945492SAndroid Build Coastguard Worker #include <string.h> 5*c9945492SAndroid Build Coastguard Worker #include <stdlib.h> 6*c9945492SAndroid Build Coastguard Worker #include "internal.h" 7*c9945492SAndroid Build Coastguard Worker mbsrtowcs(wchar_t * restrict ws,const char ** restrict src,size_t wn,mbstate_t * restrict st)8*c9945492SAndroid Build Coastguard Workersize_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbstate_t *restrict st) 9*c9945492SAndroid Build Coastguard Worker { 10*c9945492SAndroid Build Coastguard Worker const unsigned char *s = (const void *)*src; 11*c9945492SAndroid Build Coastguard Worker size_t wn0 = wn; 12*c9945492SAndroid Build Coastguard Worker unsigned c = 0; 13*c9945492SAndroid Build Coastguard Worker 14*c9945492SAndroid Build Coastguard Worker if (st && (c = *(unsigned *)st)) { 15*c9945492SAndroid Build Coastguard Worker if (ws) { 16*c9945492SAndroid Build Coastguard Worker *(unsigned *)st = 0; 17*c9945492SAndroid Build Coastguard Worker goto resume; 18*c9945492SAndroid Build Coastguard Worker } else { 19*c9945492SAndroid Build Coastguard Worker goto resume0; 20*c9945492SAndroid Build Coastguard Worker } 21*c9945492SAndroid Build Coastguard Worker } 22*c9945492SAndroid Build Coastguard Worker 23*c9945492SAndroid Build Coastguard Worker if (MB_CUR_MAX==1) { 24*c9945492SAndroid Build Coastguard Worker if (!ws) return strlen((const char *)s); 25*c9945492SAndroid Build Coastguard Worker for (;;) { 26*c9945492SAndroid Build Coastguard Worker if (!wn) { 27*c9945492SAndroid Build Coastguard Worker *src = (const void *)s; 28*c9945492SAndroid Build Coastguard Worker return wn0; 29*c9945492SAndroid Build Coastguard Worker } 30*c9945492SAndroid Build Coastguard Worker if (!*s) break; 31*c9945492SAndroid Build Coastguard Worker c = *s++; 32*c9945492SAndroid Build Coastguard Worker *ws++ = CODEUNIT(c); 33*c9945492SAndroid Build Coastguard Worker wn--; 34*c9945492SAndroid Build Coastguard Worker } 35*c9945492SAndroid Build Coastguard Worker *ws = 0; 36*c9945492SAndroid Build Coastguard Worker *src = 0; 37*c9945492SAndroid Build Coastguard Worker return wn0-wn; 38*c9945492SAndroid Build Coastguard Worker } 39*c9945492SAndroid Build Coastguard Worker 40*c9945492SAndroid Build Coastguard Worker if (!ws) for (;;) { 41*c9945492SAndroid Build Coastguard Worker #ifdef __GNUC__ 42*c9945492SAndroid Build Coastguard Worker typedef uint32_t __attribute__((__may_alias__)) w32; 43*c9945492SAndroid Build Coastguard Worker if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { 44*c9945492SAndroid Build Coastguard Worker while (!(( *(w32*)s | *(w32*)s-0x01010101) & 0x80808080)) { 45*c9945492SAndroid Build Coastguard Worker s += 4; 46*c9945492SAndroid Build Coastguard Worker wn -= 4; 47*c9945492SAndroid Build Coastguard Worker } 48*c9945492SAndroid Build Coastguard Worker } 49*c9945492SAndroid Build Coastguard Worker #endif 50*c9945492SAndroid Build Coastguard Worker if (*s-1u < 0x7f) { 51*c9945492SAndroid Build Coastguard Worker s++; 52*c9945492SAndroid Build Coastguard Worker wn--; 53*c9945492SAndroid Build Coastguard Worker continue; 54*c9945492SAndroid Build Coastguard Worker } 55*c9945492SAndroid Build Coastguard Worker if (*s-SA > SB-SA) break; 56*c9945492SAndroid Build Coastguard Worker c = bittab[*s++-SA]; 57*c9945492SAndroid Build Coastguard Worker resume0: 58*c9945492SAndroid Build Coastguard Worker if (OOB(c,*s)) { s--; break; } 59*c9945492SAndroid Build Coastguard Worker s++; 60*c9945492SAndroid Build Coastguard Worker if (c&(1U<<25)) { 61*c9945492SAndroid Build Coastguard Worker if (*s-0x80u >= 0x40) { s-=2; break; } 62*c9945492SAndroid Build Coastguard Worker s++; 63*c9945492SAndroid Build Coastguard Worker if (c&(1U<<19)) { 64*c9945492SAndroid Build Coastguard Worker if (*s-0x80u >= 0x40) { s-=3; break; } 65*c9945492SAndroid Build Coastguard Worker s++; 66*c9945492SAndroid Build Coastguard Worker } 67*c9945492SAndroid Build Coastguard Worker } 68*c9945492SAndroid Build Coastguard Worker wn--; 69*c9945492SAndroid Build Coastguard Worker c = 0; 70*c9945492SAndroid Build Coastguard Worker } else for (;;) { 71*c9945492SAndroid Build Coastguard Worker if (!wn) { 72*c9945492SAndroid Build Coastguard Worker *src = (const void *)s; 73*c9945492SAndroid Build Coastguard Worker return wn0; 74*c9945492SAndroid Build Coastguard Worker } 75*c9945492SAndroid Build Coastguard Worker #ifdef __GNUC__ 76*c9945492SAndroid Build Coastguard Worker typedef uint32_t __attribute__((__may_alias__)) w32; 77*c9945492SAndroid Build Coastguard Worker if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { 78*c9945492SAndroid Build Coastguard Worker while (wn>=5 && !(( *(w32*)s | *(w32*)s-0x01010101) & 0x80808080)) { 79*c9945492SAndroid Build Coastguard Worker *ws++ = *s++; 80*c9945492SAndroid Build Coastguard Worker *ws++ = *s++; 81*c9945492SAndroid Build Coastguard Worker *ws++ = *s++; 82*c9945492SAndroid Build Coastguard Worker *ws++ = *s++; 83*c9945492SAndroid Build Coastguard Worker wn -= 4; 84*c9945492SAndroid Build Coastguard Worker } 85*c9945492SAndroid Build Coastguard Worker } 86*c9945492SAndroid Build Coastguard Worker #endif 87*c9945492SAndroid Build Coastguard Worker if (*s-1u < 0x7f) { 88*c9945492SAndroid Build Coastguard Worker *ws++ = *s++; 89*c9945492SAndroid Build Coastguard Worker wn--; 90*c9945492SAndroid Build Coastguard Worker continue; 91*c9945492SAndroid Build Coastguard Worker } 92*c9945492SAndroid Build Coastguard Worker if (*s-SA > SB-SA) break; 93*c9945492SAndroid Build Coastguard Worker c = bittab[*s++-SA]; 94*c9945492SAndroid Build Coastguard Worker resume: 95*c9945492SAndroid Build Coastguard Worker if (OOB(c,*s)) { s--; break; } 96*c9945492SAndroid Build Coastguard Worker c = (c<<6) | *s++-0x80; 97*c9945492SAndroid Build Coastguard Worker if (c&(1U<<31)) { 98*c9945492SAndroid Build Coastguard Worker if (*s-0x80u >= 0x40) { s-=2; break; } 99*c9945492SAndroid Build Coastguard Worker c = (c<<6) | *s++-0x80; 100*c9945492SAndroid Build Coastguard Worker if (c&(1U<<31)) { 101*c9945492SAndroid Build Coastguard Worker if (*s-0x80u >= 0x40) { s-=3; break; } 102*c9945492SAndroid Build Coastguard Worker c = (c<<6) | *s++-0x80; 103*c9945492SAndroid Build Coastguard Worker } 104*c9945492SAndroid Build Coastguard Worker } 105*c9945492SAndroid Build Coastguard Worker *ws++ = c; 106*c9945492SAndroid Build Coastguard Worker wn--; 107*c9945492SAndroid Build Coastguard Worker c = 0; 108*c9945492SAndroid Build Coastguard Worker } 109*c9945492SAndroid Build Coastguard Worker 110*c9945492SAndroid Build Coastguard Worker if (!c && !*s) { 111*c9945492SAndroid Build Coastguard Worker if (ws) { 112*c9945492SAndroid Build Coastguard Worker *ws = 0; 113*c9945492SAndroid Build Coastguard Worker *src = 0; 114*c9945492SAndroid Build Coastguard Worker } 115*c9945492SAndroid Build Coastguard Worker return wn0-wn; 116*c9945492SAndroid Build Coastguard Worker } 117*c9945492SAndroid Build Coastguard Worker errno = EILSEQ; 118*c9945492SAndroid Build Coastguard Worker if (ws) *src = (const void *)s; 119*c9945492SAndroid Build Coastguard Worker return -1; 120*c9945492SAndroid Build Coastguard Worker } 121