1 krisbash 1.1
2 #include "strings.h"
3
4 /* Strlcat and Strlcpy */
5 #define DEST char
6 #define SRC char
7 #define STRLCAT Strlcat
8 #define STRLCPY Strlcpy
9 #include "strlcat.h"
10 #include "strlcpy.h"
11 #undef STRLCAT
12 #undef STRLCPY
13 #undef DEST
14 #undef SRC
15
16 /* Wcslcat and Wcslcpy */
17 #define DEST wchar_t
18 #define SRC wchar_t
19 #define STRLCAT Wcslcat
20 #define STRLCPY Wcslcpy
21 #include "strlcat.h"
22 krisbash 1.1 #include "strlcpy.h"
23 #undef STRLCAT
24 #undef STRLCPY
25 #undef DEST
26 #undef SRC
27
28 /* StrWcslcat and StrWcslcpy */
29 #define DEST char
30 #define SRC wchar_t
31 #define STRLCPY StrWcslcpy
32 #include "strlcpy.h"
33 #undef STRLCPY
34 #undef DEST
35 #undef SRC
36
37 /* WcsStrlcat and WcsStrlcpy */
38 #define DEST wchar_t
39 #define SRC char
40 #define STRLCPY WcsStrlcpy
41 #include "strlcpy.h"
42 #undef STRLCPY
43 krisbash 1.1 #undef DEST
44 #undef SRC
45
46 /* TcsStrlcat and TcsStrlcpy */
47 #define DEST TChar
48 #define SRC char
49 #define STRLCAT TcsStrlcat
50 #define STRLCPY TcsStrlcpy
51 #include "strlcat.h"
52 #include "strlcpy.h"
53 #undef STRLCAT
54 #undef STRLCPY
55 #undef DEST
56 #undef SRC
57
58 // OACR just doesn't get that the length of *result will be in *size
59 // disabling this warning
60 #ifdef _MSC_VER
61 #pragma prefast(push)
62 #pragma prefast (disable: 28196)
63 #endif
64 krisbash 1.1
65 _Post_satisfies_(*size == _String_length_(*result))
66 void TcsFromUInt64(_Pre_writable_size_(64) PAL_Char buf[64], PAL_Uint64 value, _Outptr_result_z_ const PAL_Char **result, _Out_opt_ size_t* size)
67 {
68 PAL_Char* p;
69
70 p = &buf[63];
71 *p = PAL_T('\0');
72
73 do
74 {
75 *--p = PAL_T('0') + value % 10;
76 }
77 while (value /= 10);
78
79 *result = p;
80
81 if(size)
82 {
83 *size = (PAL_Sint32)(&buf[63] - p);
84 }
85 krisbash 1.1 }
86
87 #ifdef _MSC_VER
88 #pragma prefast(pop)
89 #endif
90
91 #if !defined(CONFIG_FAVORSIZE)
92
93 #if defined(_MSC_VER)
94 #pragma warning( push )
95 #pragma warning( disable : 4125 )
96 #endif
97
98 // The following defines string literals for the numbers 0 through 63. The
99 // first character is the length of the string. The subsequent characters
100 // are the string literal iteslf.
101 static const char* _numberStrings[] =
102 {
103 "\0010",
104 "\0011",
105 "\0012",
106 krisbash 1.1 "\0013",
107 "\0014",
108 "\0015",
109 "\0016",
110 "\0017",
111 "\0018",
112 "\0019",
113 "\00210",
114 "\00211",
115 "\00212",
116 "\00213",
117 "\00214",
118 "\00215",
119 "\00216",
120 "\00217",
121 "\00218",
122 "\00219",
123 "\00220",
124 "\00221",
125 "\00222",
126 "\00223",
127 krisbash 1.1 "\00224",
128 "\00225",
129 "\00226",
130 "\00227",
131 "\00228",
132 "\00229",
133 "\00230",
134 "\00231",
135 "\00232",
136 "\00233",
137 "\00234",
138 "\00235",
139 "\00236",
140 "\00237",
141 "\00238",
142 "\00239",
143 "\00240",
144 "\00241",
145 "\00242",
146 "\00243",
147 "\00244",
148 krisbash 1.1 "\00245",
149 "\00246",
150 "\00247",
151 "\00248",
152 "\00249",
153 "\00250",
154 "\00251",
155 "\00252",
156 "\00253",
157 "\00254",
158 "\00255",
159 "\00256",
160 "\00257",
161 "\00258",
162 "\00259",
163 "\00260",
164 "\00261",
165 "\00262",
166 "\00263",
167 };
168 #if defined(_MSC_VER)
169 krisbash 1.1 #pragma warning( pop )
170 #endif
171
172 #endif /* !defined(CONFIG_FAVORSIZE) */
173
174 #ifdef _MSC_VER
175 #pragma prefast(push)
176 #pragma prefast (disable: 28196)
177 #endif
178
179 _Post_satisfies_(*size == _String_length_(*result))
180 void Uint64ToStr(_Pre_writable_size_(21) char buf[21], PAL_Uint64 value, _Outptr_result_z_ const char **result, _Out_opt_ size_t* size)
181 {
182 char* p;
183
184 #if !defined(CONFIG_FAVORSIZE)
185
186 if (value < 64)
187 {
188 if(size)
189 {
190 krisbash 1.1 *size = _numberStrings[value][0];
191 }
192 *result = &_numberStrings[value][1];
193 }
194
195 #endif /* !defined(CONFIG_FAVORSIZE)*/
196
197 p = &buf[20];
198 *p = '\0';
199
200 do
201 {
202 *--p = '0' + value % 10;
203 }
204 while (value /= 10);
205
206 if(size)
207 {
208 *size = &buf[20] - p;
209 }
210
211 krisbash 1.1 *result = p;
212 }
213
214 #ifdef _MSC_VER
215 #pragma prefast(pop)
216 #endif
217
218
219 _Use_decl_annotations_
220 const char* Uint32ToStr(char buf[11], PAL_Uint32 x, size_t* size)
221 {
222 char* p;
223
224 #if !defined(CONFIG_FAVORSIZE)
225
226 if (x < 64)
227 {
228 *size = _numberStrings[x][0];
229 return &_numberStrings[x][1];
230 }
231
232 krisbash 1.1 #endif /* !defined(CONFIG_FAVORSIZE)*/
233
234 p = &buf[10];
235 *p = '\0';
236
237 do
238 {
239 *--p = '0' + x % 10;
240 }
241 while (x /= 10);
242
243 *size = &buf[10] - p;
244 return p;
245 }
246
247 #if defined(CONFIG_ENABLE_WCHAR)
248 _Use_decl_annotations_
249 const TChar* Uint32ToZStr(TChar buf[11], PAL_Uint32 x, size_t* size)
250 {
251 TChar* p = &buf[10];
252 *p = '\0';
253 krisbash 1.1
254 do
255 {
256 *--p = '0' + x % 10;
257 }
258 while (x /= 10);
259
260 *size = &buf[10] - p;
261 return p;
262 }
263 #endif
264
265 #ifdef _MSC_VER
266 #pragma prefast(push)
267 #pragma prefast (disable: 28196)
268 #endif
269
270 #if defined(CONFIG_ENABLE_WCHAR)
271
272 _Post_satisfies_(*size == _String_length_(*result))
273 void Uint64ToZStr(_Pre_writable_size_(21) TChar buf[21], PAL_Uint64 value, _Outptr_result_z_ const TChar **result, _Out_opt_ size_t* size)
274 krisbash 1.1 {
275 TChar* p = &buf[20];
276 *p = PAL_T('\0');
277
278 do
279 {
280 *--p = PAL_T('0') + value % 10;
281 }
282 while (value /= 10);
283
284 if(size)
285 {
286 *size = &buf[20] - p;
287 }
288 *result = p;
289 }
290 #endif
291
292 _Post_satisfies_(*size == _String_length_(*result))
293 void Sint64ToZStr(_Pre_writable_size_(64) TChar buf[64], PAL_Sint64 value, _Outptr_result_z_ const TChar **result, _Out_opt_ size_t* size)
294 {
295 krisbash 1.1 TChar* p;
296
297 PAL_Boolean isNegative = PAL_FALSE;
298 if(value < 0)
299 {
300 isNegative = 1;
301 value = -value;
302 }
303
304 p = &buf[63];
305 *p = PAL_T('\0');
306
307 do
308 {
309 *--p = PAL_T('0') + value % 10;
310 }
311 while (value /= 10);
312
313 if(isNegative)
314 {
315 *--p = PAL_T('-');
316 krisbash 1.1 }
317
318 if(size)
319 {
320 *size = (PAL_Sint32)(&buf[63] - p);
321 }
322
323 *result = p;
324 }
325
326 #if !defined(CONFIG_HAVE_WCSCASECMP)
327
328 int wcsncasecmp(const wchar_t* s1, const wchar_t* s2, size_t n)
329 {
330 wchar_t s1Char, s2Char;
331 const wchar_t *end = s1 + n - 1;
332 if(!s1 || !s2)
333 return -1;
334
335 while(s1 <= end)
336 {
337 krisbash 1.1 s1Char = PAL_tolower(*s1);
338 s2Char = PAL_tolower(*s2);
339 if(s1Char != s2Char)
340 return (int)(s1Char - s2Char);
341 s1++;
342 s2++;
343 }
344 return 0;
345 }
346
347 int wcscasecmp(const wchar_t* s1, const wchar_t* s2)
348 {
349 wchar_t s1Char, s2Char;
350 if(!s1 || !s2)
351 return -1;
352
353 while(*s1 && *s2)
354 {
355 s1Char = PAL_tolower(*s1);
356 s2Char = PAL_tolower(*s2);
357 if(s1Char != s2Char)
358 krisbash 1.1 return (int)(s1Char - s2Char);
359 s1++;
360 s2++;
361 }
362
363 return (int)((unsigned int)*s1 - (unsigned int)*s2);
364 }
365 #endif
366
367 #if !defined(CONFIG_HAVE_WCSTOLL)
368 #include <errno.h>
369
370 PAL_INLINE int __WcsToll_GetDigitValue(wchar_t c, int b)
371 {
372 int result = -1;
373 if(c >= L'0' && c <= L'9')
374 {
375 result = (int)(c - L'0');
376 }
377 else if(c >= L'A' && c <= L'Z')
378 {
379 krisbash 1.1 result = 10 + (int)(c - L'A');
380 }
381 else if(c >= L'a' && c <= L'z')
382 {
383 result = 10 + (int)(c - L'a');
384 }
385
386 if((result != -1) && (result >= b))
387 {
388 result = -1;
389 }
390
391 return result;
392 }
393
394 long long wcstoll(const wchar_t* s, wchar_t** e, int b)
395 {
396 PAL_Boolean isNegative = PAL_FALSE;
397 double value = 0;
398 int curDigit = 0;
399
400 krisbash 1.1 if(!s)
401 goto Error_EINVAL;
402
403 /* rejecting invalid base */
404 if((b < 0) || (b == 1) || (b > 36))
405 goto Error_EINVAL;
406
407 /* moving past any spaces */
408 while(*s && iswspace(*s))
409 s++;
410
411 /* Making sure string doesnt end here */
412 if(!(*s))
413 goto Error_EINVAL;
414
415 /* check if this is -ve number */
416 if(*s == L'-')
417 {
418 isNegative = PAL_TRUE;
419 s++;
420 }
421 krisbash 1.1
422 /* check if this is +ve number */
423 if(*s == L'+')
424 s++;
425
426 /* check if this is octal/hex number */
427 if(*s == L'0')
428 {
429 s++;
430 if((*s == L'x') || (*s == L'X'))
431 {
432 s++;
433
434 if((b == 0) || (b == 16))
435 b = 16;
436 else
437 goto Error_EINVAL;
438 }
439 else
440 {
441 if((b == 0) || (b == 8))
442 krisbash 1.1 b = 8;
443 else
444 goto Error_EINVAL;
445 }
446 }
447
448 /* if base is 0 still; we set it to 10 */
449 if(b == 0)
450 b = 10;
451
452 if(__WcsToll_GetDigitValue(*s, b) < 0)
453 goto Error_EINVAL;
454
455 while(*s)
456 {
457 curDigit = __WcsToll_GetDigitValue(*s, b);
458 if(curDigit < 0)
459 {
460 goto End;
461 }
462
463 krisbash 1.1 value = (value * b) + curDigit;
464
465 if(value > PAL_SINT64_MAX)
466 {
467 goto Error_ERANGE;
468 }
469
470 if(isNegative && ((-1) * (value)) < PAL_SINT64_MIN)
471 {
472 goto Error_ERANGE;
473 }
474
475 s++;
476 }
477
478 goto End;
479
480 Error_EINVAL:
481 errno = EINVAL;
482 goto End;
483 Error_ERANGE:
484 krisbash 1.1 errno = ERANGE;
485 goto End;
486 End:
487 if(e)
488 {
489 *e = (wchar_t *)s;
490 }
491 return (long long)value;
492 }
493 #endif
494
495 #if defined(CONFIG_ENABLE_WCHAR)
496
497 /*----------------------------------------------------------------------------*/
498 /**
499 Convert a UTF-32 string to a UTF-8 string
500
501 Anticipated usage of this is that it will be a 2-pass use where first pass computes the length
502 and second pass just does the conversion; the firstNonAscii is variable is kind of used as a state variable between the two passes
503 to optimize conversion of single byte strings; but it is optional if you do not want to use it
504
505 krisbash 1.1 \param [in] utf32 the UTF-32 string
506 \param [out] _size the number of words in the string
507 \param [inout] firstNonAscii the position in utf8 of the first non-ASCII character;
508 \param [out] utf8 the UTF-8 string; NULL for the first (evaluation) pass
509 \param [in] utf8Size size of the utf8 buffer
510 \returns the size of the converted string
511 */
512
513 #if defined(_MSC_VER)
514
515 int ConvertWideCharToUtf8Windows(
516 const Utf32Char* utf32,
517 size_t utf32Size,
518 size_t* firstNonAscii,
519 Utf8Char* utf8,
520 int utf8Size)
521 {
522 int lastError = 0;
523 PAL_UNUSED(firstNonAscii);
524
525 if(utf8 == NULL)
526 krisbash 1.1 utf8Size = WideCharToMultiByte(CP_UTF8, 0, utf32, utf32Size, NULL, 0, NULL, NULL);
527 else
528 utf8Size = WideCharToMultiByte(CP_UTF8, 0, utf32, utf32Size, (LPSTR)utf8, utf8Size, NULL, NULL);
529
530 return utf8Size;
531 }
532
533 #else
534
535
536 int ConvertWideCharToUtf8NonWindows(
537 const Utf32Char* utf32,
538 size_t utf32Size,
539 size_t* firstNonAscii,
540 Utf8Char* utf8,
541 int utf8Size)
542 {
543 Utf32Char c;
544 Utf8Char* p = utf8;
545 const Utf8Char INVALID_CHAR = '?';
546 const Utf32Char CODE_POINT_MAXIMUM_VALUE = 0x10FFFF;
547 krisbash 1.1 // turn off the ASCII-only code for the first pass
548 size_t firstNonAsciiChar = utf8 == NULL ? 0 : (firstNonAscii ? *firstNonAscii : 0);
549 size_t pos = 0;
550
551 PAL_UNUSED(utf8Size);
552
553 // do the ASCII-only conversion for the beginning characters on the second pass
554 for (pos = 0; pos < firstNonAsciiChar; pos++)
555 {
556 *p++ = (Utf8Char)*(utf32 + pos);
557 }
558
559 // If this is the first pass or firstNonAsciiChar < utf32Size, handle the
560 // rest of the string, which includes multi-byte characters. If the
561 // string was found to be pure ASCII on the first pass, this is never
562 // executed on the second pass
563 if(firstNonAscii)
564 *firstNonAscii = utf32Size;
565 for (pos = firstNonAsciiChar; pos < utf32Size; pos++)
566 {
567 c = *(utf32 + pos);
568 krisbash 1.1 if (c < 0x0080)
569 { // an ASCII character
570 if (utf8 != NULL)
571 *p = (Utf8Char)c;
572 p++;
573 }
574 else
575 {
576 if (firstNonAscii)
577 {
578 if(pos < *firstNonAscii)
579 *firstNonAscii = pos;
580 }
581
582 if (c < 0x0800)
583 { // a 2-byte character
584 if (utf8 != NULL)
585 {
586 *p = (Utf8Char)((c >> 6) | 0x00C0);
587 *(p + 1) = (Utf8Char)((c & 0x003F) | 0x0080);
588 }
589 krisbash 1.1 p += 2;
590 }
591 else if (c <= 0x00010000)
592 { // a 3-byte character
593 if (utf8 != NULL)
594 {
595 *p = (Utf8Char)(((c >> 12) & 0x0000000F) | 0x000000E0);
596 *(p + 1) = (Utf8Char)(((c >> 6) & 0x0000003F) | 0x00000080);
597 *(p + 2) = (Utf8Char)((c & 0x0000003F) | 0x00000080);
598 }
599 p += 3;
600 }
601 else if(c <= CODE_POINT_MAXIMUM_VALUE)
602 { // a 4-byte character
603 if (utf8 != NULL)
604 {
605 *p = (Utf8Char)(((c >> 18) & 0x00000007) | 0x000000F0);
606 *(p + 1) = (Utf8Char)(((c >> 12) & 0x0000003F) | 0x00000080);
607 *(p + 2) = (Utf8Char)(((c >> 6) & 0x0000003F) | 0x00000080);
608 *(p + 3) = (Utf8Char)((c & 0x0000003F) | 0x00000080);
609 }
610 krisbash 1.1 p += 4;
611 }
612 else
613 {
614 if (utf8 != NULL)
615 *p = INVALID_CHAR; /* In this case, if the conversion can not find the character, it will put an invalid character in the result */
616 p++;
617 }
618 }
619 }
620
621 return (int)(p - utf8);
622 }
623
624 #endif
625
626 int ConvertWideCharToMultiByte(
627 const Utf32Char* utf32,
628 size_t utf32Size,
629 size_t* firstNonAscii,
630 Utf8Char* utf8,
631 krisbash 1.1 int utf8Size)
632 {
633 #if defined(_MSC_VER)
634 return ConvertWideCharToUtf8Windows(utf32, utf32Size, firstNonAscii, utf8, utf8Size);
635 #else
636 return ConvertWideCharToUtf8NonWindows(utf32, utf32Size, firstNonAscii, utf8, utf8Size);
637 #endif
638 }
639 #endif
|