1 // SoftEther VPN Source Code - Stable Edition Repository
2 // Mayaqua Kernel
3 //
4 // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
5 //
6 // Copyright (c) Daiyuu Nobori.
7 // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
8 // Copyright (c) SoftEther Corporation.
9 // Copyright (c) all contributors on SoftEther VPN project in GitHub.
10 //
11 // All Rights Reserved.
12 //
13 // http://www.softether.org/
14 //
15 // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
16 // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
17 //
18 // License: The Apache License, Version 2.0
19 // https://www.apache.org/licenses/LICENSE-2.0
20 //
21 // DISCLAIMER
22 // ==========
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 // SOFTWARE.
31 //
32 // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
33 // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
34 // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
35 // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
36 // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
37 // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
38 // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
39 // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
40 // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
41 // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
42 // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
43 // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
44 // LAW OR COURT RULE.
45 //
46 // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
47 // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
48 // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
49 // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
50 // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
51 // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
52 // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
53 // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
54 // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
55 // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
56 // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
57 // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
58 // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
59 // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
60 // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
61 // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
62 // STATEMENT FOR WARNING AND DISCLAIMER.
63 //
64 // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
65 // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
66 // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
67 //
68 //
69 // SOURCE CODE CONTRIBUTION
70 // ------------------------
71 //
72 // Your contribution to SoftEther VPN Project is much appreciated.
73 // Please send patches to us through GitHub.
74 // Read the SoftEther VPN Patch Acceptance Policy in advance:
75 // http://www.softether.org/5-download/src/9.patch
76 //
77 //
78 // DEAR SECURITY EXPERTS
79 // ---------------------
80 //
81 // If you find a bug or a security vulnerability please kindly inform us
82 // about the problem immediately so that we can fix the security problem
83 // to protect a lot of users around the world as soon as possible.
84 //
85 // Our e-mail address for security reports is:
86 // softether-vpn-security [at] softether.org
87 //
88 // Please note that the above e-mail address is not a technical support
89 // inquiry address. If you need technical assistance, please visit
90 // http://www.softether.org/ and ask your question on the users forum.
91 //
92 // Thank you for your cooperation.
93 //
94 //
95 // NO MEMORY OR RESOURCE LEAKS
96 // ---------------------------
97 //
98 // The memory-leaks and resource-leaks verification under the stress
99 // test has been passed before release this source code.
100
101
102 // Internat.c
103 // String conversion library for internationalization
104
105 #include <GlobalConst.h>
106
107 #include <stdio.h>
108 #include <stdlib.h>
109 #include <string.h>
110 #include <wchar.h>
111 #include <stdarg.h>
112 #include <time.h>
113 #include <errno.h>
114 #include <Mayaqua/Mayaqua.h>
115
116 extern LOCK *token_lock;
117 static char charset[MAX_SIZE] = "EUCJP";
118 static LOCK *iconv_lock = NULL;
119 void *iconv_cache_wide_to_str = 0;
120 void *iconv_cache_str_to_wide = 0;
121
122 // Initialize the string
ClearUniStr(wchar_t * str,UINT str_size)123 void ClearUniStr(wchar_t *str, UINT str_size)
124 {
125 UniStrCpy(str, str_size, L"");
126 }
127
128 // Examine whether the string contains the specified character
UniInChar(wchar_t * string,wchar_t c)129 bool UniInChar(wchar_t *string, wchar_t c)
130 {
131 UINT i, len;
132 // Validate arguments
133 if (string == NULL)
134 {
135 return false;
136 }
137
138 len = UniStrLen(string);
139
140 for (i = 0;i < len;i++)
141 {
142 if (string[i] == c)
143 {
144 return true;
145 }
146 }
147
148 return false;
149 }
150
151 // Check whether the string is included
UniInStr(wchar_t * str,wchar_t * keyword)152 bool UniInStr(wchar_t *str, wchar_t *keyword)
153 {
154 return UniInStrEx(str, keyword, false);
155 }
UniInStrEx(wchar_t * str,wchar_t * keyword,bool case_sensitive)156 bool UniInStrEx(wchar_t *str, wchar_t *keyword, bool case_sensitive)
157 {
158 // Validate arguments
159 if (UniIsEmptyStr(str) || UniIsEmptyStr(keyword))
160 {
161 return false;
162 }
163
164 if (UniSearchStrEx(str, keyword, 0, case_sensitive) == INFINITE)
165 {
166 return false;
167 }
168
169 return true;
170 }
171
172 // Convert to binary data
UniStrToBin(wchar_t * str)173 BUF *UniStrToBin(wchar_t *str)
174 {
175 char *str_a = CopyUniToStr(str);
176 BUF *ret;
177
178 ret = StrToBin(str_a);
179
180 Free(str_a);
181
182 return ret;
183 }
184
185 // Generate a sequence of specified characters
UniMakeCharArray(wchar_t c,UINT count)186 wchar_t *UniMakeCharArray(wchar_t c, UINT count)
187 {
188 UINT i;
189 wchar_t *ret = Malloc(sizeof(wchar_t) * (count + 1));
190
191 for (i = 0;i < count;i++)
192 {
193 ret[i] = c;
194 }
195
196 ret[count] = 0;
197
198 return ret;
199 }
200
201 // Check whether the character is safe
UniIsSafeChar(wchar_t c)202 bool UniIsSafeChar(wchar_t c)
203 {
204 UINT i, len;
205 wchar_t *check_str =
206 L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
207 L"abcdefghijklmnopqrstuvwxyz"
208 L"0123456789"
209 L" ()-_#%&.";
210
211 len = UniStrLen(check_str);
212 for (i = 0;i < len;i++)
213 {
214 if (c == check_str[i])
215 {
216 return true;
217 }
218 }
219 return false;
220 }
221
222 // Convert the token list to a string list
UniTokenListToList(UNI_TOKEN_LIST * t)223 LIST *UniTokenListToList(UNI_TOKEN_LIST *t)
224 {
225 UINT i;
226 LIST *o;
227 // Validate arguments
228 if (t == NULL)
229 {
230 return NULL;
231 }
232
233 o = NewListFast(NULL);
234 for (i = 0;i < t->NumTokens;i++)
235 {
236 Insert(o, UniCopyStr(t->Token[i]));
237 }
238
239 return o;
240 }
241
242 // Convert a string list to a token list
UniListToTokenList(LIST * o)243 UNI_TOKEN_LIST *UniListToTokenList(LIST *o)
244 {
245 UINT i;
246 UNI_TOKEN_LIST *t;
247 // Validate arguments
248 if (o == NULL)
249 {
250 return NULL;
251 }
252
253 t = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
254 t->NumTokens = LIST_NUM(o);
255 t->Token = ZeroMalloc(sizeof(wchar_t *) * t->NumTokens);
256 for (i = 0;i < LIST_NUM(o);i++)
257 {
258 t->Token[i] = UniCopyStr(LIST_DATA(o, i));
259 }
260
261 return t;
262 }
263
264 // Free the string list
UniFreeStrList(LIST * o)265 void UniFreeStrList(LIST *o)
266 {
267 UINT i;
268 // Validate arguments
269 if (o == NULL)
270 {
271 return;
272 }
273
274 for (i = 0;i < LIST_NUM(o);i++)
275 {
276 wchar_t *s = LIST_DATA(o, i);
277 Free(s);
278 }
279
280 ReleaseList(o);
281 }
282
283 // Convert the string list to a string
UniStrListToStr(LIST * o)284 BUF *UniStrListToStr(LIST *o)
285 {
286 BUF *b;
287 UINT i;
288 wchar_t c;
289 // Validate arguments
290 if (o == NULL)
291 {
292 return NULL;
293 }
294 b = NewBuf();
295
296 for (i = 0;i < LIST_NUM(o);i++)
297 {
298 wchar_t *s = LIST_DATA(o, i);
299 WriteBuf(b, s, UniStrSize(s));
300 }
301
302 c = 0;
303 WriteBuf(b, &c, sizeof(c));
304
305 SeekBuf(b, 0, 0);
306
307 return b;
308 }
309
310 // Convert a (NULL delimited) string to list
UniStrToStrList(wchar_t * str,UINT size)311 LIST *UniStrToStrList(wchar_t *str, UINT size)
312 {
313 LIST *o;
314 wchar_t *tmp;
315 UINT tmp_size;
316 UINT i;
317 // Validate arguments
318 if (str == NULL)
319 {
320 return NULL;
321 }
322
323 o = NewListFast(NULL);
324
325 i = 0;
326 while (true)
327 {
328 if (i >= size)
329 {
330 break;
331 }
332 if (*str == 0)
333 {
334 break;
335 }
336
337 tmp_size = UniStrSize(str);
338 tmp = ZeroMalloc(tmp_size);
339 UniStrCpy(tmp, tmp_size, str);
340 Add(o, tmp);
341 str += UniStrLen(str) + 1;
342 i++;
343 }
344
345 return o;
346 }
347
348 // Normalize the line breaks
UniNormalizeCrlf(wchar_t * str)349 wchar_t *UniNormalizeCrlf(wchar_t *str)
350 {
351 wchar_t *ret;
352 UINT ret_size, i, len, wp;
353 // Validate arguments
354 if (str == NULL)
355 {
356 return NULL;
357 }
358
359 len = UniStrLen(str);
360 ret_size = sizeof(wchar_t) * (len + 32) * 2;
361 ret = Malloc(ret_size);
362
363 wp = 0;
364
365 for (i = 0;i < len;i++)
366 {
367 wchar_t c = str[i];
368
369 switch (c)
370 {
371 case L'\r':
372 if (str[i + 1] == L'\n')
373 {
374 i++;
375 }
376 ret[wp++] = L'\r';
377 ret[wp++] = L'\n';
378 break;
379
380 case L'\n':
381 ret[wp++] = L'\r';
382 ret[wp++] = L'\n';
383 break;
384
385 default:
386 ret[wp++] = c;
387 break;
388 }
389 }
390
391 ret[wp++] = 0;
392
393 return ret;
394 }
395
396 // Check whether str ends with the key
UniEndWith(wchar_t * str,wchar_t * key)397 bool UniEndWith(wchar_t *str, wchar_t *key)
398 {
399 UINT str_len;
400 UINT key_len;
401 // Validate arguments
402 if (str == NULL || key == NULL)
403 {
404 return false;
405 }
406
407 // Comparison
408 str_len = UniStrLen(str);
409 key_len = UniStrLen(key);
410 if (str_len < key_len)
411 {
412 return false;
413 }
414
415 if (UniStrCmpi(str + (str_len - key_len), key) == 0)
416 {
417 return true;
418 }
419 else
420 {
421 return false;
422 }
423 }
424
425 // Check whether str starts with the key
UniStartWith(wchar_t * str,wchar_t * key)426 bool UniStartWith(wchar_t *str, wchar_t *key)
427 {
428 UINT str_len;
429 UINT key_len;
430 wchar_t *tmp;
431 bool ret;
432 // Validate arguments
433 if (str == NULL || key == NULL)
434 {
435 return false;
436 }
437
438 // Comparison
439 str_len = UniStrLen(str);
440 key_len = UniStrLen(key);
441 if (str_len < key_len)
442 {
443 return false;
444 }
445 if (str_len == 0 || key_len == 0)
446 {
447 return false;
448 }
449 tmp = CopyUniStr(str);
450 tmp[key_len] = 0;
451
452 if (UniStrCmpi(tmp, key) == 0)
453 {
454 ret = true;
455 }
456 else
457 {
458 ret = false;
459 }
460
461 Free(tmp);
462
463 return ret;
464 }
465
466 // Convert the integer to a comma-separated string
UniToStr3(wchar_t * str,UINT size,UINT64 value)467 void UniToStr3(wchar_t *str, UINT size, UINT64 value)
468 {
469 char tmp[MAX_SIZE];
470 // Validate arguments
471 if (str == NULL)
472 {
473 return;
474 }
475
476 ToStr3(tmp, sizeof(tmp), value);
477
478 StrToUni(str, size, tmp);
479 }
480
481 // Format of the string (internal function)
InternalFormatArgs(wchar_t * fmt,va_list args,bool ansi_mode)482 wchar_t *InternalFormatArgs(wchar_t *fmt, va_list args, bool ansi_mode)
483 {
484 UINT i, len;
485 wchar_t *tmp;
486 UINT tmp_size;
487 LIST *o;
488 UINT mode = 0;
489 UINT wp;
490 UINT total_size;
491 wchar_t *ret;
492 // Validate arguments
493 if (fmt == NULL)
494 {
495 return NULL;
496 }
497
498 len = UniStrLen(fmt);
499 tmp_size = UniStrSize(fmt);
500 tmp = Malloc(tmp_size);
501
502 o = NewListFast(NULL);
503
504 mode = 0;
505
506 wp = 0;
507
508 for (i = 0;i < len;i++)
509 {
510 wchar_t c = fmt[i];
511
512 if (mode == 0)
513 {
514 // Normal character mode
515 switch (c)
516 {
517 case L'%':
518 // The start of the format specification
519 if (fmt[i + 1] == L'%')
520 {
521 // If the next character is also '%', output a '%' simply
522 i++;
523 tmp[wp++] = c;
524 }
525 else
526 {
527 // Shift the state if the next character is not a '%'
528 mode = 1;
529 tmp[wp++] = 0;
530 wp = 0;
531 Add(o, CopyUniStr(tmp));
532 tmp[wp++] = c;
533 }
534 break;
535 default:
536 // Ordinary character
537 tmp[wp++] = c;
538 break;
539 }
540 }
541 else
542 {
543 char *tag;
544 char dst[MAX_SIZE];
545 wchar_t *target_str;
546 wchar_t *padding_str;
547 bool left_padding;
548 UINT target_str_len;
549 UINT total_len;
550 wchar_t *output_str;
551 UINT padding;
552 // Formatting mode
553 switch (c)
554 {
555 case L'c':
556 case L'C':
557 case L'd':
558 case L'i':
559 case L'o':
560 case L'u':
561 case L'x':
562 case L'X':
563 // int type
564 tmp[wp++] = c;
565 tmp[wp++] = 0;
566 tag = CopyUniToStr(tmp);
567
568 #ifdef OS_WIN32
569 ReplaceStrEx(tag, 0, tag, "ll", "I64", false);
570 #else // OS_WIN32
571 ReplaceStrEx(tag, 0, tag, "I64", "ll", false);
572 #endif // OS_WIN32
573
574 if ((UniStrLen(tmp) >= 5 && tmp[UniStrLen(tmp) - 4] == L'I' &&
575 tmp[UniStrLen(tmp) - 3] == L'6' &&
576 tmp[UniStrLen(tmp) - 2] == L'4') ||
577 (
578 UniStrLen(tmp) >= 4 && tmp[UniStrLen(tmp) - 3] == L'l' &&
579 tmp[UniStrLen(tmp) - 2] == L'l'))
580 {
581 #ifdef OS_WIN32
582 _snprintf(dst, sizeof(dst), tag, va_arg(args, UINT64));
583 #else // OS_WIN32
584 snprintf(dst, sizeof(dst), tag, va_arg(args, UINT64));
585 #endif // OS_WIN32
586 }
587 else
588 {
589 #ifdef OS_WIN32
590 _snprintf(dst, sizeof(dst), tag, va_arg(args, int));
591 #else // OS_WIN32
592 snprintf(dst, sizeof(dst), tag, va_arg(args, int));
593 #endif // OS_WIN32
594 }
595
596 Free(tag);
597 Add(o, CopyStrToUni(dst));
598
599 wp = 0;
600 mode = 0;
601 break;
602 case L'e':
603 case L'E':
604 case L'f':
605 case L'g':
606 case L'G':
607 // Double type
608 tmp[wp++] = c;
609 tmp[wp++] = 0;
610 tag = CopyUniToStr(tmp);
611
612 #ifdef OS_WIN32
613 _snprintf(dst, sizeof(dst), tag, va_arg(args, double));
614 #else // OS_WIN32
615 snprintf(dst, sizeof(dst), tag, va_arg(args, double));
616 #endif // OS_WIN32
617
618 Free(tag);
619 Add(o, CopyStrToUni(dst));
620
621 wp = 0;
622 mode = 0;
623 break;
624 case L'n':
625 case L'p':
626 // Pointer type
627 tmp[wp++] = c;
628 tmp[wp++] = 0;
629 tag = ZeroMalloc(UniStrSize(tmp) + 32);
630 UniToStr(tag, 0, tmp);
631
632 #ifdef OS_WIN32
633 _snprintf(dst, sizeof(dst), tag, va_arg(args, void *));
634 #else // OS_WIN32
635 snprintf(dst, sizeof(dst), tag, va_arg(args, void *));
636 #endif // OS_WIN32
637
638 Free(tag);
639 Add(o, CopyStrToUni(dst));
640
641 wp = 0;
642 mode = 0;
643 break;
644 case L'r':
645 case L'R':
646 // IP address type
647 tmp[wp++] = c;
648 tmp[wp++] = 0;
649
650 Zero(dst, sizeof(dst));
651 IPToStr(dst, sizeof(dst), va_arg(args, void *));
652
653 Add(o, CopyStrToUni(dst));
654
655 wp = 0;
656 mode = 0;
657 break;
658
659 case L's':
660 case L'S':
661 // String type
662 tmp[wp++] = c;
663 tmp[wp++] = 0;
664
665 if (ansi_mode == false)
666 {
667 if (c == L'S')
668 {
669 c = L's';
670 }
671 else
672 {
673 c = L'S';
674 }
675 }
676
677 if (c == L's')
678 {
679 target_str = CopyStrToUni(va_arg(args, char *));
680 }
681 else
682 {
683 target_str = CopyUniStr(va_arg(args, wchar_t *));
684 }
685
686 if (target_str == NULL)
687 {
688 target_str = CopyUniStr(L"(null)");
689 }
690
691 padding = 0;
692 left_padding = false;
693 if (tmp[1] == L'-')
694 {
695 // Left aligned
696 if (UniStrLen(tmp) >= 3)
697 {
698 padding = UniToInt(&tmp[2]);
699 }
700 left_padding = true;
701 }
702 else
703 {
704 // Right aligned
705 if (UniStrLen(tmp) >= 2)
706 {
707 padding = UniToInt(&tmp[1]);
708 }
709 }
710
711 target_str_len = UniStrWidth(target_str);
712
713 if (padding > target_str_len)
714 {
715 UINT len = padding - target_str_len;
716 UINT i;
717 padding_str = ZeroMalloc(sizeof(wchar_t) * (len + 1));
718 for (i = 0;i < len;i++)
719 {
720 padding_str[i] = L' ';
721 }
722 }
723 else
724 {
725 padding_str = ZeroMalloc(sizeof(wchar_t));
726 }
727
728 total_len = sizeof(wchar_t) * (UniStrLen(padding_str) + UniStrLen(target_str) + 1);
729 output_str = ZeroMalloc(total_len);
730 output_str[0] = 0;
731
732 if (left_padding == false)
733 {
734 UniStrCat(output_str, total_len, padding_str);
735 }
736 UniStrCat(output_str, total_len, target_str);
737 if (left_padding)
738 {
739 UniStrCat(output_str, total_len, padding_str);
740 }
741
742 Add(o, output_str);
743
744 Free(target_str);
745 Free(padding_str);
746
747 wp = 0;
748 mode = 0;
749 break;
750 default:
751 // Normal string
752 tmp[wp++] = c;
753 break;
754 }
755 }
756 }
757 tmp[wp++] = 0;
758 wp = 0;
759
760 if (UniStrLen(tmp) >= 1)
761 {
762 Add(o, CopyUniStr(tmp));
763 }
764
765 total_size = sizeof(wchar_t);
766 for (i = 0;i < LIST_NUM(o);i++)
767 {
768 wchar_t *s = LIST_DATA(o, i);
769 total_size += UniStrLen(s) * sizeof(wchar_t);
770 }
771
772 ret = ZeroMalloc(total_size);
773 for (i = 0;i < LIST_NUM(o);i++)
774 {
775 wchar_t *s = LIST_DATA(o, i);
776 UniStrCat(ret, total_size, s);
777 Free(s);
778 }
779
780 ReleaseList(o);
781
782 Free(tmp);
783
784 return ret;
785 }
786
787 // Get the width of the string
UniStrWidth(wchar_t * str)788 UINT UniStrWidth(wchar_t *str)
789 {
790 UINT i, len, ret;
791 // Validate arguments
792 if (str == NULL)
793 {
794 return 0;
795 }
796
797 ret = 0;
798 len = UniStrLen(str);
799 for (i = 0;i < len;i++)
800 {
801 if (str[i] <= 255)
802 {
803 ret++;
804 }
805 else
806 {
807 ret += 2;
808 }
809 }
810 return ret;
811 }
812
813 // Display a dump of Unicode string
DumpUniStr(wchar_t * str)814 void DumpUniStr(wchar_t *str)
815 {
816 UINT i, len;
817 char *s;
818 // Validate arguments
819 if (str == NULL)
820 {
821 return;
822 }
823
824 s = CopyUniToStr(str);
825
826 Print("DumpUniStr: %s\n ", s);
827
828 len = UniStrLen(str);
829 for (i = 0;i < len;i++)
830 {
831 Print("0x%04X ", str[i]);
832 }
833 Print("\n");
834
835 Free(s);
836 }
837
838 // Display the dump of the string
DumpStr(char * str)839 void DumpStr(char *str)
840 {
841 UINT i, len;
842 // Validate arguments
843 if (str == NULL)
844 {
845 return;
846 }
847
848 Print("DumpStr: %s\n ", str);
849
850 len = StrLen(str);
851 for (i = 0;i < len;i++)
852 {
853 Print("0x%02X ", str[i]);
854 }
855 Print("\n");
856 }
857
858 // Convert string of 2 byte/character to wchar_t of 4 byte/character
Utf16ToWide(USHORT * str)859 wchar_t *Utf16ToWide(USHORT *str)
860 {
861 wchar_t *ret;
862 UINT len, i;
863 // Validate arguments
864 if (str == NULL)
865 {
866 return NULL;
867 }
868
869 len = 0;
870 while (true)
871 {
872 if (str[len] == 0)
873 {
874 break;
875 }
876 len++;
877 }
878
879 ret = Malloc((len + 1) * sizeof(wchar_t));
880 for (i = 0;i < len + 1;i++)
881 {
882 ret[i] = (wchar_t)str[i];
883 }
884
885 return ret;
886 }
887
888 // Convert wchar_t string of 4 byte/character to string of 2 byte/character
WideToUtf16(wchar_t * str)889 USHORT *WideToUtf16(wchar_t *str)
890 {
891 USHORT *ret;
892 UINT len;
893 UINT ret_size;
894 UINT i;
895 // Validate arguments
896 if (str == NULL)
897 {
898 return NULL;
899 }
900
901 len = UniStrLen(str);
902
903 ret_size = (len + 1) * 2;
904 ret = Malloc(ret_size);
905
906 for (i = 0;i < len + 1;i++)
907 {
908 ret[i] = (USHORT)str[i];
909 }
910
911 return ret;
912 }
913
914 // Initialization of the International Library
InitInternational()915 void InitInternational()
916 {
917 #ifdef OS_UNIX
918 void *d;
919
920 if (iconv_lock != NULL)
921 {
922 return;
923 }
924
925 GetCurrentCharSet(charset, sizeof(charset));
926 d = IconvWideToStrInternal();
927 if (d == (void *)-1)
928 {
929 #ifdef UNIX_MACOS
930 StrCpy(charset, sizeof(charset), "utf-8");
931 #else // UNIX_MACOS
932 StrCpy(charset, sizeof(charset), "EUCJP");
933 #endif // UNIX_MACOS
934 d = IconvWideToStrInternal();
935 if (d == (void *)-1)
936 {
937 StrCpy(charset, sizeof(charset), "US");
938 }
939 else
940 {
941 IconvFreeInternal(d);
942 }
943 }
944 else
945 {
946 IconvFreeInternal(d);
947 }
948
949 iconv_lock = NewLockMain();
950
951 iconv_cache_wide_to_str = IconvWideToStrInternal();
952 iconv_cache_str_to_wide = IconvStrToWideInternal();
953 #endif // OS_UNIX
954 }
955
956 // Release of the International Library
FreeInternational()957 void FreeInternational()
958 {
959 #ifdef OS_UNIX
960 #endif // OS_UNIX
961 }
962
963 #ifdef OS_UNIX
964
965 // Calculate the size when the string converted to Unicode
UnixCalcStrToUni(char * str)966 UINT UnixCalcStrToUni(char *str)
967 {
968 wchar_t *tmp;
969 UINT len, tmp_size;
970 UINT ret;
971 // Validate arguments
972 if (str == NULL)
973 {
974 return 0;
975 }
976
977 len = StrLen(str);
978 tmp_size = len * 5 + 10;
979 tmp = ZeroMalloc(tmp_size);
980 UnixStrToUni(tmp, tmp_size, str);
981 ret = UniStrLen(tmp);
982 Free(tmp);
983
984 return (ret + 1) * sizeof(wchar_t);
985 }
986
987 // Convert the strings to Unicode
UnixStrToUni(wchar_t * s,UINT size,char * str)988 UINT UnixStrToUni(wchar_t *s, UINT size, char *str)
989 {
990 void *d;
991 char *inbuf;
992 size_t insize;
993 char *outbuf;
994 char *outbuf_orig;
995 size_t outsize;
996 wchar_t *tmp;
997 // Validate arguments
998 if (s == NULL || str == NULL)
999 {
1000 return 0;
1001 }
1002
1003 d = IconvStrToWide();
1004 if (d == (void *)-1)
1005 {
1006 UniStrCpy(s, size, L"");
1007 return 0;
1008 }
1009
1010 inbuf = (char *)str;
1011 insize = StrLen(str) + 1;
1012 outsize = insize * 5 + 10;
1013 outbuf_orig = outbuf = ZeroMalloc(outsize);
1014
1015 if (iconv((iconv_t)d, (char **)&inbuf, (size_t *)&insize, (char **)&outbuf, (size_t *)&outsize) == (size_t)(-1))
1016 {
1017 Free(outbuf_orig);
1018 UniStrCpy(s, size, L"");
1019 IconvFree(d);
1020 return 0;
1021 }
1022
1023 tmp = Utf16ToWide((USHORT *)outbuf_orig);
1024 Free(outbuf_orig);
1025
1026 UniStrCpy(s, size, tmp);
1027 IconvFree(d);
1028
1029 Free(tmp);
1030
1031 return UniStrLen(s);
1032 }
1033
1034 // Calculate the size when the Unicode converted to string
UnixCalcUniToStr(wchar_t * s)1035 UINT UnixCalcUniToStr(wchar_t *s)
1036 {
1037 char *tmp;
1038 UINT tmp_size;
1039 UINT ret;
1040 // Validate arguments
1041 if (s == NULL)
1042 {
1043 return 0;
1044 }
1045
1046 tmp_size = UniStrLen(s) * 5 + 10;
1047 tmp = ZeroMalloc(tmp_size);
1048 UnixUniToStr(tmp, tmp_size, s);
1049
1050 ret = StrSize(tmp);
1051 Free(tmp);
1052
1053 return ret;
1054 }
1055
1056 // Converted a Unicode string to a string
UnixUniToStr(char * str,UINT size,wchar_t * s)1057 UINT UnixUniToStr(char *str, UINT size, wchar_t *s)
1058 {
1059 USHORT *tmp;
1060 char *inbuf;
1061 size_t insize;
1062 char *outbuf;
1063 char *outbuf_orig;
1064 size_t outsize;
1065 void *d;
1066 // Validate arguments
1067 if (str == NULL || s == NULL)
1068 {
1069 return 0;
1070 }
1071
1072 // Convert a wchar_t string to sequence of 2-bytes first
1073 tmp = WideToUtf16(s);
1074 inbuf = (char *)tmp;
1075 insize = (UniStrLen(s) + 1) * 2;
1076 outsize = insize * 5 + 10;
1077 outbuf_orig = outbuf = ZeroMalloc(outsize);
1078
1079 d = IconvWideToStr();
1080 if (d == (void *)-1)
1081 {
1082 StrCpy(str, size, "");
1083 Free(outbuf);
1084 Free(tmp);
1085 return 0;
1086 }
1087
1088 if (iconv((iconv_t)d, (char **)&inbuf, (size_t *)&insize, (char **)&outbuf, (size_t *)&outsize) == (size_t)(-1))
1089 {
1090 Free(outbuf_orig);
1091 IconvFree(d);
1092 StrCpy(str, size, "");
1093 Free(tmp);
1094 return 0;
1095 }
1096
1097 StrCpy(str, size, outbuf_orig);
1098
1099 Free(outbuf_orig);
1100 IconvFree(d);
1101 Free(tmp);
1102
1103 return StrLen(str);
1104 }
1105
1106 // Converted the whcar_t to char
IconvWideToStrInternal()1107 void *IconvWideToStrInternal()
1108 {
1109 return (void *)iconv_open(charset, IsBigEndian() ? "UTF-16BE" : "UTF-16LE");
1110 }
1111
1112 // Convert the char to a wchar_t
IconvStrToWideInternal()1113 void *IconvStrToWideInternal()
1114 {
1115 return (void *)iconv_open(IsBigEndian() ? "UTF-16BE" : "UTF-16LE", charset);
1116 }
1117
1118 // Close the handle
IconvFreeInternal(void * d)1119 int IconvFreeInternal(void *d)
1120 {
1121 iconv_close((iconv_t)d);
1122 return 0;
1123 }
1124
IconvWideToStr()1125 void *IconvWideToStr()
1126 {
1127 if (iconv_cache_wide_to_str == (void *)-1)
1128 {
1129 return (void *)-1;
1130 }
1131
1132 Lock(iconv_lock);
1133
1134 return iconv_cache_wide_to_str;
1135 }
1136
IconvStrToWide()1137 void *IconvStrToWide()
1138 {
1139 if (iconv_cache_str_to_wide == (void *)-1)
1140 {
1141 return (void *)-1;
1142 }
1143
1144 Lock(iconv_lock);
1145
1146 return iconv_cache_str_to_wide;
1147 }
1148
IconvFree(void * d)1149 int IconvFree(void *d)
1150 {
1151 Unlock(iconv_lock);
1152
1153 return 0;
1154 }
1155
1156 // Get the character set that is currently used from the environment variable
GetCurrentCharSet(char * name,UINT size)1157 void GetCurrentCharSet(char *name, UINT size)
1158 {
1159 char tmp[MAX_SIZE];
1160 TOKEN_LIST *t;
1161 // Validate arguments
1162 if (name == NULL)
1163 {
1164 return;
1165 }
1166
1167 Zero(tmp, sizeof(tmp));
1168 if (GetEnv("LANG", tmp, sizeof(tmp)) == false || IsEmptyStr(tmp))
1169 {
1170 Zero(tmp, sizeof(tmp));
1171 if (GetEnv("LOCATION", tmp, sizeof(tmp)) == false || IsEmptyStr(tmp))
1172 {
1173 StrCpy(tmp, sizeof(tmp), "C");
1174 }
1175 }
1176
1177 Trim(tmp);
1178
1179 t = ParseToken(tmp, ".");
1180 if (t->NumTokens >= 2)
1181 {
1182 StrCpy(name, size, t->Token[1]);
1183 }
1184 else
1185 {
1186 if (t->NumTokens == 1)
1187 {
1188 StrCpy(name, size, t->Token[0]);
1189 }
1190 else
1191 {
1192 StrCpy(name, size, "eucJP");
1193 }
1194 }
1195 FreeToken(t);
1196
1197 StrUpper(name);
1198 }
1199
1200 #endif // OS_UNIX
1201
1202 // Check whether the specified string is a space
UniIsEmptyStr(wchar_t * str)1203 bool UniIsEmptyStr(wchar_t *str)
1204 {
1205 return IsEmptyUniStr(str);
1206 }
IsEmptyUniStr(wchar_t * str)1207 bool IsEmptyUniStr(wchar_t *str)
1208 {
1209 bool ret;
1210 wchar_t *s;
1211 // Validate arguments
1212 if (str == NULL)
1213 {
1214 return true;
1215 }
1216
1217 s = UniCopyStr(str);
1218
1219 UniTrim(s);
1220 if (UniStrLen(s) == 0)
1221 {
1222 ret = true;
1223 }
1224 else
1225 {
1226 ret = false;
1227 }
1228
1229 Free(s);
1230
1231 return ret;
1232 }
1233
1234 // Check whether the specified string is a number
UniIsNum(wchar_t * str)1235 bool UniIsNum(wchar_t *str)
1236 {
1237 char tmp[MAX_SIZE];
1238
1239 // Validate arguments
1240 if (str == NULL)
1241 {
1242 return false;
1243 }
1244
1245 UniToStrForSingleChars(tmp, sizeof(tmp), str);
1246
1247 return IsNum(tmp);
1248 }
1249
1250
1251 // Empty Unicode token list
UniNullToken()1252 UNI_TOKEN_LIST *UniNullToken()
1253 {
1254 UNI_TOKEN_LIST *ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
1255 ret->Token = ZeroMalloc(0);
1256
1257 return ret;
1258 }
1259
1260 // Empty Unicode token list (Alias)
NullUniToken()1261 UNI_TOKEN_LIST *NullUniToken()
1262 {
1263 return UniNullToken();
1264 }
1265
1266 // Convert the token list to Unicode token list
TokenListToUniTokenList(TOKEN_LIST * src)1267 UNI_TOKEN_LIST *TokenListToUniTokenList(TOKEN_LIST *src)
1268 {
1269 UNI_TOKEN_LIST *ret;
1270 UINT i;
1271 // Validate arguments
1272 if (src == NULL)
1273 {
1274 return NULL;
1275 }
1276
1277 ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
1278 ret->NumTokens = src->NumTokens;
1279 ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);
1280
1281 for (i = 0;i < ret->NumTokens;i++)
1282 {
1283 ret->Token[i] = CopyStrToUni(src->Token[i]);
1284 }
1285
1286 return ret;
1287 }
1288
1289 // Convert a Unicode token list to a token list
UniTokenListToTokenList(UNI_TOKEN_LIST * src)1290 TOKEN_LIST *UniTokenListToTokenList(UNI_TOKEN_LIST *src)
1291 {
1292 TOKEN_LIST *ret;
1293 UINT i;
1294 // Validate arguments
1295 if (src == NULL)
1296 {
1297 return NULL;
1298 }
1299
1300 ret = ZeroMalloc(sizeof(TOKEN_LIST));
1301 ret->NumTokens = src->NumTokens;
1302 ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);
1303
1304 for (i = 0;i < ret->NumTokens;i++)
1305 {
1306 ret->Token[i] = CopyUniToStr(src->Token[i]);
1307 }
1308
1309 return ret;
1310 }
1311
1312 // Unicode string copy
UniCopyStr(wchar_t * str)1313 wchar_t *UniCopyStr(wchar_t *str)
1314 {
1315 return CopyUniStr(str);
1316 }
1317
1318 // Copy the token list
UniCopyToken(UNI_TOKEN_LIST * src)1319 UNI_TOKEN_LIST *UniCopyToken(UNI_TOKEN_LIST *src)
1320 {
1321 UNI_TOKEN_LIST *ret;
1322 UINT i;
1323 // Validate arguments
1324 if (src == NULL)
1325 {
1326 return NULL;
1327 }
1328
1329 ret = ZeroMalloc(sizeof(TOKEN_LIST));
1330 ret->NumTokens = src->NumTokens;
1331 ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);
1332 for (i = 0;i < ret->NumTokens;i++)
1333 {
1334 ret->Token[i] = CopyUniStr(src->Token[i]);
1335 }
1336
1337 return ret;
1338 }
1339
1340 // Parse the command line string
UniParseCmdLine(wchar_t * str)1341 UNI_TOKEN_LIST *UniParseCmdLine(wchar_t *str)
1342 {
1343 UNI_TOKEN_LIST *t;
1344 LIST *o;
1345 UINT i, len, wp, mode;
1346 wchar_t c;
1347 wchar_t *tmp;
1348 bool ignore_space = false;
1349 // Validate arguments
1350 if (str == NULL)
1351 {
1352 // There is no token
1353 return UniNullToken();
1354 }
1355
1356 o = NewListFast(NULL);
1357 tmp = Malloc(UniStrSize(str) + 32);
1358
1359 wp = 0;
1360 mode = 0;
1361
1362 len = UniStrLen(str);
1363 for (i = 0;i < len;i++)
1364 {
1365 c = str[i];
1366
1367 switch (mode)
1368 {
1369 case 0:
1370 // Mode to discover the next token
1371 if (c == L' ' || c == L'\t')
1372 {
1373 // Advance to the next character
1374 }
1375 else
1376 {
1377 // Start of the token
1378 if (c == L'\"')
1379 {
1380 if (str[i + 1] == L'\"')
1381 {
1382 // Regarded "" as a single " character
1383 tmp[wp++] = L'\"';
1384 i++;
1385 }
1386 else
1387 {
1388 // Single "(double-quote) enables the flag to ignore space
1389 ignore_space = true;
1390 }
1391 }
1392 else
1393 {
1394 tmp[wp++] = c;
1395 }
1396
1397 mode = 1;
1398 }
1399 break;
1400
1401 case 1:
1402 if (ignore_space == false && (c == L' ' || c == L'\t'))
1403 {
1404 // End of the token
1405 tmp[wp++] = 0;
1406 wp = 0;
1407
1408 Insert(o, UniCopyStr(tmp));
1409 mode = 0;
1410 }
1411 else
1412 {
1413 if (c == L'\"')
1414 {
1415 if (str[i + 1] == L'\"')
1416 {
1417 // Regarded "" as a single " character
1418 tmp[wp++] = L'\"';
1419 i++;
1420 }
1421 else
1422 {
1423 if (ignore_space == false)
1424 {
1425 // Single "(double-quote) enables the flag to ignore space
1426 ignore_space = true;
1427 }
1428 else
1429 {
1430 // Disable the flag to ignore space
1431 ignore_space = false;
1432 }
1433 }
1434 }
1435 else
1436 {
1437 tmp[wp++] = c;
1438 }
1439 }
1440 break;
1441 }
1442 }
1443
1444 if (wp != 0)
1445 {
1446 tmp[wp++] = 0;
1447 Insert(o, UniCopyStr(tmp));
1448 }
1449
1450 Free(tmp);
1451
1452 t = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
1453 t->NumTokens = LIST_NUM(o);
1454 t->Token = ZeroMalloc(sizeof(wchar_t *) * t->NumTokens);
1455 for (i = 0;i < t->NumTokens;i++)
1456 {
1457 t->Token[i] = LIST_DATA(o, i);
1458 }
1459
1460 ReleaseList(o);
1461
1462 return t;
1463 }
1464
1465 // Convert Unicode string to 64bit integer
UniToInt64(wchar_t * str)1466 UINT64 UniToInt64(wchar_t *str)
1467 {
1468 char tmp[MAX_SIZE];
1469 // Validate arguments
1470 if (str == NULL)
1471 {
1472 return 0;
1473 }
1474
1475 UniToStrForSingleChars(tmp, sizeof(tmp), str);
1476
1477 return ToInt64(tmp);
1478 }
1479
1480 // Convert a 64-bit integer to a Unicode string
UniToStr64(wchar_t * str,UINT64 value)1481 void UniToStr64(wchar_t *str, UINT64 value)
1482 {
1483 char tmp[MAX_SIZE];
1484 // Validate arguments
1485 if (str == NULL)
1486 {
1487 return;
1488 }
1489
1490 ToStr64(tmp, value);
1491
1492 StrToUni(str, 0, tmp);
1493 }
1494
1495 // Convert an ANSI string to UTF
StrToUtf(char * utfstr,UINT size,char * str)1496 UINT StrToUtf(char *utfstr, UINT size, char *str)
1497 {
1498 char *tmp;
1499 // Validate arguments
1500 if (utfstr == NULL || str == NULL)
1501 {
1502 StrCpy(utfstr, size, "");
1503 return 0;
1504 }
1505
1506 tmp = CopyStrToUtf(str);
1507
1508 StrCpy(utfstr, size, tmp);
1509
1510 Free(tmp);
1511
1512 return StrLen(utfstr);
1513 }
1514
1515 // Convert an UTF string to an ANSI string
UtfToStr(char * str,UINT size,char * utfstr)1516 UINT UtfToStr(char *str, UINT size, char *utfstr)
1517 {
1518 char *tmp;
1519 // Validate arguments
1520 if (str == NULL || utfstr == NULL)
1521 {
1522 StrCpy(str, size, "");
1523 return 0;
1524 }
1525
1526 tmp = CopyUtfToStr(utfstr);
1527
1528 StrCpy(str, size, tmp);
1529
1530 Free(tmp);
1531
1532 return StrLen(str);
1533 }
1534
1535 // Convert the Unicode string to the UTF string
UniToUtf(char * utfstr,UINT size,wchar_t * unistr)1536 UINT UniToUtf(char *utfstr, UINT size, wchar_t *unistr)
1537 {
1538 char *tmp;
1539 // Validate arguments
1540 if (utfstr == NULL || unistr == NULL)
1541 {
1542 StrCpy(utfstr, size, "");
1543 return 0;
1544 }
1545
1546 tmp = CopyUniToStr(unistr);
1547
1548 StrCpy(utfstr, size, tmp);
1549
1550 Free(tmp);
1551
1552 return StrLen(utfstr);
1553 }
1554
1555 // Convert the UTF string to a Unicode string
UtfToUni(wchar_t * unistr,UINT size,char * utfstr)1556 UINT UtfToUni(wchar_t *unistr, UINT size, char *utfstr)
1557 {
1558 wchar_t *tmp;
1559 // Validate arguments
1560 if (unistr == NULL || utfstr == NULL)
1561 {
1562 UniStrCpy(unistr, size, L"");
1563 return 0;
1564 }
1565
1566 tmp = CopyUtfToUni(utfstr);
1567
1568 UniStrCpy(unistr, size, tmp);
1569
1570 Free(tmp);
1571
1572 return UniStrLen(unistr);
1573 }
1574
1575 // Copy the UTF-8 string to a Unicode string
CopyUtfToUni(char * utfstr)1576 wchar_t *CopyUtfToUni(char *utfstr)
1577 {
1578 UINT size;
1579 wchar_t *ret;
1580 UINT utfstr_len;
1581 // Validate arguments
1582 if (utfstr == NULL)
1583 {
1584 return NULL;
1585 }
1586
1587 utfstr_len = StrLen(utfstr);
1588
1589 size = CalcUtf8ToUni((BYTE *)utfstr, utfstr_len);
1590 ret = ZeroMalloc(size + sizeof(wchar_t));
1591 Utf8ToUni(ret, size, (BYTE *)utfstr, utfstr_len);
1592
1593 return ret;
1594 }
1595
1596 // Copy the UTF8 string to the ANSI string
CopyUtfToStr(char * utfstr)1597 char *CopyUtfToStr(char *utfstr)
1598 {
1599 wchar_t *uni;
1600 char *ret;
1601 // Validate arguments
1602 if (utfstr == NULL)
1603 {
1604 return NULL;
1605 }
1606
1607 uni = CopyUtfToUni(utfstr);
1608 if (uni == NULL)
1609 {
1610 return CopyStr("");
1611 }
1612
1613 ret = CopyUniToStr(uni);
1614
1615 Free(uni);
1616
1617 return ret;
1618 }
1619
1620 // Copy a Unicode string to ANSI string
CopyUniToStr(wchar_t * unistr)1621 char *CopyUniToStr(wchar_t *unistr)
1622 {
1623 char *str;
1624 UINT str_size;
1625 // Validate arguments
1626 if (unistr == NULL)
1627 {
1628 return NULL;
1629 }
1630
1631 str_size = CalcUniToStr(unistr);
1632 if (str_size == 0)
1633 {
1634 return CopyStr("");
1635 }
1636 str = Malloc(str_size);
1637 UniToStr(str, str_size, unistr);
1638
1639 return str;
1640 }
1641
1642 // Copy an ANSI string to a Unicode string
CopyStrToUni(char * str)1643 wchar_t *CopyStrToUni(char *str)
1644 {
1645 wchar_t *uni;
1646 UINT uni_size;
1647 // Validate arguments
1648 if (str == NULL)
1649 {
1650 return NULL;
1651 }
1652
1653 uni_size = CalcStrToUni(str);
1654 if (uni_size == 0)
1655 {
1656 return CopyUniStr(L"");
1657 }
1658 uni = Malloc(uni_size);
1659 StrToUni(uni, uni_size, str);
1660
1661 return uni;
1662 }
1663
1664 // Copy a Unicode string to UTF-8 string
CopyUniToUtf(wchar_t * unistr)1665 char *CopyUniToUtf(wchar_t *unistr)
1666 {
1667 UINT size;
1668 char *ret;
1669 // Validate arguments
1670 if (unistr == NULL)
1671 {
1672 return NULL;
1673 }
1674
1675 size = CalcUniToUtf8(unistr);
1676 ret = ZeroMalloc(size + sizeof(char));
1677
1678 UniToUtf8((char *)ret, size, unistr);
1679
1680 return ret;
1681 }
1682
1683 // Copy ANSI string to UTF8 string
CopyStrToUtf(char * str)1684 char *CopyStrToUtf(char *str)
1685 {
1686 wchar_t *unistr;
1687 char *ret;
1688 // Validate arguments
1689 if (str == NULL)
1690 {
1691 return NULL;
1692 }
1693
1694 unistr = CopyStrToUni(str);
1695 if (unistr == NULL)
1696 {
1697 return CopyStr("");
1698 }
1699
1700 ret = CopyUniToUtf(unistr);
1701
1702 Free(unistr);
1703
1704 return ret;
1705 }
1706
1707 // Copy the Unicode string
CopyUniStr(wchar_t * str)1708 wchar_t *CopyUniStr(wchar_t *str)
1709 {
1710 UINT len;
1711 wchar_t *dst;
1712 // Validate arguments
1713 if (str == NULL)
1714 {
1715 return NULL;
1716 }
1717
1718 len = UniStrLen(str);
1719 dst = Malloc((len + 1) * sizeof(wchar_t));
1720 UniStrCpy(dst, 0, str);
1721
1722 return dst;
1723 }
1724
1725 // Check whether the string is safe
IsSafeUniStr(wchar_t * str)1726 bool IsSafeUniStr(wchar_t *str)
1727 {
1728 UINT i, len;
1729 // Validate arguments
1730 if (str == NULL)
1731 {
1732 return false;
1733 }
1734
1735 len = UniStrLen(str);
1736 for (i = 0;i < len;i++)
1737 {
1738 if (IsSafeUniChar(str[i]) == false)
1739 {
1740 return false;
1741 }
1742 }
1743 if (str[0] == L' ')
1744 {
1745 return false;
1746 }
1747 if (len != 0)
1748 {
1749 if (str[len - 1] == L' ')
1750 {
1751 return false;
1752 }
1753 }
1754 return true;
1755 }
1756
1757 // Check whether the character is safe
IsSafeUniChar(wchar_t c)1758 bool IsSafeUniChar(wchar_t c)
1759 {
1760 UINT i, len;
1761 wchar_t *check_str =
1762 L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1763 L"abcdefghijklmnopqrstuvwxyz"
1764 L"0123456789"
1765 L" ()-_#%&.";
1766
1767 len = UniStrLen(check_str);
1768 for (i = 0;i < len;i++)
1769 {
1770 if (c == check_str[i])
1771 {
1772 return true;
1773 }
1774 }
1775 return false;
1776 }
1777
1778 // Convert an UTF-8 string to an ANSI string
Utf8ToStr(char * str,UINT str_size,BYTE * u,UINT size)1779 UINT Utf8ToStr(char *str, UINT str_size, BYTE *u, UINT size)
1780 {
1781 UINT ret, uni_size;
1782 wchar_t *tmp;
1783 // Validate arguments
1784 if (u == NULL || str == NULL)
1785 {
1786 return 0;
1787 }
1788
1789 // Convert to Unicode
1790 uni_size = CalcUtf8ToUni(u, size);
1791 if (uni_size == 0)
1792 {
1793 if (str_size >= 1)
1794 {
1795 StrCpy(str, 0, "");
1796 return 0;
1797 }
1798 }
1799 tmp = Malloc(uni_size);
1800 Utf8ToUni(tmp, uni_size, u, size);
1801
1802 // Convert to ANSI
1803 ret = UniToStr(str, str_size, tmp);
1804 Free(tmp);
1805
1806 return ret;
1807 }
1808
1809 // Get the size required when UTF-8 string is converted to ANSI string
CalcUtf8ToStr(BYTE * u,UINT size)1810 UINT CalcUtf8ToStr(BYTE *u, UINT size)
1811 {
1812 UINT ret, uni_size;
1813 wchar_t *tmp;
1814 // Validate arguments
1815 if (u == NULL)
1816 {
1817 return 0;
1818 }
1819
1820 // Convert to Unicode
1821 uni_size = CalcUtf8ToUni(u, size);
1822 if (uni_size == 0)
1823 {
1824 return 0;
1825 }
1826 tmp = Malloc(uni_size);
1827 Utf8ToUni(tmp, uni_size, u, size);
1828
1829 // Convert to ANSI
1830 ret = CalcUniToStr(tmp);
1831 Free(tmp);
1832
1833 return ret;
1834 }
1835
1836 // Convert an ANSI string to UTF-8 string
StrToUtf8(BYTE * u,UINT size,char * str)1837 UINT StrToUtf8(BYTE *u, UINT size, char *str)
1838 {
1839 UINT ret, uni_size;
1840 wchar_t *tmp;
1841 // Validate arguments
1842 if (u == NULL || str == NULL)
1843 {
1844 return 0;
1845 }
1846
1847 // Convert to Unicode
1848 uni_size = CalcStrToUni(str);
1849 if (uni_size == 0)
1850 {
1851 return 0;
1852 }
1853 tmp = Malloc(uni_size);
1854 StrToUni(tmp, uni_size, str);
1855
1856 // Convert to UTF-8
1857 ret = UniToUtf8(u, size, tmp);
1858
1859 Free(tmp);
1860
1861 return ret;
1862 }
1863
1864 // Get the required buffer size to convert an ANSI string to an UTF-8 string
CalcStrToUtf8(char * str)1865 UINT CalcStrToUtf8(char *str)
1866 {
1867 UINT ret;
1868 UINT uni_size;
1869 wchar_t *tmp;
1870 // Validate arguments
1871 if (str == NULL)
1872 {
1873 return 0;
1874 }
1875
1876 // Convert to Unicode
1877 uni_size = CalcStrToUni(str);
1878 if (uni_size == 0)
1879 {
1880 return 0;
1881 }
1882 tmp = Malloc(uni_size);
1883 StrToUni(tmp, uni_size, str);
1884
1885 // Get the size as it was converted to UTF-8
1886 ret = CalcUniToUtf8(tmp);
1887 Free(tmp);
1888
1889 return ret;
1890 }
1891
1892 // Convert Unicode string to ANSI string
UniToStr(char * str,UINT size,wchar_t * s)1893 UINT UniToStr(char *str, UINT size, wchar_t *s)
1894 {
1895 #ifdef OS_WIN32
1896 UINT ret;
1897 char *tmp;
1898 UINT new_size;
1899 // Validate arguments
1900 if (s == NULL || str == NULL)
1901 {
1902 return 0;
1903 }
1904
1905 new_size = CalcUniToStr(s);
1906 if (new_size == 0)
1907 {
1908 if (size >= 1)
1909 {
1910 StrCpy(str, 0, "");
1911 }
1912 return 0;
1913 }
1914 tmp = Malloc(new_size);
1915 tmp[0] = 0;
1916 wcstombs(tmp, s, new_size);
1917 tmp[new_size - 1] = 0;
1918 ret = StrCpy(str, size, tmp);
1919 Free(tmp);
1920
1921 return ret;
1922 #else // OS_WIN32
1923 return UnixUniToStr(str, size, s);
1924 #endif // OS_WIN32
1925 }
1926
1927 // Get the required number of bytes to convert Unicode string to the ANSI string
CalcUniToStr(wchar_t * s)1928 UINT CalcUniToStr(wchar_t *s)
1929 {
1930 #ifdef OS_WIN32
1931 UINT ret;
1932 // Validate arguments
1933 if (s == NULL)
1934 {
1935 return 0;
1936 }
1937
1938 ret = (UINT)wcstombs(NULL, s, UniStrLen(s));
1939 if (ret == (UINT)-1)
1940 {
1941 return 0;
1942 }
1943
1944 return ret + 1;
1945 #else // OS_WIN32
1946 return UnixCalcUniToStr(s);
1947 #endif // OS_WIN32
1948 }
1949
1950 // Converted an ANSI string to a Unicode string
StrToUni(wchar_t * s,UINT size,char * str)1951 UINT StrToUni(wchar_t *s, UINT size, char *str)
1952 {
1953 #ifdef OS_WIN32
1954 UINT ret;
1955 wchar_t *tmp;
1956 UINT new_size;
1957 // Validate arguments
1958 if (s == NULL || str == NULL)
1959 {
1960 return 0;
1961 }
1962
1963 new_size = CalcStrToUni(str);
1964 if (new_size == 0)
1965 {
1966 if (size >= 2)
1967 {
1968 UniStrCpy(s, 0, L"");
1969 }
1970 return 0;
1971 }
1972 tmp = Malloc(new_size);
1973 tmp[0] = 0;
1974 mbstowcs(tmp, str, StrLen(str));
1975 tmp[(new_size - 1) / sizeof(wchar_t)] = 0;
1976 ret = UniStrCpy(s, size, tmp);
1977 Free(tmp);
1978
1979 return ret;
1980 #else // OS_WIN32
1981 return UnixStrToUni(s, size, str);
1982 #endif // OS_WIN32
1983 }
1984
1985 // Get the required buffer size for converting an ANSI string to an Unicode string
CalcStrToUni(char * str)1986 UINT CalcStrToUni(char *str)
1987 {
1988 #ifdef OS_WIN32
1989 UINT ret;
1990 // Validate arguments
1991 if (str == NULL)
1992 {
1993 return 0;
1994 }
1995
1996 ret = (UINT)mbstowcs(NULL, str, StrLen(str));
1997 if (ret == (UINT)-1)
1998 {
1999 return 0;
2000 }
2001
2002 return (ret + 1) * sizeof(wchar_t);
2003 #else // OS_WIN32
2004 return UnixCalcStrToUni(str);
2005 #endif // OS_WIN32
2006 }
2007
2008 // Convert the UTF-8 strings to a Unicode string
Utf8ToUni(wchar_t * s,UINT size,BYTE * u,UINT u_size)2009 UINT Utf8ToUni(wchar_t *s, UINT size, BYTE *u, UINT u_size)
2010 {
2011 UINT i, wp, num;
2012 // Validate arguments
2013 if (s == NULL || u == NULL)
2014 {
2015 return 0;
2016 }
2017 if (size == 0)
2018 {
2019 size = 0x3fffffff;
2020 }
2021 if (u_size == 0)
2022 {
2023 u_size = StrLen((char *)u);
2024 }
2025
2026 i = 0;
2027 wp = 0;
2028 num = 0;
2029 while (true)
2030 {
2031 UINT type;
2032 wchar_t c;
2033 BYTE c1, c2;
2034
2035 type = GetUtf8Type(u, u_size, i);
2036 if (type == 0)
2037 {
2038 break;
2039 }
2040 switch (type)
2041 {
2042 case 1:
2043 c1 = 0;
2044 c2 = u[i];
2045 break;
2046 case 2:
2047 c1 = (((u[i] & 0x1c) >> 2) & 0x07);
2048 c2 = (((u[i] & 0x03) << 6) & 0xc0) | (u[i + 1] & 0x3f);
2049 break;
2050 case 3:
2051 c1 = ((((u[i] & 0x0f) << 4) & 0xf0)) | (((u[i + 1] & 0x3c) >> 2) & 0x0f);
2052 c2 = (((u[i + 1] & 0x03) << 6) & 0xc0) | (u[i + 2] & 0x3f);
2053 break;
2054 }
2055 i += type;
2056
2057 c = 0;
2058
2059 if (IsBigEndian())
2060 {
2061 if (sizeof(wchar_t) == 2)
2062 {
2063 ((BYTE *)&c)[0] = c1;
2064 ((BYTE *)&c)[1] = c2;
2065 }
2066 else
2067 {
2068 ((BYTE *)&c)[2] = c1;
2069 ((BYTE *)&c)[3] = c2;
2070 }
2071 }
2072 else
2073 {
2074 ((BYTE *)&c)[0] = c2;
2075 ((BYTE *)&c)[1] = c1;
2076 }
2077
2078 if (wp < ((size / sizeof(wchar_t)) - 1))
2079 {
2080 s[wp++] = c;
2081 num++;
2082 }
2083 else
2084 {
2085 break;
2086 }
2087 }
2088
2089 if (wp < (size / sizeof(wchar_t)))
2090 {
2091 s[wp++] = 0;
2092 }
2093
2094 return num;
2095 }
2096
2097 // Get the buffer size when converted UTF-8 to Unicode
CalcUtf8ToUni(BYTE * u,UINT u_size)2098 UINT CalcUtf8ToUni(BYTE *u, UINT u_size)
2099 {
2100 // Validate arguments
2101 if (u == NULL)
2102 {
2103 return 0;
2104 }
2105 if (u_size == 0)
2106 {
2107 u_size = StrLen((char *)u);
2108 }
2109
2110 return (Utf8Len(u, u_size) + 1) * sizeof(wchar_t);
2111 }
2112
2113 // Get the number of characters in UTF-8 string
Utf8Len(BYTE * u,UINT size)2114 UINT Utf8Len(BYTE *u, UINT size)
2115 {
2116 UINT i, num;
2117 // Validate arguments
2118 if (u == NULL)
2119 {
2120 return 0;
2121 }
2122 if (size == 0)
2123 {
2124 size = StrLen((char *)u);
2125 }
2126
2127 i = num = 0;
2128 while (true)
2129 {
2130 UINT type;
2131
2132 type = GetUtf8Type(u, size, i);
2133 if (type == 0)
2134 {
2135 break;
2136 }
2137 i += type;
2138 num++;
2139 }
2140
2141 return num;
2142 }
2143
2144 // Convert an Unicode string to UTF-8 string
UniToUtf8(BYTE * u,UINT size,wchar_t * s)2145 UINT UniToUtf8(BYTE *u, UINT size, wchar_t *s)
2146 {
2147 UINT i, len, type, wp;
2148 // Validate arguments
2149 if (u == NULL || s == NULL)
2150 {
2151 return 0;
2152 }
2153 if (size == 0)
2154 {
2155 size = 0x3fffffff;
2156 }
2157
2158 len = UniStrLen(s);
2159 wp = 0;
2160 for (i = 0;i < len;i++)
2161 {
2162 BYTE c1, c2;
2163 wchar_t c = s[i];
2164
2165 if (IsBigEndian())
2166 {
2167 if (sizeof(wchar_t) == 2)
2168 {
2169 c1 = ((BYTE *)&c)[0];
2170 c2 = ((BYTE *)&c)[1];
2171 }
2172 else
2173 {
2174 c1 = ((BYTE *)&c)[2];
2175 c2 = ((BYTE *)&c)[3];
2176 }
2177 }
2178 else
2179 {
2180 c1 = ((BYTE *)&c)[1];
2181 c2 = ((BYTE *)&c)[0];
2182 }
2183
2184 type = GetUniType(s[i]);
2185 switch (type)
2186 {
2187 case 1:
2188 if (wp < size)
2189 {
2190 u[wp++] = c2;
2191 }
2192 break;
2193 case 2:
2194 if (wp < size)
2195 {
2196 u[wp++] = 0xc0 | (((((c1 & 0x07) << 2) & 0x1c)) | (((c2 & 0xc0) >> 6) & 0x03));
2197 }
2198 if (wp < size)
2199 {
2200 u[wp++] = 0x80 | (c2 & 0x3f);
2201 }
2202 break;
2203 case 3:
2204 if (wp < size)
2205 {
2206 u[wp++] = 0xe0 | (((c1 & 0xf0) >> 4) & 0x0f);
2207 }
2208 if (wp < size)
2209 {
2210 u[wp++] = 0x80 | (((c1 & 0x0f) << 2) & 0x3c) | (((c2 & 0xc0) >> 6) & 0x03);
2211 }
2212 if (wp < size)
2213 {
2214 u[wp++] = 0x80 | (c2 & 0x3f);
2215 }
2216 break;
2217 }
2218 }
2219 if (wp < size)
2220 {
2221 u[wp] = 0;
2222 }
2223 return wp;
2224 }
2225
2226 // Calculating the length of the string when converting Unicode string to UTF-8 string
CalcUniToUtf8(wchar_t * s)2227 UINT CalcUniToUtf8(wchar_t *s)
2228 {
2229 UINT i, len, size;
2230 // Validate arguments
2231 if (s == NULL)
2232 {
2233 return 0;
2234 }
2235
2236 size = 0;
2237 len = UniStrLen(s);
2238 for (i = 0;i < len;i++)
2239 {
2240 size += GetUniType(s[i]);
2241 }
2242
2243 return size;
2244 }
2245
2246 // 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)2247 UINT GetUtf8Type(BYTE *s, UINT size, UINT offset)
2248 {
2249 // Validate arguments
2250 if (s == NULL)
2251 {
2252 return 0;
2253 }
2254 if ((offset + 1) > size)
2255 {
2256 return 0;
2257 }
2258 if ((s[offset] & 0x80) == 0)
2259 {
2260 // 1 byte
2261 return 1;
2262 }
2263 if ((s[offset] & 0x20) == 0)
2264 {
2265 // 2 bytes
2266 if ((offset + 2) > size)
2267 {
2268 return 0;
2269 }
2270 return 2;
2271 }
2272 // 3 bytes
2273 if ((offset + 3) > size)
2274 {
2275 return 0;
2276 }
2277 return 3;
2278 }
2279
2280 // Type of the converted character 'c' to UTF-8 (in bytes)
GetUniType(wchar_t c)2281 UINT GetUniType(wchar_t c)
2282 {
2283 BYTE c1, c2;
2284
2285 if (IsBigEndian())
2286 {
2287 if (sizeof(wchar_t) == 2)
2288 {
2289 c1 = ((BYTE *)&c)[0];
2290 c2 = ((BYTE *)&c)[1];
2291 }
2292 else
2293 {
2294 c1 = ((BYTE *)&c)[2];
2295 c2 = ((BYTE *)&c)[3];
2296 }
2297 }
2298 else
2299 {
2300 c1 = ((BYTE *)&c)[1];
2301 c2 = ((BYTE *)&c)[0];
2302 }
2303
2304 if (c1 == 0)
2305 {
2306 if (c2 <= 0x7f)
2307 {
2308 // 1 byte
2309 return 1;
2310 }
2311 else
2312 {
2313 // 2 bytes
2314 return 2;
2315 }
2316 }
2317 if ((c1 & 0xf8) == 0)
2318 {
2319 // 2 bytes
2320 return 2;
2321 }
2322 // 3 bytes
2323 return 3;
2324 }
2325
2326 // String replacing (case-insensitive)
UniReplaceStri(wchar_t * dst,UINT size,wchar_t * string,wchar_t * old_keyword,wchar_t * new_keyword)2327 UINT UniReplaceStri(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword)
2328 {
2329 return UniReplaceStrEx(dst, size, string, old_keyword, new_keyword, false);
2330 }
2331
2332 // String replacing (case-sensitive)
UniReplaceStr(wchar_t * dst,UINT size,wchar_t * string,wchar_t * old_keyword,wchar_t * new_keyword)2333 UINT UniReplaceStr(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword)
2334 {
2335 return UniReplaceStrEx(dst, size, string, old_keyword, new_keyword, true);
2336 }
2337
2338 // Replacement of string
UniReplaceStrEx(wchar_t * dst,UINT size,wchar_t * string,wchar_t * old_keyword,wchar_t * new_keyword,bool case_sensitive)2339 UINT UniReplaceStrEx(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword, bool case_sensitive)
2340 {
2341 UINT i, j, num, len_string, len_old, len_new, len_ret, wp;
2342 wchar_t *ret;
2343 // Validate arguments
2344 if (string == NULL || old_keyword == NULL || new_keyword == NULL)
2345 {
2346 return 0;
2347 }
2348
2349 // Get the length of the string
2350 len_string = UniStrLen(string);
2351 len_old = UniStrLen(old_keyword);
2352 len_new = UniStrLen(new_keyword);
2353
2354 // Get the final string length
2355 len_ret = UniCalcReplaceStrEx(string, old_keyword, new_keyword, case_sensitive);
2356 // Memory allocation
2357 ret = Malloc((len_ret + 1) * sizeof(wchar_t));
2358 ret[len_ret] = 0;
2359
2360 // Search and Replace
2361 i = j = num = wp = 0;
2362 while (true)
2363 {
2364 i = UniSearchStrEx(string, old_keyword, i, case_sensitive);
2365 if (i == INFINITE)
2366 {
2367 Copy(&ret[wp], &string[j], (len_string - j) * sizeof(wchar_t));
2368 wp += len_string - j;
2369 break;
2370 }
2371 num++;
2372 Copy(&ret[wp], &string[j], (i - j) * sizeof(wchar_t));
2373 wp += i - j;
2374 Copy(&ret[wp], new_keyword, len_new * sizeof(wchar_t));
2375 wp += len_new;
2376 i += len_old;
2377 j = i;
2378 }
2379
2380 // Copy of the search results
2381 UniStrCpy(dst, size, ret);
2382
2383 // Memory release
2384 Free(ret);
2385
2386 return num;
2387 }
2388
2389 // Calculate the length of the result of string replacement
UniCalcReplaceStrEx(wchar_t * string,wchar_t * old_keyword,wchar_t * new_keyword,bool case_sensitive)2390 UINT UniCalcReplaceStrEx(wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword, bool case_sensitive)
2391 {
2392 UINT i, num;
2393 UINT len_string, len_old, len_new;
2394 // Validate arguments
2395 if (string == NULL || old_keyword == NULL || new_keyword == NULL)
2396 {
2397 return 0;
2398 }
2399
2400 // Get the length of the string
2401 len_string = UniStrLen(string);
2402 len_old = UniStrLen(old_keyword);
2403 len_new = UniStrLen(new_keyword);
2404
2405 if (len_old == len_new)
2406 {
2407 return len_string;
2408 }
2409
2410 // Search process
2411 num = 0;
2412 i = 0;
2413 while (true)
2414 {
2415 i = UniSearchStrEx(string, old_keyword, i, case_sensitive);
2416 if (i == INFINITE)
2417 {
2418 break;
2419 }
2420 i += len_old;
2421 num++;
2422 }
2423
2424 // Calculation
2425 return len_string + len_new * num - len_old * num;
2426 }
2427
2428 // Search for a string (distinguish between upper / lower case)
UniSearchStr(wchar_t * string,wchar_t * keyword,UINT start)2429 UINT UniSearchStr(wchar_t *string, wchar_t *keyword, UINT start)
2430 {
2431 return UniSearchStrEx(string, keyword, start, true);
2432 }
2433
2434 // Search for a string (Don't distinguish between upper / lower case)
UniSearchStri(wchar_t * string,wchar_t * keyword,UINT start)2435 UINT UniSearchStri(wchar_t *string, wchar_t *keyword, UINT start)
2436 {
2437 return UniSearchStrEx(string, keyword, start, false);
2438 }
2439
2440 // Return the position of the first found of the keyword in the string
2441 // (Found in first character: returns 0, Not found: returns INFINITE)
UniSearchStrEx(wchar_t * string,wchar_t * keyword,UINT start,bool case_sensitive)2442 UINT UniSearchStrEx(wchar_t *string, wchar_t *keyword, UINT start, bool case_sensitive)
2443 {
2444 UINT len_string, len_keyword;
2445 UINT i;
2446 wchar_t *cmp_string, *cmp_keyword;
2447 bool found;
2448 // Validate arguments
2449 if (string == NULL || keyword == NULL)
2450 {
2451 return INFINITE;
2452 }
2453
2454 // Get the length of string
2455 len_string = UniStrLen(string);
2456 if (len_string <= start)
2457 {
2458 // Value of start is invalid
2459 return INFINITE;
2460 }
2461
2462 // Get the length of the keyword
2463 len_keyword = UniStrLen(keyword);
2464 if (len_keyword == 0)
2465 {
2466 // There is no keyword
2467 return INFINITE;
2468 }
2469
2470 if (len_string < len_keyword)
2471 {
2472 return INFINITE;
2473 }
2474
2475 if (len_string == len_keyword)
2476 {
2477 if (case_sensitive)
2478 {
2479 if (UniStrCmp(string, keyword) == 0)
2480 {
2481 return 0;
2482 }
2483 else
2484 {
2485 return INFINITE;
2486 }
2487 }
2488 else
2489 {
2490 if (UniStrCmpi(string, keyword) == 0)
2491 {
2492 return 0;
2493 }
2494 else
2495 {
2496 return INFINITE;
2497 }
2498 }
2499 }
2500
2501 if (case_sensitive)
2502 {
2503 cmp_string = string;
2504 cmp_keyword = keyword;
2505 }
2506 else
2507 {
2508 cmp_string = Malloc((len_string + 1) * sizeof(wchar_t));
2509 UniStrCpy(cmp_string, (len_string + 1) * sizeof(wchar_t), string);
2510 cmp_keyword = Malloc((len_keyword + 1) * sizeof(wchar_t));
2511 UniStrCpy(cmp_keyword, (len_keyword + 1) * sizeof(wchar_t), keyword);
2512 UniStrUpper(cmp_string);
2513 UniStrUpper(cmp_keyword);
2514 }
2515
2516 // Search
2517 found = false;
2518 for (i = start;i < (len_string - len_keyword + 1);i++)
2519 {
2520 // Compare
2521 if (!wcsncmp(&cmp_string[i], cmp_keyword, len_keyword))
2522 {
2523 // Found
2524 found = true;
2525 break;
2526 }
2527 }
2528
2529 if (case_sensitive == false)
2530 {
2531 // Memory release
2532 Free(cmp_keyword);
2533 Free(cmp_string);
2534 }
2535
2536 if (found == false)
2537 {
2538 return INFINITE;
2539 }
2540 return i;
2541 }
2542
2543 // Release of the token list
UniFreeToken(UNI_TOKEN_LIST * tokens)2544 void UniFreeToken(UNI_TOKEN_LIST *tokens)
2545 {
2546 UINT i;
2547 if (tokens == NULL)
2548 {
2549 return;
2550 }
2551 for (i = 0;i < tokens->NumTokens;i++)
2552 {
2553 Free(tokens->Token[i]);
2554 }
2555 Free(tokens->Token);
2556 Free(tokens);
2557 }
2558
2559 // Parse token for UNIX
UnixUniParseToken(wchar_t * src,wchar_t * separator)2560 UNI_TOKEN_LIST *UnixUniParseToken(wchar_t *src, wchar_t *separator)
2561 {
2562 UNI_TOKEN_LIST *ret;
2563 TOKEN_LIST *t;
2564 char *src_s;
2565 char *sep_s;
2566
2567 // Validate arguments
2568 if (src == NULL || separator == NULL)
2569 {
2570 ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
2571 ret->Token = ZeroMalloc(0);
2572 return ret;
2573 }
2574
2575 src_s = CopyUniToStr(src);
2576 sep_s = CopyUniToStr(separator);
2577
2578 t = ParseToken(src_s, sep_s);
2579
2580 ret = TokenListToUniTokenList(t);
2581 FreeToken(t);
2582
2583 Free(src_s);
2584 Free(sep_s);
2585
2586 return ret;
2587 }
2588
2589 // Parse the token
UniParseToken(wchar_t * src,wchar_t * separator)2590 UNI_TOKEN_LIST *UniParseToken(wchar_t *src, wchar_t *separator)
2591 {
2592 #ifdef OS_WIN32
2593 UNI_TOKEN_LIST *ret;
2594 wchar_t *tmp;
2595 wchar_t *str1, *str2;
2596 UINT len, num;
2597
2598 #ifdef OS_UNIX
2599 wchar_t *state = NULL;
2600 #endif // OS_UNIX
2601
2602 // Validate arguments
2603 if (src == NULL)
2604 {
2605 ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));
2606 ret->Token = ZeroMalloc(0);
2607 return ret;
2608 }
2609 if (separator == NULL)
2610 {
2611 separator = L" .\t\r\n";
2612 }
2613 len = UniStrLen(src);
2614 str1 = Malloc((len + 1) * sizeof(wchar_t));
2615 str2 = Malloc((len + 1) * sizeof(wchar_t));
2616 UniStrCpy(str1, 0, src);
2617 UniStrCpy(str2, 0, src);
2618
2619 Lock(token_lock);
2620 {
2621 tmp = wcstok(str1, separator
2622 #ifdef OS_UNIX
2623 , &state
2624 #endif // OS_UNIX
2625 );
2626 num = 0;
2627 while (tmp != NULL)
2628 {
2629 num++;
2630 tmp = wcstok(NULL, separator
2631 #ifdef OS_UNIX
2632 , &state
2633 #endif // OS_UNIX
2634 );
2635 }
2636 ret = Malloc(sizeof(UNI_TOKEN_LIST));
2637 ret->NumTokens = num;
2638 ret->Token = (wchar_t **)Malloc(sizeof(wchar_t *) * num);
2639 num = 0;
2640 tmp = wcstok(str2, separator
2641 #ifdef OS_UNIX
2642 , &state
2643 #endif // OS_UNIX
2644 );
2645 while (tmp != NULL)
2646 {
2647 ret->Token[num] = (wchar_t *)Malloc((UniStrLen(tmp) + 1) * sizeof(wchar_t));
2648 UniStrCpy(ret->Token[num], 0, tmp);
2649 num++;
2650 tmp = wcstok(NULL, separator
2651 #ifdef OS_UNIX
2652 , &state
2653 #endif // OS_UNIX
2654 );
2655 }
2656 }
2657 Unlock(token_lock);
2658
2659 Free(str1);
2660 Free(str2);
2661 return ret;
2662 #else // OS_WIN32
2663 return UnixUniParseToken(src, separator);
2664 #endif // OS_WIN32
2665 }
2666
2667 // Get a line from standard input
UniGetLine(wchar_t * str,UINT size)2668 bool UniGetLine(wchar_t *str, UINT size)
2669 {
2670 #ifdef OS_WIN32
2671 return UniGetLineWin32(str, size);
2672 #else // OS_WIN32
2673 return UniGetLineUnix(str, size);
2674 #endif // OS_WIN32
2675 }
AnsiGetLineUnix(char * str,UINT size)2676 void AnsiGetLineUnix(char *str, UINT size)
2677 {
2678 // Validate arguments
2679 if (str == NULL)
2680 {
2681 char tmp[MAX_SIZE];
2682 fgets(tmp, sizeof(tmp) - 1, stdin);
2683 return;
2684 }
2685 if (size <= 1)
2686 {
2687 return;
2688 }
2689
2690 // Read data from standard input
2691 fgets(str, (int)(size - 1), stdin);
2692
2693 TrimCrlf(str);
2694 }
UniGetLineUnix(wchar_t * str,UINT size)2695 bool UniGetLineUnix(wchar_t *str, UINT size)
2696 {
2697 char *str_a;
2698 UINT str_a_size = size;
2699 if (str == NULL || size < sizeof(wchar_t))
2700 {
2701 return false;
2702 }
2703 if (str_a_size >= 0x7fffffff)
2704 {
2705 str_a_size = MAX_SIZE;
2706 }
2707 str_a_size *= 2;
2708
2709 str_a = ZeroMalloc(str_a_size);
2710
2711 AnsiGetLineUnix(str_a, str_a_size);
2712
2713 StrToUni(str, size, str_a);
2714
2715 Free(str_a);
2716
2717 return true;
2718 }
UniGetLineWin32(wchar_t * str,UINT size)2719 bool UniGetLineWin32(wchar_t *str, UINT size)
2720 {
2721 bool ret = false;
2722
2723 #ifdef OS_WIN32
2724 ret = Win32InputW(str, size);
2725 #endif // OS_WIN32
2726
2727 return ret;
2728 }
2729
2730 // Remove '\r\n' at the end
UniTrimCrlf(wchar_t * str)2731 void UniTrimCrlf(wchar_t *str)
2732 {
2733 UINT len;
2734 // Validate arguments
2735 if (str == NULL)
2736 {
2737 return;
2738 }
2739 len = UniStrLen(str);
2740 if (len == 0)
2741 {
2742 return;
2743 }
2744
2745 if (str[len - 1] == L'\n')
2746 {
2747 if (len >= 2 && str[len - 2] == L'\r')
2748 {
2749 str[len - 2] = 0;
2750 }
2751 str[len - 1] = 0;
2752 }
2753 else if(str[len - 1] == L'\r')
2754 {
2755 str[len - 1] = 0;
2756 }
2757 }
2758
2759 // Remove white space of the both side of the string
UniTrim(wchar_t * str)2760 void UniTrim(wchar_t *str)
2761 {
2762 // Validate arguments
2763 if (str == NULL)
2764 {
2765 return;
2766 }
2767
2768 UniTrimLeft(str);
2769 UniTrimRight(str);
2770 }
2771
2772 // Remove white space on the right side of the string
UniTrimRight(wchar_t * str)2773 void UniTrimRight(wchar_t *str)
2774 {
2775 wchar_t *buf, *tmp;
2776 UINT len, i, wp, wp2;
2777 bool flag;
2778 // Validate arguments
2779 if (str == NULL)
2780 {
2781 return;
2782 }
2783 len = UniStrLen(str);
2784 if (len == 0)
2785 {
2786 return;
2787 }
2788 if (str[len - 1] != L' ' && str[len - 1] != L'\t')
2789 {
2790 return;
2791 }
2792
2793 buf = Malloc((len + 1) * sizeof(wchar_t));
2794 tmp = Malloc((len + 1) * sizeof(wchar_t));
2795 flag = false;
2796 wp = wp2 = 0;
2797 for (i = 0;i < len;i++)
2798 {
2799 if (str[i] != L' ' && str[i] != L'\t')
2800 {
2801 Copy(&buf[wp], tmp, wp2 * sizeof(wchar_t));
2802 wp += wp2;
2803 wp2 = 0;
2804 buf[wp++] = str[i];
2805 }
2806 else
2807 {
2808 tmp[wp2++] = str[i];
2809 }
2810 }
2811 buf[wp] = 0;
2812 UniStrCpy(str, 0, buf);
2813 Free(buf);
2814 Free(tmp);
2815 }
2816
2817 // Remove white space from the left side of the string
UniTrimLeft(wchar_t * str)2818 void UniTrimLeft(wchar_t *str)
2819 {
2820 wchar_t *buf;
2821 UINT len, i, wp;
2822 bool flag;
2823 // Validate arguments
2824 if (str == NULL)
2825 {
2826 return;
2827 }
2828 len = UniStrLen(str);
2829 if (len == 0)
2830 {
2831 return;
2832 }
2833 if (str[0] != L' ' && str[0] != L'\t')
2834 {
2835 return;
2836 }
2837
2838 buf = Malloc((len + 1) * sizeof(wchar_t));
2839 flag = false;
2840 wp = 0;
2841 for (i = 0;i < len;i++)
2842 {
2843 if (str[i] != L' ' && str[i] != L'\t')
2844 {
2845 flag = true;
2846 }
2847 if (flag)
2848 {
2849 buf[wp++] = str[i];
2850 }
2851 }
2852 buf[wp] = 0;
2853 UniStrCpy(str, 0, buf);
2854 Free(buf);
2855 }
2856
2857 // Convert an integer to a hexadecimal string (8-digit fixed)
UniToStrx8(wchar_t * str,UINT i)2858 void UniToStrx8(wchar_t *str, UINT i)
2859 {
2860 UniFormat(str, 0, L"0x%08x", i);
2861 }
2862
2863 // Convert an integer to a hexadecimal string
UniToStrx(wchar_t * str,UINT i)2864 void UniToStrx(wchar_t *str, UINT i)
2865 {
2866 UniFormat(str, 0, L"0x%02x", i);
2867 }
2868
2869 // Convert a signed integer to a string
UniToStri(wchar_t * str,int i)2870 void UniToStri(wchar_t *str, int i)
2871 {
2872 UniFormat(str, 0, L"%i", i);
2873 }
2874
2875 // Convert an integer to a string
UniToStru(wchar_t * str,UINT i)2876 void UniToStru(wchar_t *str, UINT i)
2877 {
2878 UniFormat(str, 0, L"%u", i);
2879 }
2880
2881 // Convert the string to signed integer
UniToInti(wchar_t * str)2882 int UniToInti(wchar_t *str)
2883 {
2884 char tmp[128];
2885 // Validate arguments
2886 if (str == NULL)
2887 {
2888 return 0;
2889 }
2890
2891 UniToStrForSingleChars(tmp, sizeof(tmp), str);
2892
2893 return ToInt(tmp);
2894 }
2895
2896 // Convert a string to an integer
UniToInt(wchar_t * str)2897 UINT UniToInt(wchar_t *str)
2898 {
2899 char tmp[128];
2900 // Validate arguments
2901 if (str == NULL)
2902 {
2903 return 0;
2904 }
2905
2906 UniToStrForSingleChars(tmp, sizeof(tmp), str);
2907
2908 return ToInti(tmp);
2909 }
2910
2911 // Convert only single-byte characters in the Unicode string to a char string
UniToStrForSingleChars(char * dst,UINT dst_size,wchar_t * src)2912 void UniToStrForSingleChars(char *dst, UINT dst_size, wchar_t *src)
2913 {
2914 UINT i;
2915 // Validate arguments
2916 if (dst == NULL || src == NULL)
2917 {
2918 return;
2919 }
2920
2921 for (i = 0;i < UniStrLen(src) + 1;i++)
2922 {
2923 wchar_t s = src[i];
2924 char d;
2925
2926 if (s == 0)
2927 {
2928 d = 0;
2929 }
2930 else if (s <= 0xff)
2931 {
2932 d = (char)s;
2933 }
2934 else
2935 {
2936 d = ' ';
2937 }
2938
2939 dst[i] = d;
2940 }
2941 }
2942
2943 // Format string replacement for 64-bit
UniReplaceFormatStringFor64(wchar_t * fmt)2944 wchar_t *UniReplaceFormatStringFor64(wchar_t *fmt)
2945 {
2946 wchar_t *tmp;
2947 wchar_t *ret;
2948 UINT tmp_size;
2949 // Validate arguments
2950 if (fmt == NULL)
2951 {
2952 return NULL;
2953 }
2954
2955 tmp_size = UniStrSize(fmt) * 2;
2956 tmp = ZeroMalloc(tmp_size);
2957
2958 #ifdef OS_WIN32
2959 UniReplaceStrEx(tmp, tmp_size, fmt, L"%ll", L"%I64", false);
2960 #else // OS_WIN32
2961 UniReplaceStrEx(tmp, tmp_size, fmt, L"%I64", L"%ll", false);
2962
2963 if (1)
2964 {
2965 UINT i, len;
2966 bool f = false;
2967 len = UniStrLen(tmp);
2968 for (i = 0;i < len;i++)
2969 {
2970 if (tmp[i] == L'%')
2971 {
2972 f = true;
2973 }
2974
2975 if (f)
2976 {
2977 switch (tmp[i])
2978 {
2979 case L'c':
2980 case L'C':
2981 case L'd':
2982 case L'i':
2983 case L'o':
2984 case L'u':
2985 case L'x':
2986 case L'X':
2987 case L'e':
2988 case L'E':
2989 case L'f':
2990 case L'g':
2991 case L'G':
2992 case L'n':
2993 case L'p':
2994 case L's':
2995 case L'S':
2996 if (tmp[i] == L's')
2997 {
2998 tmp[i] = L'S';
2999 }
3000 else if (tmp[i] == L'S')
3001 {
3002 tmp[i] = L's';
3003 }
3004 f = false;
3005 break;
3006 }
3007 }
3008 }
3009 }
3010
3011 #endif // OS_WIN32
3012
3013 ret = CopyUniStr(tmp);
3014 Free(tmp);
3015
3016 return ret;
3017 }
3018
3019 // Get lines from a string
UniGetLines(wchar_t * str)3020 UNI_TOKEN_LIST *UniGetLines(wchar_t *str)
3021 {
3022 UINT i, len;
3023 BUF *b = NULL;
3024 LIST *o;
3025 UNI_TOKEN_LIST *ret;
3026 // Validate arguments
3027 if (str == NULL)
3028 {
3029 return UniNullToken();
3030 }
3031
3032 o = NewListFast(NULL);
3033
3034 len = UniStrLen(str);
3035
3036 b = NewBuf();
3037
3038 for (i = 0;i < len;i++)
3039 {
3040 wchar_t c = str[i];
3041 bool f = false;
3042
3043 if (c == L'\r')
3044 {
3045 if (str[i + 1] == L'\n')
3046 {
3047 i++;
3048 }
3049 f = true;
3050 }
3051 else if (c == L'\n')
3052 {
3053 f = true;
3054 }
3055
3056 if (f)
3057 {
3058 wchar_t zero = 0;
3059 wchar_t *s;
3060 WriteBuf(b, &zero, sizeof(wchar_t));
3061
3062 s = (wchar_t *)b->Buf;
3063
3064 Add(o, UniCopyStr(s));
3065
3066 ClearBuf(b);
3067 }
3068 else
3069 {
3070 WriteBuf(b, &c, sizeof(wchar_t));
3071 }
3072 }
3073
3074 if (true)
3075 {
3076 wchar_t zero = 0;
3077 wchar_t *s;
3078 WriteBuf(b, &zero, sizeof(wchar_t));
3079
3080 s = (wchar_t *)b->Buf;
3081
3082 Add(o, UniCopyStr(s));
3083
3084 ClearBuf(b);
3085 }
3086
3087 FreeBuf(b);
3088
3089 ret = UniListToTokenList(o);
3090
3091 UniFreeStrList(o);
3092
3093 return ret;
3094 }
3095
3096 // Display the string on the screen
UniPrintStr(wchar_t * string)3097 void UniPrintStr(wchar_t *string)
3098 {
3099 // Validate arguments
3100 if (string == NULL)
3101 {
3102 return;
3103 }
3104
3105 #ifdef OS_UNIX
3106 if (true)
3107 {
3108 char *str = CopyUniToStr(string);
3109
3110 if (str != NULL)
3111 {
3112 fputs(str, stdout);
3113 }
3114 else
3115 {
3116 fputs("", stdout);
3117 }
3118
3119 Free(str);
3120 }
3121 #else // OS_UNIX
3122 Win32PrintW(string);
3123 #endif // OS_UNIX
3124 }
3125
3126 // Display a string with arguments
UniPrintArgs(wchar_t * fmt,va_list args)3127 void UniPrintArgs(wchar_t *fmt, va_list args)
3128 {
3129 wchar_t *str;
3130 // Validate arguments
3131 if (fmt == NULL)
3132 {
3133 return;
3134 }
3135
3136 str = InternalFormatArgs(fmt, args, false);
3137
3138 UniPrintStr(str);
3139
3140 Free(str);
3141 }
3142
3143 // Display the string
UniPrint(wchar_t * fmt,...)3144 void UniPrint(wchar_t *fmt, ...)
3145 {
3146 va_list args;
3147 // Validate arguments
3148 if (fmt == NULL)
3149 {
3150 return;
3151 }
3152
3153 va_start(args, fmt);
3154 UniPrintArgs(fmt, args);
3155 va_end(args);
3156 }
3157
3158 // Display debug string with arguments
UniDebugArgs(wchar_t * fmt,va_list args)3159 void UniDebugArgs(wchar_t *fmt, va_list args)
3160 {
3161 if (g_debug == false)
3162 {
3163 return;
3164 }
3165
3166 UniPrintArgs(fmt, args);
3167 }
3168
3169 // Display a debug string
UniDebug(wchar_t * fmt,...)3170 void UniDebug(wchar_t *fmt, ...)
3171 {
3172 va_list args;
3173 // Validate arguments
3174 if (fmt == NULL)
3175 {
3176 return;
3177 }
3178
3179 va_start(args, fmt);
3180 UniDebugArgs(fmt, args);
3181 va_end(args);
3182 }
3183
3184 // Format a string (argument list)
UniFormatArgs(wchar_t * buf,UINT size,wchar_t * fmt,va_list args)3185 void UniFormatArgs(wchar_t *buf, UINT size, wchar_t *fmt, va_list args)
3186 {
3187 wchar_t *ret;
3188 // Validate arguments
3189 if (buf == NULL || fmt == NULL)
3190 {
3191 return;
3192 }
3193 if (size == 1)
3194 {
3195 return;
3196 }
3197
3198 // KS
3199 KS_INC(KS_FORMAT_COUNT);
3200
3201 ret = InternalFormatArgs(fmt, args, false);
3202
3203 UniStrCpy(buf, size, ret);
3204
3205 Free(ret);
3206 }
3207
3208 // Format the string, and copy it
CopyUniFormat(wchar_t * fmt,...)3209 wchar_t *CopyUniFormat(wchar_t *fmt, ...)
3210 {
3211 wchar_t *ret, *str;
3212 UINT size;
3213 va_list args;
3214 // Validate arguments
3215 if (fmt == NULL)
3216 {
3217 return NULL;
3218 }
3219
3220 size = MAX(UniStrSize(fmt) * 10, MAX_SIZE * 10);
3221 str = Malloc(size);
3222
3223 va_start(args, fmt);
3224 UniFormatArgs(str, size, fmt, args);
3225
3226 ret = UniCopyStr(str);
3227 Free(str);
3228 va_end(args);
3229
3230 return ret;
3231 }
3232
3233 // Format the string
UniFormat(wchar_t * buf,UINT size,wchar_t * fmt,...)3234 void UniFormat(wchar_t *buf, UINT size, wchar_t *fmt, ...)
3235 {
3236 va_list args;
3237 // Validate arguments
3238 if (buf == NULL || fmt == NULL)
3239 {
3240 return;
3241 }
3242
3243 va_start(args, fmt);
3244 UniFormatArgs(buf, size, fmt, args);
3245 va_end(args);
3246 }
3247
3248 // Flexible string comparison
UniSoftStrCmp(wchar_t * str1,wchar_t * str2)3249 int UniSoftStrCmp(wchar_t *str1, wchar_t *str2)
3250 {
3251 UINT ret;
3252 wchar_t *tmp1, *tmp2;
3253 // Validate arguments
3254 if (str1 == NULL && str2 == NULL)
3255 {
3256 return 0;
3257 }
3258 if (str1 == NULL)
3259 {
3260 return 1;
3261 }
3262 if (str2 == NULL)
3263 {
3264 return -1;
3265 }
3266
3267 tmp1 = CopyUniStr(str1);
3268 tmp2 = CopyUniStr(str2);
3269
3270 UniTrim(tmp1);
3271 UniTrim(tmp2);
3272
3273 ret = UniStrCmpi(tmp1, tmp2);
3274
3275 Free(tmp1);
3276 Free(tmp2);
3277
3278 return ret;
3279 }
3280
3281 // Compare the strings in case-insensitive mode
UniStrCmpi(wchar_t * str1,wchar_t * str2)3282 int UniStrCmpi(wchar_t *str1, wchar_t *str2)
3283 {
3284 UINT i;
3285 // Validate arguments
3286 if (str1 == NULL && str2 == NULL)
3287 {
3288 return 0;
3289 }
3290 if (str1 == NULL)
3291 {
3292 return 1;
3293 }
3294 if (str2 == NULL)
3295 {
3296 return -1;
3297 }
3298
3299 // String comparison
3300 i = 0;
3301 while (true)
3302 {
3303 wchar_t c1, c2;
3304 c1 = UniToUpper(str1[i]);
3305 c2 = UniToUpper(str2[i]);
3306 if (c1 > c2)
3307 {
3308 return 1;
3309 }
3310 else if (c1 < c2)
3311 {
3312 return -1;
3313 }
3314 if (str1[i] == 0 || str2[i] == 0)
3315 {
3316 return 0;
3317 }
3318 i++;
3319 }
3320 }
3321
3322 // Compare the string
UniStrCmp(wchar_t * str1,wchar_t * str2)3323 int UniStrCmp(wchar_t *str1, wchar_t *str2)
3324 {
3325 // Validate arguments
3326 if (str1 == NULL && str2 == NULL)
3327 {
3328 return 0;
3329 }
3330 if (str1 == NULL)
3331 {
3332 return 1;
3333 }
3334 if (str2 == NULL)
3335 {
3336 return -1;
3337 }
3338
3339 return wcscmp(str1, str2);
3340 }
3341
3342 // Uncapitalize the string
UniStrLower(wchar_t * str)3343 void UniStrLower(wchar_t *str)
3344 {
3345 UINT i, len;
3346 // Validate arguments
3347 if (str == NULL)
3348 {
3349 return;
3350 }
3351
3352 len = UniStrLen(str);
3353 for (i = 0;i < len;i++)
3354 {
3355 str[i] = UniToLower(str[i]);
3356 }
3357 }
3358
3359 // Capitalize the string
UniStrUpper(wchar_t * str)3360 void UniStrUpper(wchar_t *str)
3361 {
3362 UINT i, len;
3363 // Validate arguments
3364 if (str == NULL)
3365 {
3366 return;
3367 }
3368
3369 len = UniStrLen(str);
3370 for (i = 0;i < len;i++)
3371 {
3372 str[i] = UniToUpper(str[i]);
3373 }
3374 }
3375
3376 // Uncapitalize a character
UniToLower(wchar_t c)3377 wchar_t UniToLower(wchar_t c)
3378 {
3379 if (c >= L'A' && c <= L'Z')
3380 {
3381 c += L'a' - L'A';
3382 }
3383
3384 return c;
3385 }
3386
3387 // Capitalize a character
UniToUpper(wchar_t c)3388 wchar_t UniToUpper(wchar_t c)
3389 {
3390 if (c >= L'a' && c <= L'z')
3391 {
3392 c -= L'a' - L'A';
3393 }
3394
3395 return c;
3396 }
3397
3398 // String concatenation
UniStrCat(wchar_t * dst,UINT size,wchar_t * src)3399 UINT UniStrCat(wchar_t *dst, UINT size, wchar_t *src)
3400 {
3401 UINT len1, len2, len_test;
3402 // Validate arguments
3403 if (dst == NULL || src == NULL)
3404 {
3405 return 0;
3406 }
3407 if (size != 0 && size < sizeof(wchar_t))
3408 {
3409 return 0;
3410 }
3411 if (size == sizeof(wchar_t))
3412 {
3413 wcscpy(dst, L"");
3414 return 0;
3415 }
3416 if (size == 0)
3417 {
3418 // Ignore the length
3419 size = 0x3fffffff;
3420 }
3421
3422 len1 = UniStrLen(dst);
3423 len2 = UniStrLen(src);
3424 len_test = len1 + len2 + 1;
3425 if (len_test > (size / sizeof(wchar_t)))
3426 {
3427 if (len2 <= (len_test - (size / sizeof(wchar_t))))
3428 {
3429 return 0;
3430 }
3431 len2 -= len_test - (size / sizeof(wchar_t));
3432 }
3433 Copy(&dst[len1], src, len2 * sizeof(wchar_t));
3434 dst[len1 + len2] = 0;
3435
3436 return len1 + len2;
3437 }
UniStrCatLeft(wchar_t * dst,UINT size,wchar_t * src)3438 UINT UniStrCatLeft(wchar_t *dst, UINT size, wchar_t *src)
3439 {
3440 wchar_t *s;
3441 // Validate arguments
3442 if (dst == NULL || src == NULL)
3443 {
3444 return 0;
3445 }
3446
3447 s = UniCopyStr(dst);
3448 UniStrCpy(dst, size, s);
3449 UniStrCat(dst, size, src);
3450 Free(s);
3451
3452 return UniStrLen(dst);
3453 }
3454
3455 // String copy
UniStrCpy(wchar_t * dst,UINT size,wchar_t * src)3456 UINT UniStrCpy(wchar_t *dst, UINT size, wchar_t *src)
3457 {
3458 UINT len;
3459 // Validate arguments
3460 if (dst == NULL || src == NULL)
3461 {
3462 if (src == NULL && dst != NULL)
3463 {
3464 if (size >= sizeof(wchar_t))
3465 {
3466 dst[0] = L'\0';
3467 }
3468 }
3469 return 0;
3470 }
3471 if (dst == src)
3472 {
3473 return UniStrLen(src);
3474 }
3475 if (size != 0 && size < sizeof(wchar_t))
3476 {
3477 return 0;
3478 }
3479 if (size == sizeof(wchar_t))
3480 {
3481 wcscpy(dst, L"");
3482 return 0;
3483 }
3484 if (size == 0)
3485 {
3486 // Ignore the length
3487 size = 0x3fffffff;
3488 }
3489
3490 // Check the length
3491 len = UniStrLen(src);
3492 if (len <= (size / sizeof(wchar_t) - 1))
3493 {
3494 Copy(dst, src, (len + 1) * sizeof(wchar_t));
3495 }
3496 else
3497 {
3498 len = size / sizeof(wchar_t) - 1;
3499 Copy(dst, src, len * sizeof(wchar_t));
3500 dst[len] = 0;
3501 }
3502
3503 return len;
3504 }
3505
3506 // Check whether the character is within specified buffer size
UniCheckStrSize(wchar_t * str,UINT size)3507 bool UniCheckStrSize(wchar_t *str, UINT size)
3508 {
3509 // Validate arguments
3510 if (str == NULL || size <= 1)
3511 {
3512 return false;
3513 }
3514
3515 return UniCheckStrLen(str, size / sizeof(wchar_t) - 1);
3516 }
3517
3518 // Check whether the number of characters is within specified length
UniCheckStrLen(wchar_t * str,UINT len)3519 bool UniCheckStrLen(wchar_t *str, UINT len)
3520 {
3521 UINT count = 0;
3522 UINT i;
3523 // Validate arguments
3524 if (str == NULL)
3525 {
3526 return false;
3527 }
3528
3529 for (i = 0;;i++)
3530 {
3531 if (str[i] == 0)
3532 {
3533 return true;
3534 }
3535 count++;
3536 if (count > len)
3537 {
3538 return false;
3539 }
3540 }
3541 }
3542
3543 // Get the buffer size needed to store the string
UniStrSize(wchar_t * str)3544 UINT UniStrSize(wchar_t *str)
3545 {
3546 // Validate arguments
3547 if (str == NULL)
3548 {
3549 return 0;
3550 }
3551
3552 return (UniStrLen(str) + 1) * sizeof(wchar_t);
3553 }
3554
3555 // Get the length of the string
UniStrLen(wchar_t * str)3556 UINT UniStrLen(wchar_t *str)
3557 {
3558 UINT i;
3559 // Validate arguments
3560 if (str == NULL)
3561 {
3562 return 0;
3563 }
3564
3565 i = 0;
3566 while (true)
3567 {
3568 if (str[i] == 0)
3569 {
3570 break;
3571 }
3572 i++;
3573 }
3574
3575 return i;
3576 }
3577
3578