1 #include <string.h>
2 #include <wchar.h>
3 #include <wctype.h>
4
5 // Returns 1 if 'wc' is in the 'delim' string, 0 otherwise.
_wc_indelim(wchar_t wc,const wchar_t * delim)6 static int _wc_indelim(wchar_t wc, const wchar_t* delim) {
7 while (*delim) {
8 if (wc == *delim)
9 return 1;
10 delim++;
11 }
12 return 0;
13 }
14
wcpcpy(wchar_t * to,const wchar_t * from)15 wchar_t *wcpcpy(wchar_t *to, const wchar_t *from) {
16 size_t n = 0;
17 for (;;) {
18 wchar_t wc = from[n];
19 to[n] = wc;
20 if (wc == L'\0')
21 break;
22 n++;
23 }
24 return to + n;
25 }
26
wcpncpy(wchar_t * dst,const wchar_t * src,size_t n)27 wchar_t *wcpncpy(wchar_t *dst, const wchar_t *src, size_t n) {
28 size_t i;
29 for (i = 0; i < n; ++i) {
30 wchar_t wc = src[i];
31 dst[i] = wc;
32 if (wc == L'\0')
33 break;
34 }
35 while (i < n) {
36 dst[i] = L'\0';
37 ++i;
38 }
39 return &dst[n-1];
40 }
41
wcscasecmp(const wchar_t * s1,const wchar_t * s2)42 int wcscasecmp(const wchar_t *s1, const wchar_t *s2) {
43 size_t n = 0;
44 for (;;) {
45 wchar_t wc1 = towlower(s1[n]);
46 wchar_t wc2 = towlower(s2[n]);
47 if (wc1 != wc2)
48 return (wc1 > wc2) ? +1 : -1;
49 if (wc1 == L'\0')
50 return 0;
51 n++;
52 }
53 }
54
wcscat(wchar_t * s1,const wchar_t * s2)55 wchar_t *wcscat(wchar_t *s1, const wchar_t *s2) {
56 size_t n = 0;
57 while (s1[n] != L'\0')
58 n++;
59
60 size_t i = 0;
61 for (;;) {
62 wchar_t wc = s2[i];
63 s1[n+i] = wc;
64 if (wc == L'\0')
65 break;
66 i++;
67 }
68 return s1;
69 }
70
wcslcat(wchar_t * dst,const wchar_t * src,size_t siz)71 size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t siz) {
72 // Sanity check simplifies code below
73 if (siz == 0)
74 return 0;
75
76 // Skip dst characters.
77 size_t n = 0;
78 while (n < siz && dst[n] != L'\0')
79 n++;
80
81 if (n == siz)
82 return n + wcslen(src);
83
84 // Copy as much source characters as they fit into siz-1 bytes.
85 size_t i;
86 for (i = 0; n+i+1 < siz && src[i] != L'\0'; ++i)
87 dst[n+i] = src[i];
88
89 // Always zero terminate destination
90 dst[n+i] = L'\0';
91
92 // Skip remaining source characters
93 while (src[i] != L'\0')
94 i++;
95
96 return n+i;
97 }
98
wcslcpy(wchar_t * dst,const wchar_t * src,size_t siz)99 size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz) {
100 size_t i;
101
102 // Copy all non-zero bytes that fit into siz-1 destination bytes
103 for (i = 0; i + 1 < siz && src[i] != L'\0'; ++i)
104 dst[i] = src[i];
105
106 // Always zero-terminate destination buffer
107 dst[i] = L'\0';
108
109 // Skip other source characters.
110 while (src[i] != L'\0')
111 ++i;
112
113 return i;
114 }
115
wcslen(const wchar_t * s)116 size_t wcslen(const wchar_t *s) {
117 size_t n = 0;
118 for (;;) {
119 wchar_t wc = s[n];
120 if (wc == L'\0')
121 return n;
122 n++;
123 }
124 }
125
wcsncasecmp(const wchar_t * s1,const wchar_t * s2,size_t n)126 int wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
127 size_t i;
128 for (i = 0; i < n; ++i) {
129 wchar_t wc1 = towlower(s1[i]);
130 wchar_t wc2 = towlower(s2[i]);
131 if (wc1 != wc2)
132 return (wc1 > wc2) ? +1 : -1;
133 }
134 return 0;
135 }
136
wcsncat(wchar_t * s1,const wchar_t * s2,size_t n)137 wchar_t *wcsncat(wchar_t *s1, const wchar_t *s2, size_t n) {
138 size_t start = 0;
139 while (s1[start] != L'\0')
140 start++;
141
142 // Append s2.
143 size_t i;
144 for (i = 0; i < n; ++i) {
145 wchar_t wc = s2[i];
146 s1[start + i] = wc;
147 if (wc == L'\0')
148 break;
149 }
150 return (wchar_t*)s1;
151 }
152
wcsncmp(const wchar_t * s1,const wchar_t * s2,size_t n)153 int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
154 size_t i;
155 for (i = 0; i < n; ++i) {
156 wchar_t wc = s1[i];
157 if (wc != s2[i])
158 return (wc > s2[i]) ? +1 : -1;
159 if (wc == L'\0')
160 break;
161 }
162 return 0;
163 }
164
wcsncpy(wchar_t * dst,const wchar_t * src,size_t n)165 wchar_t *wcsncpy(wchar_t *dst, const wchar_t *src, size_t n) {
166 // Copy initial characters.
167 size_t i;
168 for (i = 0; i < n; ++i) {
169 wchar_t wc = src[i];
170 if (wc == L'\0')
171 break;
172 dst[i] = wc;
173 }
174 // zero-pad the remainder.
175 for ( ; i < n; ++i)
176 dst[i] = L'\0';
177
178 return dst;
179 }
180
wcsnlen(const wchar_t * s,size_t maxlen)181 size_t wcsnlen(const wchar_t *s, size_t maxlen) {
182 size_t n;
183 for (n = 0; n < maxlen; ++n) {
184 if (s[n] == L'\0')
185 break;
186 }
187 return n;
188 }
189
wcspbrk(const wchar_t * s,const wchar_t * set)190 wchar_t *wcspbrk(const wchar_t *s, const wchar_t *set) {
191 size_t n = 0;
192 for (;;) {
193 wchar_t wc = s[n];
194 if (!wc)
195 return NULL;
196 if (_wc_indelim(wc, set))
197 return (wchar_t*)&s[n];
198 n++;
199 }
200 }
201
wcschr(const wchar_t * s,wchar_t c)202 wchar_t *wcschr(const wchar_t *s, wchar_t c) {
203 char dummy[1 - 2*(sizeof(wchar_t) != 4)];
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
wcstof(const wchar_t * nptr,wchar_t ** endptr)352 float wcstof(const wchar_t* nptr, wchar_t** endptr) {
353 #warning Not implemented
354 return 0;
355 }
356
wcstol(const wchar_t * nptr,wchar_t ** endptr,int base)357 long wcstol(const wchar_t* nptr, wchar_t** endptr, int base) {
358 #warning Not implemented
359 return 0;
360 }
361
wcstold(const wchar_t * nptr,wchar_t ** endptr)362 long double wcstold(const wchar_t* nptr, wchar_t** endptr) {
363 #warning Not implemented
364 return 0;
365 }
366
wcstoll(const wchar_t * nptr,wchar_t ** endptr,int base)367 long long wcstoll(const wchar_t* nptr, wchar_t** endptr, int base) {
368 #warning Not implemented
369 return 0;
370 }
371
wcstoull(const wchar_t * nptr,wchar_t ** endptr,int base)372 unsigned long long wcstoull(const wchar_t* nptr, wchar_t** endptr, int base) {
373 #warning Not implemented
374 return 0;
375 }
376