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 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 if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { 42 while (!(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) { 43 s += 4; 44 wn -= 4; 45 } 46 } 47 if (*s-1u < 0x7f) { 48 s++; 49 wn--; 50 continue; 51 } 52 if (*s-SA > SB-SA) break; 53 c = bittab[*s++-SA]; 54resume0: 55 if (OOB(c,*s)) { s--; break; } 56 s++; 57 if (c&(1U<<25)) { 58 if (*s-0x80u >= 0x40) { s-=2; break; } 59 s++; 60 if (c&(1U<<19)) { 61 if (*s-0x80u >= 0x40) { s-=3; break; } 62 s++; 63 } 64 } 65 wn--; 66 c = 0; 67 } else for (;;) { 68 if (!wn) { 69 *src = (const void *)s; 70 return wn0; 71 } 72 if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { 73 while (wn>=5 && !(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) { 74 *ws++ = *s++; 75 *ws++ = *s++; 76 *ws++ = *s++; 77 *ws++ = *s++; 78 wn -= 4; 79 } 80 } 81 if (*s-1u < 0x7f) { 82 *ws++ = *s++; 83 wn--; 84 continue; 85 } 86 if (*s-SA > SB-SA) break; 87 c = bittab[*s++-SA]; 88resume: 89 if (OOB(c,*s)) { s--; break; } 90 c = (c<<6) | *s++-0x80; 91 if (c&(1U<<31)) { 92 if (*s-0x80u >= 0x40) { s-=2; break; } 93 c = (c<<6) | *s++-0x80; 94 if (c&(1U<<31)) { 95 if (*s-0x80u >= 0x40) { s-=3; break; } 96 c = (c<<6) | *s++-0x80; 97 } 98 } 99 *ws++ = c; 100 wn--; 101 c = 0; 102 } 103 104 if (!c && !*s) { 105 if (ws) { 106 *ws = 0; 107 *src = 0; 108 } 109 return wn0-wn; 110 } 111 errno = EILSEQ; 112 if (ws) *src = (const void *)s; 113 return -1; 114} 115