OLD | NEW |
1 /* | 1 /* |
2 * This code was written by Rich Felker in 2010; no copyright is claimed. | 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 | 3 * This code is in the public domain. Attribution is appreciated but |
4 * unnecessary. | 4 * unnecessary. |
5 */ | 5 */ |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <wchar.h> | 8 #include <wchar.h> |
9 #include <errno.h> | 9 #include <errno.h> |
10 #include <string.h> | 10 #include <string.h> |
11 #include <stdlib.h> | 11 #include <stdlib.h> |
12 #include "internal.h" | 12 #include "internal.h" |
13 | 13 |
14 size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbs
tate_t *restrict st) | 14 size_t mbsrtowcs(wchar_t* restrict ws, |
15 { | 15 const char** restrict src, |
16 » const unsigned char *s = (const void *)*src; | 16 size_t wn, |
17 » size_t wn0 = wn; | 17 mbstate_t* restrict st) { |
18 » unsigned c = 0; | 18 const unsigned char* s = (const void*)*src; |
| 19 size_t wn0 = wn; |
| 20 unsigned c = 0; |
19 | 21 |
20 » if (st && (c = *(unsigned *)st)) { | 22 if (st && (c = *(unsigned*)st)) { |
21 » » if (ws) { | 23 if (ws) { |
22 » » » *(unsigned *)st = 0; | 24 *(unsigned*)st = 0; |
23 » » » goto resume; | 25 goto resume; |
24 » » } else { | 26 } else { |
25 » » » goto resume0; | 27 goto resume0; |
26 » » } | 28 } |
27 » } | 29 } |
28 | 30 |
29 » if (MB_CUR_MAX==1) { | 31 if (MB_CUR_MAX == 1) { |
30 » » if (!ws) return strlen((const char *)s); | 32 if (!ws) |
31 » » for (;;) { | 33 return strlen((const char*)s); |
32 » » » if (!wn) { | 34 for (;;) { |
33 » » » » *src = (const void *)s; | 35 if (!wn) { |
34 » » » » return wn0; | 36 *src = (const void*)s; |
35 » » » } | 37 return wn0; |
36 » » » if (!*s) break; | 38 } |
37 » » » c = *s++; | 39 if (!*s) |
38 » » » *ws++ = CODEUNIT(c); | 40 break; |
39 » » » wn--; | 41 c = *s++; |
40 » » } | 42 *ws++ = CODEUNIT(c); |
41 » » *ws = 0; | 43 wn--; |
42 » » *src = 0; | 44 } |
43 » » return wn0-wn; | 45 *ws = 0; |
44 » } | 46 *src = 0; |
| 47 return wn0 - wn; |
| 48 } |
45 | 49 |
46 » if (!ws) for (;;) { | 50 if (!ws) |
47 » » if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { | 51 for (;;) { |
48 » » » while (!(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0
x80808080)) { | 52 if (*s - 1u < 0x7f && (uintptr_t)s % 4 == 0) { |
49 » » » » s += 4; | 53 while (!((*(uint32_t*)s | *(uint32_t*)s - 0x01010101) & 0x80808080)) { |
50 » » » » wn -= 4; | 54 s += 4; |
51 » » » } | 55 wn -= 4; |
52 » » } | 56 } |
53 » » if (*s-1u < 0x7f) { | 57 } |
54 » » » s++; | 58 if (*s - 1u < 0x7f) { |
55 » » » wn--; | 59 s++; |
56 » » » continue; | 60 wn--; |
57 » » } | 61 continue; |
58 » » if (*s-SA > SB-SA) break; | 62 } |
59 » » c = bittab[*s++-SA]; | 63 if (*s - SA > SB - SA) |
60 resume0: | 64 break; |
61 » » if (OOB(c,*s)) { s--; break; } | 65 c = bittab[*s++ - SA]; |
62 » » s++; | 66 resume0: |
63 » » if (c&(1U<<25)) { | 67 if (OOB(c, *s)) { |
64 » » » if (*s-0x80u >= 0x40) { s-=2; break; } | 68 s--; |
65 » » » s++; | 69 break; |
66 » » » if (c&(1U<<19)) { | 70 } |
67 » » » » if (*s-0x80u >= 0x40) { s-=3; break; } | 71 s++; |
68 » » » » s++; | 72 if (c & (1U << 25)) { |
69 » » » } | 73 if (*s - 0x80u >= 0x40) { |
70 » » } | 74 s -= 2; |
71 » » wn--; | 75 break; |
72 » » c = 0; | 76 } |
73 » } else for (;;) { | 77 s++; |
74 » » if (!wn) { | 78 if (c & (1U << 19)) { |
75 » » » *src = (const void *)s; | 79 if (*s - 0x80u >= 0x40) { |
76 » » » return wn0; | 80 s -= 3; |
77 » » } | 81 break; |
78 » » if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) { | 82 } |
79 » » » while (wn>=5 && !(( *(uint32_t*)s | *(uint32_t*)s-0x0101
0101) & 0x80808080)) { | 83 s++; |
80 » » » » *ws++ = *s++; | 84 } |
81 » » » » *ws++ = *s++; | 85 } |
82 » » » » *ws++ = *s++; | 86 wn--; |
83 » » » » *ws++ = *s++; | 87 c = 0; |
84 » » » » wn -= 4; | 88 } |
85 » » » } | 89 else |
86 » » } | 90 for (;;) { |
87 » » if (*s-1u < 0x7f) { | 91 if (!wn) { |
88 » » » *ws++ = *s++; | 92 *src = (const void*)s; |
89 » » » wn--; | 93 return wn0; |
90 » » » continue; | 94 } |
91 » » } | 95 if (*s - 1u < 0x7f && (uintptr_t)s % 4 == 0) { |
92 » » if (*s-SA > SB-SA) break; | 96 while (wn >= 5 && |
93 » » c = bittab[*s++-SA]; | 97 !((*(uint32_t*)s | *(uint32_t*)s - 0x01010101) & 0x80808080)) { |
94 resume: | 98 *ws++ = *s++; |
95 » » if (OOB(c,*s)) { s--; break; } | 99 *ws++ = *s++; |
96 » » c = (c<<6) | *s++-0x80; | 100 *ws++ = *s++; |
97 » » if (c&(1U<<31)) { | 101 *ws++ = *s++; |
98 » » » if (*s-0x80u >= 0x40) { s-=2; break; } | 102 wn -= 4; |
99 » » » c = (c<<6) | *s++-0x80; | 103 } |
100 » » » if (c&(1U<<31)) { | 104 } |
101 » » » » if (*s-0x80u >= 0x40) { s-=3; break; } | 105 if (*s - 1u < 0x7f) { |
102 » » » » c = (c<<6) | *s++-0x80; | 106 *ws++ = *s++; |
103 » » » } | 107 wn--; |
104 » » } | 108 continue; |
105 » » *ws++ = c; | 109 } |
106 » » wn--; | 110 if (*s - SA > SB - SA) |
107 » » c = 0; | 111 break; |
108 » } | 112 c = bittab[*s++ - SA]; |
| 113 resume: |
| 114 if (OOB(c, *s)) { |
| 115 s--; |
| 116 break; |
| 117 } |
| 118 c = (c << 6) | *s++ - 0x80; |
| 119 if (c & (1U << 31)) { |
| 120 if (*s - 0x80u >= 0x40) { |
| 121 s -= 2; |
| 122 break; |
| 123 } |
| 124 c = (c << 6) | *s++ - 0x80; |
| 125 if (c & (1U << 31)) { |
| 126 if (*s - 0x80u >= 0x40) { |
| 127 s -= 3; |
| 128 break; |
| 129 } |
| 130 c = (c << 6) | *s++ - 0x80; |
| 131 } |
| 132 } |
| 133 *ws++ = c; |
| 134 wn--; |
| 135 c = 0; |
| 136 } |
109 | 137 |
110 » if (!c && !*s) { | 138 if (!c && !*s) { |
111 » » if (ws) { | 139 if (ws) { |
112 » » » *ws = 0; | 140 *ws = 0; |
113 » » » *src = 0; | 141 *src = 0; |
114 » » } | 142 } |
115 » » return wn0-wn; | 143 return wn0 - wn; |
116 » } | 144 } |
117 » errno = EILSEQ; | 145 errno = EILSEQ; |
118 » if (ws) *src = (const void *)s; | 146 if (ws) |
119 » return -1; | 147 *src = (const void*)s; |
| 148 return -1; |
120 } | 149 } |
OLD | NEW |