1 /* 2 * This code was written by Rich Felker in 2010; no copyright is claimed. 3 * This code is in the public domain. Attribution is appreciated but 4 * unnecessary. 5 */ 6 7 #include <stdint.h> 8 #include <wchar.h> 9 #include <errno.h> 10 #include "internal.h" 11 mbsrtowcs(wchar_t * restrict ws,const char ** restrict src,size_t wn,mbstate_t * restrict st)12size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbstate_t *restrict st) 13 { 14 const unsigned char *s = (const void *)*src; 15 size_t wn0 = wn; 16 unsigned c = 0; 17 18 if (st && (c = *(unsigned *)st)) { 19 if (ws) { 20 *(unsigned *)st = 0; 21 goto resume; 22 } else { 23 goto resume0; 24 } 25 } 26 27 if (!ws) for (;;) { 28 if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { 29 while (!(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) { 30 s += 4; 31 wn -= 4; 32 } 33 } 34 if (*s-1u < 0x7f) { 35 s++; 36 wn--; 37 continue; 38 } 39 if (*s-SA > SB-SA) break; 40 c = bittab[*s++-SA]; 41 resume0: 42 if (OOB(c,*s)) { s--; break; } 43 s++; 44 if (c&(1U<<25)) { 45 if (*s-0x80u >= 0x40) { s-=2; break; } 46 s++; 47 if (c&(1U<<19)) { 48 if (*s-0x80u >= 0x40) { s-=3; break; } 49 s++; 50 } 51 } 52 wn--; 53 c = 0; 54 } else for (;;) { 55 if (!wn) { 56 *src = (const void *)s; 57 return wn0; 58 } 59 if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { 60 while (wn>=5 && !(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) { 61 *ws++ = *s++; 62 *ws++ = *s++; 63 *ws++ = *s++; 64 *ws++ = *s++; 65 wn -= 4; 66 } 67 } 68 if (*s-1u < 0x7f) { 69 *ws++ = *s++; 70 wn--; 71 continue; 72 } 73 if (*s-SA > SB-SA) break; 74 c = bittab[*s++-SA]; 75 resume: 76 if (OOB(c,*s)) { s--; break; } 77 c = (c<<6) | *s++-0x80; 78 if (c&(1U<<31)) { 79 if (*s-0x80u >= 0x40) { s-=2; break; } 80 c = (c<<6) | *s++-0x80; 81 if (c&(1U<<31)) { 82 if (*s-0x80u >= 0x40) { s-=3; break; } 83 c = (c<<6) | *s++-0x80; 84 } 85 } 86 *ws++ = c; 87 wn--; 88 c = 0; 89 } 90 91 if (!c && !*s) { 92 if (ws) { 93 *ws = 0; 94 *src = 0; 95 } 96 return wn0-wn; 97 } 98 errno = EILSEQ; 99 if (ws) *src = (const void *)s; 100 return -1; 101 } 102