1 // -*- C++ -*-
2 //===-------------------- support/android/wchar_support.c ------------------===//
3 //
4 // The LLVM Compiler Infrastructure
5 //
6 // This file is dual licensed under the MIT and the University of Illinois Open
7 // Source Licenses. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10
11 #include <string.h>
12 #include <wchar.h>
13 #include <wctype.h>
14
15 // Returns 1 if 'wc' is in the 'delim' string, 0 otherwise.
_wc_indelim(wchar_t wc,const wchar_t * delim)16 static int _wc_indelim(wchar_t wc, const wchar_t* delim) {
17 while (*delim) {
18 if (wc == *delim)
19 return 1;
20 delim++;
21 }
22 return 0;
23 }
24
wcpcpy(wchar_t * to,const wchar_t * from)25 wchar_t *wcpcpy(wchar_t *to, const wchar_t *from) {
26 size_t n = 0;
27 for (;;) {
28 wchar_t wc = from[n];
29 to[n] = wc;
30 if (wc == L'\0')
31 break;
32 n++;
33 }
34 return to + n;
35 }
36
wcpncpy(wchar_t * dst,const wchar_t * src,size_t n)37 wchar_t *wcpncpy(wchar_t *dst, const wchar_t *src, size_t n) {
38 size_t i;
39 for (i = 0; i < n; ++i) {
40 wchar_t wc = src[i];
41 dst[i] = wc;
42 if (wc == L'\0')
43 break;
44 }
45 while (i < n) {
46 dst[i] = L'\0';
47 ++i;
48 }
49 return &dst[n-1];
50 }
51
wcscasecmp(const wchar_t * s1,const wchar_t * s2)52 int wcscasecmp(const wchar_t *s1, const wchar_t *s2) {
53 size_t n = 0;
54 for (;;) {
55 wchar_t wc1 = towlower(s1[n]);
56 wchar_t wc2 = towlower(s2[n]);
57 if (wc1 != wc2)
58 return (wc1 > wc2) ? +1 : -1;
59 if (wc1 == L'\0')
60 return 0;
61 n++;
62 }
63 }
64
wcscat(wchar_t * s1,const wchar_t * s2)65 wchar_t *wcscat(wchar_t *s1, const wchar_t *s2) {
66 size_t n = 0;
67 while (s1[n] != L'\0')
68 n++;
69
70 size_t i = 0;
71 for (;;) {
72 wchar_t wc = s2[i];
73 s1[n+i] = wc;
74 if (wc == L'\0')
75 break;
76 i++;
77 }
78 return s1;
79 }
80
wcslcat(wchar_t * dst,const wchar_t * src,size_t siz)81 size_t wcslcat(wchar_t *dst, const wchar_t *src, size_t siz) {
82 // Sanity check simplifies code below
83 if (siz == 0)
84 return 0;
85
86 // Skip dst characters.
87 size_t n = 0;
88 while (n < siz && dst[n] != L'\0')
89 n++;
90
91 if (n == siz)
92 return n + wcslen(src);
93
94 // Copy as much source characters as they fit into siz-1 bytes.
95 size_t i;
96 for (i = 0; n+i+1 < siz && src[i] != L'\0'; ++i)
97 dst[n+i] = src[i];
98
99 // Always zero terminate destination
100 dst[n+i] = L'\0';
101
102 // Skip remaining source characters
103 while (src[i] != L'\0')
104 i++;
105
106 return n+i;
107 }
108
wcslcpy(wchar_t * dst,const wchar_t * src,size_t siz)109 size_t wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz) {
110 size_t i;
111
112 // Copy all non-zero bytes that fit into siz-1 destination bytes
113 for (i = 0; i + 1 < siz && src[i] != L'\0'; ++i)
114 dst[i] = src[i];
115
116 // Always zero-terminate destination buffer
117 dst[i] = L'\0';
118
119 // Skip other source characters.
120 while (src[i] != L'\0')
121 ++i;
122
123 return i;
124 }
125
wcslen(const wchar_t * s)126 size_t wcslen(const wchar_t *s) {
127 size_t n = 0;
128 for (;;) {
129 wchar_t wc = s[n];
130 if (wc == L'\0')
131 return n;
132 n++;
133 }
134 }
135
wcsncasecmp(const wchar_t * s1,const wchar_t * s2,size_t n)136 int wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
137 size_t i;
138 for (i = 0; i < n; ++i) {
139 wchar_t wc1 = towlower(s1[i]);
140 wchar_t wc2 = towlower(s2[i]);
141 if (wc1 != wc2)
142 return (wc1 > wc2) ? +1 : -1;
143 }
144 return 0;
145 }
146
wcsncat(wchar_t * s1,const wchar_t * s2,size_t n)147 wchar_t *wcsncat(wchar_t *s1, const wchar_t *s2, size_t n) {
148 size_t start = 0;
149 while (s1[start] != L'\0')
150 start++;
151
152 // Append s2.
153 size_t i;
154 for (i = 0; i < n; ++i) {
155 wchar_t wc = s2[i];
156 s1[start + i] = wc;
157 if (wc == L'\0')
158 break;
159 }
160 return (wchar_t*)s1;
161 }
162
wcsncmp(const wchar_t * s1,const wchar_t * s2,size_t n)163 int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
164 size_t i;
165 for (i = 0; i < n; ++i) {
166 wchar_t wc = s1[i];
167 if (wc != s2[i])
168 return (wc > s2[i]) ? +1 : -1;
169 if (wc == L'\0')
170 break;
171 }
172 return 0;
173 }
174
wcsncpy(wchar_t * dst,const wchar_t * src,size_t n)175 wchar_t *wcsncpy(wchar_t *dst, const wchar_t *src, size_t n) {
176 // Copy initial characters.
177 size_t i;
178 for (i = 0; i < n; ++i) {
179 wchar_t wc = src[i];
180 if (wc == L'\0')
181 break;
182 dst[i] = wc;
183 }
184 // zero-pad the remainder.
185 for ( ; i < n; ++i)
186 dst[i] = L'\0';
187
188 return dst;
189 }
190
wcsnlen(const wchar_t * s,size_t maxlen)191 size_t wcsnlen(const wchar_t *s, size_t maxlen) {
192 size_t n;
193 for (n = 0; n < maxlen; ++n) {
194 if (s[n] == L'\0')
195 break;
196 }
197 return n;
198 }
199
wcspbrk(const wchar_t * s,const wchar_t * set)200 wchar_t *wcspbrk(const wchar_t *s, const wchar_t *set) {
201 size_t n = 0;
202 for (;;) {
203 wchar_t wc = s[n];
204 if (!wc)
205 return NULL;
206 if (_wc_indelim(wc, set))
207 return (wchar_t*)&s[n];
208 n++;
209 }
210 }
211
wcsrchr(const wchar_t * s,wchar_t c)212 wchar_t *wcsrchr(const wchar_t *s, wchar_t c) {
213 size_t n = 0;
214 wchar_t* last = NULL;
215 for (;;) {
216 wchar_t wc = s[n];
217 if (wc == c)
218 last = (wchar_t*)s + n;
219 if (wc == L'\0')
220 break;
221 n++;
222 }
223 return last;
224 }
225
wcsspn(const wchar_t * s,const wchar_t * set)226 size_t wcsspn(const wchar_t *s, const wchar_t *set) {
227 size_t n = 0;
228 for (;;) {
229 wchar_t wc = s[n];
230 if (wc == L'\0')
231 break;
232 if (!_wc_indelim(wc, set))
233 break;
234 ++n;
235 }
236 return n;
237 }
238
wcsstr(const wchar_t * s,const wchar_t * find)239 wchar_t *wcsstr(const wchar_t *s, const wchar_t *find) {
240 wchar_t find_c;
241
242 // Always find the empty string
243 find_c = *find++;
244 if (!find_c)
245 return (wchar_t*)s;
246
247 size_t find_len = wcslen(find);
248
249 for (;;) {
250 wchar_t* p = wcschr(s, find_c);
251 if (p == NULL)
252 return NULL;
253
254 if (!wmemcmp(p, find, find_len))
255 return p;
256
257 s = p + 1;
258 }
259 return NULL;
260 }
261
wcstok(wchar_t * s,const wchar_t * delim,wchar_t ** last)262 wchar_t *wcstok(wchar_t *s, const wchar_t *delim, wchar_t **last) {
263 if (s == NULL) {
264 s = *last;
265 if (s == NULL)
266 return NULL;
267 }
268
269 // Skip leading delimiters first.
270 size_t i = 0;
271 wchar_t wc;
272 for (;;) {
273 wc = s[i];
274 if (wc && _wc_indelim(wc, delim)) {
275 i++;
276 continue;
277 }
278 break;
279 }
280
281 if (!wc) {
282 // Nothing left.
283 *last = NULL;
284 return NULL;
285 }
286
287 size_t tok_start = i;
288
289 // Skip non delimiters now.
290 for (;;) {
291 wc = s[i];
292 if (wc && !_wc_indelim(wc, delim)) {
293 i++;
294 continue;
295 }
296 break;
297 }
298
299 if (!wc) {
300 *last = NULL;
301 } else {
302 s[i] = L'\0';
303 *last = &s[i+1];
304 }
305 return &s[tok_start];
306 }
307
wcswidth(const wchar_t * str,size_t n)308 int wcswidth(const wchar_t *str, size_t n) {
309 int len = 0;
310 size_t i;
311 for (i = 0; i < n; ++i) {
312 wchar_t wc = str[i];
313 if (wc == L'\0')
314 break;
315 int l = wcwidth(wc);
316 if (l < 0)
317 return -1;
318 len += l;
319 }
320 return len;
321 }
322
323 // TODO(digit): Handle real collations.
wcsxfrm(wchar_t * dst,const wchar_t * src,size_t len)324 size_t wcsxfrm(wchar_t *dst, const wchar_t *src, size_t len) {
325 // Handle trivial case first.
326 if (src[0] == L'\0') {
327 if (len != 0)
328 dst[0] = L'\0';
329 return 0;
330 }
331
332 size_t slen = wcslen(src);
333 if (len > 0) {
334 if (slen < len)
335 wcscpy(dst, src);
336 else {
337 wcsncpy(dst, src, len-1);
338 dst[len - 1] = L'\0';
339 }
340 }
341 return slen;
342 }
343
wmemchr(const wchar_t * s,wchar_t c,size_t n)344 wchar_t * wmemchr(const wchar_t *s, wchar_t c, size_t n) {
345 size_t i;
346 for (i = 0; i < n; ++i) {
347 if (s[i] == c)
348 return (wchar_t*)&s[i];
349 }
350 return NULL;
351 }
352
wmemcmp(const wchar_t * s1,const wchar_t * s2,size_t n)353 int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
354 size_t i;
355 for (i = 0; i < n; ++i) {
356 if (s1[i] == s2[i])
357 continue;
358 if (s1[i] > s2[i])
359 return 1;
360 else
361 return -1;
362 }
363 return 0;
364 }
365
wmemcpy(wchar_t * d,const wchar_t * s,size_t n)366 wchar_t * wmemcpy(wchar_t *d, const wchar_t *s, size_t n) {
367 return (wchar_t *)memcpy((char*)d,
368 (const char*)s,
369 n * sizeof(wchar_t));
370 }
371
wmemmove(wchar_t * d,const wchar_t * s,size_t n)372 wchar_t* wmemmove(wchar_t* d, const wchar_t* s, size_t n) {
373 return (wchar_t* )memmove((char*)d,
374 (const char*)s,
375 n * sizeof(wchar_t));
376 }
377
wmemset(wchar_t * s,wchar_t c,size_t n)378 wchar_t* wmemset(wchar_t* s, wchar_t c, size_t n) {
379 size_t i;
380 for (i = 0; i < n; ++i)
381 s[i] = c;
382 return s;
383 }
384
wcstof(const wchar_t * nptr,wchar_t ** endptr)385 float wcstof(const wchar_t* nptr, wchar_t** endptr) {
386 #warning Not implemented
387 return 0;
388 }
389
wcstol(const wchar_t * nptr,wchar_t ** endptr,int base)390 long wcstol(const wchar_t* nptr, wchar_t** endptr, int base) {
391 #warning Not implemented
392 return 0;
393 }
394
wcstold(const wchar_t * nptr,wchar_t ** endptr)395 long double wcstold(const wchar_t* nptr, wchar_t** endptr) {
396 #warning Not implemented
397 return 0;
398 }
399
wcstoll(const wchar_t * nptr,wchar_t ** endptr,int base)400 long long wcstoll(const wchar_t* nptr, wchar_t** endptr, int base) {
401 #warning Not implemented
402 return 0;
403 }
404
wcstoull(const wchar_t * nptr,wchar_t ** endptr,int base)405 unsigned long long wcstoull(const wchar_t* nptr, wchar_t** endptr, int base) {
406 #warning Not implemented
407 return 0;
408 }
409
wcsnrtombs(char * dst,const wchar_t ** src,size_t nwc,size_t len,mbstate_t * ps)410 size_t wcsnrtombs(char *dst,
411 const wchar_t **src,
412 size_t nwc, size_t len,
413 mbstate_t *ps) {
414 #warning Not implemented
415 return 0;
416 }
417
mbsnrtowcs(wchar_t * dst,const char ** src,size_t nmc,size_t len,mbstate_t * ps)418 size_t mbsnrtowcs(wchar_t *dst,
419 const char **src, size_t nmc,
420 size_t len, mbstate_t *ps) {
421 #warning Not implemented
422 return 0;
423 }
424