* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Mayaqua / Internat.c
1 // SoftEther UT-VPN SourceCode\r
2 // \r
3 // Copyright (C) 2004-2010 SoftEther Corporation.\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.\r
6 // All Rights Reserved.\r
7 // \r
8 // http://utvpn.tsukuba.ac.jp/\r
9 // \r
10 // This program is free software; you can redistribute it and/or\r
11 // modify it under the terms of the GNU General Public License\r
12 // version 2 as published by the Free Software Foundation.\r
13 // \r
14 // This program is distributed in the hope that it will be useful,\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
17 // GNU General Public License for more details.\r
18 // \r
19 // You should have received a copy of the GNU General Public License version 2\r
20 // along with this program; if not, write to the Free Software\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
22 // \r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
28 // \r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって\r
32 // ホストされています。\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
34 // および、試験または研究のために利用が行われることを想定して配布\r
35 // しています。\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
37 // あります。\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
42 // に組み込みさせていただきます。\r
43 // \r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
46 // \r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
51 // ください。\r
52 // \r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
58 // 公益保護にご協力いただきますようお願い申し上げます。\r
59 // \r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
62 // を保護するための努力を行います。\r
63 // \r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
65 // 日本国内の脆弱性情報届出受付公的機関:\r
66 //         独立行政法人 情報処理推進機構\r
67 //         http://www.ipa.go.jp/security/vuln/report/\r
68 // \r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/\r
71 \r
72 // -----------------------------------------------\r
73 // [ChangeLog]\r
74 // 2010.05.20\r
75 //  新規リリース by SoftEther\r
76 // -----------------------------------------------\r
77 \r
78 // Internat.c\r
79 // 国際化のための文字列変換ライブラリ\r
80 \r
81 #include <stdio.h>\r
82 #include <stdlib.h>\r
83 #include <string.h>\r
84 #include <wchar.h>\r
85 #include <stdarg.h>\r
86 #include <time.h>\r
87 #include <errno.h>\r
88 #include <Mayaqua/Mayaqua.h>\r
89 \r
90 extern LOCK *token_lock;\r
91 static char charset[MAX_SIZE] = "EUCJP";\r
92 static LOCK *iconv_lock = NULL;\r
93 void *iconv_cache_wide_to_str = 0;\r
94 void *iconv_cache_str_to_wide = 0;\r
95 \r
96 // 文字列が含まれているかどうかチェック\r
97 bool UniInStr(wchar_t *str, wchar_t *keyword)\r
98 {\r
99         return UniInStrEx(str, keyword, false);\r
100 }\r
101 bool UniInStrEx(wchar_t *str, wchar_t *keyword, bool case_sensitive)\r
102 {\r
103         // 引数チェック\r
104         if (UniIsEmptyStr(str) || UniIsEmptyStr(keyword))\r
105         {\r
106                 return false;\r
107         }\r
108 \r
109         if (UniSearchStrEx(str, keyword, 0, case_sensitive) == INFINITE)\r
110         {\r
111                 return false;\r
112         }\r
113 \r
114         return true;\r
115 }\r
116 \r
117 // バイナリデータに変換\r
118 BUF *UniStrToBin(wchar_t *str)\r
119 {\r
120         char *str_a = CopyUniToStr(str);\r
121         BUF *ret;\r
122 \r
123         ret = StrToBin(str_a);\r
124 \r
125         Free(str_a);\r
126 \r
127         return ret;\r
128 }\r
129 \r
130 // 指定した文字の列を生成する\r
131 wchar_t *UniMakeCharArray(wchar_t c, UINT count)\r
132 {\r
133         UINT i;\r
134         wchar_t *ret = Malloc(sizeof(wchar_t) * (count + 1));\r
135 \r
136         for (i = 0;i < count;i++)\r
137         {\r
138                 ret[i] = c;\r
139         }\r
140 \r
141         ret[count] = 0;\r
142 \r
143         return ret;\r
144 }\r
145 \r
146 // 安全な文字かどうかチェック\r
147 bool UniIsSafeChar(wchar_t c)\r
148 {\r
149         UINT i, len;\r
150         wchar_t *check_str =\r
151                 L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"\r
152                 L"abcdefghijklmnopqrstuvwxyz"\r
153                 L"0123456789"\r
154                 L" ()-_#%&.";\r
155 \r
156         len = UniStrLen(check_str);\r
157         for (i = 0;i < len;i++)\r
158         {\r
159                 if (c == check_str[i])\r
160                 {\r
161                         return true;\r
162                 }\r
163         }\r
164         return false;\r
165 }\r
166 \r
167 // トークンリストを文字列リストに変換する\r
168 LIST *UniTokenListToList(UNI_TOKEN_LIST *t)\r
169 {\r
170         UINT i;\r
171         LIST *o;\r
172         // 引数チェック\r
173         if (t == NULL)\r
174         {\r
175                 return NULL;\r
176         }\r
177 \r
178         o = NewListFast(NULL);\r
179         for (i = 0;i < t->NumTokens;i++)\r
180         {\r
181                 Insert(o, UniCopyStr(t->Token[i]));\r
182         }\r
183 \r
184         return o;\r
185 }\r
186 \r
187 // 文字列リストをトークンリストに変換する\r
188 UNI_TOKEN_LIST *UniListToTokenList(LIST *o)\r
189 {\r
190         UINT i;\r
191         UNI_TOKEN_LIST *t;\r
192         // 引数チェック\r
193         if (o == NULL)\r
194         {\r
195                 return NULL;\r
196         }\r
197 \r
198         t = ZeroMalloc(sizeof(UNI_TOKEN_LIST));\r
199         t->NumTokens = LIST_NUM(o);\r
200         t->Token = ZeroMalloc(sizeof(wchar_t *) * t->NumTokens);\r
201         for (i = 0;i < LIST_NUM(o);i++)\r
202         {\r
203                 t->Token[i] = UniCopyStr(LIST_DATA(o, i));\r
204         }\r
205 \r
206         return t;\r
207 }\r
208 \r
209 // 文字列リストを解放する\r
210 void UniFreeStrList(LIST *o)\r
211 {\r
212         UINT i;\r
213         // 引数チェック\r
214         if (o == NULL)\r
215         {\r
216                 return;\r
217         }\r
218 \r
219         for (i = 0;i < LIST_NUM(o);i++)\r
220         {\r
221                 wchar_t *s = LIST_DATA(o, i);\r
222                 Free(s);\r
223         }\r
224 \r
225         ReleaseList(o);\r
226 }\r
227 \r
228 // 文字列リストを文字列に変換する\r
229 BUF *UniStrListToStr(LIST *o)\r
230 {\r
231         BUF *b;\r
232         UINT i;\r
233         wchar_t c;\r
234         // 引数チェック\r
235         if (o == NULL)\r
236         {\r
237                 return NULL;\r
238         }\r
239         b = NewBuf();\r
240 \r
241         for (i = 0;i < LIST_NUM(o);i++)\r
242         {\r
243                 wchar_t *s = LIST_DATA(o, i);\r
244                 WriteBuf(b, s, UniStrSize(s));\r
245         }\r
246 \r
247         c = 0;\r
248         WriteBuf(b, &c, sizeof(c));\r
249 \r
250         SeekBuf(b, 0, 0);\r
251 \r
252         return b;\r
253 }\r
254 \r
255 // 文字列 (NULL区切り) をリストに変換する\r
256 LIST *UniStrToStrList(wchar_t *str, UINT size)\r
257 {\r
258         LIST *o;\r
259         wchar_t *tmp;\r
260         UINT tmp_size;\r
261         UINT i;\r
262         // 引数チェック\r
263         if (str == NULL)\r
264         {\r
265                 return NULL;\r
266         }\r
267 \r
268         o = NewListFast(NULL);\r
269 \r
270         i = 0;\r
271         while (true)\r
272         {\r
273                 if (i >= size)\r
274                 {\r
275                         break;\r
276                 }\r
277                 if (*str == 0)\r
278                 {\r
279                         break;\r
280                 }\r
281 \r
282                 tmp_size = UniStrSize(str);\r
283                 tmp = ZeroMalloc(tmp_size);\r
284                 UniStrCpy(tmp, tmp_size, str);\r
285                 Add(o, tmp);\r
286                 str += UniStrLen(str) + 1;\r
287                 i++;\r
288         }\r
289 \r
290         return o;\r
291 }\r
292 \r
293 // 改行コードを正規化する\r
294 wchar_t *UniNormalizeCrlf(wchar_t *str)\r
295 {\r
296         wchar_t *ret;\r
297         UINT ret_size, i, len, wp;\r
298         // 引数チェック\r
299         if (str == NULL)\r
300         {\r
301                 return NULL;\r
302         }\r
303 \r
304         len = UniStrLen(str);\r
305         ret_size = sizeof(wchar_t) * (len + 32) * 2;\r
306         ret = Malloc(ret_size);\r
307 \r
308         wp = 0;\r
309 \r
310         for (i = 0;i < len;i++)\r
311         {\r
312                 wchar_t c = str[i];\r
313 \r
314                 switch (c)\r
315                 {\r
316                 case L'\r':\r
317                         if (str[i + 1] == L'\n')\r
318                         {\r
319                                 i++;\r
320                         }\r
321                         ret[wp++] = L'\r';\r
322                         ret[wp++] = L'\n';\r
323                         break;\r
324 \r
325                 case L'\n':\r
326                         ret[wp++] = L'\r';\r
327                         ret[wp++] = L'\n';\r
328                         break;\r
329 \r
330                 default:\r
331                         ret[wp++] = c;\r
332                         break;\r
333                 }\r
334         }\r
335 \r
336         ret[wp++] = 0;\r
337 \r
338         return ret;\r
339 }\r
340 \r
341 // str が key で終了するかどうかチェック\r
342 bool UniEndWith(wchar_t *str, wchar_t *key)\r
343 {\r
344         UINT str_len;\r
345         UINT key_len;\r
346         // 引数チェック\r
347         if (str == NULL || key == NULL)\r
348         {\r
349                 return false;\r
350         }\r
351 \r
352         // 比較\r
353         str_len = UniStrLen(str);\r
354         key_len = UniStrLen(key);\r
355         if (str_len < key_len)\r
356         {\r
357                 return false;\r
358         }\r
359 \r
360         if (UniStrCmpi(str + (str_len - key_len), key) == 0)\r
361         {\r
362                 return true;\r
363         }\r
364         else\r
365         {\r
366                 return false;\r
367         }\r
368 }\r
369 \r
370 // str が key で始まるかどうかチェック\r
371 bool UniStartWith(wchar_t *str, wchar_t *key)\r
372 {\r
373         UINT str_len;\r
374         UINT key_len;\r
375         wchar_t *tmp;\r
376         bool ret;\r
377         // 引数チェック\r
378         if (str == NULL || key == NULL)\r
379         {\r
380                 return false;\r
381         }\r
382 \r
383         // 比較\r
384         str_len = UniStrLen(str);\r
385         key_len = UniStrLen(key);\r
386         if (str_len < key_len)\r
387         {\r
388                 return false;\r
389         }\r
390         if (str_len == 0 || key_len == 0)\r
391         {\r
392                 return false;\r
393         }\r
394         tmp = CopyUniStr(str);\r
395         tmp[key_len] = 0;\r
396 \r
397         if (UniStrCmpi(tmp, key) == 0)\r
398         {\r
399                 ret = true;\r
400         }\r
401         else\r
402         {\r
403                 ret = false;\r
404         }\r
405 \r
406         Free(tmp);\r
407 \r
408         return ret;\r
409 }\r
410 \r
411 // 整数をカンマ区切り文字列に変換する\r
412 void UniToStr3(wchar_t *str, UINT size, UINT64 value)\r
413 {\r
414         char tmp[MAX_SIZE];\r
415         // 引数チェック\r
416         if (str == NULL)\r
417         {\r
418                 return;\r
419         }\r
420 \r
421         ToStr3(tmp, sizeof(tmp), value);\r
422 \r
423         StrToUni(str, size, tmp);\r
424 }\r
425 \r
426 // 文字列のフォーマット (内部関数)\r
427 wchar_t *InternalFormatArgs(wchar_t *fmt, va_list args, bool ansi_mode)\r
428 {\r
429         UINT i, len;\r
430         wchar_t *tmp;\r
431         UINT tmp_size;\r
432         LIST *o;\r
433         UINT mode = 0;\r
434         UINT wp;\r
435         UINT total_size;\r
436         wchar_t *ret;\r
437         // 引数チェック\r
438         if (fmt == NULL)\r
439         {\r
440                 return NULL;\r
441         }\r
442 \r
443         len = UniStrLen(fmt);\r
444         tmp_size = UniStrSize(fmt);\r
445         tmp = Malloc(tmp_size);\r
446 \r
447         o = NewListFast(NULL);\r
448 \r
449         mode = 0;\r
450 \r
451         wp = 0;\r
452 \r
453         for (i = 0;i < len;i++)\r
454         {\r
455                 wchar_t c = fmt[i];\r
456 \r
457                 if (mode == 0)\r
458                 {\r
459                         // 通常の文字モード\r
460                         switch (c)\r
461                         {\r
462                         case L'%':\r
463                                 // 書式指定の開始\r
464                                 if (fmt[i + 1] == L'%')\r
465                                 {\r
466                                         // 次の文字も % の場合は % を一文字出力するだけ\r
467                                         i++;\r
468                                         tmp[wp++] = c;\r
469                                 }\r
470                                 else\r
471                                 {\r
472                                         // 次の文字が % でない場合は状態遷移を行う\r
473                                         mode = 1;\r
474                                         tmp[wp++] = 0;\r
475                                         wp = 0;\r
476                                         Add(o, CopyUniStr(tmp));\r
477                                         tmp[wp++] = c;\r
478                                 }\r
479                                 break;\r
480                         default:\r
481                                 // 通常の文字\r
482                                 tmp[wp++] = c;\r
483                                 break;\r
484                         }\r
485                 }\r
486                 else\r
487                 {\r
488                         char *tag;\r
489                         char dst[MAX_SIZE];\r
490                         wchar_t *target_str;\r
491                         wchar_t *padding_str;\r
492                         bool left_padding;\r
493                         UINT target_str_len;\r
494                         UINT total_len;\r
495                         wchar_t *output_str;\r
496                         UINT padding;\r
497                         // 書式指定モード\r
498                         switch (c)\r
499                         {\r
500                         case L'c':\r
501                         case L'C':\r
502                         case L'd':\r
503                         case L'i':\r
504                         case L'o':\r
505                         case L'u':\r
506                         case L'x':\r
507                         case L'X':\r
508                                 // int 型\r
509                                 tmp[wp++] = c;\r
510                                 tmp[wp++] = 0;\r
511                                 tag = CopyUniToStr(tmp);\r
512 \r
513                                 #ifdef  OS_WIN32\r
514                                         ReplaceStrEx(tag, 0, tag, "ll", "I64", false);\r
515                                 #else   // OS_WIN32\r
516                                         ReplaceStrEx(tag, 0, tag, "I64", "ll", false);\r
517                                 #endif  // OS_WIN32\r
518 \r
519                                 if ((UniStrLen(tmp) >= 5 && tmp[UniStrLen(tmp) - 4] == L'I' &&\r
520                                         tmp[UniStrLen(tmp) - 3] == L'6' &&\r
521                                         tmp[UniStrLen(tmp) - 2] == L'4') ||\r
522                                         (\r
523                                         UniStrLen(tmp) >= 4 && tmp[UniStrLen(tmp) - 3] == L'l' &&\r
524                                         tmp[UniStrLen(tmp) - 2] == L'l'))\r
525                                 {\r
526                                         #ifdef  OS_WIN32\r
527                                                 _snprintf(dst, sizeof(dst), tag, va_arg(args, UINT64));\r
528                                         #else   // OS_WIN32\r
529                                                 snprintf(dst, sizeof(dst), tag, va_arg(args, UINT64));\r
530                                         #endif  // OS_WIN32\r
531                                 }\r
532                                 else\r
533                                 {\r
534                                         #ifdef  OS_WIN32\r
535                                                 _snprintf(dst, sizeof(dst), tag, va_arg(args, int));\r
536                                         #else   // OS_WIN32\r
537                                                 snprintf(dst, sizeof(dst), tag, va_arg(args, int));\r
538                                         #endif  // OS_WIN32\r
539                                 }\r
540 \r
541                                 Free(tag);\r
542                                 Add(o, CopyStrToUni(dst));\r
543 \r
544                                 wp = 0;\r
545                                 mode = 0;\r
546                                 break;\r
547                         case L'e':\r
548                         case L'E':\r
549                         case L'f':\r
550                         case L'g':\r
551                         case L'G':\r
552                                 // double 型\r
553                                 tmp[wp++] = c;\r
554                                 tmp[wp++] = 0;\r
555                                 tag = CopyUniToStr(tmp);\r
556 \r
557                                 #ifdef  OS_WIN32\r
558                                         _snprintf(dst, sizeof(dst), tag, va_arg(args, double));\r
559                                 #else   // OS_WIN32\r
560                                         snprintf(dst, sizeof(dst), tag, va_arg(args, double));\r
561                                 #endif  // OS_WIN32\r
562 \r
563                                 Free(tag);\r
564                                 Add(o, CopyStrToUni(dst));\r
565 \r
566                                 wp = 0;\r
567                                 mode = 0;\r
568                                 break;\r
569                         case L'n':\r
570                         case L'p':\r
571                                 // ポインタ型\r
572                                 tmp[wp++] = c;\r
573                                 tmp[wp++] = 0;\r
574                                 tag = ZeroMalloc(UniStrSize(tmp) + 32);\r
575                                 UniToStr(tag, 0, tmp);\r
576 \r
577                                 #ifdef  OS_WIN32\r
578                                         _snprintf(dst, sizeof(dst), tag, va_arg(args, void *));\r
579                                 #else   // OS_WIN32\r
580                                         snprintf(dst, sizeof(dst), tag, va_arg(args, void *));\r
581                                 #endif  // OS_WIN32\r
582 \r
583                                 Free(tag);\r
584                                 Add(o, CopyStrToUni(dst));\r
585 \r
586                                 wp = 0;\r
587                                 mode = 0;\r
588                                 break;\r
589                         case L's':\r
590                         case L'S':\r
591                                 // 文字列型\r
592                                 tmp[wp++] = c;\r
593                                 tmp[wp++] = 0;\r
594 \r
595                                 if (ansi_mode == false)\r
596                                 {\r
597                                         if (c == L'S')\r
598                                         {\r
599                                                 c = L's';\r
600                                         }\r
601                                         else\r
602                                         {\r
603                                                 c = L'S';\r
604                                         }\r
605                                 }\r
606 \r
607                                 if (c == L's')\r
608                                 {\r
609                                         target_str = CopyStrToUni(va_arg(args, char *));\r
610                                 }\r
611                                 else\r
612                                 {\r
613                                         target_str = CopyUniStr(va_arg(args, wchar_t *));\r
614                                 }\r
615 \r
616                                 if (target_str == NULL)\r
617                                 {\r
618                                         target_str = CopyUniStr(L"(null)");\r
619                                 }\r
620 \r
621                                 padding = 0;\r
622                                 left_padding = false;\r
623                                 if (tmp[1] == L'-')\r
624                                 {\r
625                                         // 左詰め\r
626                                         if (UniStrLen(tmp) >= 3)\r
627                                         {\r
628                                                 padding = UniToInt(&tmp[2]);\r
629                                         }\r
630                                         left_padding = true;\r
631                                 }\r
632                                 else\r
633                                 {\r
634                                         // 右詰め\r
635                                         if (UniStrLen(tmp) >= 2)\r
636                                         {\r
637                                                 padding = UniToInt(&tmp[1]);\r
638                                         }\r
639                                 }\r
640 \r
641                                 target_str_len = UniStrWidth(target_str);\r
642 \r
643                                 if (padding > target_str_len)\r
644                                 {\r
645                                         UINT len = padding - target_str_len;\r
646                                         UINT i;\r
647                                         padding_str = ZeroMalloc(sizeof(wchar_t) * (len + 1));\r
648                                         for (i = 0;i < len;i++)\r
649                                         {\r
650                                                 padding_str[i] = L' ';\r
651                                         }\r
652                                 }\r
653                                 else\r
654                                 {\r
655                                         padding_str = ZeroMalloc(sizeof(wchar_t));\r
656                                 }\r
657 \r
658                                 total_len = sizeof(wchar_t) * (UniStrLen(padding_str) + UniStrLen(target_str) + 1);\r
659                                 output_str = ZeroMalloc(total_len);\r
660                                 output_str[0] = 0;\r
661 \r
662                                 if (left_padding == false)\r
663                                 {\r
664                                         UniStrCat(output_str, total_len, padding_str);\r
665                                 }\r
666                                 UniStrCat(output_str, total_len, target_str);\r
667                                 if (left_padding)\r
668                                 {\r
669                                         UniStrCat(output_str, total_len, padding_str);\r
670                                 }\r
671 \r
672                                 Add(o, output_str);\r
673 \r
674                                 Free(target_str);\r
675                                 Free(padding_str);\r
676 \r
677                                 wp = 0;\r
678                                 mode = 0;\r
679                                 break;\r
680                         default:\r
681                                 // 通常の文字列\r
682                                 tmp[wp++] = c;\r
683                                 break;\r
684                         }\r
685                 }\r
686         }\r
687         tmp[wp++] = 0;\r
688         wp = 0;\r
689 \r
690         if (UniStrLen(tmp) >= 1)\r
691         {\r
692                 Add(o, CopyUniStr(tmp));\r
693         }\r
694 \r
695         total_size = sizeof(wchar_t);\r
696         for (i = 0;i < LIST_NUM(o);i++)\r
697         {\r
698                 wchar_t *s = LIST_DATA(o, i);\r
699                 total_size += UniStrLen(s) * sizeof(wchar_t);\r
700         }\r
701 \r
702         ret = ZeroMalloc(total_size);\r
703         for (i = 0;i < LIST_NUM(o);i++)\r
704         {\r
705                 wchar_t *s = LIST_DATA(o, i);\r
706                 UniStrCat(ret, total_size, s);\r
707                 Free(s);\r
708         }\r
709 \r
710         ReleaseList(o);\r
711 \r
712         Free(tmp);\r
713 \r
714         return ret;\r
715 }\r
716 \r
717 // 文字列の横幅サイズを取得する\r
718 UINT UniStrWidth(wchar_t *str)\r
719 {\r
720         UINT i, len, ret;\r
721         // 引数チェック\r
722         if (str == NULL)\r
723         {\r
724                 return 0;\r
725         }\r
726 \r
727         ret = 0;\r
728         len = UniStrLen(str);\r
729         for (i = 0;i < len;i++)\r
730         {\r
731                 if (str[i] <= 255)\r
732                 {\r
733                         ret++;\r
734                 }\r
735                 else\r
736                 {\r
737                         ret += 2;\r
738                 }\r
739         }\r
740         return ret;\r
741 }\r
742 \r
743 // Unicode 文字列をダンプ表示する\r
744 void DumpUniStr(wchar_t *str)\r
745 {\r
746         UINT i, len;\r
747         char *s;\r
748         // 引数チェック\r
749         if (str == NULL)\r
750         {\r
751                 return;\r
752         }\r
753 \r
754         s = CopyUniToStr(str);\r
755 \r
756         Print("DumpUniStr: %s\n  ", s);\r
757 \r
758         len = UniStrLen(str);\r
759         for (i = 0;i < len;i++)\r
760         {\r
761                 Print("0x%04X ", str[i]);\r
762         }\r
763         Print("\n");\r
764 \r
765         Free(s);\r
766 }\r
767 \r
768 // 文字列をダンプ表示する\r
769 void DumpStr(char *str)\r
770 {\r
771         UINT i, len;\r
772         // 引数チェック\r
773         if (str == NULL)\r
774         {\r
775                 return;\r
776         }\r
777 \r
778         Print("DumpStr: %s\n  ", str);\r
779 \r
780         len = StrLen(str);\r
781         for (i = 0;i < len;i++)\r
782         {\r
783                 Print("0x%02X ", str[i]);\r
784         }\r
785         Print("\n");\r
786 }\r
787 \r
788 // 1 文字 2 バイトの文字列を 1 文字 4 場合の wchar_t に変換する\r
789 wchar_t *Utf16ToWide(USHORT *str)\r
790 {\r
791         wchar_t *ret;\r
792         UINT len, i;\r
793         // 引数チェック\r
794         if (str == NULL)\r
795         {\r
796                 return NULL;\r
797         }\r
798 \r
799         len = 0;\r
800         while (true)\r
801         {\r
802                 if (str[len] == 0)\r
803                 {\r
804                         break;\r
805                 }\r
806                 len++;\r
807         }\r
808 \r
809         ret = Malloc((len + 1) * sizeof(wchar_t));\r
810         for (i = 0;i < len + 1;i++)\r
811         {\r
812                 ret[i] = (wchar_t)str[i];\r
813         }\r
814 \r
815         return ret;\r
816 }\r
817 \r
818 // 1 文字 4 バイトの wchar_t 文字列を 1 文字 2 バイトに変換する\r
819 USHORT *WideToUtf16(wchar_t *str)\r
820 {\r
821         USHORT *ret;\r
822         UINT len;\r
823         UINT ret_size;\r
824         UINT i;\r
825         // 引数チェック\r
826         if (str == NULL)\r
827         {\r
828                 return NULL;\r
829         }\r
830 \r
831         len = UniStrLen(str);\r
832 \r
833         ret_size = (len + 1) * 2;\r
834         ret = Malloc(ret_size);\r
835 \r
836         for (i = 0;i < len + 1;i++)\r
837         {\r
838                 ret[i] = (USHORT)str[i];\r
839         }\r
840 \r
841         return ret;\r
842 }\r
843 \r
844 // 国際ライブラリの初期化\r
845 void InitInternational()\r
846 {\r
847 #ifdef  OS_UNIX\r
848         void *d;\r
849 \r
850         if (iconv_lock != NULL)\r
851         {\r
852                 return;\r
853         }\r
854 \r
855         GetCurrentCharSet(charset, sizeof(charset));\r
856         d = IconvWideToStrInternal();\r
857         if (d == (void *)-1)\r
858         {\r
859 #ifdef  UNIX_MACOS\r
860                 StrCpy(charset, sizeof(charset), "utf8");\r
861 #else   // UNIX_MACOS\r
862                 StrCpy(charset, sizeof(charset), "EUCJP");\r
863 #endif  // UNIX_MACOS\r
864                 d = IconvWideToStrInternal();\r
865                 if (d == (void *)-1)\r
866                 {\r
867                         StrCpy(charset, sizeof(charset), "US");\r
868                 }\r
869                 else\r
870                 {\r
871                         IconvFreeInternal(d);\r
872                 }\r
873         }\r
874         else\r
875         {\r
876                 IconvFreeInternal(d);\r
877         }\r
878 \r
879         iconv_lock = NewLockMain();\r
880 \r
881         iconv_cache_wide_to_str = IconvWideToStrInternal();\r
882         iconv_cache_str_to_wide = IconvStrToWideInternal();\r
883 #endif  // OS_UNIX\r
884 }\r
885 \r
886 // 国際ライブラリの解放\r
887 void FreeInternational()\r
888 {\r
889 #ifdef  OS_UNIX\r
890 #endif  // OS_UNIX\r
891 }\r
892 \r
893 #ifdef  OS_UNIX\r
894 \r
895 // 文字列を Unicode に変換した場合のサイズを計算する\r
896 UINT UnixCalcStrToUni(char *str)\r
897 {\r
898         wchar_t *tmp;\r
899         UINT len, tmp_size;\r
900         UINT ret;\r
901         // 引数チェック\r
902         if (str == NULL)\r
903         {\r
904                 return 0;\r
905         }\r
906 \r
907         len = StrLen(str);\r
908         tmp_size = len * 5 + 10;\r
909         tmp = ZeroMalloc(tmp_size);\r
910         UnixStrToUni(tmp, tmp_size, str);\r
911         ret = UniStrLen(tmp);\r
912         Free(tmp);\r
913 \r
914         return (ret + 1) * sizeof(wchar_t);\r
915 }\r
916 \r
917 // 文字列を Unicode に変換する\r
918 UINT UnixStrToUni(wchar_t *s, UINT size, char *str)\r
919 {\r
920         void *d;\r
921         char *inbuf;\r
922         size_t insize;\r
923         char *outbuf;\r
924         char *outbuf_orig;\r
925         size_t outsize;\r
926         wchar_t *tmp;\r
927         // 引数チェック\r
928         if (s == NULL || str == NULL)\r
929         {\r
930                 return 0;\r
931         }\r
932 \r
933         d = IconvStrToWide();\r
934         if (d == (void *)-1)\r
935         {\r
936                 UniStrCpy(s, size, L"");\r
937                 return 0;\r
938         }\r
939 \r
940         inbuf = (char *)str;\r
941         insize = StrLen(str) + 1;\r
942         outsize = insize * 5 + 10;\r
943         outbuf_orig = outbuf = ZeroMalloc(outsize);\r
944 \r
945         if (iconv((iconv_t)d, (char **)&inbuf, (size_t *)&insize, (char **)&outbuf, (size_t *)&outsize) == (size_t)(-1))\r
946         {\r
947                 Free(outbuf_orig);\r
948                 UniStrCpy(s, size, L"");\r
949                 IconvFree(d);\r
950                 return 0;\r
951         }\r
952 \r
953         tmp = Utf16ToWide((USHORT *)outbuf_orig);\r
954         Free(outbuf_orig);\r
955 \r
956         UniStrCpy(s, size, tmp);\r
957         IconvFree(d);\r
958 \r
959         Free(tmp);\r
960 \r
961         return UniStrLen(s);\r
962 }\r
963 \r
964 // Unicode を文字列にした場合のサイズを計算する\r
965 UINT UnixCalcUniToStr(wchar_t *s)\r
966 {\r
967         char *tmp;\r
968         UINT tmp_size;\r
969         UINT ret;\r
970         // 引数チェック\r
971         if (s == NULL)\r
972         {\r
973                 return 0;\r
974         }\r
975 \r
976         tmp_size = UniStrLen(s) * 5 + 10;\r
977         tmp = ZeroMalloc(tmp_size);\r
978         UnixUniToStr(tmp, tmp_size, s);\r
979 \r
980         ret = StrSize(tmp);\r
981         Free(tmp);\r
982 \r
983         return ret;\r
984 }\r
985 \r
986 // Unicode を文字列に変換する\r
987 UINT UnixUniToStr(char *str, UINT size, wchar_t *s)\r
988 {\r
989         USHORT *tmp;\r
990         char *inbuf;\r
991         size_t insize;\r
992         char *outbuf;\r
993         char *outbuf_orig;\r
994         size_t outsize;\r
995         void *d;\r
996         // 引数チェック\r
997         if (str == NULL || s == NULL)\r
998         {\r
999                 return 0;\r
1000         }\r
1001 \r
1002         // まず wchar_t 文字列を 2 バイトの並びに変換する\r
1003         tmp = WideToUtf16(s);\r
1004         inbuf = (char *)tmp;\r
1005         insize = (UniStrLen(s) + 1) * 2;\r
1006         outsize = insize * 5 + 10;\r
1007         outbuf_orig = outbuf = ZeroMalloc(outsize);\r
1008 \r
1009         d = IconvWideToStr();\r
1010         if (d == (void *)-1)\r
1011         {\r
1012                 StrCpy(str, size, "");\r
1013                 Free(outbuf);\r
1014                 Free(tmp);\r
1015                 return 0;\r
1016         }\r
1017 \r
1018         if (iconv((iconv_t)d, (char **)&inbuf, (size_t *)&insize, (char **)&outbuf, (size_t *)&outsize) == (size_t)(-1))\r
1019         {\r
1020                 Free(outbuf_orig);\r
1021                 IconvFree(d);\r
1022                 StrCpy(str, size, "");\r
1023                 Free(tmp);\r
1024                 return 0;\r
1025         }\r
1026 \r
1027         StrCpy(str, size, outbuf_orig);\r
1028 \r
1029         Free(outbuf_orig);\r
1030         IconvFree(d);\r
1031         Free(tmp);\r
1032 \r
1033         return StrLen(str);\r
1034 }\r
1035 \r
1036 // whcar_t を char に変換する\r
1037 void *IconvWideToStrInternal()\r
1038 {\r
1039         return (void *)iconv_open(charset, IsBigEndian() ? "UTF-16BE" : "UTF-16LE");\r
1040 }\r
1041 \r
1042 // char を wchar_t に変換する\r
1043 void *IconvStrToWideInternal()\r
1044 {\r
1045         return (void *)iconv_open(IsBigEndian() ? "UTF-16BE" : "UTF-16LE", charset);\r
1046 }\r
1047 \r
1048 // ハンドルを閉じる\r
1049 int IconvFreeInternal(void *d)\r
1050 {\r
1051         iconv_close((iconv_t)d);\r
1052         return 0;\r
1053 }\r
1054 \r
1055 void *IconvWideToStr()\r
1056 {\r
1057         if (iconv_cache_wide_to_str == (void *)-1)\r
1058         {\r
1059                 return (void *)-1;\r
1060         }\r
1061 \r
1062         Lock(iconv_lock);\r
1063 \r
1064         return iconv_cache_wide_to_str;\r
1065 }\r
1066 \r
1067 void *IconvStrToWide()\r
1068 {\r
1069         if (iconv_cache_str_to_wide == (void *)-1)\r
1070         {\r
1071                 return (void *)-1;\r
1072         }\r
1073 \r
1074         Lock(iconv_lock);\r
1075 \r
1076         return iconv_cache_str_to_wide;\r
1077 }\r
1078 \r
1079 int IconvFree(void *d)\r
1080 {\r
1081         Unlock(iconv_lock);\r
1082 \r
1083         return 0;\r
1084 }\r
1085 \r
1086 // 現在使用されている文字セットを環境変数から取得する\r
1087 void GetCurrentCharSet(char *name, UINT size)\r
1088 {\r
1089         char tmp[MAX_SIZE];\r
1090         TOKEN_LIST *t;\r
1091         // 引数チェック\r
1092         if (name == NULL)\r
1093         {\r
1094                 return;\r
1095         }\r
1096 \r
1097         if (GetEnv("LANG", tmp, sizeof(tmp)) == false)\r
1098         {\r
1099                 if (GetEnv("LOCATION", tmp, sizeof(tmp)) == false)\r
1100                 {\r
1101                         StrCpy(tmp, sizeof(tmp), "ja_JP.eucJP");\r
1102                 }\r
1103         }\r
1104 \r
1105         Trim(tmp);\r
1106 \r
1107         t = ParseToken(tmp, ".");\r
1108         if (t->NumTokens >= 2)\r
1109         {\r
1110                 StrCpy(name, size, t->Token[1]);\r
1111         }\r
1112         else\r
1113         {\r
1114                 if (t->NumTokens == 1)\r
1115                 {\r
1116                         StrCpy(name, size, t->Token[0]);\r
1117                 }\r
1118                 else\r
1119                 {\r
1120                         StrCpy(name, size, "eucJP");\r
1121                 }\r
1122         }\r
1123         FreeToken(t);\r
1124 \r
1125         StrUpper(name);\r
1126 }\r
1127 \r
1128 #endif  // OS_UNIX\r
1129 \r
1130 // 指定された文字列が空白かどうかチェック\r
1131 bool UniIsEmptyStr(wchar_t *str)\r
1132 {\r
1133         return IsEmptyUniStr(str);\r
1134 }\r
1135 bool IsEmptyUniStr(wchar_t *str)\r
1136 {\r
1137         bool ret;\r
1138         wchar_t *s;\r
1139         // 引数チェック\r
1140         if (str == NULL)\r
1141         {\r
1142                 return true;\r
1143         }\r
1144 \r
1145         s = UniCopyStr(str);\r
1146 \r
1147         UniTrim(s);\r
1148         if (UniStrLen(s) == 0)\r
1149         {\r
1150                 ret = true;\r
1151         }\r
1152         else\r
1153         {\r
1154                 ret = false;\r
1155         }\r
1156 \r
1157         Free(s);\r
1158 \r
1159         return ret;\r
1160 }\r
1161 \r
1162 // 指定された文字列が数字かどうかチェック\r
1163 bool UniIsNum(wchar_t *str)\r
1164 {\r
1165         char tmp[MAX_SIZE];\r
1166 \r
1167         // 引数チェック\r
1168         if (str == NULL)\r
1169         {\r
1170                 return false;\r
1171         }\r
1172 \r
1173         UniToStr(tmp, sizeof(tmp), str);\r
1174 \r
1175         return IsNum(tmp);\r
1176 }\r
1177 \r
1178 \r
1179 // 中身が無い Unicode トークンリスト\r
1180 UNI_TOKEN_LIST *UniNullToken()\r
1181 {\r
1182         UNI_TOKEN_LIST *ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));\r
1183         ret->Token = ZeroMalloc(0);\r
1184 \r
1185         return ret;\r
1186 }\r
1187 \r
1188 // 中身が無い Unicode トークンリスト (別名)\r
1189 UNI_TOKEN_LIST *NullUniToken()\r
1190 {\r
1191         return UniNullToken();\r
1192 }\r
1193 \r
1194 // トークンリストを Unicode トークンリストに変換する\r
1195 UNI_TOKEN_LIST *TokenListToUniTokenList(TOKEN_LIST *src)\r
1196 {\r
1197         UNI_TOKEN_LIST *ret;\r
1198         UINT i;\r
1199         // 引数チェック\r
1200         if (src == NULL)\r
1201         {\r
1202                 return NULL;\r
1203         }\r
1204 \r
1205         ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));\r
1206         ret->NumTokens = src->NumTokens;\r
1207         ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);\r
1208 \r
1209         for (i = 0;i < ret->NumTokens;i++)\r
1210         {\r
1211                 ret->Token[i] = CopyStrToUni(src->Token[i]);\r
1212         }\r
1213 \r
1214         return ret;\r
1215 }\r
1216 \r
1217 // Unicode トークンリストをトークンリストに変換する\r
1218 TOKEN_LIST *UniTokenListToTokenList(UNI_TOKEN_LIST *src)\r
1219 {\r
1220         TOKEN_LIST *ret;\r
1221         UINT i;\r
1222         // 引数チェック\r
1223         if (src == NULL)\r
1224         {\r
1225                 return NULL;\r
1226         }\r
1227 \r
1228         ret = ZeroMalloc(sizeof(TOKEN_LIST));\r
1229         ret->NumTokens = src->NumTokens;\r
1230         ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);\r
1231 \r
1232         for (i = 0;i < ret->NumTokens;i++)\r
1233         {\r
1234                 ret->Token[i] = CopyUniToStr(src->Token[i]);\r
1235         }\r
1236 \r
1237         return ret;\r
1238 }\r
1239 \r
1240 // Unicode 文字列コピー\r
1241 wchar_t *UniCopyStr(wchar_t *str)\r
1242 {\r
1243         return CopyUniStr(str);\r
1244 }\r
1245 \r
1246 // トークンリストのコピー\r
1247 UNI_TOKEN_LIST *UniCopyToken(UNI_TOKEN_LIST *src)\r
1248 {\r
1249         UNI_TOKEN_LIST *ret;\r
1250         UINT i;\r
1251         // 引数チェック\r
1252         if (src == NULL)\r
1253         {\r
1254                 return NULL;\r
1255         }\r
1256 \r
1257         ret = ZeroMalloc(sizeof(TOKEN_LIST));\r
1258         ret->NumTokens = src->NumTokens;\r
1259         ret->Token = ZeroMalloc(sizeof(wchar_t *) * ret->NumTokens);\r
1260         for (i = 0;i < ret->NumTokens;i++)\r
1261         {\r
1262                 ret->Token[i] = CopyUniStr(src->Token[i]);\r
1263         }\r
1264 \r
1265         return ret;\r
1266 }\r
1267 \r
1268 // コマンドライン文字列をパースする\r
1269 UNI_TOKEN_LIST *UniParseCmdLine(wchar_t *str)\r
1270 {\r
1271         UNI_TOKEN_LIST *t;\r
1272         LIST *o;\r
1273         UINT i, len, wp, mode;\r
1274         wchar_t c;\r
1275         wchar_t *tmp;\r
1276         bool ignore_space = false;\r
1277         // 引数チェック\r
1278         if (str == NULL)\r
1279         {\r
1280                 // トークン無し\r
1281                 return UniNullToken();\r
1282         }\r
1283 \r
1284         o = NewListFast(NULL);\r
1285         tmp = Malloc(UniStrSize(str) + 32);\r
1286 \r
1287         wp = 0;\r
1288         mode = 0;\r
1289 \r
1290         len = UniStrLen(str);\r
1291         for (i = 0;i < len;i++)\r
1292         {\r
1293                 c = str[i];\r
1294 \r
1295                 switch (mode)\r
1296                 {\r
1297                 case 0:\r
1298                         // 次のトークンを発見するモード\r
1299                         if (c == L' ' || c == L'\t')\r
1300                         {\r
1301                                 // 次の文字へ進める\r
1302                         }\r
1303                         else\r
1304                         {\r
1305                                 // トークンの開始\r
1306                                 if (c == L'\"')\r
1307                                 {\r
1308                                         if (str[i + 1] == L'\"')\r
1309                                         {\r
1310                                                 // 2 重の " は 1 個の " 文字として見なす\r
1311                                                 tmp[wp++] = L'\"';\r
1312                                                 i++;\r
1313                                         }\r
1314                                         else\r
1315                                         {\r
1316                                                 // 1 個の " はスペース無視フラグを有効にする\r
1317                                                 ignore_space = true;\r
1318                                         }\r
1319                                 }\r
1320                                 else\r
1321                                 {\r
1322                                         tmp[wp++] = c;\r
1323                                 }\r
1324 \r
1325                                 mode = 1;\r
1326                         }\r
1327                         break;\r
1328 \r
1329                 case 1:\r
1330                         if (ignore_space == false && (c == L' ' || c == L'\t'))\r
1331                         {\r
1332                                 // トークンの終了\r
1333                                 tmp[wp++] = 0;\r
1334                                 wp = 0;\r
1335 \r
1336                                 Insert(o, UniCopyStr(tmp));\r
1337                                 mode = 0;\r
1338                         }\r
1339                         else\r
1340                         {\r
1341                                 if (c == L'\"')\r
1342                                 {\r
1343                                         if (str[i + 1] == L'\"')\r
1344                                         {\r
1345                                                 // 2 重の " は 1 個の " 文字として見なす\r
1346                                                 tmp[wp++] = L'\"';\r
1347                                                 i++;\r
1348                                         }\r
1349                                         else\r
1350                                         {\r
1351                                                 if (ignore_space == false)\r
1352                                                 {\r
1353                                                         // 1 個の " はスペース無視フラグを有効にする\r
1354                                                         ignore_space = true;\r
1355                                                 }\r
1356                                                 else\r
1357                                                 {\r
1358                                                         // スペース無視フラグを無効にする\r
1359                                                         ignore_space = false;\r
1360                                                 }\r
1361                                         }\r
1362                                 }\r
1363                                 else\r
1364                                 {\r
1365                                         tmp[wp++] = c;\r
1366                                 }\r
1367                         }\r
1368                         break;\r
1369                 }\r
1370         }\r
1371 \r
1372         if (wp != 0)\r
1373         {\r
1374                 tmp[wp++] = 0;\r
1375                 Insert(o, UniCopyStr(tmp));\r
1376         }\r
1377 \r
1378         Free(tmp);\r
1379 \r
1380         t = ZeroMalloc(sizeof(UNI_TOKEN_LIST));\r
1381         t->NumTokens = LIST_NUM(o);\r
1382         t->Token = ZeroMalloc(sizeof(wchar_t *) * t->NumTokens);\r
1383         for (i = 0;i < t->NumTokens;i++)\r
1384         {\r
1385                 t->Token[i] = LIST_DATA(o, i);\r
1386         }\r
1387 \r
1388         ReleaseList(o);\r
1389 \r
1390         return t;\r
1391 }\r
1392 \r
1393 // Unicode 文字列を 64bit 整数に変換する\r
1394 UINT64 UniToInt64(wchar_t *str)\r
1395 {\r
1396         char tmp[MAX_SIZE];\r
1397         // 引数チェック\r
1398         if (str == NULL)\r
1399         {\r
1400                 return 0;\r
1401         }\r
1402 \r
1403         UniToStr(tmp, sizeof(tmp), str);\r
1404 \r
1405         return ToInt64(tmp);\r
1406 }\r
1407 \r
1408 // 64bit 整数を Unicode 文字列に変換する\r
1409 void UniToStr64(wchar_t *str, UINT64 value)\r
1410 {\r
1411         char tmp[MAX_SIZE];\r
1412         // 引数チェック\r
1413         if (str == NULL)\r
1414         {\r
1415                 return;\r
1416         }\r
1417 \r
1418         ToStr64(tmp, value);\r
1419 \r
1420         StrToUni(str, 0, tmp);\r
1421 }\r
1422 \r
1423 // ANSI を UTF に変換する\r
1424 UINT StrToUtf(char *utfstr, UINT size, char *str)\r
1425 {\r
1426         char *tmp;\r
1427         // 引数チェック\r
1428         if (utfstr == NULL || str == NULL)\r
1429         {\r
1430                 StrCpy(utfstr, size, "");\r
1431                 return 0;\r
1432         }\r
1433 \r
1434         tmp = CopyStrToUtf(str);\r
1435 \r
1436         StrCpy(utfstr, size, tmp);\r
1437 \r
1438         Free(tmp);\r
1439 \r
1440         return StrLen(utfstr);\r
1441 }\r
1442 \r
1443 // UTF を ANSI に変換する\r
1444 UINT UtfToStr(char *str, UINT size, char *utfstr)\r
1445 {\r
1446         char *tmp;\r
1447         // 引数チェック\r
1448         if (str == NULL || utfstr == NULL)\r
1449         {\r
1450                 StrCpy(str, size, "");\r
1451                 return 0;\r
1452         }\r
1453 \r
1454         tmp = CopyUtfToStr(utfstr);\r
1455 \r
1456         StrCpy(str, size, tmp);\r
1457 \r
1458         Free(tmp);\r
1459 \r
1460         return StrLen(str);\r
1461 }\r
1462 \r
1463 // Unicode を UTF に変換する\r
1464 UINT UniToUtf(char *utfstr, UINT size, wchar_t *unistr)\r
1465 {\r
1466         char *tmp;\r
1467         // 引数チェック\r
1468         if (utfstr == NULL || unistr == NULL)\r
1469         {\r
1470                 StrCpy(utfstr, size, "");\r
1471                 return 0;\r
1472         }\r
1473 \r
1474         tmp = CopyUniToStr(unistr);\r
1475 \r
1476         StrCpy(utfstr, size, tmp);\r
1477 \r
1478         Free(tmp);\r
1479 \r
1480         return StrLen(utfstr);\r
1481 }\r
1482 \r
1483 // UTF を Unicode に変換する\r
1484 UINT UtfToUni(wchar_t *unistr, UINT size, char *utfstr)\r
1485 {\r
1486         wchar_t *tmp;\r
1487         // 引数チェック\r
1488         if (unistr == NULL || utfstr == NULL)\r
1489         {\r
1490                 UniStrCpy(unistr, size, L"");\r
1491                 return 0;\r
1492         }\r
1493 \r
1494         tmp = CopyUtfToUni(utfstr);\r
1495 \r
1496         UniStrCpy(unistr, size, tmp);\r
1497 \r
1498         Free(tmp);\r
1499 \r
1500         return UniStrLen(unistr);\r
1501 }\r
1502 \r
1503 // UTF8 文字列を Unicode 文字列にコピーする\r
1504 wchar_t *CopyUtfToUni(char *utfstr)\r
1505 {\r
1506         UINT size;\r
1507         wchar_t *ret;\r
1508         UINT utfstr_len;\r
1509         // 引数チェック\r
1510         if (utfstr == NULL)\r
1511         {\r
1512                 return NULL;\r
1513         }\r
1514 \r
1515         utfstr_len = StrLen(utfstr);\r
1516 \r
1517         size = CalcUtf8ToUni((BYTE *)utfstr, utfstr_len);\r
1518         ret = ZeroMalloc(size + sizeof(wchar_t));\r
1519         Utf8ToUni(ret, size, (BYTE *)utfstr, utfstr_len);\r
1520 \r
1521         return ret;\r
1522 }\r
1523 \r
1524 // UTF8 文字列を ANSI 文字列にコピーする\r
1525 char *CopyUtfToStr(char *utfstr)\r
1526 {\r
1527         wchar_t *uni;\r
1528         char *ret;\r
1529         // 引数チェック\r
1530         if (utfstr == NULL)\r
1531         {\r
1532                 return NULL;\r
1533         }\r
1534 \r
1535         uni = CopyUtfToUni(utfstr);\r
1536         if (uni == NULL)\r
1537         {\r
1538                 return CopyStr("");\r
1539         }\r
1540 \r
1541         ret = CopyUniToStr(uni);\r
1542 \r
1543         Free(uni);\r
1544 \r
1545         return ret;\r
1546 }\r
1547 \r
1548 // Unicode 文字列を ANSI 文字列にコピーする\r
1549 char *CopyUniToStr(wchar_t *unistr)\r
1550 {\r
1551         char *str;\r
1552         UINT str_size;\r
1553         // 引数チェック\r
1554         if (unistr == NULL)\r
1555         {\r
1556                 return NULL;\r
1557         }\r
1558 \r
1559         str_size = CalcUniToStr(unistr);\r
1560         if (str_size == 0)\r
1561         {\r
1562                 return CopyStr("");\r
1563         }\r
1564         str = Malloc(str_size);\r
1565         UniToStr(str, str_size, unistr);\r
1566 \r
1567         return str;\r
1568 }\r
1569 \r
1570 // ANSI 文字列を Unicode 文字列にコピーする\r
1571 wchar_t *CopyStrToUni(char *str)\r
1572 {\r
1573         wchar_t *uni;\r
1574         UINT uni_size;\r
1575         // 引数チェック\r
1576         if (str == NULL)\r
1577         {\r
1578                 return NULL;\r
1579         }\r
1580 \r
1581         uni_size = CalcStrToUni(str);\r
1582         if (uni_size == 0)\r
1583         {\r
1584                 return CopyUniStr(L"");\r
1585         }\r
1586         uni = Malloc(uni_size);\r
1587         StrToUni(uni, uni_size, str);\r
1588 \r
1589         return uni;\r
1590 }\r
1591 \r
1592 // Unicode 文字列を UTF8 文字列にコピーする\r
1593 char *CopyUniToUtf(wchar_t *unistr)\r
1594 {\r
1595         UINT size;\r
1596         char *ret;\r
1597         // 引数チェック\r
1598         if (unistr == NULL)\r
1599         {\r
1600                 return NULL;\r
1601         }\r
1602 \r
1603         size = CalcUniToUtf8(unistr);\r
1604         ret = ZeroMalloc(size + sizeof(char));\r
1605 \r
1606         UniToUtf8((char *)ret, size, unistr);\r
1607 \r
1608         return ret;\r
1609 }\r
1610 \r
1611 // ANSI 文字列を UTF8 文字列にコピーする\r
1612 char *CopyStrToUtf(char *str)\r
1613 {\r
1614         wchar_t *unistr;\r
1615         char *ret;\r
1616         // 引数チェック\r
1617         if (str == NULL)\r
1618         {\r
1619                 return NULL;\r
1620         }\r
1621 \r
1622         unistr = CopyStrToUni(str);\r
1623         if (unistr == NULL)\r
1624         {\r
1625                 return CopyStr("");\r
1626         }\r
1627 \r
1628         ret = CopyUniToUtf(unistr);\r
1629 \r
1630         Free(unistr);\r
1631 \r
1632         return ret;\r
1633 }\r
1634 \r
1635 // Unicode 文字列をコピーする\r
1636 wchar_t *CopyUniStr(wchar_t *str)\r
1637 {\r
1638         UINT len;\r
1639         wchar_t *dst;\r
1640         // 引数チェック\r
1641         if (str == NULL)\r
1642         {\r
1643                 return NULL;\r
1644         }\r
1645 \r
1646         len = UniStrLen(str);\r
1647         dst = Malloc((len + 1) * sizeof(wchar_t));\r
1648         UniStrCpy(dst, 0, str);\r
1649 \r
1650         return dst;\r
1651 }\r
1652 \r
1653 // 安全な文字列かどうかチェック\r
1654 bool IsSafeUniStr(wchar_t *str)\r
1655 {\r
1656         UINT i, len;\r
1657         // 引数チェック\r
1658         if (str == NULL)\r
1659         {\r
1660                 return false;\r
1661         }\r
1662 \r
1663         len = UniStrLen(str);\r
1664         for (i = 0;i < len;i++)\r
1665         {\r
1666                 if (IsSafeUniChar(str[i]) == false)\r
1667                 {\r
1668                         return false;\r
1669                 }\r
1670         }\r
1671         if (str[0] == L' ')\r
1672         {\r
1673                 return false;\r
1674         }\r
1675         if (len != 0)\r
1676         {\r
1677                 if (str[len - 1] == L' ')\r
1678                 {\r
1679                         return false;\r
1680                 }\r
1681         }\r
1682         return true;\r
1683 }\r
1684 \r
1685 // 安全な文字かどうかチェック\r
1686 bool IsSafeUniChar(wchar_t c)\r
1687 {\r
1688         UINT i, len;\r
1689         wchar_t *check_str =\r
1690                 L"ABCDEFGHIJKLMNOPQRSTUVWXYZ"\r
1691                 L"abcdefghijklmnopqrstuvwxyz"\r
1692                 L"0123456789"\r
1693                 L" ()-_#%&.";\r
1694 \r
1695         len = UniStrLen(check_str);\r
1696         for (i = 0;i < len;i++)\r
1697         {\r
1698                 if (c == check_str[i])\r
1699                 {\r
1700                         return true;\r
1701                 }\r
1702         }\r
1703         return false;\r
1704 }\r
1705 \r
1706 // UTF-8 文字列を ANSI 文字列に変換する\r
1707 UINT Utf8ToStr(char *str, UINT str_size, BYTE *u, UINT size)\r
1708 {\r
1709         UINT ret, uni_size;\r
1710         wchar_t *tmp;\r
1711         // 引数チェック\r
1712         if (u == NULL || str == NULL)\r
1713         {\r
1714                 return 0;\r
1715         }\r
1716 \r
1717         // Unicode に変換する\r
1718         uni_size = CalcUtf8ToUni(u, size);\r
1719         if (uni_size == 0)\r
1720         {\r
1721                 if (str_size >= 1)\r
1722                 {\r
1723                         StrCpy(str, 0, "");\r
1724                         return 0;\r
1725                 }\r
1726         }\r
1727         tmp = Malloc(uni_size);\r
1728         Utf8ToUni(tmp, uni_size, u, size);\r
1729 \r
1730         // ANSI に変換する\r
1731         ret = UniToStr(str, str_size, tmp);\r
1732         Free(tmp);\r
1733 \r
1734         return ret;\r
1735 }\r
1736 \r
1737 // UTF-8 文字列を ANSI 文字列に変換した場合に必要なサイズを取得する\r
1738 UINT CalcUtf8ToStr(BYTE *u, UINT size)\r
1739 {\r
1740         UINT ret, uni_size;\r
1741         wchar_t *tmp;\r
1742         // 引数チェック\r
1743         if (u == NULL)\r
1744         {\r
1745                 return 0;\r
1746         }\r
1747 \r
1748         // Unicode に変換する\r
1749         uni_size = CalcUtf8ToUni(u, size);\r
1750         if (uni_size == 0)\r
1751         {\r
1752                 return 0;\r
1753         }\r
1754         tmp = Malloc(uni_size);\r
1755         Utf8ToUni(tmp, uni_size, u, size);\r
1756 \r
1757         // ANSI に変換する\r
1758         ret = CalcUniToStr(tmp);\r
1759         Free(tmp);\r
1760 \r
1761         return ret;\r
1762 }\r
1763 \r
1764 // ANSI 文字列を UTF-8 文字列に変換する\r
1765 UINT StrToUtf8(BYTE *u, UINT size, char *str)\r
1766 {\r
1767         UINT ret, uni_size;\r
1768         wchar_t *tmp;\r
1769         // 引数チェック\r
1770         if (u == NULL || str == NULL)\r
1771         {\r
1772                 return 0;\r
1773         }\r
1774 \r
1775         // Unicode に変換する\r
1776         uni_size = CalcStrToUni(str);\r
1777         if (uni_size == 0)\r
1778         {\r
1779                 return 0;\r
1780         }\r
1781         tmp = Malloc(uni_size);\r
1782         StrToUni(tmp, uni_size, str);\r
1783 \r
1784         // UTF-8 に変換する\r
1785         ret = UniToUtf8(u, size, tmp);\r
1786 \r
1787         Free(tmp);\r
1788 \r
1789         return ret;\r
1790 }\r
1791 \r
1792 // ANSI 文字列を UTF-8 文字列に変換するために必要なサイズを取得する\r
1793 UINT CalcStrToUtf8(char *str)\r
1794 {\r
1795         UINT ret;\r
1796         UINT uni_size;\r
1797         wchar_t *tmp;\r
1798         // 引数チェック\r
1799         if (str == NULL)\r
1800         {\r
1801                 return 0;\r
1802         }\r
1803 \r
1804         // Unicode に変換する\r
1805         uni_size = CalcStrToUni(str);\r
1806         if (uni_size == 0)\r
1807         {\r
1808                 return 0;\r
1809         }\r
1810         tmp = Malloc(uni_size);\r
1811         StrToUni(tmp, uni_size, str);\r
1812 \r
1813         // UTF-8 に変換した場合のサイズを取得する\r
1814         ret = CalcUniToUtf8(tmp);\r
1815         Free(tmp);\r
1816 \r
1817         return ret;\r
1818 }\r
1819 \r
1820 // Unicode 文字列を ANSI 文字列に変換する\r
1821 UINT UniToStr(char *str, UINT size, wchar_t *s)\r
1822 {\r
1823 #ifdef  OS_WIN32\r
1824         UINT ret;\r
1825         char *tmp;\r
1826         UINT new_size;\r
1827         // 引数チェック\r
1828         if (s == NULL || str == NULL)\r
1829         {\r
1830                 return 0;\r
1831         }\r
1832 \r
1833         new_size = CalcUniToStr(s);\r
1834         if (new_size == 0)\r
1835         {\r
1836                 if (size >= 1)\r
1837                 {\r
1838                         StrCpy(str, 0, "");\r
1839                 }\r
1840                 return 0;\r
1841         }\r
1842         tmp = Malloc(new_size);\r
1843         tmp[0] = 0;\r
1844         wcstombs(tmp, s, new_size);\r
1845         tmp[new_size - 1] = 0;\r
1846         ret = StrCpy(str, size, tmp);\r
1847         Free(tmp);\r
1848 \r
1849         return ret;\r
1850 #else   // OS_WIN32\r
1851         return UnixUniToStr(str, size, s);\r
1852 #endif  // OS_WIN32\r
1853 }\r
1854 \r
1855 // Unicode 文字列を ANSI 文字列に変換するための必要なバイト数を取得する\r
1856 UINT CalcUniToStr(wchar_t *s)\r
1857 {\r
1858 #ifdef  OS_WIN32\r
1859         UINT ret;\r
1860         // 引数チェック\r
1861         if (s == NULL)\r
1862         {\r
1863                 return 0;\r
1864         }\r
1865 \r
1866         ret = (UINT)wcstombs(NULL, s, UniStrLen(s));\r
1867         if (ret == (UINT)-1)\r
1868         {\r
1869                 return 0;\r
1870         }\r
1871 \r
1872         return ret + 1;\r
1873 #else   // OS_WIN32\r
1874         return UnixCalcUniToStr(s);\r
1875 #endif  // OS_WIN32\r
1876 }\r
1877 \r
1878 // ANSI 文字列を Unicode 文字列に変換する\r
1879 UINT StrToUni(wchar_t *s, UINT size, char *str)\r
1880 {\r
1881 #ifdef  OS_WIN32\r
1882         UINT ret;\r
1883         wchar_t *tmp;\r
1884         UINT new_size;\r
1885         // 引数チェック\r
1886         if (s == NULL || str == NULL)\r
1887         {\r
1888                 return 0;\r
1889         }\r
1890 \r
1891         new_size = CalcStrToUni(str);\r
1892         if (new_size == 0)\r
1893         {\r
1894                 if (size >= 2)\r
1895                 {\r
1896                         UniStrCpy(s, 0, L"");\r
1897                 }\r
1898                 return 0;\r
1899         }\r
1900         tmp = Malloc(new_size);\r
1901         tmp[0] = 0;\r
1902         mbstowcs(tmp, str, StrLen(str));\r
1903         tmp[(new_size - 1) / sizeof(wchar_t)] = 0;\r
1904         ret = UniStrCpy(s, size, tmp);\r
1905         Free(tmp);\r
1906 \r
1907         return ret;\r
1908 #else   // OS_WIN32\r
1909         return UnixStrToUni(s, size, str);\r
1910 #endif  // OS_WIN32\r
1911 }\r
1912 \r
1913 // ANSI 文字列を Unicode 文字列に変換するための必要なバイト数を取得する\r
1914 UINT CalcStrToUni(char *str)\r
1915 {\r
1916 #ifdef  OS_WIN32\r
1917         UINT ret;\r
1918         // 引数チェック\r
1919         if (str == NULL)\r
1920         {\r
1921                 return 0;\r
1922         }\r
1923 \r
1924         ret = (UINT)mbstowcs(NULL, str, StrLen(str));\r
1925         if (ret == (UINT)-1)\r
1926         {\r
1927                 return 0;\r
1928         }\r
1929 \r
1930         return (ret + 1) * sizeof(wchar_t);\r
1931 #else   // OS_WIN32\r
1932         return UnixCalcStrToUni(str);\r
1933 #endif  // OS_WIN32\r
1934 }\r
1935 \r
1936 // UTF-8 文字列を Unicode 文字列に変換する\r
1937 UINT Utf8ToUni(wchar_t *s, UINT size, BYTE *u, UINT u_size)\r
1938 {\r
1939         UINT i, wp, num;\r
1940         // 引数チェック\r
1941         if (s == NULL || u == NULL)\r
1942         {\r
1943                 return 0;\r
1944         }\r
1945         if (size == 0)\r
1946         {\r
1947                 size = 0x3fffffff;\r
1948         }\r
1949         if (u_size == 0)\r
1950         {\r
1951                 u_size = StrLen((char *)u);\r
1952         }\r
1953 \r
1954         i = 0;\r
1955         wp = 0;\r
1956         num = 0;\r
1957         while (true)\r
1958         {\r
1959                 UINT type;\r
1960                 wchar_t c;\r
1961                 BYTE c1, c2;\r
1962 \r
1963                 type = GetUtf8Type(u, u_size, i);\r
1964                 if (type == 0)\r
1965                 {\r
1966                         break;\r
1967                 }\r
1968                 switch (type)\r
1969                 {\r
1970                 case 1:\r
1971                         c1 = 0;\r
1972                         c2 = u[i];\r
1973                         break;\r
1974                 case 2:\r
1975                         c1 = (((u[i] & 0x1c) >> 2) & 0x07);\r
1976                         c2 = (((u[i] & 0x03) << 6) & 0xc0) | (u[i + 1] & 0x3f);\r
1977                         break;\r
1978                 case 3:\r
1979                         c1 = ((((u[i] & 0x0f) << 4) & 0xf0)) | (((u[i + 1] & 0x3c) >> 2) & 0x0f);\r
1980                         c2 = (((u[i + 1] & 0x03) << 6) & 0xc0) | (u[i + 2] & 0x3f);\r
1981                         break;\r
1982                 }\r
1983                 i += type;\r
1984 \r
1985                 c = 0;\r
1986 \r
1987                 if (IsBigEndian())\r
1988                 {\r
1989                         if (sizeof(wchar_t) == 2)\r
1990                         {\r
1991                                 ((BYTE *)&c)[0] = c1;\r
1992                                 ((BYTE *)&c)[1] = c2;\r
1993                         }\r
1994                         else\r
1995                         {\r
1996                                 ((BYTE *)&c)[2] = c1;\r
1997                                 ((BYTE *)&c)[3] = c2;\r
1998                         }\r
1999                 }\r
2000                 else\r
2001                 {\r
2002                         ((BYTE *)&c)[0] = c2;\r
2003                         ((BYTE *)&c)[1] = c1;\r
2004                 }\r
2005 \r
2006                 if (wp < ((size / sizeof(wchar_t)) - 1))\r
2007                 {\r
2008                         s[wp++] = c;\r
2009                         num++;\r
2010                 }\r
2011                 else\r
2012                 {\r
2013                         break;\r
2014                 }\r
2015         }\r
2016 \r
2017         if (wp < (size / sizeof(wchar_t)))\r
2018         {\r
2019                 s[wp++] = 0;\r
2020         }\r
2021 \r
2022         return num;\r
2023 }\r
2024 \r
2025 // UTF-8 を Unicode に変換した場合のバッファサイズを取得する\r
2026 UINT CalcUtf8ToUni(BYTE *u, UINT u_size)\r
2027 {\r
2028         // 引数チェック\r
2029         if (u == NULL)\r
2030         {\r
2031                 return 0;\r
2032         }\r
2033         if (u_size == 0)\r
2034         {\r
2035                 u_size = StrLen((char *)u);\r
2036         }\r
2037 \r
2038         return (Utf8Len(u, u_size) + 1) * sizeof(wchar_t);\r
2039 }\r
2040 \r
2041 // UTF-8 文字列の文字数を取得する\r
2042 UINT Utf8Len(BYTE *u, UINT size)\r
2043 {\r
2044         UINT i, num;\r
2045         // 引数チェック\r
2046         if (u == NULL)\r
2047         {\r
2048                 return 0;\r
2049         }\r
2050         if (size == 0)\r
2051         {\r
2052                 size = StrLen((char *)u);\r
2053         }\r
2054 \r
2055         i = num = 0;\r
2056         while (true)\r
2057         {\r
2058                 UINT type;\r
2059 \r
2060                 type = GetUtf8Type(u, size, i);\r
2061                 if (type == 0)\r
2062                 {\r
2063                         break;\r
2064                 }\r
2065                 i += type;\r
2066                 num++;\r
2067         }\r
2068 \r
2069         return num;\r
2070 }\r
2071 \r
2072 // Unicode 文字列を UTF-8 文字列に変換する\r
2073 UINT UniToUtf8(BYTE *u, UINT size, wchar_t *s)\r
2074 {\r
2075         UINT i, len, type, wp;\r
2076         // 引数チェック\r
2077         if (u == NULL || s == NULL)\r
2078         {\r
2079                 return 0;\r
2080         }\r
2081         if (size == 0)\r
2082         {\r
2083                 size = 0x3fffffff;\r
2084         }\r
2085 \r
2086         len = UniStrLen(s);\r
2087         wp = 0;\r
2088         for (i = 0;i < len;i++)\r
2089         {\r
2090                 BYTE c1, c2;\r
2091                 wchar_t c = s[i];\r
2092 \r
2093                 if (IsBigEndian())\r
2094                 {\r
2095                         if (sizeof(wchar_t) == 2)\r
2096                         {\r
2097                                 c1 = ((BYTE *)&c)[0];\r
2098                                 c2 = ((BYTE *)&c)[1];\r
2099                         }\r
2100                         else\r
2101                         {\r
2102                                 c1 = ((BYTE *)&c)[2];\r
2103                                 c2 = ((BYTE *)&c)[3];\r
2104                         }\r
2105                 }\r
2106                 else\r
2107                 {\r
2108                         c1 = ((BYTE *)&c)[1];\r
2109                         c2 = ((BYTE *)&c)[0];\r
2110                 }\r
2111 \r
2112                 type = GetUniType(s[i]);\r
2113                 switch (type)\r
2114                 {\r
2115                 case 1:\r
2116                         if (wp < size)\r
2117                         {\r
2118                                 u[wp++] = c2;\r
2119                         }\r
2120                         break;\r
2121                 case 2:\r
2122                         if (wp < size)\r
2123                         {\r
2124                                 u[wp++] = 0xc0 | (((((c1 & 0x07) << 2) & 0x1c)) | (((c2 & 0xc0) >> 6) & 0x03));\r
2125                         }\r
2126                         if (wp < size)\r
2127                         {\r
2128                                 u[wp++] = 0x80 | (c2 & 0x3f);\r
2129                         }\r
2130                         break;\r
2131                 case 3:\r
2132                         if (wp < size)\r
2133                         {\r
2134                                 u[wp++] = 0xe0 | (((c1 & 0xf0) >> 4) & 0x0f);\r
2135                         }\r
2136                         if (wp < size)\r
2137                         {\r
2138                                 u[wp++] = 0x80 | (((c1 & 0x0f) << 2) & 0x3c) | (((c2 & 0xc0) >> 6) & 0x03);\r
2139                         }\r
2140                         if (wp < size)\r
2141                         {\r
2142                                 u[wp++] = 0x80 | (c2 & 0x3f);\r
2143                         }\r
2144                         break;\r
2145                 }\r
2146         }\r
2147         if (wp < size)\r
2148         {\r
2149                 u[wp] = 0;\r
2150         }\r
2151         return wp;\r
2152 }\r
2153 \r
2154 // Unicode 文字列を UTF-8 文字列に変換した場合の文字列長を計算する\r
2155 UINT CalcUniToUtf8(wchar_t *s)\r
2156 {\r
2157         UINT i, len, size;\r
2158         // 引数チェック\r
2159         if (s == NULL)\r
2160         {\r
2161                 return 0;\r
2162         }\r
2163 \r
2164         size = 0;\r
2165         len = UniStrLen(s);\r
2166         for (i = 0;i < len;i++)\r
2167         {\r
2168                 size += GetUniType(s[i]);\r
2169         }\r
2170 \r
2171         return size;\r
2172 }\r
2173 \r
2174 // s で始まる UTF-8 文字列の offset 番地の最初の 1 文字が何バイトで構成されているかを取得\r
2175 UINT GetUtf8Type(BYTE *s, UINT size, UINT offset)\r
2176 {\r
2177         // 引数チェック\r
2178         if (s == NULL)\r
2179         {\r
2180                 return 0;\r
2181         }\r
2182         if ((offset + 1) > size)\r
2183         {\r
2184                 return 0;\r
2185         }\r
2186         if ((s[offset] & 0x80) == 0)\r
2187         {\r
2188                 // 1 バイト\r
2189                 return 1;\r
2190         }\r
2191         if ((s[offset] & 0x20) == 0)\r
2192         {\r
2193                 // 2 バイト\r
2194                 if ((offset + 2) > size)\r
2195                 {\r
2196                         return 0;\r
2197                 }\r
2198                 return 2;\r
2199         }\r
2200         // 3 バイト\r
2201         if ((offset + 3) > size)\r
2202         {\r
2203                 return 0;\r
2204         }\r
2205         return 3;\r
2206 }\r
2207 \r
2208 // 文字 c を UTF-8 に変換した場合の種類 (バイト数)\r
2209 UINT GetUniType(wchar_t c)\r
2210 {\r
2211         BYTE c1, c2;\r
2212 \r
2213         if (IsBigEndian())\r
2214         {\r
2215                 if (sizeof(wchar_t) == 2)\r
2216                 {\r
2217                         c1 = ((BYTE *)&c)[0];\r
2218                         c2 = ((BYTE *)&c)[1];\r
2219                 }\r
2220                 else\r
2221                 {\r
2222                         c1 = ((BYTE *)&c)[2];\r
2223                         c2 = ((BYTE *)&c)[3];\r
2224                 }\r
2225         }\r
2226         else\r
2227         {\r
2228                 c1 = ((BYTE *)&c)[1];\r
2229                 c2 = ((BYTE *)&c)[0];\r
2230         }\r
2231 \r
2232         if (c1 == 0)\r
2233         {\r
2234                 if (c2 <= 0x7f)\r
2235                 {\r
2236                         // 1 バイト\r
2237                         return 1;\r
2238                 }\r
2239                 else\r
2240                 {\r
2241                         // 2 バイト\r
2242                         return 2;\r
2243                 }\r
2244         }\r
2245         if ((c1 & 0xf8) == 0)\r
2246         {\r
2247                 // 2 バイト\r
2248                 return 2;\r
2249         }\r
2250         // 3 バイト\r
2251         return 3;\r
2252 }\r
2253 \r
2254 // 文字列の置換 (大文字小文字を区別しない)\r
2255 UINT UniReplaceStri(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword)\r
2256 {\r
2257         return UniReplaceStrEx(dst, size, string, old_keyword, new_keyword, false);\r
2258 }\r
2259 \r
2260 // 文字列の置換 (大文字小文字を区別する)\r
2261 UINT UniReplaceStr(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword)\r
2262 {\r
2263         return UniReplaceStrEx(dst, size, string, old_keyword, new_keyword, true);\r
2264 }\r
2265 \r
2266 // 文字列の置換\r
2267 UINT UniReplaceStrEx(wchar_t *dst, UINT size, wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword, bool case_sensitive)\r
2268 {\r
2269         UINT i, j, num, len_string, len_old, len_new, len_ret, wp;\r
2270         wchar_t *ret;\r
2271         // 引数チェック\r
2272         if (string == NULL || old_keyword == NULL || new_keyword == NULL)\r
2273         {\r
2274                 return 0;\r
2275         }\r
2276 \r
2277         // 文字列長の取得\r
2278         len_string = UniStrLen(string);\r
2279         len_old = UniStrLen(old_keyword);\r
2280         len_new = UniStrLen(new_keyword);\r
2281 \r
2282         // 最終文字列長の取得\r
2283         len_ret = UniCalcReplaceStrEx(string, old_keyword, new_keyword, case_sensitive);\r
2284         // メモリ確保\r
2285         ret = Malloc((len_ret + 1) * sizeof(wchar_t));\r
2286         ret[len_ret] = 0;\r
2287 \r
2288         // 検索と置換\r
2289         i = j = num = wp = 0;\r
2290         while (true)\r
2291         {\r
2292                 i = UniSearchStrEx(string, old_keyword, i, case_sensitive);\r
2293                 if (i == INFINITE)\r
2294                 {\r
2295                         Copy(&ret[wp], &string[j], (len_string - j) * sizeof(wchar_t));\r
2296                         wp += len_string - j;\r
2297                         break;\r
2298                 }\r
2299                 num++;\r
2300                 Copy(&ret[wp], &string[j], (i - j) * sizeof(wchar_t));\r
2301                 wp += i - j;\r
2302                 Copy(&ret[wp], new_keyword, len_new * sizeof(wchar_t));\r
2303                 wp += len_new;\r
2304                 i += len_old;\r
2305                 j = i;\r
2306         }\r
2307 \r
2308         // 検索結果のコピー\r
2309         UniStrCpy(dst, size, ret);\r
2310 \r
2311         // メモリ解放\r
2312         Free(ret);\r
2313 \r
2314         return num;\r
2315 }\r
2316 \r
2317 // 文字列の置換後の文字列長を計算する\r
2318 UINT UniCalcReplaceStrEx(wchar_t *string, wchar_t *old_keyword, wchar_t *new_keyword, bool case_sensitive)\r
2319 {\r
2320         UINT i, num;\r
2321         UINT len_string, len_old, len_new;\r
2322         // 引数チェック\r
2323         if (string == NULL || old_keyword == NULL || new_keyword == NULL)\r
2324         {\r
2325                 return 0;\r
2326         }\r
2327 \r
2328         // 文字列長の取得\r
2329         len_string = UniStrLen(string);\r
2330         len_old = UniStrLen(old_keyword);\r
2331         len_new = UniStrLen(new_keyword);\r
2332 \r
2333         if (len_old == len_new)\r
2334         {\r
2335                 return len_string;\r
2336         }\r
2337 \r
2338         // 検索処理\r
2339         num = 0;\r
2340         i = 0;\r
2341         while (true)\r
2342         {\r
2343                 i = UniSearchStrEx(string, old_keyword, i, case_sensitive);\r
2344                 if (i == INFINITE)\r
2345                 {\r
2346                         break;\r
2347                 }\r
2348                 i += len_old;\r
2349                 num++;\r
2350         }\r
2351 \r
2352         // 計算\r
2353         return len_string + len_new * num - len_old * num;\r
2354 }\r
2355 \r
2356 // 文字列の検索 (大文字 / 小文字を区別する)\r
2357 UINT UniSearchStr(wchar_t *string, wchar_t *keyword, UINT start)\r
2358 {\r
2359         return UniSearchStrEx(string, keyword, start, true);\r
2360 }\r
2361 \r
2362 // 文字列の検索 (大文字 / 小文字を区別しない)\r
2363 UINT UniSearchStri(wchar_t *string, wchar_t *keyword, UINT start)\r
2364 {\r
2365         return UniSearchStrEx(string, keyword, start, false);\r
2366 }\r
2367 \r
2368 // 文字列 string から文字列 keyword を検索して最初に見つかった文字の場所を返す\r
2369 // (1文字目に見つかったら 0, 見つからなかったら INFINITE)\r
2370 UINT UniSearchStrEx(wchar_t *string, wchar_t *keyword, UINT start, bool case_sensitive)\r
2371 {\r
2372         UINT len_string, len_keyword;\r
2373         UINT i;\r
2374         wchar_t *cmp_string, *cmp_keyword;\r
2375         bool found;\r
2376         // 引数チェック\r
2377         if (string == NULL || keyword == NULL)\r
2378         {\r
2379                 return INFINITE;\r
2380         }\r
2381 \r
2382         // string の長さを取得\r
2383         len_string = UniStrLen(string);\r
2384         if (len_string <= start)\r
2385         {\r
2386                 // start の値が不正\r
2387                 return INFINITE;\r
2388         }\r
2389 \r
2390         // keyword の長さを取得\r
2391         len_keyword = UniStrLen(keyword);\r
2392         if (len_keyword == 0)\r
2393         {\r
2394                 // キーワードが無い\r
2395                 return INFINITE;\r
2396         }\r
2397 \r
2398         if (len_string < len_keyword)\r
2399         {\r
2400                 return INFINITE;\r
2401         }\r
2402 \r
2403         if (len_string == len_keyword)\r
2404         {\r
2405                 if (case_sensitive)\r
2406                 {\r
2407                         if (UniStrCmp(string, keyword) == 0)\r
2408                         {\r
2409                                 return 0;\r
2410                         }\r
2411                         else\r
2412                         {\r
2413                                 return INFINITE;\r
2414                         }\r
2415                 }\r
2416                 else\r
2417                 {\r
2418                         if (UniStrCmpi(string, keyword) == 0)\r
2419                         {\r
2420                                 return 0;\r
2421                         }\r
2422                         else\r
2423                         {\r
2424                                 return INFINITE;\r
2425                         }\r
2426                 }\r
2427         }\r
2428 \r
2429         if (case_sensitive)\r
2430         {\r
2431                 cmp_string = string;\r
2432                 cmp_keyword = keyword;\r
2433         }\r
2434         else\r
2435         {\r
2436                 cmp_string = Malloc((len_string + 1) * sizeof(wchar_t));\r
2437                 UniStrCpy(cmp_string, (len_string + 1) * sizeof(wchar_t), string);\r
2438                 cmp_keyword = Malloc((len_keyword + 1) * sizeof(wchar_t));\r
2439                 UniStrCpy(cmp_keyword, (len_keyword + 1) * sizeof(wchar_t), keyword);\r
2440                 UniStrUpper(cmp_string);\r
2441                 UniStrUpper(cmp_keyword);\r
2442         }\r
2443 \r
2444         // 検索\r
2445         found = false;\r
2446         for (i = start;i < (len_string - len_keyword + 1);i++)\r
2447         {\r
2448                 // 比較する\r
2449                 if (!wcsncmp(&cmp_string[i], cmp_keyword, len_keyword))\r
2450                 {\r
2451                         // 発見した\r
2452                         found = true;\r
2453                         break;\r
2454                 }\r
2455         }\r
2456 \r
2457         if (case_sensitive == false)\r
2458         {\r
2459                 // メモリ解放\r
2460                 Free(cmp_keyword);\r
2461                 Free(cmp_string);\r
2462         }\r
2463 \r
2464         if (found == false)\r
2465         {\r
2466                 return INFINITE;\r
2467         }\r
2468         return i;\r
2469 }\r
2470 \r
2471 // トークンリストの解放\r
2472 void UniFreeToken(UNI_TOKEN_LIST *tokens)\r
2473 {\r
2474         UINT i;\r
2475         if (tokens == NULL)\r
2476         {\r
2477                 return;\r
2478         }\r
2479         for (i = 0;i < tokens->NumTokens;i++)\r
2480         {\r
2481                 Free(tokens->Token[i]);\r
2482         }\r
2483         Free(tokens->Token);\r
2484         Free(tokens);\r
2485 }\r
2486 \r
2487 // UNIX 版トークンのパース\r
2488 UNI_TOKEN_LIST *UnixUniParseToken(wchar_t *src, wchar_t *separator)\r
2489 {\r
2490         UNI_TOKEN_LIST *ret;\r
2491         TOKEN_LIST *t;\r
2492         char *src_s;\r
2493         char *sep_s;\r
2494 \r
2495         // 引数チェック\r
2496         if (src == NULL || separator == NULL)\r
2497         {\r
2498                 ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));\r
2499                 ret->Token = ZeroMalloc(0);\r
2500                 return ret;\r
2501         }\r
2502 \r
2503         src_s = CopyUniToStr(src);\r
2504         sep_s = CopyUniToStr(separator);\r
2505 \r
2506         t = ParseToken(src_s, sep_s);\r
2507 \r
2508         ret = TokenListToUniTokenList(t);\r
2509         FreeToken(t);\r
2510 \r
2511         Free(src_s);\r
2512         Free(sep_s);\r
2513 \r
2514         return ret;\r
2515 }\r
2516 \r
2517 // トークンのパース\r
2518 UNI_TOKEN_LIST *UniParseToken(wchar_t *src, wchar_t *separator)\r
2519 {\r
2520 #ifdef  OS_WIN32\r
2521         UNI_TOKEN_LIST *ret;\r
2522         wchar_t *tmp;\r
2523         wchar_t *str1, *str2;\r
2524         UINT len, num;\r
2525 \r
2526 #ifdef  OS_UNIX\r
2527         wchar_t *state = NULL;\r
2528 #endif  // OS_UNIX\r
2529 \r
2530         // 引数チェック\r
2531         if (src == NULL)\r
2532         {\r
2533                 ret = ZeroMalloc(sizeof(UNI_TOKEN_LIST));\r
2534                 ret->Token = ZeroMalloc(0);\r
2535                 return ret;\r
2536         }\r
2537         if (separator == NULL)\r
2538         {\r
2539                 separator = L" .\t\r\n";\r
2540         }\r
2541         len = UniStrLen(src);\r
2542         str1 = Malloc((len + 1) * sizeof(wchar_t));\r
2543         str2 = Malloc((len + 1) * sizeof(wchar_t));\r
2544         UniStrCpy(str1, 0, src);\r
2545         UniStrCpy(str2, 0, src);\r
2546 \r
2547         Lock(token_lock);\r
2548         {\r
2549                 tmp = wcstok(str1, separator\r
2550 #ifdef  OS_UNIX\r
2551                         , &state\r
2552 #endif  // OS_UNIX\r
2553                         );\r
2554                 num = 0;\r
2555                 while (tmp != NULL)\r
2556                 {\r
2557                         num++;\r
2558                         tmp = wcstok(NULL, separator\r
2559 #ifdef  OS_UNIX\r
2560                                 , &state\r
2561 #endif  // OS_UNIX\r
2562                                 );\r
2563                 }\r
2564                 ret = Malloc(sizeof(UNI_TOKEN_LIST));\r
2565                 ret->NumTokens = num;\r
2566                 ret->Token = (wchar_t **)Malloc(sizeof(wchar_t *) * num);\r
2567                 num = 0;\r
2568                 tmp = wcstok(str2, separator\r
2569 #ifdef  OS_UNIX\r
2570                         , &state\r
2571 #endif  // OS_UNIX\r
2572                         );\r
2573                 while (tmp != NULL)\r
2574                 {\r
2575                         ret->Token[num] = (wchar_t *)Malloc((UniStrLen(tmp) + 1) * sizeof(wchar_t));\r
2576                         UniStrCpy(ret->Token[num], 0, tmp);\r
2577                         num++;\r
2578                         tmp = wcstok(NULL, separator\r
2579 #ifdef  OS_UNIX\r
2580                                 , &state\r
2581 #endif  // OS_UNIX\r
2582                                 );\r
2583                 }\r
2584         }\r
2585         Unlock(token_lock);\r
2586 \r
2587         Free(str1);\r
2588         Free(str2);\r
2589         return ret;\r
2590 #else   // OS_WIN32\r
2591         return UnixUniParseToken(src, separator);\r
2592 #endif  // OS_WIN32\r
2593 }\r
2594 \r
2595 // 1 行を標準入力から取得\r
2596 bool UniGetLine(wchar_t *str, UINT size)\r
2597 {\r
2598 #ifdef  OS_WIN32\r
2599         return UniGetLineWin32(str, size);\r
2600 #else   // OS_WIN32\r
2601         return UniGetLineUnix(str, size);\r
2602 #endif  // OS_WIN32\r
2603 }\r
2604 void AnsiGetLineUnix(char *str, UINT size)\r
2605 {\r
2606         // 引数チェック\r
2607         if (str == NULL)\r
2608         {\r
2609                 char tmp[MAX_SIZE];\r
2610                 fgets(tmp, sizeof(tmp) - 1, stdin);\r
2611                 return;\r
2612         }\r
2613         if (size <= 1)\r
2614         {\r
2615                 return;\r
2616         }\r
2617 \r
2618         // 標準入力からデータを読み込み\r
2619         fgets(str, (int)(size - 1), stdin);\r
2620 \r
2621         TrimCrlf(str);\r
2622 }\r
2623 bool UniGetLineUnix(wchar_t *str, UINT size)\r
2624 {\r
2625         char *str_a;\r
2626         UINT str_a_size = size;\r
2627         if (str == NULL || size < sizeof(wchar_t))\r
2628         {\r
2629                 return false;\r
2630         }\r
2631         if (str_a_size >= 0x7fffffff)\r
2632         {\r
2633                 str_a_size = MAX_SIZE;\r
2634         }\r
2635         str_a_size *= 2;\r
2636 \r
2637         str_a = ZeroMalloc(str_a_size);\r
2638 \r
2639         AnsiGetLineUnix(str_a, str_a_size);\r
2640 \r
2641         StrToUni(str, size, str_a);\r
2642 \r
2643         Free(str_a);\r
2644 \r
2645         return true;\r
2646 }\r
2647 bool UniGetLineWin32(wchar_t *str, UINT size)\r
2648 {\r
2649         bool ret = false;\r
2650 \r
2651 #ifdef  OS_WIN32\r
2652         ret = Win32InputW(str, size);\r
2653 #endif  // OS_WIN32\r
2654 \r
2655         return ret;\r
2656 }\r
2657 \r
2658 // 末尾の \r \n を削除\r
2659 void UniTrimCrlf(wchar_t *str)\r
2660 {\r
2661         UINT len;\r
2662         // 引数チェック\r
2663         if (str == NULL)\r
2664         {\r
2665                 return;\r
2666         }\r
2667         len = UniStrLen(str);\r
2668         if (len == 0)\r
2669         {\r
2670                 return;\r
2671         }\r
2672 \r
2673         if (str[len - 1] == L'\n')\r
2674         {\r
2675                 if (len >= 2 && str[len - 2] == L'\r')\r
2676                 {\r
2677                         str[len - 2] = 0;\r
2678                 }\r
2679                 str[len - 1] = 0;\r
2680         }\r
2681         else if(str[len - 1] == L'\r')\r
2682         {\r
2683                 str[len - 1] = 0;\r
2684         }\r
2685 }\r
2686 \r
2687 // 文字列の左右の空白を削除\r
2688 void UniTrim(wchar_t *str)\r
2689 {\r
2690         // 引数チェック\r
2691         if (str == NULL)\r
2692         {\r
2693                 return;\r
2694         }\r
2695 \r
2696         UniTrimLeft(str);\r
2697         UniTrimRight(str);\r
2698 }\r
2699 \r
2700 // 文字列の右側の空白を削除\r
2701 void UniTrimRight(wchar_t *str)\r
2702 {\r
2703         wchar_t *buf, *tmp;\r
2704         UINT len, i, wp, wp2;\r
2705         bool flag;\r
2706         // 引数チェック\r
2707         if (str == NULL)\r
2708         {\r
2709                 return;\r
2710         }\r
2711         len = UniStrLen(str);\r
2712         if (len == 0)\r
2713         {\r
2714                 return;\r
2715         }\r
2716         if (str[len - 1] != L' ' && str[len - 1] != L'\t')\r
2717         {\r
2718                 return;\r
2719         }\r
2720 \r
2721         buf = Malloc((len + 1) * sizeof(wchar_t));\r
2722         tmp = Malloc((len + 1) * sizeof(wchar_t));\r
2723         flag = false;\r
2724         wp = wp2 = 0;\r
2725         for (i = 0;i < len;i++)\r
2726         {\r
2727                 if (str[i] != L' ' && str[i] != L'\t')\r
2728                 {\r
2729                         Copy(&buf[wp], tmp, wp2 * sizeof(wchar_t));\r
2730                         wp += wp2;\r
2731                         wp2 = 0;\r
2732                         buf[wp++] = str[i];\r
2733                 }\r
2734                 else\r
2735                 {\r
2736                         tmp[wp2++] = str[i];\r
2737                 }\r
2738         }\r
2739         buf[wp] = 0;\r
2740         UniStrCpy(str, 0, buf);\r
2741         Free(buf);\r
2742         Free(tmp);\r
2743 }\r
2744 \r
2745 // 文字列の左側の空白を削除\r
2746 void UniTrimLeft(wchar_t *str)\r
2747 {\r
2748         wchar_t *buf;\r
2749         UINT len, i, wp;\r
2750         bool flag;\r
2751         // 引数チェック\r
2752         if (str == NULL)\r
2753         {\r
2754                 return;\r
2755         }\r
2756         len = UniStrLen(str);\r
2757         if (len == 0)\r
2758         {\r
2759                 return;\r
2760         }\r
2761         if (str[0] != L' ' && str[0] != L'\t')\r
2762         {\r
2763                 return;\r
2764         }\r
2765 \r
2766         buf = Malloc((len + 1) * sizeof(wchar_t));\r
2767         flag = false;\r
2768         wp = 0;\r
2769         for (i = 0;i < len;i++)\r
2770         {\r
2771                 if (str[i] != L' ' && str[i] != L'\t')\r
2772                 {\r
2773                         flag = true;\r
2774                 }\r
2775                 if (flag)\r
2776                 {\r
2777                         buf[wp++] = str[i];\r
2778                 }\r
2779         }\r
2780         buf[wp] = 0;\r
2781         UniStrCpy(str, 0, buf);\r
2782         Free(buf);\r
2783 }\r
2784 \r
2785 // 整数を 16 進文字列に変換 (8桁固定)\r
2786 void UniToStrx8(wchar_t *str, UINT i)\r
2787 {\r
2788         UniFormat(str, 0, L"0x%08x", i);\r
2789 }\r
2790 \r
2791 // 整数を 16 進文字列に変換\r
2792 void UniToStrx(wchar_t *str, UINT i)\r
2793 {\r
2794         UniFormat(str, 0, L"0x%02x", i);\r
2795 }\r
2796 \r
2797 // 符号付整数を文字列に変換\r
2798 void UniToStri(wchar_t *str, int i)\r
2799 {\r
2800         UniFormat(str, 0, L"%i", i);\r
2801 }\r
2802 \r
2803 // 整数を文字列に変換\r
2804 void UniToStru(wchar_t *str, UINT i)\r
2805 {\r
2806         UniFormat(str, 0, L"%u", i);\r
2807 }\r
2808 \r
2809 // 文字列を符号付整数に変換\r
2810 int UniToInti(wchar_t *str)\r
2811 {\r
2812         char tmp[128];\r
2813         // 引数チェック\r
2814         if (str == NULL)\r
2815         {\r
2816                 return 0;\r
2817         }\r
2818 \r
2819         UniToStr(tmp, sizeof(tmp), str);\r
2820 \r
2821         return ToInt(tmp);\r
2822 }\r
2823 \r
2824 // 文字列を整数に変換\r
2825 UINT UniToInt(wchar_t *str)\r
2826 {\r
2827         char tmp[128];\r
2828         // 引数チェック\r
2829         if (str == NULL)\r
2830         {\r
2831                 return 0;\r
2832         }\r
2833 \r
2834         UniToStr(tmp, sizeof(tmp), str);\r
2835 \r
2836         return ToInti(tmp);\r
2837 }\r
2838 \r
2839 // 64bit 用フォーマット文字列置換\r
2840 wchar_t *UniReplaceFormatStringFor64(wchar_t *fmt)\r
2841 {\r
2842         wchar_t *tmp;\r
2843         wchar_t *ret;\r
2844         UINT tmp_size;\r
2845         // 引数チェック\r
2846         if (fmt == NULL)\r
2847         {\r
2848                 return NULL;\r
2849         }\r
2850 \r
2851         tmp_size = UniStrSize(fmt) * 2;\r
2852         tmp = ZeroMalloc(tmp_size);\r
2853 \r
2854 #ifdef  OS_WIN32\r
2855         UniReplaceStrEx(tmp, tmp_size, fmt, L"%ll", L"%I64", false);\r
2856 #else   // OS_WIN32\r
2857         UniReplaceStrEx(tmp, tmp_size, fmt, L"%I64", L"%ll", false);\r
2858 \r
2859         if (1)\r
2860         {\r
2861                 UINT i, len;\r
2862                 bool f = false;\r
2863                 len = UniStrLen(tmp);\r
2864                 for (i = 0;i < len;i++)\r
2865                 {\r
2866                         if (tmp[i] == L'%')\r
2867                         {\r
2868                                 f = true;\r
2869                         }\r
2870 \r
2871                         if (f)\r
2872                         {\r
2873                                 switch (tmp[i])\r
2874                                 {\r
2875                                 case L'c':\r
2876                                 case L'C':\r
2877                                 case L'd':\r
2878                                 case L'i':\r
2879                                 case L'o':\r
2880                                 case L'u':\r
2881                                 case L'x':\r
2882                                 case L'X':\r
2883                                 case L'e':\r
2884                                 case L'E':\r
2885                                 case L'f':\r
2886                                 case L'g':\r
2887                                 case L'G':\r
2888                                 case L'n':\r
2889                                 case L'p':\r
2890                                 case L's':\r
2891                                 case L'S':\r
2892                                         if (tmp[i] == L's')\r
2893                                         {\r
2894                                                 tmp[i] = L'S';\r
2895                                         }\r
2896                                         else if (tmp[i] == L'S')\r
2897                                         {\r
2898                                                 tmp[i] = L's';\r
2899                                         }\r
2900                                         f = false;\r
2901                                         break;\r
2902                                 }\r
2903                         }\r
2904                 }\r
2905         }\r
2906 \r
2907 #endif  // OS_WIN32\r
2908 \r
2909         ret = CopyUniStr(tmp);\r
2910         Free(tmp);\r
2911 \r
2912         return ret;\r
2913 }\r
2914 \r
2915 // 文字列を画面に表示する\r
2916 void UniPrintStr(wchar_t *string)\r
2917 {\r
2918         // 引数チェック\r
2919         if (string == NULL)\r
2920         {\r
2921                 return;\r
2922         }\r
2923 \r
2924 #ifdef  OS_UNIX\r
2925         if (true)\r
2926         {\r
2927                 char *str = CopyUniToStr(string);\r
2928 \r
2929                 if (str != NULL)\r
2930                 {\r
2931                         fputs(str, stdout);\r
2932                 }\r
2933                 else\r
2934                 {\r
2935                         fputs("", stdout);\r
2936                 }\r
2937 \r
2938                 Free(str);\r
2939         }\r
2940 #else   // OS_UNIX\r
2941         Win32PrintW(string);\r
2942 #endif  // OS_UNIX\r
2943 }\r
2944 \r
2945 // 文字列を引数付きで表示する\r
2946 void UniPrintArgs(wchar_t *fmt, va_list args)\r
2947 {\r
2948         wchar_t *str;\r
2949         // 引数チェック\r
2950         if (fmt == NULL)\r
2951         {\r
2952                 return;\r
2953         }\r
2954 \r
2955         str = InternalFormatArgs(fmt, args, false);\r
2956 \r
2957         UniPrintStr(str);\r
2958 \r
2959         Free(str);\r
2960 }\r
2961 \r
2962 // 文字列を表示する\r
2963 void UniPrint(wchar_t *fmt, ...)\r
2964 {\r
2965         va_list args;\r
2966         // 引数チェック\r
2967         if (fmt == NULL)\r
2968         {\r
2969                 return;\r
2970         }\r
2971 \r
2972         va_start(args, fmt);\r
2973         UniPrintArgs(fmt, args);\r
2974         va_end(args);\r
2975 }\r
2976 \r
2977 // デバッグ文字列を引数付きで表示する\r
2978 void UniDebugArgs(wchar_t *fmt, va_list args)\r
2979 {\r
2980         if (g_debug == false)\r
2981         {\r
2982                 return;\r
2983         }\r
2984 \r
2985         UniPrintArgs(fmt, args);\r
2986 }\r
2987 \r
2988 // デバッグ文字列を表示する\r
2989 void UniDebug(wchar_t *fmt, ...)\r
2990 {\r
2991         va_list args;\r
2992         // 引数チェック\r
2993         if (fmt == NULL)\r
2994         {\r
2995                 return;\r
2996         }\r
2997 \r
2998         va_start(args, fmt);\r
2999         UniDebugArgs(fmt, args);\r
3000         va_end(args);\r
3001 }\r
3002 \r
3003 // 文字列をフォーマットする (引数リスト)\r
3004 void UniFormatArgs(wchar_t *buf, UINT size, wchar_t *fmt, va_list args)\r
3005 {\r
3006         wchar_t *ret;\r
3007         // 引数チェック\r
3008         if (buf == NULL || fmt == NULL)\r
3009         {\r
3010                 return;\r
3011         }\r
3012         if (size == 1)\r
3013         {\r
3014                 return;\r
3015         }\r
3016 \r
3017         // KS\r
3018         KS_INC(KS_FORMAT_COUNT);\r
3019 \r
3020         ret = InternalFormatArgs(fmt, args, false);\r
3021 \r
3022         UniStrCpy(buf, size, ret);\r
3023 \r
3024         Free(ret);\r
3025 }\r
3026 \r
3027 // 文字列をフォーマットして結果をコピーする\r
3028 wchar_t *CopyUniFormat(wchar_t *fmt, ...)\r
3029 {\r
3030         wchar_t *ret, *str;\r
3031         UINT size;\r
3032         va_list args;\r
3033         // 引数チェック\r
3034         if (fmt == NULL)\r
3035         {\r
3036                 return NULL;\r
3037         }\r
3038 \r
3039         size = MAX(UniStrSize(fmt) * 10, MAX_SIZE * 10);\r
3040         str = Malloc(size);\r
3041 \r
3042         va_start(args, fmt);\r
3043         UniFormatArgs(str, size, fmt, args);\r
3044 \r
3045         ret = UniCopyStr(str);\r
3046         Free(str);\r
3047         va_end(args);\r
3048 \r
3049         return ret;\r
3050 }\r
3051 \r
3052 // 文字列をフォーマットする\r
3053 void UniFormat(wchar_t *buf, UINT size, wchar_t *fmt, ...)\r
3054 {\r
3055         va_list args;\r
3056         // 引数チェック\r
3057         if (buf == NULL || fmt == NULL)\r
3058         {\r
3059                 return;\r
3060         }\r
3061 \r
3062         va_start(args, fmt);\r
3063         UniFormatArgs(buf, size, fmt, args);\r
3064         va_end(args);\r
3065 }\r
3066 \r
3067 // 柔軟な文字列比較\r
3068 int UniSoftStrCmp(wchar_t *str1, wchar_t *str2)\r
3069 {\r
3070         UINT ret;\r
3071         wchar_t *tmp1, *tmp2;\r
3072         // 引数チェック\r
3073         if (str1 == NULL && str2 == NULL)\r
3074         {\r
3075                 return 0;\r
3076         }\r
3077         if (str1 == NULL)\r
3078         {\r
3079                 return 1;\r
3080         }\r
3081         if (str2 == NULL)\r
3082         {\r
3083                 return -1;\r
3084         }\r
3085 \r
3086         tmp1 = CopyUniStr(str1);\r
3087         tmp2 = CopyUniStr(str2);\r
3088 \r
3089         UniTrim(tmp1);\r
3090         UniTrim(tmp2);\r
3091 \r
3092         ret = UniStrCmpi(tmp1, tmp2);\r
3093 \r
3094         Free(tmp1);\r
3095         Free(tmp2);\r
3096 \r
3097         return ret;\r
3098 }\r
3099 \r
3100 // 文字列を大文字・小文字を区別せずに比較する\r
3101 int UniStrCmpi(wchar_t *str1, wchar_t *str2)\r
3102 {\r
3103         UINT i;\r
3104         // 引数チェック\r
3105         if (str1 == NULL && str2 == NULL)\r
3106         {\r
3107                 return 0;\r
3108         }\r
3109         if (str1 == NULL)\r
3110         {\r
3111                 return 1;\r
3112         }\r
3113         if (str2 == NULL)\r
3114         {\r
3115                 return -1;\r
3116         }\r
3117 \r
3118         // 文字列比較\r
3119         i = 0;\r
3120         while (true)\r
3121         {\r
3122                 wchar_t c1, c2;\r
3123                 c1 = UniToUpper(str1[i]);\r
3124                 c2 = UniToUpper(str2[i]);\r
3125                 if (c1 > c2)\r
3126                 {\r
3127                         return 1;\r
3128                 }\r
3129                 else if (c1 < c2)\r
3130                 {\r
3131                         return -1;\r
3132                 }\r
3133                 if (str1[i] == 0 || str2[i] == 0)\r
3134                 {\r
3135                         return 0;\r
3136                 }\r
3137                 i++;\r
3138         }\r
3139 }\r
3140 \r
3141 // 文字列を比較する\r
3142 int UniStrCmp(wchar_t *str1, wchar_t *str2)\r
3143 {\r
3144         // 引数チェック\r
3145         if (str1 == NULL && str2 == NULL)\r
3146         {\r
3147                 return 0;\r
3148         }\r
3149         if (str1 == NULL)\r
3150         {\r
3151                 return 1;\r
3152         }\r
3153         if (str2 == NULL)\r
3154         {\r
3155                 return -1;\r
3156         }\r
3157 \r
3158         return wcscmp(str1, str2);\r
3159 }\r
3160 \r
3161 // 文字列を小文字にする\r
3162 void UniStrLower(wchar_t *str)\r
3163 {\r
3164         UINT i, len;\r
3165         // 引数チェック\r
3166         if (str == NULL)\r
3167         {\r
3168                 return;\r
3169         }\r
3170 \r
3171         len = UniStrLen(str);\r
3172         for (i = 0;i < len;i++)\r
3173         {\r
3174                 str[i] = UniToLower(str[i]);\r
3175         }\r
3176 }\r
3177 \r
3178 // 文字列を大文字にする\r
3179 void UniStrUpper(wchar_t *str)\r
3180 {\r
3181         UINT i, len;\r
3182         // 引数チェック\r
3183         if (str == NULL)\r
3184         {\r
3185                 return;\r
3186         }\r
3187 \r
3188         len = UniStrLen(str);\r
3189         for (i = 0;i < len;i++)\r
3190         {\r
3191                 str[i] = UniToUpper(str[i]);\r
3192         }\r
3193 }\r
3194 \r
3195 // 文字を小文字にする\r
3196 wchar_t UniToLower(wchar_t c)\r
3197 {\r
3198         if (c >= L'A' && c <= L'Z')\r
3199         {\r
3200                 c += L'a' - L'A';\r
3201         }\r
3202 \r
3203         return c;\r
3204 }\r
3205 \r
3206 // 文字を大文字にする\r
3207 wchar_t UniToUpper(wchar_t c)\r
3208 {\r
3209         if (c >= L'a' && c <= L'z')\r
3210         {\r
3211                 c -= L'a' - L'A';\r
3212         }\r
3213 \r
3214         return c;\r
3215 }\r
3216 \r
3217 // 文字列結合\r
3218 UINT UniStrCat(wchar_t *dst, UINT size, wchar_t *src)\r
3219 {\r
3220         UINT len1, len2, len_test;\r
3221         // 引数チェック\r
3222         if (dst == NULL || src == NULL)\r
3223         {\r
3224                 return 0;\r
3225         }\r
3226         if (size != 0 && size < sizeof(wchar_t))\r
3227         {\r
3228                 return 0;\r
3229         }\r
3230         if (size == sizeof(wchar_t))\r
3231         {\r
3232                 wcscpy(dst, L"");\r
3233                 return 0;\r
3234         }\r
3235         if (size == 0)\r
3236         {\r
3237                 // 長さ無視\r
3238                 size = 0x3fffffff;\r
3239         }\r
3240 \r
3241         len1 = UniStrLen(dst);\r
3242         len2 = UniStrLen(src);\r
3243         len_test = len1 + len2 + 1;\r
3244         if (len_test > (size / sizeof(wchar_t)))\r
3245         {\r
3246                 if (len2 <= (len_test - (size / sizeof(wchar_t))))\r
3247                 {\r
3248                         return 0;\r
3249                 }\r
3250                 len2 -= len_test - (size / sizeof(wchar_t));\r
3251         }\r
3252         Copy(&dst[len1], src, len2 * sizeof(wchar_t));\r
3253         dst[len1 + len2] = 0;\r
3254 \r
3255         return len1 + len2;\r
3256 }\r
3257 UINT UniStrCatLeft(wchar_t *dst, UINT size, wchar_t *src)\r
3258 {\r
3259         wchar_t *s;\r
3260         // 引数チェック\r
3261         if (dst == NULL || src == NULL)\r
3262         {\r
3263                 return 0;\r
3264         }\r
3265 \r
3266         s = UniCopyStr(dst);\r
3267         UniStrCpy(dst, size, s);\r
3268         UniStrCat(dst, size, src);\r
3269         Free(s);\r
3270 \r
3271         return UniStrLen(dst);\r
3272 }\r
3273 \r
3274 // 文字列コピー\r
3275 UINT UniStrCpy(wchar_t *dst, UINT size, wchar_t *src)\r
3276 {\r
3277         UINT len;\r
3278         // 引数チェック\r
3279         if (dst == NULL || src == NULL)\r
3280         {\r
3281                 if (src == NULL && dst != NULL)\r
3282                 {\r
3283                         if (size >= sizeof(wchar_t))\r
3284                         {\r
3285                                 dst[0] = L'\0';\r
3286                         }\r
3287                 }\r
3288                 return 0;\r
3289         }\r
3290         if (dst == src)\r
3291         {\r
3292                 return UniStrLen(src);\r
3293         }\r
3294         if (size != 0 && size < sizeof(wchar_t))\r
3295         {\r
3296                 return 0;\r
3297         }\r
3298         if (size == sizeof(wchar_t))\r
3299         {\r
3300                 wcscpy(dst, L"");\r
3301                 return 0;\r
3302         }\r
3303         if (size == 0)\r
3304         {\r
3305                 // 長さ無視\r
3306                 size = 0x3fffffff;\r
3307         }\r
3308 \r
3309         // 長さをチェック\r
3310         len = UniStrLen(src);\r
3311         if (len <= (size / sizeof(wchar_t) - 1))\r
3312         {\r
3313                 Copy(dst, src, (len + 1) * sizeof(wchar_t));\r
3314         }\r
3315         else\r
3316         {\r
3317                 len = size / 2 - 1;\r
3318                 Copy(dst, src, len * sizeof(wchar_t));\r
3319                 dst[len] = 0;\r
3320         }\r
3321 \r
3322         return len;\r
3323 }\r
3324 \r
3325 // 文字が指定されたバッファサイズ以内かどうかチェック\r
3326 bool UniCheckStrSize(wchar_t *str, UINT size)\r
3327 {\r
3328         // 引数チェック\r
3329         if (str == NULL || size <= 1)\r
3330         {\r
3331                 return false;\r
3332         }\r
3333 \r
3334         return UniCheckStrLen(str, size / sizeof(wchar_t) - 1);\r
3335 }\r
3336 \r
3337 // 文字数が指定された長さ以内かどうかチェック\r
3338 bool UniCheckStrLen(wchar_t *str, UINT len)\r
3339 {\r
3340         UINT count = 0;\r
3341         UINT i;\r
3342         // 引数チェック\r
3343         if (str == NULL)\r
3344         {\r
3345                 return false;\r
3346         }\r
3347 \r
3348         for (i = 0;;i++)\r
3349         {\r
3350                 if (str[i] == 0)\r
3351                 {\r
3352                         return true;\r
3353                 }\r
3354                 count++;\r
3355                 if (count > len)\r
3356                 {\r
3357                         return false;\r
3358                 }\r
3359         }\r
3360 }\r
3361 \r
3362 // 文字列の格納に必要なバッファサイズの取得\r
3363 UINT UniStrSize(wchar_t *str)\r
3364 {\r
3365         // 引数チェック\r
3366         if (str == NULL)\r
3367         {\r
3368                 return 0;\r
3369         }\r
3370 \r
3371         return (UniStrLen(str) + 1) * sizeof(wchar_t);\r
3372 }\r
3373 \r
3374 // 文字列の長さの取得\r
3375 UINT UniStrLen(wchar_t *str)\r
3376 {\r
3377         UINT i;\r
3378         // 引数チェック\r
3379         if (str == NULL)\r
3380         {\r
3381                 return 0;\r
3382         }\r
3383 \r
3384         i = 0;\r
3385         while (true)\r
3386         {\r
3387                 if (str[i] == 0)\r
3388                 {\r
3389                         break;\r
3390                 }\r
3391                 i++;\r
3392         }\r
3393 \r
3394         return i;\r
3395 }\r
3396 \r