use restrict everywhere it's required by c99 and/or posix 2008
[musl] / src / multibyte / mbsrtowcs.c
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 <stdlib.h>
8 #include <inttypes.h>
9 #include <wchar.h>
10 #include <errno.h>
11
12 #include "internal.h"
13
14 size_t mbsrtowcs(wchar_t *restrict ws, const char **restrict src, size_t wn, mbstate_t *restrict st)
15 {
16         unsigned c;
17         const unsigned char *s = (const void *)*src;
18         const wchar_t *wsorig = ws;
19
20         if (!st) st = (void *)&c, c = 0;
21         else c = *(unsigned *)st;
22
23         if (c) {
24                 *(unsigned *)st = 0;
25                 if (!ws) {
26                         wn = 0;
27                         goto resume0;
28                 }
29                 goto resume;
30         }
31
32         if (!ws) for (wn=0;;) {
33                 if (*s-SA >= SB-SA) {
34                         while (((uintptr_t)s&3) && *s-1u<0x7f) s++, wn++;
35                         while (!(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) s+=4, wn+=4;
36                         while (*s-1u<0x7f) s++, wn++;
37                         if (!*s) return wn;
38                         if (*s-SA >= SB-SA) goto ilseq2;
39                 }
40                 c = bittab[*s++-SA];
41                 do {
42 resume0:
43                         if (OOB(c,*s)) goto ilseq2; s++;
44                         c <<= 6; if (!(c&(1U<<31))) break;
45                         if (*s++-0x80u >= 0x40) goto ilseq2;
46                         c <<= 6; if (!(c&(1U<<31))) break;
47                         if (*s++-0x80u >= 0x40) goto ilseq2;
48                 } while (0);
49                 wn++; c = 0;
50         }
51
52         while (wn) {
53                 if (*s-SA >= SB-SA) {
54                         if (wn >= 7) {
55                                 while (((uintptr_t)s&3) && *s-1u<0x7f) {
56                                         *ws++ = *s++;
57                                         wn--;
58                                 }
59                                 while (wn>=4 && !(( *(uint32_t*)s | *(uint32_t*)s-0x01010101) & 0x80808080)) {
60                                         *ws++ = *s++;
61                                         *ws++ = *s++;
62                                         *ws++ = *s++;
63                                         *ws++ = *s++;
64                                         wn -= 4;
65                                 }
66                         }
67                         while (wn && *s-1u<0x7f) {
68                                 *ws++ = *s++;
69                                 wn--;
70                         }
71                         if (!wn) break;
72                         if (!*s) {
73                                 *ws = 0;
74                                 *src = 0;
75                                 return ws-wsorig;
76                         }
77                         if (*s-SA >= SB-SA) goto ilseq;
78                 }
79                 c = bittab[*s++-SA];
80                 do {
81 resume:
82                         if (OOB(c,*s)) goto ilseq;
83                         c = (c<<6) | *s++-0x80;
84                         if (!(c&(1U<<31))) break;
85
86                         if (*s-0x80u >= 0x40) goto ilseq;
87                         c = (c<<6) | *s++-0x80;
88                         if (!(c&(1U<<31))) break;
89
90                         if (*s-0x80u >= 0x40) goto ilseq;
91                         c = (c<<6) | *s++-0x80;
92                 } while (0);
93
94                 *ws++ = c; wn--; c = 0;
95         }
96         *src = (const void *)s;
97         return ws-wsorig;
98 ilseq:
99         *src = (const void *)s;
100 ilseq2:
101         /* enter permanently failing state */
102         *(unsigned *)st = FAILSTATE;
103         errno = EILSEQ;
104         return -1;
105 }