OLD | NEW |
(Empty) | |
| 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 <string.h> |
| 11 #include <stdlib.h> |
| 12 #include "internal.h" |
| 13 |
| 14 size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbs
tate_t *restrict st) |
| 15 { |
| 16 const unsigned char *s = (const void *)*src; |
| 17 size_t wn0 = wn; |
| 18 unsigned c = 0; |
| 19 |
| 20 if (st && (c = *(unsigned *)st)) { |
| 21 if (ws) { |
| 22 *(unsigned *)st = 0; |
| 23 goto resume; |
| 24 } else { |
| 25 goto resume0; |
| 26 } |
| 27 } |
| 28 |
| 29 if (MB_CUR_MAX==1) { |
| 30 if (!ws) return strlen((const char *)s); |
| 31 for (;;) { |
| 32 if (!wn) { |
| 33 *src = (const void *)s; |
| 34 return wn0; |
| 35 } |
| 36 if (!*s) break; |
| 37 c = *s++; |
| 38 *ws++ = CODEUNIT(c); |
| 39 wn--; |
| 40 } |
| 41 *ws = 0; |
| 42 *src = 0; |
| 43 return wn0-wn; |
| 44 } |
| 45 |
| 46 if (!ws) for (;;) { |
| 47 if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { |
| 48 while (!(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0
x80808080)) { |
| 49 s += 4; |
| 50 wn -= 4; |
| 51 } |
| 52 } |
| 53 if (*s-1u < 0x7f) { |
| 54 s++; |
| 55 wn--; |
| 56 continue; |
| 57 } |
| 58 if (*s-SA > SB-SA) break; |
| 59 c = bittab[*s++-SA]; |
| 60 resume0: |
| 61 if (OOB(c,*s)) { s--; break; } |
| 62 s++; |
| 63 if (c&(1U<<25)) { |
| 64 if (*s-0x80u >= 0x40) { s-=2; break; } |
| 65 s++; |
| 66 if (c&(1U<<19)) { |
| 67 if (*s-0x80u >= 0x40) { s-=3; break; } |
| 68 s++; |
| 69 } |
| 70 } |
| 71 wn--; |
| 72 c = 0; |
| 73 } else for (;;) { |
| 74 if (!wn) { |
| 75 *src = (const void *)s; |
| 76 return wn0; |
| 77 } |
| 78 if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { |
| 79 while (wn>=5 && !(( *(uint32_t*)s | *(uint32_t*)s-0x0101
0101) & 0x80808080)) { |
| 80 *ws++ = *s++; |
| 81 *ws++ = *s++; |
| 82 *ws++ = *s++; |
| 83 *ws++ = *s++; |
| 84 wn -= 4; |
| 85 } |
| 86 } |
| 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 } |
OLD | NEW |