• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
mbsrtowcs(wchar_t * restrict ws,const char ** restrict src,size_t wn,mbstate_t * restrict st)8 size_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 #ifdef __GNUC__
42 		typedef uint32_t __attribute__((__may_alias__)) w32;
43 		if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) {
44 			while (!(( *(w32*)s | *(w32*)s-0x01010101) & 0x80808080)) {
45 				s += 4;
46 				wn -= 4;
47 			}
48 		}
49 #endif
50 		if (*s-1u < 0x7f) {
51 			s++;
52 			wn--;
53 			continue;
54 		}
55 		if (*s-SA > SB-SA) break;
56 		c = bittab[*s++-SA];
57 resume0:
58 		if (OOB(c,*s)) { s--; break; }
59 		s++;
60 		if (c&(1U<<25)) {
61 			if (*s-0x80u >= 0x40) { s-=2; break; }
62 			s++;
63 			if (c&(1U<<19)) {
64 				if (*s-0x80u >= 0x40) { s-=3; break; }
65 				s++;
66 			}
67 		}
68 		wn--;
69 		c = 0;
70 	} else for (;;) {
71 		if (!wn) {
72 			*src = (const void *)s;
73 			return wn0;
74 		}
75 #ifdef __GNUC__
76 		typedef uint32_t __attribute__((__may_alias__)) w32;
77 		if (*s-1u < 0x7f && (uintptr_t)s%4 == 0) {
78 			while (wn>=5 && !(( *(w32*)s | *(w32*)s-0x01010101) & 0x80808080)) {
79 				*ws++ = *s++;
80 				*ws++ = *s++;
81 				*ws++ = *s++;
82 				*ws++ = *s++;
83 				wn -= 4;
84 			}
85 		}
86 #endif
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 }
121