1 #include <string.h>
2 #include <wchar.h>
3 #include <wctype.h>
4 #include <assert.h>
5
6 // Returns 1 if 'wc' is in the 'delim' string, 0 otherwise.
_wc_indelim(wchar_t wc,const wchar_t * delim)7 static int _wc_indelim(wchar_t wc, const wchar_t* delim) {
8 while (*delim) {
9 if (wc == *delim)
10 return 1;
11 delim++;
12 }
13 return 0;
14 }
15
wcpcpy(wchar_t * to,const wchar_t * from)16 wchar_t *wcpcpy(wchar_t *to, const wchar_t *from) {
17 size_t n = 0;
18 for (;;) {
19 wchar_t wc = from[n];
20 to[n] = wc;
21 if (wc == L'\0')
22 break;
23 n++;
24 }
25 return to + n;
26 }
27
wcpncpy(wchar_t * dst,const wchar_t * src,size_t n)28 wchar_t *wcpncpy(wchar_t *dst, const wchar_t *src, size_t n) {
29 size_t i;
30 for (i = 0; i < n; ++i) {
31 wchar_t wc = src[i];
32 dst[i] = wc;
33 if (wc == L'\0')
34 break;
35 }
36 while (i < n) {
37 dst[i] = L'\0';
38 ++i;
39 }
40 return &dst[n-1];
41 }
42
wcscasecmp(const wchar_t * s1,const wchar_t * s2)43 int wcscasecmp(const wchar_t *s1, const wchar_t *s2) {
44 size_t n = 0;
45 for (;;) {
46 wchar_t wc1 = towlower(s1[n]);
47 wchar_t wc2 = towlower(s2[n]);
48 if (wc1 != wc2)
49 return (wc1 > wc2) ? +1 : -1;
50 if (wc1 == L'\0')
51 return 0;
52 n++;
53 }
54 }
55
wcscat(wchar_t * s1,const wchar_t * s2)56 wchar_t *wcscat(wchar_t *s1, const wchar_t *s2) {
57 size_t n = 0;
58 while (s1[n] != L'\0')
59 n++;
60
61 size_t i = 0;
62 for (;;) {
63 wchar_t wc = s2[i];
64 s1[n+i] = wc;
65 if (wc == L'\0')
66 break;
67 i++;
68 }
69 return s1;
70 }
71
wcslcat(wchar_t * dst,const wchar_t * src,size_t siz)72 size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t siz) {
73 // Sanity check simplifies code below
74 if (siz == 0)
75 return 0;
76
77 // Skip dst characters.
78 size_t n = 0;
79 while (n < siz && dst[n] != L'\0')
80 n++;
81
82 if (n == siz)
83 return n + wcslen(src);
84
85 // Copy as much source characters as they fit into siz-1 bytes.
86 size_t i;
87 for (i = 0; n+i+1 < siz && src[i] != L'\0'; ++i)
88 dst[n+i] = src[i];
89
90 // Always zero terminate destination
91 dst[n+i] = L'\0';
92
93 // Skip remaining source characters
94 while (src[i] != L'\0')
95 i++;
96
97 return n+i;
98 }
99
wcslcpy(wchar_t * dst,const wchar_t * src,size_t siz)100 size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz) {
101 size_t i;
102
103 // Copy all non-zero bytes that fit into siz-1 destination bytes
104 for (i = 0; i + 1 < siz && src[i] != L'\0'; ++i)
105 dst[i] = src[i];
106
107 // Always zero-terminate destination buffer
108 dst[i] = L'\0';
109
110 // Skip other source characters.
111 while (src[i] != L'\0')
112 ++i;
113
114 return i;
115 }
116
wcslen(const wchar_t * s)117 size_t wcslen(const wchar_t *s) {
118 size_t n = 0;
119 for (;;) {
120 wchar_t wc = s[n];
121 if (wc == L'\0')
122 return n;
123 n++;
124 }
125 }
126
wcsncasecmp(const wchar_t * s1,const wchar_t * s2,size_t n)127 int wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
128 size_t i;
129 for (i = 0; i < n; ++i) {
130 wchar_t wc1 = towlower(s1[i]);
131 wchar_t wc2 = towlower(s2[i]);
132 if (wc1 != wc2)
133 return (wc1 > wc2) ? +1 : -1;
134 }
135 return 0;
136 }
137
wcsncat(wchar_t * s1,const wchar_t * s2,size_t n)138 wchar_t *wcsncat(wchar_t *s1, const wchar_t *s2, size_t n) {
139 size_t start = 0;
140 while (s1[start] != L'\0')
141 start++;
142
143 // Append s2.
144 size_t i;
145 for (i = 0; i < n; ++i) {
146 wchar_t wc = s2[i];
147 s1[start + i] = wc;
148 if (wc == L'\0')
149 break;
150 }
151 return (wchar_t*)s1;
152 }
153
wcsncmp(const wchar_t * s1,const wchar_t * s2,size_t n)154 int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
155 size_t i;
156 for (i = 0; i < n; ++i) {
157 wchar_t wc = s1[i];
158 if (wc != s2[i])
159 return (wc > s2[i]) ? +1 : -1;
160 if (wc == L'\0')
161 break;
162 }
163 return 0;
164 }
165
wcsncpy(wchar_t * dst,const wchar_t * src,size_t n)166 wchar_t *wcsncpy(wchar_t *dst, const wchar_t *src, size_t n) {
167 // Copy initial characters.
168 size_t i;
169 for (i = 0; i < n; ++i) {
170 wchar_t wc = src[i];
171 if (wc == L'\0')
172 break;
173 dst[i] = wc;
174 }
175 // zero-pad the remainder.
176 for ( ; i < n; ++i)
177 dst[i] = L'\0';
178
179 return dst;
180 }
181
wcsnlen(const wchar_t * s,size_t maxlen)182 size_t wcsnlen(const wchar_t *s, size_t maxlen) {
183 size_t n;
184 for (n = 0; n < maxlen; ++n) {
185 if (s[n] == L'\0')
186 break;
187 }
188 return n;
189 }
190
wcspbrk(const wchar_t * s,const wchar_t * set)191 wchar_t *wcspbrk(const wchar_t *s, const wchar_t *set) {
192 size_t n = 0;
193 for (;;) {
194 wchar_t wc = s[n];
195 if (!wc)
196 return NULL;
197 if (_wc_indelim(wc, set))
198 return (wchar_t*)&s[n];
199 n++;
200 }
201 }
202
wcschr(const wchar_t * s,wchar_t c)203 wchar_t *wcschr(const wchar_t *s, wchar_t c) {
204 size_t n = 0;
205 for (;;) {
206 wchar_t wc = s[n];
207 if (wc == c)
208 return (wchar_t*)s + n;
209 if (wc == L'\0')
210 return NULL;
211 n++;
212 }
213 }
214
wcsrchr(const wchar_t * s,wchar_t c)215 wchar_t *wcsrchr(const wchar_t *s, wchar_t c) {
216 size_t n = 0;
217 wchar_t* last = NULL;
218 for (;;) {
219 wchar_t wc = s[n];
220 if (wc == c)
221 last = (wchar_t*)s + n;
222 if (wc == L'\0')
223 break;
224 n++;
225 }
226 return last;
227 }
228
wcsspn(const wchar_t * s,const wchar_t * set)229 size_t wcsspn(const wchar_t *s, const wchar_t *set) {
230 size_t n = 0;
231 for (;;) {
232 wchar_t wc = s[n];
233 if (wc == L'\0')
234 break;
235 if (!_wc_indelim(wc, set))
236 break;
237 ++n;
238 }
239 return n;
240 }
241
wcsstr(const wchar_t * s,const wchar_t * find)242 wchar_t *wcsstr(const wchar_t *s, const wchar_t *find) {
243 wchar_t find_c;
244
245 // Always find the empty string
246 find_c = *find++;
247 if (!find_c)
248 return (wchar_t*)s;
249
250 size_t find_len = wcslen(find);
251
252 for (;;) {
253 wchar_t* p = wcschr(s, find_c);
254 if (p == NULL)
255 return NULL;
256
257 if (!wmemcmp(p, find, find_len))
258 return p;
259
260 s = p + 1;
261 }
262 return NULL;
263 }
264
wcstok(wchar_t * s,const wchar_t * delim,wchar_t ** last)265 wchar_t *wcstok(wchar_t *s, const wchar_t *delim, wchar_t **last) {
266 if (s == NULL) {
267 s = *last;
268 if (s == NULL)
269 return NULL;
270 }
271
272 // Skip leading delimiters first.
273 size_t i = 0;
274 wchar_t wc;
275 for (;;) {
276 wc = s[i];
277 if (wc && _wc_indelim(wc, delim)) {
278 i++;
279 continue;
280 }
281 break;
282 }
283
284 if (!wc) {
285 // Nothing left.
286 *last = NULL;
287 return NULL;
288 }
289
290 size_t tok_start = i;
291
292 // Skip non delimiters now.
293 for (;;) {
294 wc = s[i];
295 if (wc && !_wc_indelim(wc, delim)) {
296 i++;
297 continue;
298 }
299 break;
300 }
301
302 if (!wc) {
303 *last = NULL;
304 } else {
305 s[i] = L'\0';
306 *last = &s[i+1];
307 }
308 return &s[tok_start];
309 }
310
wmemchr(const wchar_t * s,wchar_t c,size_t n)311 wchar_t * wmemchr(const wchar_t *s, wchar_t c, size_t n) {
312 size_t i;
313 for (i = 0; i < n; ++i) {
314 if (s[i] == c)
315 return (wchar_t*)&s[i];
316 }
317 return NULL;
318 }
319
wmemcmp(const wchar_t * s1,const wchar_t * s2,size_t n)320 int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
321 size_t i;
322 for (i = 0; i < n; ++i) {
323 if (s1[i] == s2[i])
324 continue;
325 if (s1[i] > s2[i])
326 return 1;
327 else
328 return -1;
329 }
330 return 0;
331 }
332
wmemcpy(wchar_t * d,const wchar_t * s,size_t n)333 wchar_t * wmemcpy(wchar_t *d, const wchar_t *s, size_t n) {
334 return (wchar_t *)memcpy((char*)d,
335 (const char*)s,
336 n * sizeof(wchar_t));
337 }
338
wmemmove(wchar_t * d,const wchar_t * s,size_t n)339 wchar_t* wmemmove(wchar_t* d, const wchar_t* s, size_t n) {
340 return (wchar_t* )memmove((char*)d,
341 (const char*)s,
342 n * sizeof(wchar_t));
343 }
344
wmemset(wchar_t * s,wchar_t c,size_t n)345 wchar_t* wmemset(wchar_t* s, wchar_t c, size_t n) {
346 size_t i;
347 for (i = 0; i < n; ++i)
348 s[i] = c;
349 return s;
350 }
351