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