1 // SoftEther VPN Source Code - Developer Edition Master Branch
2 // Mayaqua Kernel
3
4
5 // Internat.c
6 // String conversion library for internationalization
7
8 #include "Internat.h"
9
10 #include "Mayaqua.h"
11 #include "Memory.h"
12 #include "Network.h"
13 #include "Object.h"
14 #include "Str.h"
15 #include "Tracking.h"
16 #include "Win32.h"
17
18 #include <stdlib.h>
19 #include <wchar.h>
20
21 #ifdef OS_UNIX
22 #include <iconv.h>
23 #endif
24
25 extern LOCK *token_lock;
26 static char charset[MAX_SIZE] = "EUCJP";
27 static LOCK *iconv_lock = NULL;
28 void *iconv_cache_wide_to_str = 0;
29 void *iconv_cache_str_to_wide = 0;
30
31 // Examine whether the string contains the specified character
UniInChar(wchar_t * string,wchar_t c)32 bool UniInChar(wchar_t *string, wchar_t c)
33 {
34 UINT i, len;
35 // Validate arguments
36 if (string == NULL)
37 {
38 return false;
39 }
40
41 len = UniStrLen(string);
42
43 for (i = 0;i < len;i++)
44 {
45 if (string[i] == c)
46 {
47 return true;
48 }
49 }
50
51 return false;
52 }
53
54 // Check whether the string is included
UniInStr(wchar_t * str,wchar_t * keyword)55 bool UniInStr(wchar_t *str, wchar_t *keyword)
56 {
57 return UniInStrEx(str, keyword, false);
58 }
UniInStrEx(wchar_t * str,wchar_t * keyword,bool case_sensitive)59 bool UniInStrEx(wchar_t *str, wchar_t *keyword, bool case_sensitive)
60 {
61 // Validate arguments
62 if (UniIsEmptyStr(str) || UniIsEmptyStr(keyword))
63 {
64 return false;
65 }
66
67 if (UniSearchStrEx(str, keyword, 0, case_sensitive) == INFINITE)
68 {
69 return false;
70 }
71
72 return true;
73 }
74
75 // Convert to binary data
UniStrToBin(wchar_t * str)76 BUF *UniStrToBin(wchar_t *str)
77 {
78 char *str_a = CopyUniToStr(str);
79 BUF *ret;
80
81 ret = StrToBin(str_a);
82
83 Free(str_a);
84
85 return ret;
86 }
87
88 // Check whether the character is safe
UniIsSafeChar(wchar_t c)89 bool UniIsSafeChar(wchar_t c)
90 {
91 UINT i, len;
92 wchar_t *check_str =
93 L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
94 L"abcdefghijklmnopqrstuvwxyz"
95 L"0123456789"
96 L" ()-_#%&.";
97
98 len = UniStrLen(check_str);
99 for (i = 0;i < len;i++)
100 {
101 if (c == check_str[i])
102 {
103 return true;
104 }
105 }
106 return false;
107 }
108
109 // Convert a string list to a token list
UniListToTokenList(LIST * o)110 UNI_TOKEN_LIST *UniListToTokenList(LIST *o)
111 {
112 UINT i;
113 UNI_TOKEN_LIST *t;
114 // Validate arguments
115 if (o == NULL)
116 {
117 return NULL;
118 }
119
120 t = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
121 t->NumTokens = LIST_NUM(o);
122 t->Token = ZeroMalloc(sizeof(wchar_t *) * t->NumTokens);
123 for (i = 0;i < LIST_NUM(o);i++)
124 {
125 t->Token[i] = UniCopyStr(LIST_DATA(o, i));
126 }
127
128 return t;
129 }
130
131 // Free the string list
UniFreeStrList(LIST * o)132 void UniFreeStrList(LIST *o)
133 {
134 UINT i;
135 // Validate arguments
136 if (o == NULL)
137 {
138 return;
139 }
140
141 for (i = 0;i < LIST_NUM(o);i++)
142 {
143 wchar_t *s = LIST_DATA(o, i);
144 Free(s);
145 }
146
147 ReleaseList(o);
148 }
149
150 // Normalize the line breaks
UniNormalizeCrlf(wchar_t * str)151 wchar_t *UniNormalizeCrlf(wchar_t *str)
152 {
153 wchar_t *ret;
154 UINT ret_size, i, len, wp;
155 // Validate arguments
156 if (str == NULL)
157 {
158 return NULL;
159 }
160
161 len = UniStrLen(str);
162 ret_size = sizeof(wchar_t) * (len + 32) * 2;
163 ret = Malloc(ret_size);
164
165 wp = 0;
166
167 for (i = 0;i < len;i++)
168 {
169 wchar_t c = str[i];
170
171 switch (c)
172 {
173 case L'\r':
174 if (str[i + 1] == L'\n')
175 {
176 i++;
177 }
178 ret[wp++] = L'\r';
179 ret[wp++] = L'\n';
180 break;
181
182 case L'\n':
183 ret[wp++] = L'\r';
184 ret[wp++] = L'\n';
185 break;
186
187 default:
188 ret[wp++] = c;
189 break;
190 }
191 }
192
193 ret[wp++] = 0;
194
195 return ret;
196 }
197
198 // Check whether str ends with the key
UniEndWith(wchar_t * str,wchar_t * key)199 bool UniEndWith(wchar_t *str, wchar_t *key)
200 {
201 UINT str_len;
202 UINT key_len;
203 // Validate arguments
204 if (str == NULL || key == NULL)
205 {
206 return false;
207 }
208
209 // Comparison
210 str_len = UniStrLen(str);
211 key_len = UniStrLen(key);
212 if (str_len < key_len)
213 {
214 return false;
215 }
216
217 if (UniStrCmpi(str + (str_len - key_len), key) == 0)
218 {
219 return true;
220 }
221 else
222 {
223 return false;
224 }
225 }
226
227 // Check whether str starts with the key
UniStartWith(wchar_t * str,wchar_t * key)228 bool UniStartWith(wchar_t *str, wchar_t *key)
229 {
230 UINT str_len;
231 UINT key_len;
232 wchar_t *tmp;
233 bool ret;
234 // Validate arguments
235 if (str == NULL || key == NULL)
236 {
237 return false;
238 }
239
240 // Comparison
241 str_len = UniStrLen(str);
242 key_len = UniStrLen(key);
243 if (str_len < key_len)
244 {
245 return false;
246 }
247 if (str_len == 0 || key_len == 0)
248 {
249 return false;
250 }
251 tmp = CopyUniStr(str);
252 tmp[key_len] = 0;
253
254 if (UniStrCmpi(tmp, key) == 0)
255 {
256 ret = true;
257 }
258 else
259 {
260 ret = false;
261 }
262
263 Free(tmp);
264
265 return ret;
266 }
267
268 // Convert the integer to a comma-separated string
UniToStr3(wchar_t * str,UINT size,UINT64 value)269 void UniToStr3(wchar_t *str, UINT size, UINT64 value)
270 {
271 char tmp[MAX_SIZE];
272 // Validate arguments
273 if (str == NULL)
274 {
275 return;
276 }
277
278 ToStr3(tmp, sizeof(tmp), value);
279
280 StrToUni(str, size, tmp);
281 }
282
283 // Format of the string (internal function)
InternalFormatArgs(wchar_t * fmt,va_list args,bool ansi_mode)284 wchar_t *InternalFormatArgs(wchar_t *fmt, va_list args, bool ansi_mode)
285 {
286 UINT i, len;
287 wchar_t *tmp;
288 UINT tmp_size;
289 LIST *o;
290 UINT mode = 0;
291 UINT wp;
292 UINT total_size;
293 wchar_t *ret;
294 // Validate arguments
295 if (fmt == NULL)
296 {
297 return NULL;
298 }
299
300 len = UniStrLen(fmt);
301 tmp_size = UniStrSize(fmt);
302 tmp = Malloc(tmp_size);
303
304 o = NewListFast(NULL);
305
306 mode = 0;
307
308 wp = 0;
309
310 for (i = 0;i < len;i++)
311 {
312 wchar_t c = fmt[i];
313
314 if (mode == 0)
315 {
316 // Normal character mode
317 switch (c)
318 {
319 case L'%':
320 // The start of the format specification
321 if (fmt[i + 1] == L'%')
322 {
323 // If the next character is also '%', output a '%' simply
324 i++;
325 tmp[wp++] = c;
326 }
327 else
328 {
329 // Shift the state if the next character is not a '%'
330 mode = 1;
331 tmp[wp++] = 0;
332 wp = 0;
333 Add(o, CopyUniStr(tmp));
334 tmp[wp++] = c;
335 }
336 break;
337 default:
338 // Ordinary character
339 tmp[wp++] = c;
340 break;
341 }
342 }
343 else
344 {
345 char *tag;
346 char dst[MAX_SIZE];
347 wchar_t *target_str;
348 wchar_t *padding_str;
349 bool left_padding;
350 UINT target_str_len;
351 UINT total_len;
352 wchar_t *output_str;
353 UINT padding;
354 // Formatting mode
355 switch (c)
356 {
357 case L'c':
358 case L'C':
359 case L'd':
360 case L'i':
361 case L'o':
362 case L'u':
363 case L'x':
364 case L'X':
365 // int type
366 tmp[wp++] = c;
367 tmp[wp++] = 0;
368 tag = CopyUniToStr(tmp);
369
370 #ifdef OS_WIN32
371 ReplaceStrEx(tag, 0, tag, "ll", "I64", false);
372 #else // OS_WIN32
373 ReplaceStrEx(tag, 0, tag, "I64", "ll", false);
374 #endif // OS_WIN32
375
376 if ((UniStrLen(tmp) >= 5 && tmp[UniStrLen(tmp) - 4] == L'I' &&
377 tmp[UniStrLen(tmp) - 3] == L'6' &&
378 tmp[UniStrLen(tmp) - 2] == L'4') ||
379 (
380 UniStrLen(tmp) >= 4 && tmp[UniStrLen(tmp) - 3] == L'l' &&
381 tmp[UniStrLen(tmp) - 2] == L'l'))
382 {
383 #ifdef OS_WIN32
384 _snprintf(dst, sizeof(dst), tag, va_arg(args, UINT64));
385 #else // OS_WIN32
386 snprintf(dst, sizeof(dst), tag, va_arg(args, UINT64));
387 #endif // OS_WIN32
388 }
389 else
390 {
391 #ifdef OS_WIN32
392 _snprintf(dst, sizeof(dst), tag, va_arg(args, int));
393 #else // OS_WIN32
394 snprintf(dst, sizeof(dst), tag, va_arg(args, int));
395 #endif // OS_WIN32
396 }
397
398 Free(tag);
399 Add(o, CopyStrToUni(dst));
400
401 wp = 0;
402 mode = 0;
403 break;
404 case L'e':
405 case L'E':
406 case L'f':
407 case L'g':
408 case L'G':
409 // Double type
410 tmp[wp++] = c;
411 tmp[wp++] = 0;
412 tag = CopyUniToStr(tmp);
413
414 #ifdef OS_WIN32
415 _snprintf(dst, sizeof(dst), tag, va_arg(args, double));
416 #else // OS_WIN32
417 snprintf(dst, sizeof(dst), tag, va_arg(args, double));
418 #endif // OS_WIN32
419
420 Free(tag);
421 Add(o, CopyStrToUni(dst));
422
423 wp = 0;
424 mode = 0;
425 break;
426 case L'n':
427 case L'p':
428 // Pointer type
429 tmp[wp++] = c;
430 tmp[wp++] = 0;
431 tag = ZeroMalloc(UniStrSize(tmp) + 32);
432 UniToStr(tag, 0, tmp);
433
434 #ifdef OS_WIN32
435 _snprintf(dst, sizeof(dst), tag, va_arg(args, void *));
436 #else // OS_WIN32
437 snprintf(dst, sizeof(dst), tag, va_arg(args, void *));
438 #endif // OS_WIN32
439
440 Free(tag);
441 Add(o, CopyStrToUni(dst));
442
443 wp = 0;
444 mode = 0;
445 break;
446 case L'r':
447 case L'R':
448 // IP address type
449 tmp[wp++] = c;
450 tmp[wp++] = 0;
451
452 Zero(dst, sizeof(dst));
453 IPToStr(dst, sizeof(dst), va_arg(args, void *));
454
455 Add(o, CopyStrToUni(dst));
456
457 wp = 0;
458 mode = 0;
459 break;
460
461 case L's':
462 case L'S':
463 // String type
464 tmp[wp++] = c;
465 tmp[wp++] = 0;
466
467 if (ansi_mode == false)
468 {
469 if (c == L'S')
470 {
471 c = L's';
472 }
473 else
474 {
475 c = L'S';
476 }
477 }
478
479 if (c == L's')
480 {
481 target_str = CopyStrToUni(va_arg(args, char *));
482 }
483 else
484 {
485 target_str = CopyUniStr(va_arg(args, wchar_t *));
486 }
487
488 if (target_str == NULL)
489 {
490 target_str = CopyUniStr(L"(null)");
491 }
492
493 padding = 0;
494 left_padding = false;
495 if (tmp[1] == L'-')
496 {
497 // Left aligned
498 if (UniStrLen(tmp) >= 3)
499 {
500 padding = UniToInt(&tmp[2]);
501 }
502 left_padding = true;
503 }
504 else
505 {
506 // Right aligned
507 if (UniStrLen(tmp) >= 2)
508 {
509 padding = UniToInt(&tmp[1]);
510 }
511 }
512
513 target_str_len = UniStrWidth(target_str);
514
515 if (padding > target_str_len)
516 {
517 UINT len = padding - target_str_len;
518 UINT i;
519 padding_str = ZeroMalloc(sizeof(wchar_t) * (len + 1));
520 for (i = 0;i < len;i++)
521 {
522 padding_str[i] = L' ';
523 }
524 }
525 else
526 {
527 padding_str = ZeroMalloc(sizeof(wchar_t));
528 }
529
530 total_len = sizeof(wchar_t) * (UniStrLen(padding_str) + UniStrLen(target_str) + 1);
531 output_str = ZeroMalloc(total_len);
532 output_str[0] = 0;
533
534 if (left_padding == false)
535 {
536 UniStrCat(output_str, total_len, padding_str);
537 }
538 UniStrCat(output_str, total_len, target_str);
539 if (left_padding)
540 {
541 UniStrCat(output_str, total_len, padding_str);
542 }
543
544 Add(o, output_str);
545
546 Free(target_str);
547 Free(padding_str);
548
549 wp = 0;
550 mode = 0;
551 break;
552 default:
553 // Normal string
554 tmp[wp++] = c;
555 break;
556 }
557 }
558 }
559 tmp[wp++] = 0;
560 wp = 0;
561
562 if (UniStrLen(tmp) >= 1)
563 {
564 Add(o, CopyUniStr(tmp));
565 }
566
567 total_size = sizeof(wchar_t);
568 for (i = 0;i < LIST_NUM(o);i++)
569 {
570 wchar_t *s = LIST_DATA(o, i);
571 total_size += UniStrLen(s) * sizeof(wchar_t);
572 }
573
574 ret = ZeroMalloc(total_size);
575 for (i = 0;i < LIST_NUM(o);i++)
576 {
577 wchar_t *s = LIST_DATA(o, i);
578 UniStrCat(ret, total_size, s);
579 Free(s);
580 }
581
582 ReleaseList(o);
583
584 Free(tmp);
585
586 return ret;
587 }
588
589 // Get the width of the string
UniStrWidth(wchar_t * str)590 UINT UniStrWidth(wchar_t *str)
591 {
592 UINT i, len, ret;
593 // Validate arguments
594 if (str == NULL)
595 {
596 return 0;
597 }
598
599 ret = 0;
600 len = UniStrLen(str);
601 for (i = 0;i < len;i++)
602 {
603 if (str[i] <= 255)
604 {
605 ret++;
606 }
607 else
608 {
609 ret += 2;
610 }
611 }
612 return ret;
613 }
614
615 // Convert string of 2 byte/character to wchar_t of 4 byte/character
Utf16ToWide(USHORT * str)616 wchar_t *Utf16ToWide(USHORT *str)
617 {
618 wchar_t *ret;
619 UINT len, i;
620 // Validate arguments
621 if (str == NULL)
622 {
623 return NULL;
624 }
625
626 len = 0;
627 while (true)
628 {
629 if (str[len] == 0)
630 {
631 break;
632 }
633 len++;
634 }
635
636 ret = Malloc((len + 1) * sizeof(wchar_t));
637 for (i = 0;i < len + 1;i++)
638 {
639 ret[i] = (wchar_t)str[i];
640 }
641
642 return ret;
643 }
644
645 // Convert wchar_t string of 4 byte/character to string of 2 byte/character
WideToUtf16(wchar_t * str)646 USHORT *WideToUtf16(wchar_t *str)
647 {
648 USHORT *ret;
649 UINT len;
650 UINT ret_size;
651 UINT i;
652 // Validate arguments
653 if (str == NULL)
654 {
655 return NULL;
656 }
657
658 len = UniStrLen(str);
659
660 ret_size = (len + 1) * 2;
661 ret = Malloc(ret_size);
662
663 for (i = 0;i < len + 1;i++)
664 {
665 ret[i] = (USHORT)str[i];
666 }
667
668 return ret;
669 }
670
671 // Initialization of the International Library
InitInternational()672 void InitInternational()
673 {
674 #ifdef OS_UNIX
675 void *d;
676
677 if (iconv_lock != NULL)
678 {
679 return;
680 }
681
682 GetCurrentCharSet(charset, sizeof(charset));
683 d = IconvWideToStrInternal();
684 if (d == (void *)-1)
685 {
686 #if defined (UNIX_MACOS) || defined (UNIX_LINUX_MUSL)
687 StrCpy(charset, sizeof(charset), "utf-8");
688 #else // defined (UNIX_MACOS) || defined (UNIX_LINUX_MUSL)
689 StrCpy(charset, sizeof(charset), "EUCJP");
690 #endif // defined (UNIX_MACOS) || defined (UNIX_LINUX_MUSL)
691 d = IconvWideToStrInternal();
692 if (d == (void *)-1)
693 {
694 StrCpy(charset, sizeof(charset), "US");
695 }
696 else
697 {
698 IconvFreeInternal(d);
699 }
700 }
701 else
702 {
703 IconvFreeInternal(d);
704 }
705
706 iconv_lock = NewLockMain();
707
708 iconv_cache_wide_to_str = IconvWideToStrInternal();
709 iconv_cache_str_to_wide = IconvStrToWideInternal();
710 #endif // OS_UNIX
711 }
712
713 // Release of the International Library
FreeInternational()714 void FreeInternational()
715 {
716 #ifdef OS_UNIX
717 #endif // OS_UNIX
718 }
719
720 #ifdef OS_UNIX
721
722 // Calculate the size when the string converted to Unicode
UnixCalcStrToUni(char * str)723 UINT UnixCalcStrToUni(char *str)
724 {
725 wchar_t *tmp;
726 UINT len, tmp_size;
727 UINT ret;
728 // Validate arguments
729 if (str == NULL)
730 {
731 return 0;
732 }
733
734 len = StrLen(str);
735 tmp_size = len * 5 + 10;
736 tmp = ZeroMalloc(tmp_size);
737 UnixStrToUni(tmp, tmp_size, str);
738 ret = UniStrLen(tmp);
739 Free(tmp);
740
741 return (ret + 1) * sizeof(wchar_t);
742 }
743
744 // Convert the strings to Unicode
UnixStrToUni(wchar_t * s,UINT size,char * str)745 UINT UnixStrToUni(wchar_t *s, UINT size, char *str)
746 {
747 void *d;
748 char *inbuf;
749 size_t insize;
750 char *outbuf;
751 char *outbuf_orig;
752 size_t outsize;
753 wchar_t *tmp;
754 // Validate arguments
755 if (s == NULL || str == NULL)
756 {
757 return 0;
758 }
759
760 d = IconvStrToWide();
761 if (d == (void *)-1)
762 {
763 UniStrCpy(s, size, L"");
764 return 0;
765 }
766
767 inbuf = (char *)str;
768 insize = StrLen(str) + 1;
769 outsize = insize * 5 + 10;
770 outbuf_orig = outbuf = ZeroMalloc(outsize);
771
772 if (iconv((iconv_t)d, (char **)&inbuf, (size_t *)&insize, (char **)&outbuf, (size_t *)&outsize) == (size_t)(-1))
773 {
774 Free(outbuf_orig);
775 UniStrCpy(s, size, L"");
776 IconvFree(d);
777 return 0;
778 }
779
780 tmp = Utf16ToWide((USHORT *)outbuf_orig);
781 Free(outbuf_orig);
782
783 UniStrCpy(s, size, tmp);
784 IconvFree(d);
785
786 Free(tmp);
787
788 return UniStrLen(s);
789 }
790
791 // Calculate the size when the Unicode converted to string
UnixCalcUniToStr(wchar_t * s)792 UINT UnixCalcUniToStr(wchar_t *s)
793 {
794 char *tmp;
795 UINT tmp_size;
796 UINT ret;
797 // Validate arguments
798 if (s == NULL)
799 {
800 return 0;
801 }
802
803 tmp_size = UniStrLen(s) * 5 + 10;
804 tmp = ZeroMalloc(tmp_size);
805 UnixUniToStr(tmp, tmp_size, s);
806
807 ret = StrSize(tmp);
808 Free(tmp);
809
810 return ret;
811 }
812
813 // Converted a Unicode string to a string
UnixUniToStr(char * str,UINT size,wchar_t * s)814 UINT UnixUniToStr(char *str, UINT size, wchar_t *s)
815 {
816 USHORT *tmp;
817 char *inbuf;
818 size_t insize;
819 char *outbuf;
820 char *outbuf_orig;
821 size_t outsize;
822 void *d;
823 // Validate arguments
824 if (str == NULL || s == NULL)
825 {
826 return 0;
827 }
828
829 // Convert a wchar_t string to sequence of 2-bytes first
830 tmp = WideToUtf16(s);
831 inbuf = (char *)tmp;
832 insize = (UniStrLen(s) + 1) * 2;
833 outsize = insize * 5 + 10;
834 outbuf_orig = outbuf = ZeroMalloc(outsize);
835
836 d = IconvWideToStr();
837 if (d == (void *)-1)
838 {
839 StrCpy(str, size, "");
840 Free(outbuf);
841 Free(tmp);
842 return 0;
843 }
844
845 if (iconv((iconv_t)d, (char **)&inbuf, (size_t *)&insize, (char **)&outbuf, (size_t *)&outsize) == (size_t)(-1))
846 {
847 Free(outbuf_orig);
848 IconvFree(d);
849 StrCpy(str, size, "");
850 Free(tmp);
851 return 0;
852 }
853
854 StrCpy(str, size, outbuf_orig);
855
856 Free(outbuf_orig);
857 IconvFree(d);
858 Free(tmp);
859
860 return StrLen(str);
861 }
862
863 // Converted the whcar_t to char
IconvWideToStrInternal()864 void *IconvWideToStrInternal()
865 {
866 return (void *)iconv_open(charset, IsBigEndian() ? "UTF-16BE" : "UTF-16LE");
867 }
868
869 // Convert the char to a wchar_t
IconvStrToWideInternal()870 void *IconvStrToWideInternal()
871 {
872 return (void *)iconv_open(IsBigEndian() ? "UTF-16BE" : "UTF-16LE", charset);
873 }
874
875 // Close the handle
IconvFreeInternal(void * d)876 int IconvFreeInternal(void *d)
877 {
878 iconv_close((iconv_t)d);
879 return 0;
880 }
881
IconvWideToStr()882 void *IconvWideToStr()
883 {
884 if (iconv_cache_wide_to_str == (void *)-1)
885 {
886 return (void *)-1;
887 }
888
889 Lock(iconv_lock);
890
891 return iconv_cache_wide_to_str;
892 }
893
IconvStrToWide()894 void *IconvStrToWide()
895 {
896 if (iconv_cache_str_to_wide == (void *)-1)
897 {
898 return (void *)-1;
899 }
900
901 Lock(iconv_lock);
902
903 return iconv_cache_str_to_wide;
904 }
905
IconvFree(void * d)906 int IconvFree(void *d)
907 {
908 Unlock(iconv_lock);
909
910 return 0;
911 }
912
913 // Get the character set that is currently used from the environment variable
GetCurrentCharSet(char * name,UINT size)914 void GetCurrentCharSet(char *name, UINT size)
915 {
916 char tmp[MAX_SIZE];
917 TOKEN_LIST *t;
918 // Validate arguments
919 if (name == NULL)
920 {
921 return;
922 }
923
924 Zero(tmp, sizeof(tmp));
925 if (GetEnv("LANG", tmp, sizeof(tmp)) == false || IsEmptyStr(tmp))
926 {
927 Zero(tmp, sizeof(tmp));
928 if (GetEnv("LOCATION", tmp, sizeof(tmp)) == false || IsEmptyStr(tmp))
929 {
930 StrCpy(tmp, sizeof(tmp), "C");
931 }
932 }
933
934 Trim(tmp);
935
936 t = ParseToken(tmp, ".");
937 if (t->NumTokens >= 2)
938 {
939 StrCpy(name, size, t->Token[1]);
940 }
941 else
942 {
943 if (t->NumTokens == 1)
944 {
945 StrCpy(name, size, t->Token[0]);
946 }
947 else
948 {
949 StrCpy(name, size, "eucJP");
950 }
951 }
952 FreeToken(t);
953
954 StrUpper(name);
955 }
956
957 #endif // OS_UNIX
958
959 // Check whether the specified string is a space
UniIsEmptyStr(wchar_t * str)960 bool UniIsEmptyStr(wchar_t *str)
961 {
962 return IsEmptyUniStr(str);
963 }
IsEmptyUniStr(wchar_t * str)964 bool IsEmptyUniStr(wchar_t *str)
965 {
966 bool ret;
967 wchar_t *s;
968 // Validate arguments
969 if (str == NULL)
970 {
971 return true;
972 }
973
974 s = UniCopyStr(str);
975
976 UniTrim(s);
977 if (UniStrLen(s) == 0)
978 {
979 ret = true;
980 }
981 else
982 {
983 ret = false;
984 }
985
986 Free(s);
987
988 return ret;
989 }
990
991 // Check whether the specified string is a number
UniIsNum(wchar_t * str)992 bool UniIsNum(wchar_t *str)
993 {
994 char tmp[MAX_SIZE];
995
996 // Validate arguments
997 if (str == NULL)
998 {
999 return false;
1000 }
1001
1002 UniToStrForSingleChars(tmp, sizeof(tmp), str);
1003
1004 return IsNum(tmp);
1005 }
1006
1007
1008 // Empty Unicode token list
UniNullToken()1009 UNI_TOKEN_LIST *UniNullToken()
1010 {
1011 UNI_TOKEN_LIST *ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
1012 ret->Token = ZeroMalloc(0);
1013
1014 return ret;
1015 }
1016
1017 // Convert the token list to Unicode token list
TokenListToUniTokenList(TOKEN_LIST * src)1018 UNI_TOKEN_LIST *TokenListToUniTokenList(TOKEN_LIST *src)
1019 {
1020 UNI_TOKEN_LIST *ret;
1021 UINT i;
1022 // Validate arguments
1023 if (src == NULL)
1024 {
1025 return NULL;
1026 }
1027
1028 ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
1029 ret->NumTokens = src->NumTokens;
1030 ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);
1031
1032 for (i = 0;i < ret->NumTokens;i++)
1033 {
1034 ret->Token[i] = CopyStrToUni(src->Token[i]);
1035 }
1036
1037 return ret;
1038 }
1039
1040 // Convert a Unicode token list to a token list
UniTokenListToTokenList(UNI_TOKEN_LIST * src)1041 TOKEN_LIST *UniTokenListToTokenList(UNI_TOKEN_LIST *src)
1042 {
1043 TOKEN_LIST *ret;
1044 UINT i;
1045 // Validate arguments
1046 if (src == NULL)
1047 {
1048 return NULL;
1049 }
1050
1051 ret = ZeroMalloc(sizeof(TOKEN_LIST));
1052 ret->NumTokens = src->NumTokens;
1053 ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
1054
1055 for (i = 0;i < ret->NumTokens;i++)
1056 {
1057 ret->Token[i] = CopyUniToStr(src->Token[i]);
1058 }
1059
1060 return ret;
1061 }
1062
1063 // Unicode string copy
UniCopyStr(wchar_t * str)1064 wchar_t *UniCopyStr(wchar_t *str)
1065 {
1066 return CopyUniStr(str);
1067 }
1068
1069 // Copy the token list
UniCopyToken(UNI_TOKEN_LIST * src)1070 UNI_TOKEN_LIST *UniCopyToken(UNI_TOKEN_LIST *src)
1071 {
1072 UNI_TOKEN_LIST *ret;
1073 UINT i;
1074 // Validate arguments
1075 if (src == NULL)
1076 {
1077 return NULL;
1078 }
1079
1080 ret = ZeroMalloc(sizeof(TOKEN_LIST));
1081 ret->NumTokens = src->NumTokens;
1082 ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);
1083 for (i = 0;i < ret->NumTokens;i++)
1084 {
1085 ret->Token[i] = CopyUniStr(src->Token[i]);
1086 }
1087
1088 return ret;
1089 }
1090
1091 // Parse the command line string
UniParseCmdLine(wchar_t * str)1092 UNI_TOKEN_LIST *UniParseCmdLine(wchar_t *str)
1093 {
1094 UNI_TOKEN_LIST *t;
1095 LIST *o;
1096 UINT i, len, wp, mode;
1097 wchar_t c;
1098 wchar_t *tmp;
1099 bool ignore_space = false;
1100 // Validate arguments
1101 if (str == NULL)
1102 {
1103 // There is no token
1104 return UniNullToken();
1105 }
1106
1107 o = NewListFast(NULL);
1108 tmp = Malloc(UniStrSize(str) + 32);
1109
1110 wp = 0;
1111 mode = 0;
1112
1113 len = UniStrLen(str);
1114 for (i = 0;i < len;i++)
1115 {
1116 c = str[i];
1117
1118 switch (mode)
1119 {
1120 case 0:
1121 // Mode to discover the next token
1122 if (c == L' ' || c == L'\t')
1123 {
1124 // Advance to the next character
1125 }
1126 else
1127 {
1128 // Start of the token
1129 if (c == L'\"')
1130 {
1131 if (str[i + 1] == L'\"')
1132 {
1133 // Regarded "" as a single " character
1134 tmp[wp++] = L'\"';
1135 i++;
1136 }
1137 else
1138 {
1139 // Single "(double-quote) enables the flag to ignore space
1140 ignore_space = true;
1141 }
1142 }
1143 else
1144 {
1145 tmp[wp++] = c;
1146 }
1147
1148 mode = 1;
1149 }
1150 break;
1151
1152 case 1:
1153 if (ignore_space == false && (c == L' ' || c == L'\t'))
1154 {
1155 // End of the token
1156 tmp[wp++] = 0;
1157 wp = 0;
1158
1159 Insert(o, UniCopyStr(tmp));
1160 mode = 0;
1161 }
1162 else
1163 {
1164 if (c == L'\"')
1165 {
1166 if (str[i + 1] == L'\"')
1167 {
1168 // Regarded "" as a single " character
1169 tmp[wp++] = L'\"';
1170 i++;
1171 }
1172 else
1173 {
1174 if (ignore_space == false)
1175 {
1176 // Single "(double-quote) enables the flag to ignore space
1177 ignore_space = true;
1178 }
1179 else
1180 {
1181 // Disable the flag to ignore space
1182 ignore_space = false;
1183 }
1184 }
1185 }
1186 else
1187 {
1188 tmp[wp++] = c;
1189 }
1190 }
1191 break;
1192 }
1193 }
1194
1195 if (wp != 0)
1196 {
1197 tmp[wp++] = 0;
1198 Insert(o, UniCopyStr(tmp));
1199 }
1200
1201 Free(tmp);
1202
1203 t = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
1204 t->NumTokens = LIST_NUM(o);
1205 t->Token = ZeroMalloc(sizeof(wchar_t *) * t->NumTokens);
1206 for (i = 0;i < t->NumTokens;i++)
1207 {
1208 t->Token[i] = LIST_DATA(o, i);
1209 }
1210
1211 ReleaseList(o);
1212
1213 return t;
1214 }
1215
1216 // Convert Unicode string to 64bit integer
UniToInt64(wchar_t * str)1217 UINT64 UniToInt64(wchar_t *str)
1218 {
1219 char tmp[MAX_SIZE];
1220 // Validate arguments
1221 if (str == NULL)
1222 {
1223 return 0;
1224 }
1225
1226 UniToStrForSingleChars(tmp, sizeof(tmp), str);
1227
1228 return ToInt64(tmp);
1229 }
1230
1231 // Convert the UTF string to a Unicode string
UtfToUni(wchar_t * unistr,UINT size,char * utfstr)1232 UINT UtfToUni(wchar_t *unistr, UINT size, char *utfstr)
1233 {
1234 wchar_t *tmp;
1235 // Validate arguments
1236 if (unistr == NULL || utfstr == NULL)
1237 {
1238 UniStrCpy(unistr, size, L"");
1239 return 0;
1240 }
1241
1242 tmp = CopyUtfToUni(utfstr);
1243
1244 UniStrCpy(unistr, size, tmp);
1245
1246 Free(tmp);
1247
1248 return UniStrLen(unistr);
1249 }
1250
1251 // Copy the UTF-8 string to a Unicode string
CopyUtfToUni(char * utfstr)1252 wchar_t *CopyUtfToUni(char *utfstr)
1253 {
1254 UINT size;
1255 wchar_t *ret;
1256 UINT utfstr_len;
1257 // Validate arguments
1258 if (utfstr == NULL)
1259 {
1260 return NULL;
1261 }
1262
1263 utfstr_len = StrLen(utfstr);
1264
1265 size = CalcUtf8ToUni((BYTE *)utfstr, utfstr_len);
1266 ret = ZeroMalloc(size + sizeof(wchar_t));
1267 Utf8ToUni(ret, size, (BYTE *)utfstr, utfstr_len);
1268
1269 return ret;
1270 }
1271
1272 // Copy a Unicode string to ANSI string
CopyUniToStr(wchar_t * unistr)1273 char *CopyUniToStr(wchar_t *unistr)
1274 {
1275 char *str;
1276 UINT str_size;
1277 // Validate arguments
1278 if (unistr == NULL)
1279 {
1280 return NULL;
1281 }
1282
1283 str_size = CalcUniToStr(unistr);
1284 if (str_size == 0)
1285 {
1286 return CopyStr("");
1287 }
1288 str = Malloc(str_size);
1289 UniToStr(str, str_size, unistr);
1290
1291 return str;
1292 }
1293
1294 // Copy an ANSI string to a Unicode string
CopyStrToUni(char * str)1295 wchar_t *CopyStrToUni(char *str)
1296 {
1297 wchar_t *uni;
1298 UINT uni_size;
1299 // Validate arguments
1300 if (str == NULL)
1301 {
1302 return NULL;
1303 }
1304
1305 uni_size = CalcStrToUni(str);
1306 if (uni_size == 0)
1307 {
1308 return CopyUniStr(L"");
1309 }
1310 uni = Malloc(uni_size);
1311 StrToUni(uni, uni_size, str);
1312
1313 return uni;
1314 }
1315
1316 // Copy a Unicode string to UTF-8 string
CopyUniToUtf(wchar_t * unistr)1317 char *CopyUniToUtf(wchar_t *unistr)
1318 {
1319 UINT size;
1320 char *ret;
1321 // Validate arguments
1322 if (unistr == NULL)
1323 {
1324 return NULL;
1325 }
1326
1327 size = CalcUniToUtf8(unistr);
1328 ret = ZeroMalloc(size + sizeof(char));
1329
1330 UniToUtf8((char *)ret, size, unistr);
1331
1332 return ret;
1333 }
1334
1335 // Copy the Unicode string
CopyUniStr(wchar_t * str)1336 wchar_t *CopyUniStr(wchar_t *str)
1337 {
1338 UINT len;
1339 wchar_t *dst;
1340 // Validate arguments
1341 if (str == NULL)
1342 {
1343 return NULL;
1344 }
1345
1346 len = UniStrLen(str);
1347 dst = Malloc((len + 1) * sizeof(wchar_t));
1348 UniStrCpy(dst, 0, str);
1349
1350 return dst;
1351 }
1352
1353 // Check whether the string is safe
IsSafeUniStr(wchar_t * str)1354 bool IsSafeUniStr(wchar_t *str)
1355 {
1356 UINT i, len;
1357 // Validate arguments
1358 if (str == NULL)
1359 {
1360 return false;
1361 }
1362
1363 len = UniStrLen(str);
1364 for (i = 0;i < len;i++)
1365 {
1366 if (IsSafeUniChar(str[i]) == false)
1367 {
1368 return false;
1369 }
1370 }
1371 if (str[0] == L' ')
1372 {
1373 return false;
1374 }
1375 if (len != 0)
1376 {
1377 if (str[len - 1] == L' ')
1378 {
1379 return false;
1380 }
1381 }
1382 return true;
1383 }
1384
1385 // Check whether the character is safe
IsSafeUniChar(wchar_t c)1386 bool IsSafeUniChar(wchar_t c)
1387 {
1388 UINT i, len;
1389 wchar_t *check_str =
1390 L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1391 L"abcdefghijklmnopqrstuvwxyz"
1392 L"0123456789"
1393 L" ()-_#%&.";
1394
1395 len = UniStrLen(check_str);
1396 for (i = 0;i < len;i++)
1397 {
1398 if (c == check_str[i])
1399 {
1400 return true;
1401 }
1402 }
1403 return false;
1404 }
1405
1406 // Convert Unicode string to ANSI string
UniToStr(char * str,UINT size,wchar_t * s)1407 UINT UniToStr(char *str, UINT size, wchar_t *s)
1408 {
1409 #ifdef OS_WIN32
1410 UINT ret;
1411 char *tmp;
1412 UINT new_size;
1413 // Validate arguments
1414 if (s == NULL || str == NULL)
1415 {
1416 return 0;
1417 }
1418
1419 new_size = CalcUniToStr(s);
1420 if (new_size == 0)
1421 {
1422 if (size >= 1)
1423 {
1424 StrCpy(str, 0, "");
1425 }
1426 return 0;
1427 }
1428 tmp = Malloc(new_size);
1429 tmp[0] = 0;
1430 wcstombs(tmp, s, new_size);
1431 tmp[new_size - 1] = 0;
1432 ret = StrCpy(str, size, tmp);
1433 Free(tmp);
1434
1435 return ret;
1436 #else // OS_WIN32
1437 return UnixUniToStr(str, size, s);
1438 #endif // OS_WIN32
1439 }
1440
1441 // Get the required number of bytes to convert Unicode string to the ANSI string
CalcUniToStr(wchar_t * s)1442 UINT CalcUniToStr(wchar_t *s)
1443 {
1444 #ifdef OS_WIN32
1445 UINT ret;
1446 // Validate arguments
1447 if (s == NULL)
1448 {
1449 return 0;
1450 }
1451
1452 ret = (UINT)wcstombs(NULL, s, UniStrLen(s));
1453 if (ret == (UINT)-1)
1454 {
1455 return 0;
1456 }
1457
1458 return ret + 1;
1459 #else // OS_WIN32
1460 return UnixCalcUniToStr(s);
1461 #endif // OS_WIN32
1462 }
1463
1464 // Converted an ANSI string to a Unicode string
StrToUni(wchar_t * s,UINT size,char * str)1465 UINT StrToUni(wchar_t *s, UINT size, char *str)
1466 {
1467 #ifdef OS_WIN32
1468 UINT ret;
1469 wchar_t *tmp;
1470 UINT new_size;
1471 // Validate arguments
1472 if (s == NULL || str == NULL)
1473 {
1474 return 0;
1475 }
1476
1477 new_size = CalcStrToUni(str);
1478 if (new_size == 0)
1479 {
1480 if (size >= 2)
1481 {
1482 UniStrCpy(s, 0, L"");
1483 }
1484 return 0;
1485 }
1486 tmp = Malloc(new_size);
1487 tmp[0] = 0;
1488 mbstowcs(tmp, str, StrLen(str));
1489 tmp[(new_size - 1) / sizeof(wchar_t)] = 0;
1490 ret = UniStrCpy(s, size, tmp);
1491 Free(tmp);
1492
1493 return ret;
1494 #else // OS_WIN32
1495 return UnixStrToUni(s, size, str);
1496 #endif // OS_WIN32
1497 }
1498
1499 // Get the required buffer size for converting an ANSI string to an Unicode string
CalcStrToUni(char * str)1500 UINT CalcStrToUni(char *str)
1501 {
1502 #ifdef OS_WIN32
1503 UINT ret;
1504 // Validate arguments
1505 if (str == NULL)
1506 {
1507 return 0;
1508 }
1509
1510 ret = (UINT)mbstowcs(NULL, str, StrLen(str));
1511 if (ret == (UINT)-1)
1512 {
1513 return 0;
1514 }
1515
1516 return (ret + 1) * sizeof(wchar_t);
1517 #else // OS_WIN32
1518 return UnixCalcStrToUni(str);
1519 #endif // OS_WIN32
1520 }
1521
1522 // Convert the UTF-8 strings to a Unicode string
Utf8ToUni(wchar_t * s,UINT size,BYTE * u,UINT u_size)1523 UINT Utf8ToUni(wchar_t *s, UINT size, BYTE *u, UINT u_size)
1524 {
1525 UINT i, wp, num;
1526 // Validate arguments
1527 if (s == NULL || u == NULL)
1528 {
1529 return 0;
1530 }
1531 if (size == 0)
1532 {
1533 size = 0x3fffffff;
1534 }
1535 if (u_size == 0)
1536 {
1537 u_size = StrLen((char *)u);
1538 }
1539
1540 i = 0;
1541 wp = 0;
1542 num = 0;
1543 while (true)
1544 {
1545 UINT type;
1546 wchar_t c = 0;
1547 BYTE c1, c2;
1548
1549 type = GetUtf8Type(u, u_size, i);
1550 if (type == 0)
1551 {
1552 break;
1553 }
1554 switch (type)
1555 {
1556 case 1:
1557 c1 = 0;
1558 c2 = u[i];
1559 break;
1560 case 2:
1561 c1 = (((u[i] & 0x1c) >> 2) & 0x07);
1562 c2 = (((u[i] & 0x03) << 6) & 0xc0) | (u[i + 1] & 0x3f);
1563 break;
1564 case 3:
1565 c1 = ((((u[i] & 0x0f) << 4) & 0xf0)) | (((u[i + 1] & 0x3c) >> 2) & 0x0f);
1566 c2 = (((u[i + 1] & 0x03) << 6) & 0xc0) | (u[i + 2] & 0x3f);
1567 break;
1568 }
1569 i += type;
1570
1571 if (IsBigEndian())
1572 {
1573 if (sizeof(wchar_t) == 2)
1574 {
1575 ((BYTE *)&c)[0] = c1;
1576 ((BYTE *)&c)[1] = c2;
1577 }
1578 else
1579 {
1580 ((BYTE *)&c)[2] = c1;
1581 ((BYTE *)&c)[3] = c2;
1582 }
1583 }
1584 else
1585 {
1586 ((BYTE *)&c)[0] = c2;
1587 ((BYTE *)&c)[1] = c1;
1588 }
1589
1590 if (wp < ((size / sizeof(wchar_t)) - 1))
1591 {
1592 s[wp++] = c;
1593 num++;
1594 }
1595 else
1596 {
1597 break;
1598 }
1599 }
1600
1601 if (wp < (size / sizeof(wchar_t)))
1602 {
1603 s[wp++] = 0;
1604 }
1605
1606 return num;
1607 }
1608
1609 // Get the buffer size when converted UTF-8 to Unicode
CalcUtf8ToUni(BYTE * u,UINT u_size)1610 UINT CalcUtf8ToUni(BYTE *u, UINT u_size)
1611 {
1612 // Validate arguments
1613 if (u == NULL)
1614 {
1615 return 0;
1616 }
1617 if (u_size == 0)
1618 {
1619 u_size = StrLen((char *)u);
1620 }
1621
1622 return (Utf8Len(u, u_size) + 1) * sizeof(wchar_t);
1623 }
1624
1625 // Get the number of characters in UTF-8 string
Utf8Len(BYTE * u,UINT size)1626 UINT Utf8Len(BYTE *u, UINT size)
1627 {
1628 UINT i, num;
1629 // Validate arguments
1630 if (u == NULL)
1631 {
1632 return 0;
1633 }
1634 if (size == 0)
1635 {
1636 size = StrLen((char *)u);
1637 }
1638
1639 i = num = 0;
1640 while (true)
1641 {
1642 UINT type;
1643
1644 type = GetUtf8Type(u, size, i);
1645 if (type == 0)
1646 {
1647 break;
1648 }
1649 i += type;
1650 num++;
1651 }
1652
1653 return num;
1654 }
1655
1656 // Convert an Unicode string to UTF-8 string
UniToUtf8(BYTE * u,UINT size,wchar_t * s)1657 UINT UniToUtf8(BYTE *u, UINT size, wchar_t *s)
1658 {
1659 UINT i, len, type, wp;
1660 // Validate arguments
1661 if (u == NULL || s == NULL)
1662 {
1663 return 0;
1664 }
1665 if (size == 0)
1666 {
1667 size = 0x3fffffff;
1668 }
1669
1670 len = UniStrLen(s);
1671 wp = 0;
1672 for (i = 0;i < len;i++)
1673 {
1674 BYTE c1, c2;
1675 wchar_t c = s[i];
1676
1677 if (IsBigEndian())
1678 {
1679 if (sizeof(wchar_t) == 2)
1680 {
1681 c1 = ((BYTE *)&c)[0];
1682 c2 = ((BYTE *)&c)[1];
1683 }
1684 else
1685 {
1686 c1 = ((BYTE *)&c)[2];
1687 c2 = ((BYTE *)&c)[3];
1688 }
1689 }
1690 else
1691 {
1692 c1 = ((BYTE *)&c)[1];
1693 c2 = ((BYTE *)&c)[0];
1694 }
1695
1696 type = GetUniType(s[i]);
1697 switch (type)
1698 {
1699 case 1:
1700 if (wp < size)
1701 {
1702 u[wp++] = c2;
1703 }
1704 break;
1705 case 2:
1706 if (wp < size)
1707 {
1708 u[wp++] = 0xc0 | (((((c1 & 0x07) << 2) & 0x1c)) | (((c2 & 0xc0) >> 6) & 0x03));
1709 }
1710 if (wp < size)
1711 {
1712 u[wp++] = 0x80 | (c2 & 0x3f);
1713 }
1714 break;
1715 case 3:
1716 if (wp < size)
1717 {
1718 u[wp++] = 0xe0 | (((c1 & 0xf0) >> 4) & 0x0f);
1719 }
1720 if (wp < size)
1721 {
1722 u[wp++] = 0x80 | (((c1 & 0x0f) << 2) & 0x3c) | (((c2 & 0xc0) >> 6) & 0x03);
1723 }
1724 if (wp < size)
1725 {
1726 u[wp++] = 0x80 | (c2 & 0x3f);
1727 }
1728 break;
1729 }
1730 }
1731 if (wp < size)
1732 {
1733 u[wp] = 0;
1734 }
1735 return wp;
1736 }
1737
1738 // Calculating the length of the string when converting Unicode string to UTF-8 string
CalcUniToUtf8(wchar_t * s)1739 UINT CalcUniToUtf8(wchar_t *s)
1740 {
1741 UINT i, len, size;
1742 // Validate arguments
1743 if (s == NULL)
1744 {
1745 return 0;
1746 }
1747
1748 size = 0;
1749 len = UniStrLen(s);
1750 for (i = 0;i < len;i++)
1751 {
1752 size += GetUniType(s[i]);
1753 }
1754
1755 return size;
1756 }
1757
1758 // Get the number of bytes of a first character of the offset address of the UTF-8 string that starts with s
GetUtf8Type(BYTE * s,UINT size,UINT offset)1759 UINT GetUtf8Type(BYTE *s, UINT size, UINT offset)
1760 {
1761 // Validate arguments
1762 if (s == NULL)
1763 {
1764 return 0;
1765 }
1766 if ((offset + 1) > size)
1767 {
1768 return 0;
1769 }
1770 if ((s[offset] & 0x80) == 0)
1771 {
1772 // 1 byte
1773 return 1;
1774 }
1775 if ((s[offset] & 0x20) == 0)
1776 {
1777 // 2 bytes
1778 if ((offset + 2) > size)
1779 {
1780 return 0;
1781 }
1782 return 2;
1783 }
1784 // 3 bytes
1785 if ((offset + 3) > size)
1786 {
1787 return 0;
1788 }
1789 return 3;
1790 }
1791
1792 // Type of the converted character 'c' to UTF-8 (in bytes)
GetUniType(wchar_t c)1793 UINT GetUniType(wchar_t c)
1794 {
1795 BYTE c1, c2;
1796
1797 if (IsBigEndian())
1798 {
1799 if (sizeof(wchar_t) == 2)
1800 {
1801 c1 = ((BYTE *)&c)[0];
1802 c2 = ((BYTE *)&c)[1];
1803 }
1804 else
1805 {
1806 c1 = ((BYTE *)&c)[2];
1807 c2 = ((BYTE *)&c)[3];
1808 }
1809 }
1810 else
1811 {
1812 c1 = ((BYTE *)&c)[1];
1813 c2 = ((BYTE *)&c)[0];
1814 }
1815
1816 if (c1 == 0)
1817 {
1818 if (c2 <= 0x7f)
1819 {
1820 // 1 byte
1821 return 1;
1822 }
1823 else
1824 {
1825 // 2 bytes
1826 return 2;
1827 }
1828 }
1829 if ((c1 & 0xf8) == 0)
1830 {
1831 // 2 bytes
1832 return 2;
1833 }
1834 // 3 bytes
1835 return 3;
1836 }
1837
1838 // String replacing (case-sensitive)
UniReplaceStr(wchar_t * dst,UINT size,wchar_t * string,wchar_t * old_keyword,wchar_t * new_keyword)1839 UINT UniReplaceStr(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword)
1840 {
1841 return UniReplaceStrEx(dst, size, string, old_keyword, new_keyword, true);
1842 }
1843
1844 // Replacement of string
UniReplaceStrEx(wchar_t * dst,UINT size,wchar_t * string,wchar_t * old_keyword,wchar_t * new_keyword,bool case_sensitive)1845 UINT UniReplaceStrEx(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword, bool case_sensitive)
1846 {
1847 UINT i, j, num, len_string, len_old, len_new, len_ret, wp;
1848 wchar_t *ret;
1849 // Validate arguments
1850 if (string == NULL || old_keyword == NULL || new_keyword == NULL)
1851 {
1852 return 0;
1853 }
1854
1855 // Get the length of the string
1856 len_string = UniStrLen(string);
1857 len_old = UniStrLen(old_keyword);
1858 len_new = UniStrLen(new_keyword);
1859
1860 // Get the final string length
1861 len_ret = UniCalcReplaceStrEx(string, old_keyword, new_keyword, case_sensitive);
1862 // Memory allocation
1863 ret = Malloc((len_ret + 1) * sizeof(wchar_t));
1864 ret[len_ret] = 0;
1865
1866 // Search and Replace
1867 i = j = num = wp = 0;
1868 while (true)
1869 {
1870 i = UniSearchStrEx(string, old_keyword, i, case_sensitive);
1871 if (i == INFINITE)
1872 {
1873 Copy(&ret[wp], &string[j], (len_string - j) * sizeof(wchar_t));
1874 wp += len_string - j;
1875 break;
1876 }
1877 num++;
1878 Copy(&ret[wp], &string[j], (i - j) * sizeof(wchar_t));
1879 wp += i - j;
1880 Copy(&ret[wp], new_keyword, len_new * sizeof(wchar_t));
1881 wp += len_new;
1882 i += len_old;
1883 j = i;
1884 }
1885
1886 // Copy of the search results
1887 UniStrCpy(dst, size, ret);
1888
1889 // Memory release
1890 Free(ret);
1891
1892 return num;
1893 }
1894
1895 // Calculate the length of the result of string replacement
UniCalcReplaceStrEx(wchar_t * string,wchar_t * old_keyword,wchar_t * new_keyword,bool case_sensitive)1896 UINT UniCalcReplaceStrEx(wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword, bool case_sensitive)
1897 {
1898 UINT i, num;
1899 UINT len_string, len_old, len_new;
1900 // Validate arguments
1901 if (string == NULL || old_keyword == NULL || new_keyword == NULL)
1902 {
1903 return 0;
1904 }
1905
1906 // Get the length of the string
1907 len_string = UniStrLen(string);
1908 len_old = UniStrLen(old_keyword);
1909 len_new = UniStrLen(new_keyword);
1910
1911 if (len_old == len_new)
1912 {
1913 return len_string;
1914 }
1915
1916 // Search process
1917 num = 0;
1918 i = 0;
1919 while (true)
1920 {
1921 i = UniSearchStrEx(string, old_keyword, i, case_sensitive);
1922 if (i == INFINITE)
1923 {
1924 break;
1925 }
1926 i += len_old;
1927 num++;
1928 }
1929
1930 // Calculation
1931 return len_string + len_new * num - len_old * num;
1932 }
1933
1934 // Search for a string (distinguish between upper / lower case)
UniSearchStr(wchar_t * string,wchar_t * keyword,UINT start)1935 UINT UniSearchStr(wchar_t *string, wchar_t *keyword, UINT start)
1936 {
1937 return UniSearchStrEx(string, keyword, start, true);
1938 }
1939
1940 // Return the position of the first found of the keyword in the string
1941 // (Found in first character: returns 0, Not found: returns INFINITE)
UniSearchStrEx(wchar_t * string,wchar_t * keyword,UINT start,bool case_sensitive)1942 UINT UniSearchStrEx(wchar_t *string, wchar_t *keyword, UINT start, bool case_sensitive)
1943 {
1944 UINT len_string, len_keyword;
1945 UINT i;
1946 wchar_t *cmp_string, *cmp_keyword;
1947 bool found;
1948 // Validate arguments
1949 if (string == NULL || keyword == NULL)
1950 {
1951 return INFINITE;
1952 }
1953
1954 // Get the length of string
1955 len_string = UniStrLen(string);
1956 if (len_string <= start)
1957 {
1958 // Value of start is invalid
1959 return INFINITE;
1960 }
1961
1962 // Get the length of the keyword
1963 len_keyword = UniStrLen(keyword);
1964 if (len_keyword == 0)
1965 {
1966 // There is no keyword
1967 return INFINITE;
1968 }
1969
1970 if (len_string < len_keyword)
1971 {
1972 return INFINITE;
1973 }
1974
1975 if (len_string == len_keyword)
1976 {
1977 if (case_sensitive)
1978 {
1979 if (UniStrCmp(string, keyword) == 0)
1980 {
1981 return 0;
1982 }
1983 else
1984 {
1985 return INFINITE;
1986 }
1987 }
1988 else
1989 {
1990 if (UniStrCmpi(string, keyword) == 0)
1991 {
1992 return 0;
1993 }
1994 else
1995 {
1996 return INFINITE;
1997 }
1998 }
1999 }
2000
2001 if (case_sensitive)
2002 {
2003 cmp_string = string;
2004 cmp_keyword = keyword;
2005 }
2006 else
2007 {
2008 cmp_string = Malloc((len_string + 1) * sizeof(wchar_t));
2009 UniStrCpy(cmp_string, (len_string + 1) * sizeof(wchar_t), string);
2010 cmp_keyword = Malloc((len_keyword + 1) * sizeof(wchar_t));
2011 UniStrCpy(cmp_keyword, (len_keyword + 1) * sizeof(wchar_t), keyword);
2012 UniStrUpper(cmp_string);
2013 UniStrUpper(cmp_keyword);
2014 }
2015
2016 // Search
2017 found = false;
2018 for (i = start;i < (len_string - len_keyword + 1);i++)
2019 {
2020 // Compare
2021 if (!wcsncmp(&cmp_string[i], cmp_keyword, len_keyword))
2022 {
2023 // Found
2024 found = true;
2025 break;
2026 }
2027 }
2028
2029 if (case_sensitive == false)
2030 {
2031 // Memory release
2032 Free(cmp_keyword);
2033 Free(cmp_string);
2034 }
2035
2036 if (found == false)
2037 {
2038 return INFINITE;
2039 }
2040 return i;
2041 }
2042
2043 // Release of the token list
UniFreeToken(UNI_TOKEN_LIST * tokens)2044 void UniFreeToken(UNI_TOKEN_LIST *tokens)
2045 {
2046 UINT i;
2047 if (tokens == NULL)
2048 {
2049 return;
2050 }
2051 for (i = 0;i < tokens->NumTokens;i++)
2052 {
2053 Free(tokens->Token[i]);
2054 }
2055 Free(tokens->Token);
2056 Free(tokens);
2057 }
2058
2059 // Parse token for UNIX
UnixUniParseToken(wchar_t * src,wchar_t * separator)2060 UNI_TOKEN_LIST *UnixUniParseToken(wchar_t *src, wchar_t *separator)
2061 {
2062 UNI_TOKEN_LIST *ret;
2063 TOKEN_LIST *t;
2064 char *src_s;
2065 char *sep_s;
2066
2067 // Validate arguments
2068 if (src == NULL || separator == NULL)
2069 {
2070 ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
2071 ret->Token = ZeroMalloc(0);
2072 return ret;
2073 }
2074
2075 src_s = CopyUniToStr(src);
2076 sep_s = CopyUniToStr(separator);
2077
2078 t = ParseToken(src_s, sep_s);
2079
2080 ret = TokenListToUniTokenList(t);
2081 FreeToken(t);
2082
2083 Free(src_s);
2084 Free(sep_s);
2085
2086 return ret;
2087 }
2088
2089 // Get a standard token delimiter
UniDefaultTokenSplitChars()2090 wchar_t *UniDefaultTokenSplitChars()
2091 {
2092 return L" ,\t\r\n";
2093 }
2094
2095 // Check whether the specified character is in the string
UniIsCharInStr(wchar_t * str,wchar_t c)2096 bool UniIsCharInStr(wchar_t *str, wchar_t c)
2097 {
2098 UINT i, len;
2099 // Validate arguments
2100 if (str == NULL)
2101 {
2102 return false;
2103 }
2104
2105 len = UniStrLen(str);
2106 for (i = 0;i < len;i++)
2107 {
2108 if (str[i] == c)
2109 {
2110 return true;
2111 }
2112 }
2113
2114 return false;
2115 }
2116
2117 // Cut out the token from the string (not ignore the blanks between delimiters)
UniParseTokenWithNullStr(wchar_t * str,wchar_t * split_chars)2118 UNI_TOKEN_LIST *UniParseTokenWithNullStr(wchar_t *str, wchar_t *split_chars)
2119 {
2120 LIST *o;
2121 UINT i, len;
2122 BUF *b;
2123 wchar_t zero = 0;
2124 UNI_TOKEN_LIST *t;
2125 // Validate arguments
2126 if (str == NULL)
2127 {
2128 return UniNullToken();
2129 }
2130 if (split_chars == NULL)
2131 {
2132 split_chars = UniDefaultTokenSplitChars();
2133 }
2134
2135 b = NewBuf();
2136 o = NewListFast(NULL);
2137
2138 len = UniStrLen(str);
2139
2140 for (i = 0;i < (len + 1);i++)
2141 {
2142 wchar_t c = str[i];
2143 bool flag = UniIsCharInStr(split_chars, c);
2144
2145 if (c == L'\0')
2146 {
2147 flag = true;
2148 }
2149
2150 if (flag == false)
2151 {
2152 WriteBuf(b, &c, sizeof(wchar_t));
2153 }
2154 else
2155 {
2156 WriteBuf(b, &zero, sizeof(wchar_t));
2157
2158 Insert(o, UniCopyStr((wchar_t *)b->Buf));
2159 ClearBuf(b);
2160 }
2161 }
2162
2163 t = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
2164 t->NumTokens = LIST_NUM(o);
2165 t->Token = ZeroMalloc(sizeof(wchar_t *) * t->NumTokens);
2166
2167 for (i = 0;i < t->NumTokens;i++)
2168 {
2169 t->Token[i] = LIST_DATA(o, i);
2170 }
2171
2172 ReleaseList(o);
2173 FreeBuf(b);
2174
2175 return t;
2176 }
2177
2178 // Cut out the token from string (Ignore blanks between delimiters)
UniParseTokenWithoutNullStr(wchar_t * str,wchar_t * split_chars)2179 UNI_TOKEN_LIST *UniParseTokenWithoutNullStr(wchar_t *str, wchar_t *split_chars)
2180 {
2181 LIST *o;
2182 UINT i, len;
2183 bool last_flag;
2184 BUF *b;
2185 wchar_t zero = 0;
2186 UNI_TOKEN_LIST *t;
2187 // Validate arguments
2188 if (str == NULL)
2189 {
2190 return UniNullToken();
2191 }
2192 if (split_chars == NULL)
2193 {
2194 split_chars = UniDefaultTokenSplitChars();
2195 }
2196
2197 b = NewBuf();
2198 o = NewListFast(NULL);
2199
2200 len = UniStrLen(str);
2201 last_flag = false;
2202
2203 for (i = 0;i < (len + 1);i++)
2204 {
2205 wchar_t c = str[i];
2206 bool flag = UniIsCharInStr(split_chars, c);
2207
2208 if (c == L'\0')
2209 {
2210 flag = true;
2211 }
2212
2213 if (flag == false)
2214 {
2215 WriteBuf(b, &c, sizeof(wchar_t));
2216 }
2217 else
2218 {
2219 if (last_flag == false)
2220 {
2221 WriteBuf(b, &zero, sizeof(wchar_t));
2222
2223 if ((UniStrLen((wchar_t *)b->Buf)) != 0)
2224 {
2225 Insert(o, UniCopyStr((wchar_t *)b->Buf));
2226 }
2227 ClearBuf(b);
2228 }
2229 }
2230
2231 last_flag = flag;
2232 }
2233
2234 t = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
2235 t->NumTokens = LIST_NUM(o);
2236 t->Token = ZeroMalloc(sizeof(wchar_t *) * t->NumTokens);
2237
2238 for (i = 0;i < t->NumTokens;i++)
2239 {
2240 t->Token[i] = LIST_DATA(o, i);
2241 }
2242
2243 ReleaseList(o);
2244 FreeBuf(b);
2245
2246 return t;
2247 }
2248
2249 // Parse the token
UniParseToken(wchar_t * src,wchar_t * separator)2250 UNI_TOKEN_LIST *UniParseToken(wchar_t *src, wchar_t *separator)
2251 {
2252 // 2020/7/20 remove strtok by dnobori
2253 return UniParseTokenWithoutNullStr(src, separator);
2254 }
2255
2256 // Get a line from standard input
UniGetLine(wchar_t * str,UINT size)2257 bool UniGetLine(wchar_t *str, UINT size)
2258 {
2259 #ifdef OS_WIN32
2260 return UniGetLineWin32(str, size);
2261 #else // OS_WIN32
2262 return UniGetLineUnix(str, size);
2263 #endif // OS_WIN32
2264 }
AnsiGetLineUnix(char * str,UINT size)2265 void AnsiGetLineUnix(char *str, UINT size)
2266 {
2267 // Validate arguments
2268 if (str == NULL)
2269 {
2270 char tmp[MAX_SIZE];
2271 fgets(tmp, sizeof(tmp) - 1, stdin);
2272 return;
2273 }
2274 if (size <= 1)
2275 {
2276 return;
2277 }
2278
2279 // Read data from standard input
2280 fgets(str, (int)(size - 1), stdin);
2281
2282 TrimCrlf(str);
2283 }
UniGetLineUnix(wchar_t * str,UINT size)2284 bool UniGetLineUnix(wchar_t *str, UINT size)
2285 {
2286 char *str_a;
2287 UINT str_a_size = size;
2288 if (str == NULL || size < sizeof(wchar_t))
2289 {
2290 return false;
2291 }
2292 if (str_a_size >= 0x7fffffff)
2293 {
2294 str_a_size = MAX_SIZE;
2295 }
2296 str_a_size *= 2;
2297
2298 str_a = ZeroMalloc(str_a_size);
2299
2300 AnsiGetLineUnix(str_a, str_a_size);
2301
2302 StrToUni(str, size, str_a);
2303
2304 Free(str_a);
2305
2306 return true;
2307 }
UniGetLineWin32(wchar_t * str,UINT size)2308 bool UniGetLineWin32(wchar_t *str, UINT size)
2309 {
2310 bool ret = false;
2311
2312 #ifdef OS_WIN32
2313 ret = Win32InputW(str, size);
2314 #endif // OS_WIN32
2315
2316 return ret;
2317 }
2318
2319 // Remove '\r\n' at the end
UniTrimCrlf(wchar_t * str)2320 void UniTrimCrlf(wchar_t *str)
2321 {
2322 UINT len;
2323 // Validate arguments
2324 if (str == NULL)
2325 {
2326 return;
2327 }
2328 len = UniStrLen(str);
2329 if (len == 0)
2330 {
2331 return;
2332 }
2333
2334 if (str[len - 1] == L'\n')
2335 {
2336 if (len >= 2 && str[len - 2] == L'\r')
2337 {
2338 str[len - 2] = 0;
2339 }
2340 str[len - 1] = 0;
2341 }
2342 else if(str[len - 1] == L'\r')
2343 {
2344 str[len - 1] = 0;
2345 }
2346 }
2347
2348 // Remove white space of the both side of the string
UniTrim(wchar_t * str)2349 void UniTrim(wchar_t *str)
2350 {
2351 // Validate arguments
2352 if (str == NULL)
2353 {
2354 return;
2355 }
2356
2357 UniTrimLeft(str);
2358 UniTrimRight(str);
2359 }
2360
2361 // Remove white space on the right side of the string
UniTrimRight(wchar_t * str)2362 void UniTrimRight(wchar_t *str)
2363 {
2364 wchar_t *buf, *tmp;
2365 UINT len, i, wp, wp2;
2366 bool flag;
2367 // Validate arguments
2368 if (str == NULL)
2369 {
2370 return;
2371 }
2372 len = UniStrLen(str);
2373 if (len == 0)
2374 {
2375 return;
2376 }
2377 if (str[len - 1] != L' ' && str[len - 1] != L'\t')
2378 {
2379 return;
2380 }
2381
2382 buf = Malloc((len + 1) * sizeof(wchar_t));
2383 tmp = Malloc((len + 1) * sizeof(wchar_t));
2384 flag = false;
2385 wp = wp2 = 0;
2386 for (i = 0;i < len;i++)
2387 {
2388 if (str[i] != L' ' && str[i] != L'\t')
2389 {
2390 Copy(&buf[wp], tmp, wp2 * sizeof(wchar_t));
2391 wp += wp2;
2392 wp2 = 0;
2393 buf[wp++] = str[i];
2394 }
2395 else
2396 {
2397 tmp[wp2++] = str[i];
2398 }
2399 }
2400 buf[wp] = 0;
2401 UniStrCpy(str, 0, buf);
2402 Free(buf);
2403 Free(tmp);
2404 }
2405
2406 // Remove white space from the left side of the string
UniTrimLeft(wchar_t * str)2407 void UniTrimLeft(wchar_t *str)
2408 {
2409 wchar_t *buf;
2410 UINT len, i, wp;
2411 bool flag;
2412 // Validate arguments
2413 if (str == NULL)
2414 {
2415 return;
2416 }
2417 len = UniStrLen(str);
2418 if (len == 0)
2419 {
2420 return;
2421 }
2422 if (str[0] != L' ' && str[0] != L'\t')
2423 {
2424 return;
2425 }
2426
2427 buf = Malloc((len + 1) * sizeof(wchar_t));
2428 flag = false;
2429 wp = 0;
2430 for (i = 0;i < len;i++)
2431 {
2432 if (str[i] != L' ' && str[i] != L'\t')
2433 {
2434 flag = true;
2435 }
2436 if (flag)
2437 {
2438 buf[wp++] = str[i];
2439 }
2440 }
2441 buf[wp] = 0;
2442 UniStrCpy(str, 0, buf);
2443 Free(buf);
2444 }
2445
2446 // Convert a signed integer to a string
UniToStri(wchar_t * str,int i)2447 void UniToStri(wchar_t *str, int i)
2448 {
2449 UniFormat(str, 0, L"%i", i);
2450 }
2451
2452 // Convert an integer to a string
UniToStru(wchar_t * str,UINT i)2453 void UniToStru(wchar_t *str, UINT i)
2454 {
2455 UniFormat(str, 0, L"%u", i);
2456 }
2457
2458 // Convert a string to an integer
UniToInt(wchar_t * str)2459 UINT UniToInt(wchar_t *str)
2460 {
2461 char tmp[128];
2462 // Validate arguments
2463 if (str == NULL)
2464 {
2465 return 0;
2466 }
2467
2468 UniToStrForSingleChars(tmp, sizeof(tmp), str);
2469
2470 return ToInti(tmp);
2471 }
2472
2473 // Convert only single-byte characters in the Unicode string to a char string
UniToStrForSingleChars(char * dst,UINT dst_size,wchar_t * src)2474 void UniToStrForSingleChars(char *dst, UINT dst_size, wchar_t *src)
2475 {
2476 UINT i;
2477 // Validate arguments
2478 if (dst == NULL || src == NULL)
2479 {
2480 return;
2481 }
2482
2483 for (i = 0;i < UniStrLen(src) + 1;i++)
2484 {
2485 wchar_t s = src[i];
2486 char d;
2487
2488 if (s == 0)
2489 {
2490 d = 0;
2491 }
2492 else if (s <= 0xff)
2493 {
2494 d = (char)s;
2495 }
2496 else
2497 {
2498 d = ' ';
2499 }
2500
2501 dst[i] = d;
2502 }
2503 }
2504
2505 // Get lines from a string
UniGetLines(wchar_t * str)2506 UNI_TOKEN_LIST *UniGetLines(wchar_t *str)
2507 {
2508 UINT i, len;
2509 BUF *b = NULL;
2510 LIST *o;
2511 UNI_TOKEN_LIST *ret;
2512 // Validate arguments
2513 if (str == NULL)
2514 {
2515 return UniNullToken();
2516 }
2517
2518 o = NewListFast(NULL);
2519
2520 len = UniStrLen(str);
2521
2522 b = NewBuf();
2523
2524 for (i = 0;i < len;i++)
2525 {
2526 wchar_t c = str[i];
2527 bool f = false;
2528
2529 if (c == L'\r')
2530 {
2531 if (str[i + 1] == L'\n')
2532 {
2533 i++;
2534 }
2535 f = true;
2536 }
2537 else if (c == L'\n')
2538 {
2539 f = true;
2540 }
2541
2542 if (f)
2543 {
2544 wchar_t zero = 0;
2545 wchar_t *s;
2546 WriteBuf(b, &zero, sizeof(wchar_t));
2547
2548 s = (wchar_t *)b->Buf;
2549
2550 Add(o, UniCopyStr(s));
2551
2552 ClearBuf(b);
2553 }
2554 else
2555 {
2556 WriteBuf(b, &c, sizeof(wchar_t));
2557 }
2558 }
2559
2560 if (true)
2561 {
2562 wchar_t zero = 0;
2563 wchar_t *s;
2564 WriteBuf(b, &zero, sizeof(wchar_t));
2565
2566 s = (wchar_t *)b->Buf;
2567
2568 Add(o, UniCopyStr(s));
2569
2570 ClearBuf(b);
2571 }
2572
2573 FreeBuf(b);
2574
2575 ret = UniListToTokenList(o);
2576
2577 UniFreeStrList(o);
2578
2579 return ret;
2580 }
2581
2582 // Display the string on the screen
UniPrintStr(wchar_t * string)2583 void UniPrintStr(wchar_t *string)
2584 {
2585 // Validate arguments
2586 if (string == NULL)
2587 {
2588 return;
2589 }
2590
2591 #ifdef OS_UNIX
2592 if (true)
2593 {
2594 char *str = CopyUniToStr(string);
2595
2596 if (str != NULL)
2597 {
2598 fputs(str, stdout);
2599 }
2600 else
2601 {
2602 fputs("", stdout);
2603 }
2604
2605 Free(str);
2606 }
2607 #else // OS_UNIX
2608 Win32PrintW(string);
2609 #endif // OS_UNIX
2610 }
2611
2612 // Display a string with arguments
UniPrintArgs(wchar_t * fmt,va_list args)2613 void UniPrintArgs(wchar_t *fmt, va_list args)
2614 {
2615 wchar_t *str;
2616 // Validate arguments
2617 if (fmt == NULL)
2618 {
2619 return;
2620 }
2621
2622 str = InternalFormatArgs(fmt, args, false);
2623
2624 UniPrintStr(str);
2625
2626 Free(str);
2627 }
2628
2629 // Display the string
UniPrint(wchar_t * fmt,...)2630 void UniPrint(wchar_t *fmt, ...)
2631 {
2632 va_list args;
2633 // Validate arguments
2634 if (fmt == NULL)
2635 {
2636 return;
2637 }
2638
2639 va_start(args, fmt);
2640 UniPrintArgs(fmt, args);
2641 va_end(args);
2642 }
2643
2644 // Display debug string with arguments
UniDebugArgs(wchar_t * fmt,va_list args)2645 void UniDebugArgs(wchar_t *fmt, va_list args)
2646 {
2647 if (g_debug == false)
2648 {
2649 return;
2650 }
2651
2652 UniPrintArgs(fmt, args);
2653 }
2654
2655 // Display a debug string
UniDebug(wchar_t * fmt,...)2656 void UniDebug(wchar_t *fmt, ...)
2657 {
2658 va_list args;
2659 // Validate arguments
2660 if (fmt == NULL)
2661 {
2662 return;
2663 }
2664
2665 va_start(args, fmt);
2666 UniDebugArgs(fmt, args);
2667 va_end(args);
2668 }
2669
2670 // Format a string (argument list)
UniFormatArgs(wchar_t * buf,UINT size,wchar_t * fmt,va_list args)2671 void UniFormatArgs(wchar_t *buf, UINT size, wchar_t *fmt, va_list args)
2672 {
2673 wchar_t *ret;
2674 // Validate arguments
2675 if (buf == NULL || fmt == NULL)
2676 {
2677 return;
2678 }
2679 if (size == 1)
2680 {
2681 return;
2682 }
2683
2684 // KS
2685 KS_INC(KS_FORMAT_COUNT);
2686
2687 ret = InternalFormatArgs(fmt, args, false);
2688
2689 UniStrCpy(buf, size, ret);
2690
2691 Free(ret);
2692 }
2693
2694 // Format the string, and copy it
CopyUniFormat(wchar_t * fmt,...)2695 wchar_t *CopyUniFormat(wchar_t *fmt, ...)
2696 {
2697 wchar_t *ret, *str;
2698 UINT size;
2699 va_list args;
2700 // Validate arguments
2701 if (fmt == NULL)
2702 {
2703 return NULL;
2704 }
2705
2706 size = MAX(UniStrSize(fmt) * 10, MAX_SIZE * 10);
2707 str = Malloc(size);
2708
2709 va_start(args, fmt);
2710 UniFormatArgs(str, size, fmt, args);
2711
2712 ret = UniCopyStr(str);
2713 Free(str);
2714 va_end(args);
2715
2716 return ret;
2717 }
2718
2719 // Format the string
UniFormat(wchar_t * buf,UINT size,wchar_t * fmt,...)2720 void UniFormat(wchar_t *buf, UINT size, wchar_t *fmt, ...)
2721 {
2722 va_list args;
2723 // Validate arguments
2724 if (buf == NULL || fmt == NULL)
2725 {
2726 return;
2727 }
2728
2729 va_start(args, fmt);
2730 UniFormatArgs(buf, size, fmt, args);
2731 va_end(args);
2732 }
2733
2734 // Flexible string comparison
UniSoftStrCmp(wchar_t * str1,wchar_t * str2)2735 int UniSoftStrCmp(wchar_t *str1, wchar_t *str2)
2736 {
2737 UINT ret;
2738 wchar_t *tmp1, *tmp2;
2739 // Validate arguments
2740 if (str1 == NULL && str2 == NULL)
2741 {
2742 return 0;
2743 }
2744 if (str1 == NULL)
2745 {
2746 return 1;
2747 }
2748 if (str2 == NULL)
2749 {
2750 return -1;
2751 }
2752
2753 tmp1 = CopyUniStr(str1);
2754 tmp2 = CopyUniStr(str2);
2755
2756 UniTrim(tmp1);
2757 UniTrim(tmp2);
2758
2759 ret = UniStrCmpi(tmp1, tmp2);
2760
2761 Free(tmp1);
2762 Free(tmp2);
2763
2764 return ret;
2765 }
2766
2767 // Compare the strings in case-insensitive mode
UniStrCmpi(wchar_t * str1,wchar_t * str2)2768 int UniStrCmpi(wchar_t *str1, wchar_t *str2)
2769 {
2770 UINT i;
2771 // Validate arguments
2772 if (str1 == NULL && str2 == NULL)
2773 {
2774 return 0;
2775 }
2776 if (str1 == NULL)
2777 {
2778 return 1;
2779 }
2780 if (str2 == NULL)
2781 {
2782 return -1;
2783 }
2784
2785 // String comparison
2786 i = 0;
2787 while (true)
2788 {
2789 wchar_t c1, c2;
2790 c1 = UniToUpper(str1[i]);
2791 c2 = UniToUpper(str2[i]);
2792 if (c1 > c2)
2793 {
2794 return 1;
2795 }
2796 else if (c1 < c2)
2797 {
2798 return -1;
2799 }
2800 if (str1[i] == 0 || str2[i] == 0)
2801 {
2802 return 0;
2803 }
2804 i++;
2805 }
2806 }
2807
2808 // Compare the string
UniStrCmp(wchar_t * str1,wchar_t * str2)2809 int UniStrCmp(wchar_t *str1, wchar_t *str2)
2810 {
2811 // Validate arguments
2812 if (str1 == NULL && str2 == NULL)
2813 {
2814 return 0;
2815 }
2816 if (str1 == NULL)
2817 {
2818 return 1;
2819 }
2820 if (str2 == NULL)
2821 {
2822 return -1;
2823 }
2824
2825 return wcscmp(str1, str2);
2826 }
2827
2828 // Uncapitalize the string
UniStrLower(wchar_t * str)2829 void UniStrLower(wchar_t *str)
2830 {
2831 UINT i, len;
2832 // Validate arguments
2833 if (str == NULL)
2834 {
2835 return;
2836 }
2837
2838 len = UniStrLen(str);
2839 for (i = 0;i < len;i++)
2840 {
2841 str[i] = UniToLower(str[i]);
2842 }
2843 }
2844
2845 // Capitalize the string
UniStrUpper(wchar_t * str)2846 void UniStrUpper(wchar_t *str)
2847 {
2848 UINT i, len;
2849 // Validate arguments
2850 if (str == NULL)
2851 {
2852 return;
2853 }
2854
2855 len = UniStrLen(str);
2856 for (i = 0;i < len;i++)
2857 {
2858 str[i] = UniToUpper(str[i]);
2859 }
2860 }
2861
2862 // Uncapitalize a character
UniToLower(wchar_t c)2863 wchar_t UniToLower(wchar_t c)
2864 {
2865 if (c >= L'A' && c <= L'Z')
2866 {
2867 c += L'a' - L'A';
2868 }
2869
2870 return c;
2871 }
2872
2873 // Capitalize a character
UniToUpper(wchar_t c)2874 wchar_t UniToUpper(wchar_t c)
2875 {
2876 if (c >= L'a' && c <= L'z')
2877 {
2878 c -= L'a' - L'A';
2879 }
2880
2881 return c;
2882 }
2883
2884 // String concatenation
UniStrCat(wchar_t * dst,UINT size,wchar_t * src)2885 UINT UniStrCat(wchar_t *dst, UINT size, wchar_t *src)
2886 {
2887 UINT len1, len2, len_test;
2888 // Validate arguments
2889 if (dst == NULL || src == NULL)
2890 {
2891 return 0;
2892 }
2893 if (size != 0 && size < sizeof(wchar_t))
2894 {
2895 return 0;
2896 }
2897 if (size == sizeof(wchar_t))
2898 {
2899 wcscpy(dst, L"");
2900 return 0;
2901 }
2902 if (size == 0)
2903 {
2904 // Ignore the length
2905 size = 0x3fffffff;
2906 }
2907
2908 len1 = UniStrLen(dst);
2909 len2 = UniStrLen(src);
2910 len_test = len1 + len2 + 1;
2911 if (len_test > (size / sizeof(wchar_t)))
2912 {
2913 if (len2 <= (len_test - (size / sizeof(wchar_t))))
2914 {
2915 return 0;
2916 }
2917 len2 -= len_test - (size / sizeof(wchar_t));
2918 }
2919 Copy(&dst[len1], src, len2 * sizeof(wchar_t));
2920 dst[len1 + len2] = 0;
2921
2922 return len1 + len2;
2923 }
2924
2925 // String copy
UniStrCpy(wchar_t * dst,UINT size,wchar_t * src)2926 UINT UniStrCpy(wchar_t *dst, UINT size, wchar_t *src)
2927 {
2928 UINT len;
2929 // Validate arguments
2930 if (dst == NULL || src == NULL)
2931 {
2932 if (src == NULL && dst != NULL)
2933 {
2934 if (size >= sizeof(wchar_t))
2935 {
2936 dst[0] = L'\0';
2937 }
2938 }
2939 return 0;
2940 }
2941 if (dst == src)
2942 {
2943 return UniStrLen(src);
2944 }
2945 if (size != 0 && size < sizeof(wchar_t))
2946 {
2947 return 0;
2948 }
2949 if (size == sizeof(wchar_t))
2950 {
2951 wcscpy(dst, L"");
2952 return 0;
2953 }
2954 if (size == 0)
2955 {
2956 // Ignore the length
2957 size = 0x3fffffff;
2958 }
2959
2960 // Check the length
2961 len = UniStrLen(src);
2962 if (len <= (size / sizeof(wchar_t) - 1))
2963 {
2964 Copy(dst, src, (len + 1) * sizeof(wchar_t));
2965 }
2966 else
2967 {
2968 len = size / sizeof(wchar_t) - 1;
2969 Copy(dst, src, len * sizeof(wchar_t));
2970 dst[len] = 0;
2971 }
2972
2973 return len;
2974 }
2975
2976 // Get the buffer size needed to store the string
UniStrSize(wchar_t * str)2977 UINT UniStrSize(wchar_t *str)
2978 {
2979 // Validate arguments
2980 if (str == NULL)
2981 {
2982 return 0;
2983 }
2984
2985 return (UniStrLen(str) + 1) * sizeof(wchar_t);
2986 }
2987
2988 // Get the length of the string
UniStrLen(wchar_t * str)2989 UINT UniStrLen(wchar_t *str)
2990 {
2991 UINT i;
2992 // Validate arguments
2993 if (str == NULL)
2994 {
2995 return 0;
2996 }
2997
2998 i = 0;
2999 while (true)
3000 {
3001 if (str[i] == 0)
3002 {
3003 break;
3004 }
3005 i++;
3006 }
3007
3008 return i;
3009 }
3010
3011