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