* copy vendor drop to trunk
[lab.git] / Dev / utvpn / utvpn-unix-v101-7101-public / src / Mayaqua / Str.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 // Str.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 // トークン関数の呼び出し用ロック処理\r
91 LOCK *token_lock = NULL;\r
92 static char *default_spliter = " ,\t\r\n";\r
93 \r
94 typedef struct BYTESTR\r
95 {\r
96         UINT64 base_value;\r
97         char *string;\r
98 } BYTESTR;\r
99 \r
100 static BYTESTR bytestr[] =\r
101 {\r
102         {0, "PBytes"},\r
103         {0, "TBytes"},\r
104         {0, "GBytes"},\r
105         {0, "MBytes"},\r
106         {0, "KBytes"},\r
107         {0, "Bytes"},\r
108 };\r
109 \r
110 // HEX 文字列を 64 bit 整数に変換\r
111 UINT64 HexToInt64(char *str)\r
112 {\r
113         UINT len, i;\r
114         UINT64 ret = 0;\r
115         // 引数チェック\r
116         if (str == NULL)\r
117         {\r
118                 return 0;\r
119         }\r
120 \r
121         if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))\r
122         {\r
123                 str += 2;\r
124         }\r
125 \r
126         len = StrLen(str);\r
127         for (i = 0;i < len;i++)\r
128         {\r
129                 char c = str[i];\r
130 \r
131                 if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))\r
132                 {\r
133                         ret = ret * 16ULL + (UINT64)HexTo4Bit(c);\r
134                 }\r
135                 else\r
136                 {\r
137                         break;\r
138                 }\r
139         }\r
140 \r
141         return ret;\r
142 }\r
143 \r
144 // HEX 文字列を 32 bit 整数に変換\r
145 UINT HexToInt(char *str)\r
146 {\r
147         UINT len, i;\r
148         UINT ret = 0;\r
149         // 引数チェック\r
150         if (str == NULL)\r
151         {\r
152                 return 0;\r
153         }\r
154 \r
155         if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))\r
156         {\r
157                 str += 2;\r
158         }\r
159 \r
160         len = StrLen(str);\r
161         for (i = 0;i < len;i++)\r
162         {\r
163                 char c = str[i];\r
164 \r
165                 if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))\r
166                 {\r
167                         ret = ret * 16 + (UINT)HexTo4Bit(c);\r
168                 }\r
169                 else\r
170                 {\r
171                         break;\r
172                 }\r
173         }\r
174 \r
175         return ret;\r
176 }\r
177 \r
178 // 64 bit 整数を HEX に変換\r
179 void ToHex64(char *str, UINT64 value)\r
180 {\r
181         char tmp[MAX_SIZE];\r
182         UINT wp = 0;\r
183         UINT len, i;\r
184         // 引数チェック\r
185         if (str == NULL)\r
186         {\r
187                 return;\r
188         }\r
189 \r
190         // 空文字に設定\r
191         StrCpy(tmp, 0, "");\r
192 \r
193         // 末尾桁から追加する\r
194         while (true)\r
195         {\r
196                 UINT a = (UINT)(value % (UINT64)16);\r
197                 value = value / (UINT)16;\r
198                 tmp[wp++] = FourBitToHex(a);\r
199                 if (value == 0)\r
200                 {\r
201                         tmp[wp++] = 0;\r
202                         break;\r
203                 }\r
204         }\r
205 \r
206         // 逆順にする\r
207         len = StrLen(tmp);\r
208         for (i = 0;i < len;i++)\r
209         {\r
210                 str[len - i - 1] = tmp[i];\r
211         }\r
212         str[len] = 0;\r
213 }\r
214 \r
215 // 32 bit 整数を HEX に変換\r
216 void ToHex(char *str, UINT value)\r
217 {\r
218         char tmp[MAX_SIZE];\r
219         UINT wp = 0;\r
220         UINT len, i;\r
221         // 引数チェック\r
222         if (str == NULL)\r
223         {\r
224                 return;\r
225         }\r
226 \r
227         // 空文字に設定\r
228         StrCpy(tmp, 0, "");\r
229 \r
230         // 末尾桁から追加する\r
231         while (true)\r
232         {\r
233                 UINT a = (UINT)(value % (UINT)16);\r
234                 value = value / (UINT)16;\r
235                 tmp[wp++] = FourBitToHex(a);\r
236                 if (value == 0)\r
237                 {\r
238                         tmp[wp++] = 0;\r
239                         break;\r
240                 }\r
241         }\r
242 \r
243         // 逆順にする\r
244         len = StrLen(tmp);\r
245         for (i = 0;i < len;i++)\r
246         {\r
247                 str[len - i - 1] = tmp[i];\r
248         }\r
249         str[len] = 0;\r
250 }\r
251 \r
252 // 4 bit 数値を 16 進文字列に変換\r
253 char FourBitToHex(UINT value)\r
254 {\r
255         value = value % 16;\r
256 \r
257         if (value <= 9)\r
258         {\r
259                 return '0' + value;\r
260         }\r
261         else\r
262         {\r
263                 return 'a' + (value - 10);\r
264         }\r
265 }\r
266 \r
267 // 16 進文字列を 4 bit 整数に変換\r
268 UINT HexTo4Bit(char c)\r
269 {\r
270         if ('0' <= c && c <= '9')\r
271         {\r
272                 return c - '0';\r
273         }\r
274         else if ('a' <= c && c <= 'f')\r
275         {\r
276                 return c - 'a' + 10;\r
277         }\r
278         else if ('A' <= c && c <= 'F')\r
279         {\r
280                 return c - 'A' + 10;\r
281         }\r
282         else\r
283         {\r
284                 return 0;\r
285         }\r
286 }\r
287 \r
288 // 標準のトークン区切り文字を取得する\r
289 char *DefaultTokenSplitChars()\r
290 {\r
291         return " ,\t\r\n";\r
292 }\r
293 \r
294 // 指定された文字が文字列に含まれるかどうかチェック\r
295 bool IsCharInStr(char *str, char c)\r
296 {\r
297         UINT i, len;\r
298         // 引数チェック\r
299         if (str == NULL)\r
300         {\r
301                 return false;\r
302         }\r
303 \r
304         len = StrLen(str);\r
305         for (i = 0;i < len;i++)\r
306         {\r
307                 if (str[i] == c)\r
308                 {\r
309                         return true;\r
310                 }\r
311         }\r
312 \r
313         return false;\r
314 }\r
315 \r
316 // 文字列からトークンを切り出す (区切り文字間の空間を無視しない)\r
317 TOKEN_LIST *ParseTokenWithNullStr(char *str, char *split_chars)\r
318 {\r
319         LIST *o;\r
320         UINT i, len;\r
321         BUF *b;\r
322         char zero = 0;\r
323         TOKEN_LIST *t;\r
324         // 引数チェック\r
325         if (str == NULL)\r
326         {\r
327                 return NullToken();\r
328         }\r
329         if (split_chars == NULL)\r
330         {\r
331                 split_chars = DefaultTokenSplitChars();\r
332         }\r
333 \r
334         b = NewBuf();\r
335         o = NewListFast(NULL);\r
336 \r
337         len = StrLen(str);\r
338 \r
339         for (i = 0;i < (len + 1);i++)\r
340         {\r
341                 char c = str[i];\r
342                 bool flag = IsCharInStr(split_chars, c);\r
343 \r
344                 if (c == '\0')\r
345                 {\r
346                         flag = true;\r
347                 }\r
348 \r
349                 if (flag == false)\r
350                 {\r
351                         WriteBuf(b, &c, sizeof(char));\r
352                 }\r
353                 else\r
354                 {\r
355                         WriteBuf(b, &zero, sizeof(char));\r
356 \r
357                         Insert(o, CopyStr((char *)b->Buf));\r
358                         ClearBuf(b);\r
359                 }\r
360         }\r
361 \r
362         t = ZeroMalloc(sizeof(TOKEN_LIST));\r
363         t->NumTokens = LIST_NUM(o);\r
364         t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);\r
365 \r
366         for (i = 0;i < t->NumTokens;i++)\r
367         {\r
368                 t->Token[i] = LIST_DATA(o, i);\r
369         }\r
370 \r
371         ReleaseList(o);\r
372         FreeBuf(b);\r
373 \r
374         return t;\r
375 }\r
376 \r
377 // 文字列からトークンを切り出す (区切り文字間の空間を無視する)\r
378 TOKEN_LIST *ParseTokenWithoutNullStr(char *str, char *split_chars)\r
379 {\r
380         LIST *o;\r
381         UINT i, len;\r
382         bool last_flag;\r
383         BUF *b;\r
384         char zero = 0;\r
385         TOKEN_LIST *t;\r
386         // 引数チェック\r
387         if (str == NULL)\r
388         {\r
389                 return NullToken();\r
390         }\r
391         if (split_chars == NULL)\r
392         {\r
393                 split_chars = DefaultTokenSplitChars();\r
394         }\r
395 \r
396         b = NewBuf();\r
397         o = NewListFast(NULL);\r
398 \r
399         len = StrLen(str);\r
400         last_flag = false;\r
401 \r
402         for (i = 0;i < (len + 1);i++)\r
403         {\r
404                 char c = str[i];\r
405                 bool flag = IsCharInStr(split_chars, c);\r
406 \r
407                 if (c == '\0')\r
408                 {\r
409                         flag = true;\r
410                 }\r
411 \r
412                 if (flag == false)\r
413                 {\r
414                         WriteBuf(b, &c, sizeof(char));\r
415                 }\r
416                 else\r
417                 {\r
418                         if (last_flag == false)\r
419                         {\r
420                                 WriteBuf(b, &zero, sizeof(char));\r
421 \r
422                                 if ((StrLen((char *)b->Buf)) != 0)\r
423                                 {\r
424                                         Insert(o, CopyStr((char *)b->Buf));\r
425                                 }\r
426                                 ClearBuf(b);\r
427                         }\r
428                 }\r
429 \r
430                 last_flag = flag;\r
431         }\r
432 \r
433         t = ZeroMalloc(sizeof(TOKEN_LIST));\r
434         t->NumTokens = LIST_NUM(o);\r
435         t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);\r
436 \r
437         for (i = 0;i < t->NumTokens;i++)\r
438         {\r
439                 t->Token[i] = LIST_DATA(o, i);\r
440         }\r
441 \r
442         ReleaseList(o);\r
443         FreeBuf(b);\r
444 \r
445         return t;\r
446 }\r
447 \r
448 // 文字列が含まれているかどうかチェック\r
449 bool InStr(char *str, char *keyword)\r
450 {\r
451         return InStrEx(str, keyword, false);\r
452 }\r
453 bool InStrEx(char *str, char *keyword, bool case_sensitive)\r
454 {\r
455         // 引数チェック\r
456         if (IsEmptyStr(str) || IsEmptyStr(keyword))\r
457         {\r
458                 return false;\r
459         }\r
460 \r
461         if (SearchStrEx(str, keyword, 0, case_sensitive) == INFINITE)\r
462         {\r
463                 return false;\r
464         }\r
465 \r
466         return true;\r
467 }\r
468 \r
469 // INI から値を取得\r
470 UINT IniIntValue(LIST *o, char *key)\r
471 {\r
472         INI_ENTRY *e;\r
473         // 引数チェック\r
474         if (o == NULL || key == NULL)\r
475         {\r
476                 return 0;\r
477         }\r
478 \r
479         e = GetIniEntry(o, key);\r
480         if (e == NULL)\r
481         {\r
482                 return 0;\r
483         }\r
484 \r
485         return ToInt(e->Value);\r
486 }\r
487 UINT64 IniInt64Value(LIST *o, char *key)\r
488 {\r
489         INI_ENTRY *e;\r
490         // 引数チェック\r
491         if (o == NULL || key == NULL)\r
492         {\r
493                 return 0;\r
494         }\r
495 \r
496         e = GetIniEntry(o, key);\r
497         if (e == NULL)\r
498         {\r
499                 return 0;\r
500         }\r
501 \r
502         return ToInt64(e->Value);\r
503 }\r
504 char *IniStrValue(LIST *o, char *key)\r
505 {\r
506         INI_ENTRY *e;\r
507         // 引数チェック\r
508         if (o == NULL || key == NULL)\r
509         {\r
510                 return 0;\r
511         }\r
512 \r
513         e = GetIniEntry(o, key);\r
514         if (e == NULL)\r
515         {\r
516                 return "";\r
517         }\r
518 \r
519         return e->Value;\r
520 }\r
521 wchar_t *IniUniStrValue(LIST *o, char *key)\r
522 {\r
523         INI_ENTRY *e;\r
524         // 引数チェック\r
525         if (o == NULL || key == NULL)\r
526         {\r
527                 return 0;\r
528         }\r
529 \r
530         e = GetIniEntry(o, key);\r
531         if (e == NULL)\r
532         {\r
533                 return L"";\r
534         }\r
535 \r
536         return e->UnicodeValue;\r
537 }\r
538 \r
539 // INI を解放する\r
540 void FreeIni(LIST *o)\r
541 {\r
542         UINT i;\r
543         // 引数チェック\r
544         if (o == NULL)\r
545         {\r
546                 return;\r
547         }\r
548 \r
549         for (i = 0;i < LIST_NUM(o);i++)\r
550         {\r
551                 INI_ENTRY *e = LIST_DATA(o, i);\r
552 \r
553                 Free(e->Key);\r
554                 Free(e->Value);\r
555                 Free(e->UnicodeValue);\r
556 \r
557                 Free(e);\r
558         }\r
559 \r
560         ReleaseList(o);\r
561 }\r
562 \r
563 // INI ファイルのエントリを取得する\r
564 INI_ENTRY *GetIniEntry(LIST *o, char *key)\r
565 {\r
566         UINT i;\r
567         // 引数チェック\r
568         if (o == NULL || key == NULL)\r
569         {\r
570                 return NULL;\r
571         }\r
572 \r
573         for (i = 0;i < LIST_NUM(o);i++)\r
574         {\r
575                 INI_ENTRY *e = LIST_DATA(o, i);\r
576 \r
577                 if (StrCmpi(e->Key, key) == 0)\r
578                 {\r
579                         return e;\r
580                 }\r
581         }\r
582 \r
583         return NULL;\r
584 }\r
585 \r
586 // INI ファイルを読み込む\r
587 LIST *ReadIni(BUF *b)\r
588 {\r
589         LIST *o;\r
590         // 引数チェック\r
591         if (b == NULL)\r
592         {\r
593                 return NULL;\r
594         }\r
595 \r
596         o = NewListFast(NULL);\r
597 \r
598         SeekBuf(b, 0, 0);\r
599 \r
600         while (true)\r
601         {\r
602                 char *line = CfgReadNextLine(b);\r
603 \r
604                 if (line == NULL)\r
605                 {\r
606                         break;\r
607                 }\r
608 \r
609                 Trim(line);\r
610 \r
611                 if (IsEmptyStr(line) == false)\r
612                 {\r
613                         if (StartWith(line, "#") == false &&\r
614                                 StartWith(line, "//") == false &&\r
615                                 StartWith(line, ";") == false)\r
616                         {\r
617                                 char *key, *value;\r
618                                 UINT size = StrLen(line) + 1;\r
619 \r
620                                 key = ZeroMalloc(size);\r
621                                 value = ZeroMalloc(size);\r
622 \r
623                                 if (GetKeyAndValue(line, key, size, value, size, NULL))\r
624                                 {\r
625                                         UINT uni_size;\r
626                                         INI_ENTRY *e = ZeroMalloc(sizeof(INI_ENTRY));\r
627                                         e->Key = CopyStr(key);\r
628                                         e->Value = CopyStr(value);\r
629 \r
630                                         uni_size = CalcUtf8ToUni((BYTE *)value, StrLen(value));\r
631                                         e->UnicodeValue = ZeroMalloc(uni_size);\r
632                                         Utf8ToUni(e->UnicodeValue, uni_size, (BYTE *)value, StrLen(value));\r
633 \r
634                                         Add(o, e);\r
635                                 }\r
636 \r
637                                 Free(key);\r
638                                 Free(value);\r
639                         }\r
640                 }\r
641 \r
642                 Free(line);\r
643         }\r
644 \r
645         return o;\r
646 }\r
647 \r
648 // 指定された文字が区切り文字かどうかチェック\r
649 bool IsSplitChar(char c, char *split_str)\r
650 {\r
651         UINT i, len;\r
652         char c_upper = ToUpper(c);\r
653         if (split_str == NULL)\r
654         {\r
655                 split_str = default_spliter;\r
656         }\r
657 \r
658         len = StrLen(split_str);\r
659 \r
660         for (i = 0;i < len;i++)\r
661         {\r
662                 if (ToUpper(split_str[i]) == c_upper)\r
663                 {\r
664                         return true;\r
665                 }\r
666         }\r
667 \r
668         return false;\r
669 }\r
670 \r
671 // 文字列からキーと値を取得する\r
672 bool GetKeyAndValue(char *str, char *key, UINT key_size, char *value, UINT value_size, char *split_str)\r
673 {\r
674         UINT mode = 0;\r
675         UINT wp1 = 0, wp2 = 0;\r
676         UINT i, len;\r
677         char *key_tmp, *value_tmp;\r
678         bool ret = false;\r
679         if (split_str == NULL)\r
680         {\r
681                 split_str = default_spliter;\r
682         }\r
683 \r
684         len = StrLen(str);\r
685 \r
686         key_tmp = ZeroMalloc(len + 1);\r
687         value_tmp = ZeroMalloc(len + 1);\r
688 \r
689         for (i = 0;i < len;i++)\r
690         {\r
691                 char c = str[i];\r
692 \r
693                 switch (mode)\r
694                 {\r
695                 case 0:\r
696                         if (IsSplitChar(c, split_str) == false)\r
697                         {\r
698                                 mode = 1;\r
699                                 key_tmp[wp1] = c;\r
700                                 wp1++;\r
701                         }\r
702                         break;\r
703 \r
704                 case 1:\r
705                         if (IsSplitChar(c, split_str) == false)\r
706                         {\r
707                                 key_tmp[wp1] = c;\r
708                                 wp1++;\r
709                         }\r
710                         else\r
711                         {\r
712                                 mode = 2;\r
713                         }\r
714                         break;\r
715 \r
716                 case 2:\r
717                         if (IsSplitChar(c, split_str) == false)\r
718                         {\r
719                                 mode = 3;\r
720                                 value_tmp[wp2] = c;\r
721                                 wp2++;\r
722                         }\r
723                         break;\r
724 \r
725                 case 3:\r
726                         value_tmp[wp2] = c;\r
727                         wp2++;\r
728                         break;\r
729                 }\r
730         }\r
731 \r
732         if (mode != 0)\r
733         {\r
734                 ret = true;\r
735                 StrCpy(key, key_size, key_tmp);\r
736                 StrCpy(value, value_size, value_tmp);\r
737         }\r
738 \r
739         Free(key_tmp);\r
740         Free(value_tmp);\r
741 \r
742         return ret;\r
743 }\r
744 \r
745 // 指定した文字の列を生成する\r
746 char *MakeCharArray(char c, UINT count)\r
747 {\r
748         UINT i;\r
749         char *ret = Malloc(count + 1);\r
750 \r
751         for (i = 0;i < count;i++)\r
752         {\r
753                 ret[i] = c;\r
754         }\r
755 \r
756         ret[count] = 0;\r
757 \r
758         return ret;\r
759 }\r
760 void MakeCharArray2(char *str, char c, UINT count)\r
761 {\r
762         UINT i;\r
763 \r
764         for (i = 0;i < count;i++)\r
765         {\r
766                 str[i] = c;\r
767         }\r
768 \r
769         str[count] = 0;\r
770 }\r
771 \r
772 // 指定した文字列の横幅を取得する\r
773 UINT StrWidth(char *str)\r
774 {\r
775         wchar_t *s;\r
776         UINT ret;\r
777         // 引数チェック\r
778         if (str == NULL)\r
779         {\r
780                 return 0;\r
781         }\r
782 \r
783         s = CopyStrToUni(str);\r
784         ret = UniStrWidth(s);\r
785         Free(s);\r
786 \r
787         return ret;\r
788 }\r
789 \r
790 // 指定した文字列がすべて大文字かどうかチェックする\r
791 bool IsAllUpperStr(char *str)\r
792 {\r
793         UINT i, len;\r
794         // 引数チェック\r
795         if (str == NULL)\r
796         {\r
797                 return false;\r
798         }\r
799 \r
800         len = StrLen(str);\r
801 \r
802         for (i = 0;i < len;i++)\r
803         {\r
804                 char c = str[i];\r
805 \r
806                 if ((c >= '0' && c <= '9') ||\r
807                         (c >= 'A' && c <= 'Z'))\r
808                 {\r
809                 }\r
810                 else\r
811                 {\r
812                         return false;\r
813                 }\r
814         }\r
815 \r
816         return true;\r
817 }\r
818 \r
819 // 改行コードを正規化する\r
820 char *NormalizeCrlf(char *str)\r
821 {\r
822         char *ret;\r
823         UINT ret_size, i, len, wp;\r
824         // 引数チェック\r
825         if (str == NULL)\r
826         {\r
827                 return NULL;\r
828         }\r
829 \r
830         len = StrLen(str);\r
831         ret_size = sizeof(char) * (len + 32) * 2;\r
832         ret = Malloc(ret_size);\r
833 \r
834         wp = 0;\r
835 \r
836         for (i = 0;i < len;i++)\r
837         {\r
838                 char c = str[i];\r
839 \r
840                 switch (c)\r
841                 {\r
842                 case '\r':\r
843                         if (str[i + 1] == '\n')\r
844                         {\r
845                                 i++;\r
846                         }\r
847                         ret[wp++] = '\r';\r
848                         ret[wp++] = '\n';\r
849                         break;\r
850 \r
851                 case '\n':\r
852                         ret[wp++] = '\r';\r
853                         ret[wp++] = '\n';\r
854                         break;\r
855 \r
856                 default:\r
857                         ret[wp++] = c;\r
858                         break;\r
859                 }\r
860         }\r
861 \r
862         ret[wp++] = 0;\r
863 \r
864         return ret;\r
865 }\r
866 \r
867 // トークンリストを重複の無いものに変換する\r
868 TOKEN_LIST *UniqueToken(TOKEN_LIST *t)\r
869 {\r
870         UINT i, num, j, n;\r
871         TOKEN_LIST *ret;\r
872         // 引数チェック\r
873         if (t == NULL)\r
874         {\r
875                 return NULL;\r
876         }\r
877 \r
878         num = 0;\r
879         for (i = 0;i < t->NumTokens;i++)\r
880         {\r
881                 bool exists = false;\r
882 \r
883                 for (j = 0;j < i;j++)\r
884                 {\r
885                         if (StrCmpi(t->Token[j], t->Token[i]) == 0)\r
886                         {\r
887                                 exists = true;\r
888                                 break;\r
889                         }\r
890                 }\r
891 \r
892                 if (exists == false)\r
893                 {\r
894                         num++;\r
895                 }\r
896         }\r
897 \r
898         ret = ZeroMalloc(sizeof(TOKEN_LIST));\r
899         ret->Token = ZeroMalloc(sizeof(char *) * num);\r
900         ret->NumTokens = num;\r
901 \r
902         n = 0;\r
903 \r
904         for (i = 0;i < t->NumTokens;i++)\r
905         {\r
906                 bool exists = false;\r
907 \r
908                 for (j = 0;j < i;j++)\r
909                 {\r
910                         if (StrCmpi(t->Token[j], t->Token[i]) == 0)\r
911                         {\r
912                                 exists = true;\r
913                                 break;\r
914                         }\r
915                 }\r
916 \r
917                 if (exists == false)\r
918                 {\r
919                         ret->Token[n++] = CopyStr(t->Token[i]);\r
920                 }\r
921         }\r
922 \r
923         return ret;\r
924 }\r
925 \r
926 // バイト文字列に変換する (1,000 単位)\r
927 void ToStrByte1000(char *str, UINT size, UINT64 v)\r
928 {\r
929         UINT i;\r
930         // 引数チェック\r
931         if (str == NULL)\r
932         {\r
933                 return;\r
934         }\r
935 \r
936         // gcc での警告対策\r
937         bytestr[0].base_value = 1000000000UL;\r
938         bytestr[0].base_value *= 1000UL;\r
939         bytestr[0].base_value *= 1000UL;\r
940         bytestr[1].base_value = 1000000000UL;\r
941         bytestr[1].base_value *= 1000UL;\r
942         bytestr[2].base_value = 1000000000UL;\r
943         bytestr[3].base_value = 1000000UL;\r
944         bytestr[4].base_value = 1000UL;\r
945         bytestr[5].base_value = 0UL;\r
946 \r
947         for (i = 0;i < sizeof(bytestr) / sizeof(bytestr[0]);i++)\r
948         {\r
949                 BYTESTR *b = &bytestr[i];\r
950 \r
951                 if ((v * 11UL) / 10UL >= b->base_value)\r
952                 {\r
953                         if (b->base_value != 0)\r
954                         {\r
955                                 double d = (double)v / (double)b->base_value;\r
956                                 Format(str, size, "%.2f %s", d, b->string);\r
957                         }\r
958                         else\r
959                         {\r
960                                 Format(str, size, "%I64u %s", v, b->string);\r
961                         }\r
962 \r
963                         break;\r
964                 }\r
965         }\r
966 }\r
967 \r
968 // バイト文字列に変換する\r
969 void ToStrByte(char *str, UINT size, UINT64 v)\r
970 {\r
971         UINT i;\r
972         // 引数チェック\r
973         if (str == NULL)\r
974         {\r
975                 return;\r
976         }\r
977 \r
978         // gcc での警告対策\r
979         bytestr[0].base_value = 1073741824UL;\r
980         bytestr[0].base_value *= 1024UL;\r
981         bytestr[0].base_value *= 1024UL;\r
982         bytestr[1].base_value = 1073741824UL;\r
983         bytestr[1].base_value *= 1024UL;\r
984         bytestr[2].base_value = 1073741824UL;\r
985         bytestr[3].base_value = 1048576UL;\r
986         bytestr[4].base_value = 1024UL;\r
987         bytestr[5].base_value = 0UL;\r
988 \r
989         for (i = 0;i < sizeof(bytestr) / sizeof(bytestr[0]);i++)\r
990         {\r
991                 BYTESTR *b = &bytestr[i];\r
992 \r
993                 if ((v * 11UL) / 10UL >= b->base_value)\r
994                 {\r
995                         if (b->base_value != 0)\r
996                         {\r
997                                 double d = (double)v / (double)b->base_value;\r
998                                 Format(str, size, "%.2f %s", d, b->string);\r
999                         }\r
1000                         else\r
1001                         {\r
1002                                 Format(str, size, "%I64u %s", v, b->string);\r
1003                         }\r
1004 \r
1005                         break;\r
1006                 }\r
1007         }\r
1008 }\r
1009 \r
1010 // 数字を文字列に変換して 3 桁ずつカンマで区切る\r
1011 void ToStr3(char *str, UINT size, UINT64 v)\r
1012 {\r
1013         char tmp[128];\r
1014         char tmp2[128];\r
1015         UINT i, len, wp;\r
1016         // 引数チェック\r
1017         if (str == NULL)\r
1018         {\r
1019                 return;\r
1020         }\r
1021 \r
1022         ToStr64(tmp, v);\r
1023 \r
1024         wp = 0;\r
1025         len = StrLen(tmp);\r
1026 \r
1027         for (i = len - 1;((int)i) >= 0;i--)\r
1028         {\r
1029                 tmp2[wp++] = tmp[i];\r
1030         }\r
1031         tmp2[wp++] = 0;\r
1032 \r
1033         wp = 0;\r
1034 \r
1035         for (i = 0;i < len;i++)\r
1036         {\r
1037                 if (i != 0 && (i % 3) == 0)\r
1038                 {\r
1039                         tmp[wp++] = ',';\r
1040                 }\r
1041                 tmp[wp++] = tmp2[i];\r
1042         }\r
1043         tmp[wp++] = 0;\r
1044         wp = 0;\r
1045         len = StrLen(tmp);\r
1046 \r
1047         for (i = len - 1;((int)i) >= 0;i--)\r
1048         {\r
1049                 tmp2[wp++] = tmp[i];\r
1050         }\r
1051         tmp2[wp++] = 0;\r
1052 \r
1053         StrCpy(str, size, tmp2);\r
1054 }\r
1055 \r
1056 // MAC アドレスを文字列にする\r
1057 void MacToStr(char *str, UINT size, UCHAR *mac_address)\r
1058 {\r
1059         // 引数チェック\r
1060         if (str == NULL || mac_address == NULL)\r
1061         {\r
1062                 return;\r
1063         }\r
1064 \r
1065         Format(str, size, "%02X-%02X-%02X-%02X-%02X-%02X",\r
1066                 mac_address[0],\r
1067                 mac_address[1],\r
1068                 mac_address[2],\r
1069                 mac_address[3],\r
1070                 mac_address[4],\r
1071                 mac_address[5]);\r
1072 }\r
1073 \r
1074 // 文字列が空かどうか調べる\r
1075 bool IsEmptyStr(char *str)\r
1076 {\r
1077         char *s;\r
1078         // 引数チェック\r
1079         if (str == NULL)\r
1080         {\r
1081                 return true;\r
1082         }\r
1083 \r
1084         s = CopyStr(str);\r
1085         Trim(s);\r
1086 \r
1087         if (StrLen(s) == 0)\r
1088         {\r
1089                 Free(s);\r
1090                 return true;\r
1091         }\r
1092         else\r
1093         {\r
1094                 Free(s);\r
1095                 return false;\r
1096         }\r
1097 }\r
1098 \r
1099 // トークンリストを文字列リストに変換する\r
1100 LIST *TokenListToList(TOKEN_LIST *t)\r
1101 {\r
1102         UINT i;\r
1103         LIST *o;\r
1104         // 引数チェック\r
1105         if (t == NULL)\r
1106         {\r
1107                 return NULL;\r
1108         }\r
1109 \r
1110         o = NewListFast(NULL);\r
1111         for (i = 0;i < t->NumTokens;i++)\r
1112         {\r
1113                 Insert(o, CopyStr(t->Token[i]));\r
1114         }\r
1115 \r
1116         return o;\r
1117 }\r
1118 \r
1119 // 文字列リストをトークンリストに変換する\r
1120 TOKEN_LIST *ListToTokenList(LIST *o)\r
1121 {\r
1122         UINT i;\r
1123         TOKEN_LIST *t;\r
1124         // 引数チェック\r
1125         if (o == NULL)\r
1126         {\r
1127                 return NULL;\r
1128         }\r
1129 \r
1130         t = ZeroMalloc(sizeof(TOKEN_LIST));\r
1131         t->NumTokens = LIST_NUM(o);\r
1132         t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);\r
1133         for (i = 0;i < LIST_NUM(o);i++)\r
1134         {\r
1135                 t->Token[i] = CopyStr(LIST_DATA(o, i));\r
1136         }\r
1137 \r
1138         return t;\r
1139 }\r
1140 \r
1141 // 文字列リストを解放する\r
1142 void FreeStrList(LIST *o)\r
1143 {\r
1144         UINT i;\r
1145         // 引数チェック\r
1146         if (o == NULL)\r
1147         {\r
1148                 return;\r
1149         }\r
1150 \r
1151         for (i = 0;i < LIST_NUM(o);i++)\r
1152         {\r
1153                 char *s = LIST_DATA(o, i);\r
1154                 Free(s);\r
1155         }\r
1156 \r
1157         ReleaseList(o);\r
1158 }\r
1159 \r
1160 // 文字列リストを文字列に変換する\r
1161 BUF *StrListToStr(LIST *o)\r
1162 {\r
1163         BUF *b;\r
1164         UINT i;\r
1165         char c;\r
1166         // 引数チェック\r
1167         if (o == NULL)\r
1168         {\r
1169                 return NULL;\r
1170         }\r
1171         b = NewBuf();\r
1172 \r
1173         for (i = 0;i < LIST_NUM(o);i++)\r
1174         {\r
1175                 char *s = LIST_DATA(o, i);\r
1176                 WriteBuf(b, s, StrLen(s) + 1);\r
1177         }\r
1178 \r
1179         c = 0;\r
1180         WriteBuf(b, &c, 1);\r
1181 \r
1182         SeekBuf(b, 0, 0);\r
1183 \r
1184         return b;\r
1185 }\r
1186 \r
1187 // 文字列 (NULL区切り) をリストに変換する\r
1188 LIST *StrToStrList(char *str, UINT size)\r
1189 {\r
1190         LIST *o;\r
1191         char *tmp;\r
1192         UINT tmp_size;\r
1193         UINT i;\r
1194         // 引数チェック\r
1195         if (str == NULL)\r
1196         {\r
1197                 return NULL;\r
1198         }\r
1199 \r
1200         o = NewListFast(NULL);\r
1201 \r
1202         i = 0;\r
1203         while (true)\r
1204         {\r
1205                 if (i >= size)\r
1206                 {\r
1207                         break;\r
1208                 }\r
1209                 if (*str == 0)\r
1210                 {\r
1211                         break;\r
1212                 }\r
1213 \r
1214                 tmp_size = StrSize(str);\r
1215                 tmp = ZeroMalloc(tmp_size);\r
1216                 StrCpy(tmp, tmp_size, str);\r
1217                 Add(o, tmp);\r
1218                 str += StrLen(str) + 1;\r
1219                 i++;\r
1220         }\r
1221 \r
1222         return o;\r
1223 }\r
1224 \r
1225 // 指定された文字列が数字かどうかチェック\r
1226 bool IsNum(char *str)\r
1227 {\r
1228         char c;\r
1229         UINT i, len;\r
1230         UINT n = 0;\r
1231         char tmp[MAX_SIZE];\r
1232         TOKEN_LIST *t;\r
1233         // 引数チェック\r
1234         if (str == NULL)\r
1235         {\r
1236                 return false;\r
1237         }\r
1238 \r
1239         StrCpy(tmp, sizeof(tmp), str);\r
1240         Trim(tmp);\r
1241 \r
1242         if (StrLen(tmp) == 0)\r
1243         {\r
1244                 return false;\r
1245         }\r
1246 \r
1247         t = ParseToken(tmp, " ");\r
1248 \r
1249         if (t->NumTokens >= 1)\r
1250         {\r
1251                 StrCpy(tmp, sizeof(tmp), t->Token[0]);\r
1252         }\r
1253 \r
1254         FreeToken(t);\r
1255 \r
1256         len = StrLen(tmp);\r
1257         for (i = 0;i < len;i++)\r
1258         {\r
1259                 bool b = false;\r
1260                 c = tmp[i];\r
1261                 if (('0' <= c && c <= '9') || (c == '+') || (c == '-') || (c == ','))\r
1262                 {\r
1263                         b = true;\r
1264                 }\r
1265 \r
1266                 if (b == false)\r
1267                 {\r
1268                         return false;\r
1269                 }\r
1270         }\r
1271 \r
1272         for (i = 0;i < len;i++)\r
1273         {\r
1274                 c = tmp[i];\r
1275                 if (c == '-')\r
1276                 {\r
1277                         n++;\r
1278                 }\r
1279         }\r
1280         if (n >= 2)\r
1281         {\r
1282                 return false;\r
1283         }\r
1284 \r
1285         return true;\r
1286 }\r
1287 \r
1288 // 中身が無いトークンリスト\r
1289 TOKEN_LIST *NullToken()\r
1290 {\r
1291         TOKEN_LIST *ret = ZeroMalloc(sizeof(TOKEN_LIST));\r
1292         ret->Token = ZeroMalloc(0);\r
1293 \r
1294         return ret;\r
1295 }\r
1296 \r
1297 // トークンリストのコピー\r
1298 TOKEN_LIST *CopyToken(TOKEN_LIST *src)\r
1299 {\r
1300         TOKEN_LIST *ret;\r
1301         UINT i;\r
1302         // 引数チェック\r
1303         if (src == NULL)\r
1304         {\r
1305                 return NULL;\r
1306         }\r
1307 \r
1308         ret = ZeroMalloc(sizeof(TOKEN_LIST));\r
1309         ret->NumTokens = src->NumTokens;\r
1310         ret->Token = ZeroMalloc(sizeof(char *) * ret->NumTokens);\r
1311         for (i = 0;i < ret->NumTokens;i++)\r
1312         {\r
1313                 ret->Token[i] = CopyStr(src->Token[i]);\r
1314         }\r
1315 \r
1316         return ret;\r
1317 }\r
1318 \r
1319 // コマンドラインをパースする\r
1320 TOKEN_LIST *ParseCmdLine(char *str)\r
1321 {\r
1322         TOKEN_LIST *t;\r
1323         LIST *o;\r
1324         UINT i, len, wp, mode;\r
1325         char c;\r
1326         char *tmp;\r
1327         bool ignore_space = false;\r
1328         // 引数チェック\r
1329         if (str == NULL)\r
1330         {\r
1331                 // トークン無し\r
1332                 return NullToken();\r
1333         }\r
1334 \r
1335         o = NewListFast(NULL);\r
1336         tmp = Malloc(StrSize(str) + 32);\r
1337 \r
1338         wp = 0;\r
1339         mode = 0;\r
1340 \r
1341         len = StrLen(str);\r
1342         for (i = 0;i < len;i++)\r
1343         {\r
1344                 c = str[i];\r
1345 \r
1346                 switch (mode)\r
1347                 {\r
1348                 case 0:\r
1349                         // 次のトークンを発見するモード\r
1350                         if (c == ' ' || c == '\t')\r
1351                         {\r
1352                                 // 次の文字へ進める\r
1353                         }\r
1354                         else\r
1355                         {\r
1356                                 // トークンの開始\r
1357                                 if (c == '\"')\r
1358                                 {\r
1359                                         if (str[i + 1] == '\"')\r
1360                                         {\r
1361                                                 // 2 重の " は 1 個の " 文字として見なす\r
1362                                                 tmp[wp++] = '\"';\r
1363                                                 i++;\r
1364                                         }\r
1365                                         else\r
1366                                         {\r
1367                                                 // 1 個の " はスペース無視フラグを有効にする\r
1368                                                 ignore_space = true;\r
1369                                         }\r
1370                                 }\r
1371                                 else\r
1372                                 {\r
1373                                         tmp[wp++] = c;\r
1374                                 }\r
1375 \r
1376                                 mode = 1;\r
1377                         }\r
1378                         break;\r
1379 \r
1380                 case 1:\r
1381                         if (ignore_space == false && (c == ' ' || c == '\t'))\r
1382                         {\r
1383                                 // トークンの終了\r
1384                                 tmp[wp++] = 0;\r
1385                                 wp = 0;\r
1386 \r
1387                                 Insert(o, CopyStr(tmp));\r
1388                                 mode = 0;\r
1389                         }\r
1390                         else\r
1391                         {\r
1392                                 if (c == '\"')\r
1393                                 {\r
1394                                         if (str[i + 1] == '\"')\r
1395                                         {\r
1396                                                 // 2 重の " は 1 個の " 文字として見なす\r
1397                                                 tmp[wp++] = L'\"';\r
1398                                                 i++;\r
1399                                         }\r
1400                                         else\r
1401                                         {\r
1402                                                 if (ignore_space == false)\r
1403                                                 {\r
1404                                                         // 1 個の " はスペース無視フラグを有効にする\r
1405                                                         ignore_space = true;\r
1406                                                 }\r
1407                                                 else\r
1408                                                 {\r
1409                                                         // スペース無視フラグを無効にする\r
1410                                                         ignore_space = false;\r
1411                                                 }\r
1412                                         }\r
1413                                 }\r
1414                                 else\r
1415                                 {\r
1416                                         tmp[wp++] = c;\r
1417                                 }\r
1418                         }\r
1419                         break;\r
1420                 }\r
1421         }\r
1422 \r
1423         if (wp != 0)\r
1424         {\r
1425                 tmp[wp++] = 0;\r
1426                 Insert(o, CopyStr(tmp));\r
1427         }\r
1428 \r
1429         Free(tmp);\r
1430 \r
1431         t = ZeroMalloc(sizeof(TOKEN_LIST));\r
1432         t->NumTokens = LIST_NUM(o);\r
1433         t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);\r
1434         for (i = 0;i < t->NumTokens;i++)\r
1435         {\r
1436                 t->Token[i] = LIST_DATA(o, i);\r
1437         }\r
1438 \r
1439         ReleaseList(o);\r
1440 \r
1441         return t;\r
1442 }\r
1443 \r
1444 // 64bit 整数を文字列に変換\r
1445 void ToStr64(char *str, UINT64 value)\r
1446 {\r
1447         char tmp[MAX_SIZE];\r
1448         UINT wp = 0;\r
1449         UINT len, i;\r
1450         // 引数チェック\r
1451         if (str == NULL)\r
1452         {\r
1453                 return;\r
1454         }\r
1455 \r
1456         // 空文字に設定\r
1457         StrCpy(tmp, 0, "");\r
1458 \r
1459         // 末尾桁から追加する\r
1460         while (true)\r
1461         {\r
1462                 UINT a = (UINT)(value % (UINT64)10);\r
1463                 value = value / (UINT64)10;\r
1464                 tmp[wp++] = (char)('0' + a);\r
1465                 if (value == 0)\r
1466                 {\r
1467                         tmp[wp++] = 0;\r
1468                         break;\r
1469                 }\r
1470         }\r
1471 \r
1472         // 逆順にする\r
1473         len = StrLen(tmp);\r
1474         for (i = 0;i < len;i++)\r
1475         {\r
1476                 str[len - i - 1] = tmp[i];\r
1477         }\r
1478         str[len] = 0;\r
1479 }\r
1480 \r
1481 // 文字列を 64bit 整数に変換\r
1482 UINT64 ToInt64(char *str)\r
1483 {\r
1484         UINT len, i;\r
1485         UINT64 ret = 0;\r
1486         // 引数チェック\r
1487         if (str == NULL)\r
1488         {\r
1489                 return 0;\r
1490         }\r
1491 \r
1492         len = StrLen(str);\r
1493         for (i = 0;i < len;i++)\r
1494         {\r
1495                 char c = str[i];\r
1496                 if (c != ',')\r
1497                 {\r
1498                         if ('0' <= c && c <= '9')\r
1499                         {\r
1500                                 ret = ret * (UINT64)10 + (UINT64)(c - '0');\r
1501                         }\r
1502                         else\r
1503                         {\r
1504                                 break;\r
1505                         }\r
1506                 }\r
1507         }\r
1508 \r
1509         return ret;\r
1510 }\r
1511 \r
1512 // str が key で終了するかどうかチェック\r
1513 bool EndWith(char *str, char *key)\r
1514 {\r
1515         UINT str_len;\r
1516         UINT key_len;\r
1517         // 引数チェック\r
1518         if (str == NULL || key == NULL)\r
1519         {\r
1520                 return false;\r
1521         }\r
1522 \r
1523         // 比較\r
1524         str_len = StrLen(str);\r
1525         key_len = StrLen(key);\r
1526         if (str_len < key_len)\r
1527         {\r
1528                 return false;\r
1529         }\r
1530 \r
1531         if (StrCmpi(str + (str_len - key_len), key) == 0)\r
1532         {\r
1533                 return true;\r
1534         }\r
1535         else\r
1536         {\r
1537                 return false;\r
1538         }\r
1539 }\r
1540 \r
1541 // str が key で始まるかどうかチェック\r
1542 bool StartWith(char *str, char *key)\r
1543 {\r
1544         UINT str_len;\r
1545         UINT key_len;\r
1546         char *tmp;\r
1547         bool ret;\r
1548         // 引数チェック\r
1549         if (str == NULL || key == NULL)\r
1550         {\r
1551                 return false;\r
1552         }\r
1553 \r
1554         // 比較\r
1555         str_len = StrLen(str);\r
1556         key_len = StrLen(key);\r
1557         if (str_len < key_len)\r
1558         {\r
1559                 return false;\r
1560         }\r
1561         if (str_len == 0 || key_len == 0)\r
1562         {\r
1563                 return false;\r
1564         }\r
1565         tmp = CopyStr(str);\r
1566         tmp[key_len] = 0;\r
1567 \r
1568         if (StrCmpi(tmp, key) == 0)\r
1569         {\r
1570                 ret = true;\r
1571         }\r
1572         else\r
1573         {\r
1574                 ret = false;\r
1575         }\r
1576 \r
1577         Free(tmp);\r
1578 \r
1579         return ret;\r
1580 }\r
1581 \r
1582 // バイナリデータを表示\r
1583 void PrintBin(void *data, UINT size)\r
1584 {\r
1585         char *tmp;\r
1586         UINT i;\r
1587         // 引数チェック\r
1588         if (data == NULL)\r
1589         {\r
1590                 return;\r
1591         }\r
1592 \r
1593         i = size * 3 + 1;\r
1594         tmp = Malloc(i);\r
1595         BinToStrEx(tmp, i, data, size);\r
1596         Print("%s\n", tmp);\r
1597         Free(tmp);\r
1598 }\r
1599 \r
1600 // 文字列を MAC アドレスに変換する\r
1601 bool StrToMac(UCHAR *mac_address, char *str)\r
1602 {\r
1603         BUF *b;\r
1604         // 引数チェック\r
1605         if (mac_address == NULL || str == NULL)\r
1606         {\r
1607                 return false;\r
1608         }\r
1609 \r
1610         b = StrToBin(str);\r
1611         if (b == NULL)\r
1612         {\r
1613                 return false;\r
1614         }\r
1615 \r
1616         if (b->Size != 6)\r
1617         {\r
1618                 FreeBuf(b);\r
1619                 return false;\r
1620         }\r
1621 \r
1622         Copy(mac_address, b->Buf, 6);\r
1623 \r
1624         FreeBuf(b);\r
1625 \r
1626         return true;\r
1627 }\r
1628 \r
1629 // 16 進文字列をバイナリデータに変換する\r
1630 BUF *StrToBin(char *str)\r
1631 {\r
1632         BUF *b;\r
1633         UINT len, i;\r
1634         char tmp[3];\r
1635         // 引数チェック\r
1636         if (str == NULL)\r
1637         {\r
1638                 return NULL;\r
1639         }\r
1640 \r
1641         len = StrLen(str);\r
1642         tmp[0] = 0;\r
1643         b = NewBuf();\r
1644         for (i = 0;i < len;i++)\r
1645         {\r
1646                 char c = str[i];\r
1647                 c = ToUpper(c);\r
1648                 if (('0' <= c && c <= '9') || ('A' <= c && c <= 'F'))\r
1649                 {\r
1650                         if (tmp[0] == 0)\r
1651                         {\r
1652                                 tmp[0] = c;\r
1653                                 tmp[1] = 0;\r
1654                         }\r
1655                         else if (tmp[1] == 0)\r
1656                         {\r
1657                                 UCHAR data;\r
1658                                 char tmp2[64];\r
1659                                 tmp[1] = c;\r
1660                                 tmp[2] = 0;\r
1661                                 StrCpy(tmp2, sizeof(tmp2), "0x");\r
1662                                 StrCat(tmp2, sizeof(tmp2), tmp);\r
1663                                 data = (UCHAR)strtoul(tmp2, NULL, 0);\r
1664                                 WriteBuf(b, &data, 1);\r
1665                                 Zero(tmp, sizeof(tmp)); \r
1666                         }\r
1667                 }\r
1668                 else if (c == ' ' || c == ',' || c == '-' || c == ':')\r
1669                 {\r
1670                         // 何もしない\r
1671                 }\r
1672                 else\r
1673                 {\r
1674                         break;\r
1675                 }\r
1676         }\r
1677 \r
1678         return b;\r
1679 }\r
1680 \r
1681 // バイナリデータを 16 進文字列に変換する (スペースも入れる)\r
1682 void BinToStrEx(char *str, UINT str_size, void *data, UINT data_size)\r
1683 {\r
1684         char *tmp;\r
1685         UCHAR *buf = (UCHAR *)data;\r
1686         UINT size;\r
1687         UINT i;\r
1688         // 引数チェック\r
1689         if (str == NULL || data == NULL)\r
1690         {\r
1691                 return;\r
1692         }\r
1693 \r
1694         // サイズの計算\r
1695         size = data_size * 3 + 1;\r
1696         // メモリ確保\r
1697         tmp = ZeroMalloc(size);\r
1698         // 変換\r
1699         for (i = 0;i < data_size;i++)\r
1700         {\r
1701                 Format(&tmp[i * 3], 0, "%02X ", buf[i]);\r
1702         }\r
1703         Trim(tmp);\r
1704         // コピー\r
1705         StrCpy(str, str_size, tmp);\r
1706         // メモリ解放\r
1707         Free(tmp);\r
1708 }\r
1709 void BinToStrEx2(char *str, UINT str_size, void *data, UINT data_size, char padding_char)\r
1710 {\r
1711         char *tmp;\r
1712         UCHAR *buf = (UCHAR *)data;\r
1713         UINT size;\r
1714         UINT i;\r
1715         // 引数チェック\r
1716         if (str == NULL || data == NULL)\r
1717         {\r
1718                 return;\r
1719         }\r
1720 \r
1721         // サイズの計算\r
1722         size = data_size * 3 + 1;\r
1723         // メモリ確保\r
1724         tmp = ZeroMalloc(size);\r
1725         // 変換\r
1726         for (i = 0;i < data_size;i++)\r
1727         {\r
1728                 Format(&tmp[i * 3], 0, "%02X%c", buf[i], padding_char);\r
1729         }\r
1730         if (StrLen(tmp) >= 1)\r
1731         {\r
1732                 if (tmp[StrLen(tmp) - 1] == padding_char)\r
1733                 {\r
1734                         tmp[StrLen(tmp) - 1] = 0;\r
1735                 }\r
1736         }\r
1737         // コピー\r
1738         StrCpy(str, str_size, tmp);\r
1739         // メモリ解放\r
1740         Free(tmp);\r
1741 }\r
1742 // バイナリデータを文字列に変換してコピーする\r
1743 char *CopyBinToStrEx(void *data, UINT data_size)\r
1744 {\r
1745         char *ret;\r
1746         UINT size;\r
1747         // 引数チェック\r
1748         if (data == NULL)\r
1749         {\r
1750                 return NULL;\r
1751         }\r
1752 \r
1753         size = data_size * 3 + 1;\r
1754         ret = ZeroMalloc(size);\r
1755 \r
1756         BinToStrEx(ret, size, data, data_size);\r
1757 \r
1758         return ret;\r
1759 }\r
1760 char *CopyBinToStr(void *data, UINT data_size)\r
1761 {\r
1762         char *ret;\r
1763         UINT size;\r
1764         // 引数チェック\r
1765         if (data == NULL)\r
1766         {\r
1767                 return NULL;\r
1768         }\r
1769 \r
1770         size = data_size * 2 + 1;\r
1771         ret = ZeroMalloc(size);\r
1772 \r
1773         BinToStr(ret, size, data, data_size);\r
1774 \r
1775         return ret;\r
1776 }\r
1777 \r
1778 // バイナリデータを 16 進文字列に変換する\r
1779 void BinToStr(char *str, UINT str_size, void *data, UINT data_size)\r
1780 {\r
1781         char *tmp;\r
1782         UCHAR *buf = (UCHAR *)data;\r
1783         UINT size;\r
1784         UINT i;\r
1785         // 引数チェック\r
1786         if (str == NULL || data == NULL)\r
1787         {\r
1788                 if (str != NULL)\r
1789                 {\r
1790                         str[0] = 0;\r
1791                 }\r
1792                 return;\r
1793         }\r
1794 \r
1795         // サイズの計算\r
1796         size = data_size * 2 + 1;\r
1797         // メモリ確保\r
1798         tmp = ZeroMalloc(size);\r
1799         // 変換\r
1800         for (i = 0;i < data_size;i++)\r
1801         {\r
1802                 sprintf(&tmp[i * 2], "%02X", buf[i]);\r
1803         }\r
1804         // コピー\r
1805         StrCpy(str, str_size, tmp);\r
1806         // メモリ解放\r
1807         Free(tmp);\r
1808 }\r
1809 void BinToStrW(wchar_t *str, UINT str_size, void *data, UINT data_size)\r
1810 {\r
1811         char *tmp;\r
1812         UINT tmp_size;\r
1813         // 引数チェック\r
1814         if (str == NULL || data == NULL)\r
1815         {\r
1816                 if (str != NULL)\r
1817                 {\r
1818                         str[0] = 0;\r
1819                 }\r
1820                 return;\r
1821         }\r
1822 \r
1823         tmp_size = (data_size * 2 + 4) * sizeof(wchar_t);\r
1824         tmp = ZeroMalloc(tmp_size);\r
1825 \r
1826         BinToStr(tmp, tmp_size, data, data_size);\r
1827 \r
1828         StrToUni(str, str_size, tmp);\r
1829 \r
1830         Free(tmp);\r
1831 }\r
1832 \r
1833 // 160 ビット列を文字列にする\r
1834 void Bit160ToStr(char *str, UCHAR *data)\r
1835 {\r
1836         // 引数チェック\r
1837         if (str == NULL || data == NULL)\r
1838         {\r
1839                 return;\r
1840         }\r
1841 \r
1842         Format(str, 0,\r
1843                 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",\r
1844                 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], \r
1845                 data[10], data[11], data[12], data[13], data[14], data[15], data[16], data[17], data[18], data[19]);\r
1846 }\r
1847 \r
1848 // 128 ビット列を文字列にする\r
1849 void Bit128ToStr(char *str, UCHAR *data)\r
1850 {\r
1851         // 引数チェック\r
1852         if (str == NULL || data == NULL)\r
1853         {\r
1854                 return;\r
1855         }\r
1856 \r
1857         Format(str, 0,\r
1858                 "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",\r
1859                 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], \r
1860                 data[10], data[11], data[12], data[13], data[14], data[15]);\r
1861 }\r
1862 \r
1863 // 文字列をコピーする\r
1864 char *CopyStr(char *str)\r
1865 {\r
1866         UINT len;\r
1867         char *dst;\r
1868         // 引数チェック\r
1869         if (str == NULL)\r
1870         {\r
1871                 return NULL;\r
1872         }\r
1873 \r
1874         len = StrLen(str);\r
1875         dst = Malloc(len + 1);\r
1876         StrCpy(dst, len + 1, str);\r
1877         return dst;\r
1878 }\r
1879 \r
1880 // 安全な文字列かどうかチェック\r
1881 bool IsSafeStr(char *str)\r
1882 {\r
1883         UINT i, len;\r
1884         // 引数チェック\r
1885         if (str == NULL)\r
1886         {\r
1887                 return false;\r
1888         }\r
1889 \r
1890         len = StrLen(str);\r
1891         for (i = 0;i < len;i++)\r
1892         {\r
1893                 if (IsSafeChar(str[i]) == false)\r
1894                 {\r
1895                         return false;\r
1896                 }\r
1897         }\r
1898         if (str[0] == ' ')\r
1899         {\r
1900                 return false;\r
1901         }\r
1902         if (len != 0)\r
1903         {\r
1904                 if (str[len - 1] == ' ')\r
1905                 {\r
1906                         return false;\r
1907                 }\r
1908         }\r
1909         return true;\r
1910 }\r
1911 \r
1912 // 安全な文字かどうかチェック\r
1913 bool IsSafeChar(char c)\r
1914 {\r
1915         UINT i, len;\r
1916         char *check_str =\r
1917                 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\r
1918                 "abcdefghijklmnopqrstuvwxyz"\r
1919                 "0123456789"\r
1920                 " ()-_#%&.";\r
1921 \r
1922         len = StrLen(check_str);\r
1923         for (i = 0;i < len;i++)\r
1924         {\r
1925                 if (c == check_str[i])\r
1926                 {\r
1927                         return true;\r
1928                 }\r
1929         }\r
1930         return false;\r
1931 }\r
1932 \r
1933 // 文字列から指定した文字を削除する\r
1934 void TruncateCharFromStr(char *str, char replace)\r
1935 {\r
1936         char *src,*dst;\r
1937 \r
1938         if (str == NULL)\r
1939         {\r
1940                 return;\r
1941         }\r
1942 \r
1943         src = dst = str;\r
1944 \r
1945         while(*src != '\0')\r
1946         {\r
1947                 if(*src != replace)\r
1948                 {\r
1949                         *dst = *src;\r
1950                         dst++;\r
1951                 }\r
1952                 src++;\r
1953         }\r
1954         *dst = *src;\r
1955 \r
1956         //BUF *b = NewBuf();\r
1957         //UINT i, len;\r
1958         //char zero = 0;\r
1959 \r
1960         //len = StrLen(str);\r
1961         //for (i = 0;i < len;i++)\r
1962         //{\r
1963         //      char c = str[i];\r
1964 \r
1965         //      if (c != replace)\r
1966         //      {\r
1967         //              WriteBuf(b, &c, 1);\r
1968         //      }\r
1969         //}\r
1970 \r
1971         //if (b->Size == 0)\r
1972         //{\r
1973         //      char c = '_';\r
1974         //      WriteBuf(b, &c, 1);\r
1975         //}\r
1976 \r
1977         //WriteBuf(b, &zero, 1);\r
1978 \r
1979         //StrCpy(str, 0, b->Buf);\r
1980 \r
1981         //FreeBuf(b);\r
1982 }\r
1983 \r
1984 // 安全な文字以外を置き換える\r
1985 void EnSafeStr(char *str, char replace)\r
1986 {\r
1987         if (str == NULL)\r
1988         {\r
1989                 return;\r
1990         }\r
1991 \r
1992         while(*str != '\0')\r
1993         {\r
1994                 if(IsSafeChar(*str) == false)\r
1995                 {\r
1996                         *str = replace;\r
1997                 }\r
1998                 str++;\r
1999         }\r
2000 }\r
2001 \r
2002 // 文字列ライブラリの動作チェック\r
2003 bool CheckStringLibrary()\r
2004 {\r
2005         wchar_t *compare_str = L"TEST_TEST_123_123456789012345";\r
2006         char *teststr = "TEST";\r
2007         wchar_t *testunistr = L"TEST";\r
2008         wchar_t tmp[64];\r
2009         UINT i1 = 123;\r
2010         UINT64 i2 = 123456789012345ULL;\r
2011 \r
2012         UniFormat(tmp, sizeof(tmp), L"%S_%s_%u_%I64u", teststr, testunistr,\r
2013                 i1, i2);\r
2014 \r
2015         if (UniStrCmpi(tmp, compare_str) != 0)\r
2016         {\r
2017                 return false;\r
2018         }\r
2019 \r
2020         return true;\r
2021 }\r
2022 \r
2023 // 文字列ライブラリの初期化\r
2024 void InitStringLibrary()\r
2025 {\r
2026         // トークン用ロックの作成\r
2027         token_lock = NewLock();\r
2028 \r
2029         // 国際ライブラリの初期化\r
2030         InitInternational();\r
2031 \r
2032         // 動作チェック\r
2033         if (CheckStringLibrary() == false)\r
2034         {\r
2035 #ifdef  OS_WIN32\r
2036                 Alert("String Library Init Failed.\r\nPlease check your locale settings.", NULL);\r
2037 #else   // OS_WIN32\r
2038                 Alert("String Library Init Failed.\r\nPlease check your locale settings and iconv() libraries.", NULL);\r
2039 #endif  // OS_WIN32\r
2040                 exit(0);\r
2041         }\r
2042 }\r
2043 \r
2044 // 文字列ライブラリの解放\r
2045 void FreeStringLibrary()\r
2046 {\r
2047         // 国際ライブラリの解放\r
2048         FreeInternational();\r
2049 \r
2050         // トークン用ロックの解放\r
2051         DeleteLock(token_lock);\r
2052         token_lock = NULL;\r
2053 }\r
2054 \r
2055 // 文字列の置換 (大文字小文字を区別しない)\r
2056 UINT ReplaceStri(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword)\r
2057 {\r
2058         return ReplaceStrEx(dst, size, string, old_keyword, new_keyword, false);\r
2059 }\r
2060 \r
2061 // 文字列の置換 (大文字小文字を区別する)\r
2062 UINT ReplaceStr(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword)\r
2063 {\r
2064         return ReplaceStrEx(dst, size, string, old_keyword, new_keyword, true);\r
2065 }\r
2066 \r
2067 // 文字列の置換\r
2068 UINT ReplaceStrEx(char *dst, UINT size, char *string, char *old_keyword, char *new_keyword, bool case_sensitive)\r
2069 {\r
2070         UINT i, j, num;\r
2071         UINT len_string, len_old, len_new;\r
2072         UINT len_ret;\r
2073         UINT wp;\r
2074         char *ret;\r
2075         // 引数チェック\r
2076         if (string == NULL || old_keyword == NULL || new_keyword == NULL)\r
2077         {\r
2078                 return 0;\r
2079         }\r
2080 \r
2081         // 文字列長の取得\r
2082         len_string = StrLen(string);\r
2083         len_old = StrLen(old_keyword);\r
2084         len_new = StrLen(new_keyword);\r
2085 \r
2086         // 最終文字列長の計算\r
2087         len_ret = CalcReplaceStrEx(string, old_keyword, new_keyword, case_sensitive);\r
2088         // メモリ確保\r
2089         ret = Malloc(len_ret + 1);\r
2090         ret[len_ret] = '\0';\r
2091 \r
2092         // 検索と置換\r
2093         i = 0;\r
2094         j = 0;\r
2095         num = 0;\r
2096         wp = 0;\r
2097         while (true)\r
2098         {\r
2099                 i = SearchStrEx(string, old_keyword, i, case_sensitive);\r
2100                 if (i == INFINITE)\r
2101                 {\r
2102                         Copy(ret + wp, string + j, len_string - j);\r
2103                         wp += len_string - j;\r
2104                         break;\r
2105                 }\r
2106                 num++;\r
2107                 Copy(ret + wp, string + j, i - j);\r
2108                 wp += i - j;\r
2109                 Copy(ret + wp, new_keyword, len_new);\r
2110                 wp += len_new;\r
2111                 i += len_old;\r
2112                 j = i;\r
2113         }\r
2114 \r
2115         // 検索結果のコピー\r
2116         StrCpy(dst, size, ret);\r
2117 \r
2118         // メモリ解放\r
2119         Free(ret);\r
2120 \r
2121         return num;\r
2122 }\r
2123 \r
2124 // 文字列の置換後の文字列長を計算する\r
2125 UINT CalcReplaceStrEx(char *string, char *old_keyword, char *new_keyword, bool case_sensitive)\r
2126 {\r
2127         UINT i, num;\r
2128         UINT len_string, len_old, len_new;\r
2129         // 引数チェック\r
2130         if (string == NULL || old_keyword == NULL || new_keyword == NULL)\r
2131         {\r
2132                 return 0;\r
2133         }\r
2134 \r
2135         // 文字列長の取得\r
2136         len_string = StrLen(string);\r
2137         len_old = StrLen(old_keyword);\r
2138         len_new = StrLen(new_keyword);\r
2139 \r
2140         if (len_old == len_new)\r
2141         {\r
2142                 return len_string;\r
2143         }\r
2144 \r
2145         // 検索処理\r
2146         num = 0;\r
2147         i = 0;\r
2148         while (true)\r
2149         {\r
2150                 i = SearchStrEx(string, old_keyword, i, case_sensitive);\r
2151                 if (i == INFINITE)\r
2152                 {\r
2153                         break;\r
2154                 }\r
2155                 i += len_old;\r
2156                 num++;\r
2157         }\r
2158 \r
2159         // 計算\r
2160         return len_string + len_new * num - len_old * num;\r
2161 }\r
2162 \r
2163 // 文字列の検索 (大文字 / 小文字を区別する)\r
2164 UINT SearchStr(char *string, char *keyword, UINT start)\r
2165 {\r
2166         return SearchStrEx(string, keyword, start, true);\r
2167 }\r
2168 \r
2169 // 文字列の検索 (大文字 / 小文字を区別しない)\r
2170 UINT SearchStri(char *string, char *keyword, UINT start)\r
2171 {\r
2172         return SearchStrEx(string, keyword, start, false);\r
2173 }\r
2174 \r
2175 // 文字列 string から文字列 keyword を検索して最初に見つかった文字の場所を返す\r
2176 // (1文字目に見つかったら 0, 見つからなかったら INFINITE)\r
2177 UINT SearchStrEx(char *string, char *keyword, UINT start, bool case_sensitive)\r
2178 {\r
2179         UINT len_string, len_keyword;\r
2180         UINT i;\r
2181         char *cmp_string, *cmp_keyword;\r
2182         bool found;\r
2183         // 引数チェック\r
2184         if (string == NULL || keyword == NULL)\r
2185         {\r
2186                 return INFINITE;\r
2187         }\r
2188 \r
2189         // string の長さを取得\r
2190         len_string = StrLen(string);\r
2191         if (len_string <= start)\r
2192         {\r
2193                 // start の値が不正\r
2194                 return INFINITE;\r
2195         }\r
2196 \r
2197         // keyword の長さを取得\r
2198         len_keyword = StrLen(keyword);\r
2199         if (len_keyword == 0)\r
2200         {\r
2201                 // キーワードが無い\r
2202                 return INFINITE;\r
2203         }\r
2204 \r
2205         if ((len_string - start) < len_keyword)\r
2206         {\r
2207                 // キーワードの長さのほうが長い\r
2208                 return INFINITE;\r
2209         }\r
2210 \r
2211         if (case_sensitive)\r
2212         {\r
2213                 cmp_string = string;\r
2214                 cmp_keyword = keyword;\r
2215         }\r
2216         else\r
2217         {\r
2218                 cmp_string = Malloc(len_string + 1);\r
2219                 StrCpy(cmp_string, len_string + 1, string);\r
2220                 cmp_keyword = Malloc(len_keyword + 1);\r
2221                 StrCpy(cmp_keyword, len_keyword + 1, keyword);\r
2222                 StrUpper(cmp_string);\r
2223                 StrUpper(cmp_keyword);\r
2224         }\r
2225 \r
2226         // 検索\r
2227         found = false;\r
2228         for (i = start;i < (len_string - len_keyword + 1);i++)\r
2229         {\r
2230                 // 比較する\r
2231                 if (!strncmp(&cmp_string[i], cmp_keyword, len_keyword))\r
2232                 {\r
2233                         // 発見した\r
2234                         found = true;\r
2235                         break;\r
2236                 }\r
2237         }\r
2238 \r
2239         if (case_sensitive == false)\r
2240         {\r
2241                 // メモリ解放\r
2242                 Free(cmp_keyword);\r
2243                 Free(cmp_string);\r
2244         }\r
2245 \r
2246         if (found == false)\r
2247         {\r
2248                 return INFINITE;\r
2249         }\r
2250         return i;\r
2251 }\r
2252 \r
2253 // 指定した文字がトークンリスト内にあるかどうか調べる\r
2254 bool IsInToken(TOKEN_LIST *t, char *str)\r
2255 {\r
2256         UINT i;\r
2257         // 引数チェック\r
2258         if (t == NULL || str == NULL)\r
2259         {\r
2260                 return false;\r
2261         }\r
2262 \r
2263         for (i = 0;i < t->NumTokens;i++)\r
2264         {\r
2265                 if (StrCmpi(t->Token[i], str) == 0)\r
2266                 {\r
2267                         return true;\r
2268                 }\r
2269         }\r
2270 \r
2271         return false;\r
2272 }\r
2273 \r
2274 // トークンリストの解放\r
2275 void FreeToken(TOKEN_LIST *tokens)\r
2276 {\r
2277         UINT i;\r
2278         if (tokens == NULL)\r
2279         {\r
2280                 return;\r
2281         }\r
2282         for (i = 0;i < tokens->NumTokens;i++)\r
2283         {\r
2284                 if (tokens->Token[i] != 0)\r
2285                 {\r
2286                         Free(tokens->Token[i]);\r
2287                 }\r
2288         }\r
2289         Free(tokens->Token);\r
2290         Free(tokens);\r
2291 }\r
2292 \r
2293 // トークンのパース\r
2294 TOKEN_LIST *ParseToken(char *src, char *separator)\r
2295 {\r
2296         TOKEN_LIST *ret;\r
2297         char *tmp;\r
2298         char *str1, *str2;\r
2299         UINT len;\r
2300         UINT num;\r
2301         if (src == NULL)\r
2302         {\r
2303                 ret = ZeroMalloc(sizeof(TOKEN_LIST));\r
2304                 ret->Token = ZeroMalloc(0);\r
2305                 return ret;\r
2306         }\r
2307         if (separator == NULL)\r
2308         {\r
2309                 separator = " ,\t\r\n";\r
2310         }\r
2311         len = StrLen(src);\r
2312         str1 = Malloc(len + 1);\r
2313         str2 = Malloc(len + 1);\r
2314         StrCpy(str1, 0, src);\r
2315         StrCpy(str2, 0, src);\r
2316 \r
2317         Lock(token_lock);\r
2318         {\r
2319                 tmp = strtok(str1, separator);\r
2320                 num = 0;\r
2321                 while (tmp != NULL)\r
2322                 {\r
2323                         num++;\r
2324                         tmp = strtok(NULL, separator);\r
2325                 }\r
2326                 ret = Malloc(sizeof(TOKEN_LIST));\r
2327                 ret->NumTokens = num;\r
2328                 ret->Token = (char **)Malloc(sizeof(char *) * num);\r
2329                 num = 0;\r
2330                 tmp = strtok(str2, separator);\r
2331                 while (tmp != NULL)\r
2332                 {\r
2333                         ret->Token[num] = (char *)Malloc(StrLen(tmp) + 1);\r
2334                         StrCpy(ret->Token[num], 0, tmp);\r
2335                         num++;\r
2336                         tmp = strtok(NULL, separator);\r
2337                 }\r
2338         }\r
2339         Unlock(token_lock);\r
2340 \r
2341         Free(str1);\r
2342         Free(str2);\r
2343         return ret;\r
2344 }\r
2345 \r
2346 // 1 行を標準入力から取得\r
2347 bool GetLine(char *str, UINT size)\r
2348 {\r
2349         bool ret;\r
2350         wchar_t *unistr;\r
2351         UINT unistr_size = (size + 1) * sizeof(wchar_t);\r
2352 \r
2353         unistr = Malloc(unistr_size);\r
2354 \r
2355         ret = UniGetLine(unistr, unistr_size);\r
2356 \r
2357         UniToStr(str, size, unistr);\r
2358 \r
2359         Free(unistr);\r
2360 \r
2361         return ret;\r
2362 }\r
2363 \r
2364 // 末尾の \r \n を削除\r
2365 void TrimCrlf(char *str)\r
2366 {\r
2367         UINT len;\r
2368         // 引数チェック\r
2369         if (str == NULL)\r
2370         {\r
2371                 return;\r
2372         }\r
2373         len = StrLen(str);\r
2374         if (len == 0)\r
2375         {\r
2376                 return;\r
2377         }\r
2378 \r
2379         if (str[len - 1] == '\n')\r
2380         {\r
2381                 if (len >= 2 && str[len - 2] == '\r')\r
2382                 {\r
2383                         str[len - 2] = 0;\r
2384                 }\r
2385                 str[len - 1] = 0;\r
2386         }\r
2387         else if (str[len - 1] == '\r')\r
2388         {\r
2389                 str[len - 1] = 0;\r
2390         }\r
2391 }\r
2392 \r
2393 // 文字列の左右の空白を削除\r
2394 void Trim(char *str)\r
2395 {\r
2396         // 引数チェック\r
2397         if (str == NULL)\r
2398         {\r
2399                 return;\r
2400         }\r
2401 \r
2402         // 左側を trim\r
2403         TrimLeft(str);\r
2404 \r
2405         // 右側を trim\r
2406         TrimRight(str);\r
2407 }\r
2408 \r
2409 // 文字列の右側の空白を削除\r
2410 void TrimRight(char *str)\r
2411 {\r
2412         char *buf, *tmp;\r
2413         UINT len, i, wp, wp2;\r
2414         BOOL flag;\r
2415         // 引数チェック\r
2416         if (str == NULL)\r
2417         {\r
2418                 return;\r
2419         }\r
2420         len = StrLen(str);\r
2421         if (len == 0)\r
2422         {\r
2423                 return;\r
2424         }\r
2425         if (str[len - 1] != ' ' && str[len - 1] != '\t')\r
2426         {\r
2427                 return;\r
2428         }\r
2429 \r
2430         buf = Malloc(len + 1);\r
2431         tmp = Malloc(len + 1);\r
2432         flag = FALSE;\r
2433         wp = 0;\r
2434         wp2 = 0;\r
2435         for (i = 0;i < len;i++)\r
2436         {\r
2437                 if (str[i] != ' ' && str[i] != '\t')\r
2438                 {\r
2439                         Copy(buf + wp, tmp, wp2);\r
2440                         wp += wp2;\r
2441                         wp2 = 0;\r
2442                         buf[wp++] = str[i];\r
2443                 }\r
2444                 else\r
2445                 {\r
2446                         tmp[wp2++] = str[i];\r
2447                 }\r
2448         }\r
2449         buf[wp] = 0;\r
2450         StrCpy(str, 0, buf);\r
2451         Free(buf);\r
2452         Free(tmp);\r
2453 }\r
2454 \r
2455 // 文字列の左側の空白を削除\r
2456 void TrimLeft(char *str)\r
2457 {\r
2458         char *buf;\r
2459         UINT len, i, wp;\r
2460         BOOL flag;\r
2461         // 引数チェック\r
2462         if (str == NULL)\r
2463         {\r
2464                 return;\r
2465         }\r
2466         len = StrLen(str);\r
2467         if (len == 0)\r
2468         {\r
2469                 return;\r
2470         }\r
2471         if (str[0] != ' ' && str[0] != '\t')\r
2472         {\r
2473                 return;\r
2474         }\r
2475 \r
2476         buf = Malloc(len + 1);\r
2477         flag = FALSE;\r
2478         wp = 0;\r
2479         for (i = 0;i < len;i++)\r
2480         {\r
2481                 if (str[i] != ' ' && str[i] != '\t')\r
2482                 {\r
2483                         flag = TRUE;\r
2484                 }\r
2485                 if (flag)\r
2486                 {\r
2487                         buf[wp++] = str[i];\r
2488                 }\r
2489         }\r
2490         buf[wp] = 0;\r
2491         StrCpy(str, 0, buf);\r
2492         Free(buf);\r
2493 }\r
2494 \r
2495 // 整数を 16 進文字列に変換 (8桁固定)\r
2496 void ToStrx8(char *str, UINT i)\r
2497 {\r
2498         sprintf(str, "0x%08x", i);\r
2499 }\r
2500 \r
2501 // 整数を 16 進文字列に変換\r
2502 void ToStrx(char *str, UINT i)\r
2503 {\r
2504         sprintf(str, "0x%02x", i);\r
2505 }\r
2506 \r
2507 // 符号付整数を文字列に変換\r
2508 void ToStri(char *str, int i)\r
2509 {\r
2510         sprintf(str, "%i", i);\r
2511 }\r
2512 \r
2513 // 整数を文字列に変換\r
2514 void ToStr(char *str, UINT i)\r
2515 {\r
2516         sprintf(str, "%u", i);\r
2517 }\r
2518 \r
2519 // 文字列を符号付整数に変換\r
2520 int ToInti(char *str)\r
2521 {\r
2522         // 引数チェック\r
2523         if (str == NULL)\r
2524         {\r
2525                 return 0;\r
2526         }\r
2527 \r
2528         return (int)ToInt(str);\r
2529 }\r
2530 \r
2531 // 文字列を bool に変換\r
2532 bool ToBool(char *str)\r
2533 {\r
2534         char tmp[MAX_SIZE];\r
2535         // 引数チェック\r
2536         if (str == NULL)\r
2537         {\r
2538                 return false;\r
2539         }\r
2540 \r
2541         StrCpy(tmp, sizeof(tmp), str);\r
2542         Trim(tmp);\r
2543 \r
2544         if (IsEmptyStr(tmp))\r
2545         {\r
2546                 return false;\r
2547         }\r
2548 \r
2549         if (ToInt(tmp) != 0)\r
2550         {\r
2551                 return true;\r
2552         }\r
2553 \r
2554         if (StartWith("true", tmp))\r
2555         {\r
2556                 return true;\r
2557         }\r
2558 \r
2559         if (StartWith("yes", tmp))\r
2560         {\r
2561                 return true;\r
2562         }\r
2563 \r
2564         if (StartWith(tmp, "true"))\r
2565         {\r
2566                 return true;\r
2567         }\r
2568 \r
2569         if (StartWith(tmp, "yes"))\r
2570         {\r
2571                 return true;\r
2572         }\r
2573 \r
2574         return false;\r
2575 }\r
2576 \r
2577 // 文字列を整数に変換\r
2578 UINT ToInt(char *str)\r
2579 {\r
2580         // 引数チェック\r
2581         if (str == NULL)\r
2582         {\r
2583                 return 0;\r
2584         }\r
2585 \r
2586         // 8 進数表記を無視する\r
2587         while (true)\r
2588         {\r
2589                 if (*str != '0')\r
2590                 {\r
2591                         break;\r
2592                 }\r
2593                 if ((*(str + 1) == 'x') || (*(str + 1) == 'X'))\r
2594                 {\r
2595                         break;\r
2596                 }\r
2597                 str++;\r
2598         }\r
2599 \r
2600         return (UINT)strtoul(str, NULL, 0);\r
2601 }\r
2602 \r
2603 // 64bit 整数のためのフォーマット文字列を置換する\r
2604 char *ReplaceFormatStringFor64(char *fmt)\r
2605 {\r
2606         char *tmp;\r
2607         char *ret;\r
2608         UINT tmp_size;\r
2609         // 引数チェック\r
2610         if (fmt == NULL)\r
2611         {\r
2612                 return NULL;\r
2613         }\r
2614 \r
2615         tmp_size = StrSize(fmt) * 2;\r
2616         tmp = ZeroMalloc(tmp_size);\r
2617 \r
2618 #ifdef  OS_WIN32\r
2619         ReplaceStrEx(tmp, tmp_size, fmt, "%ll", "%I64", false);\r
2620 #else   // OS_WIN32\r
2621         ReplaceStrEx(tmp, tmp_size, fmt, "%I64", "%ll", false);\r
2622 #endif  // OS_WIN32\r
2623 \r
2624         ret = CopyStr(tmp);\r
2625         Free(tmp);\r
2626 \r
2627         return ret;\r
2628 }\r
2629 \r
2630 // 文字列を画面に表示する\r
2631 void PrintStr(char *str)\r
2632 {\r
2633         wchar_t *unistr = NULL;\r
2634         // 引数チェック\r
2635         if (str == NULL)\r
2636         {\r
2637                 return;\r
2638         }\r
2639 \r
2640 #ifdef  OS_UNIX\r
2641         fputs(str, stdout);\r
2642 #else   // OS_UNIX\r
2643         unistr = CopyStrToUni(str);\r
2644         UniPrintStr(unistr);\r
2645         Free(unistr);\r
2646 #endif  // OS_UNIX\r
2647 }\r
2648 \r
2649 // 文字列を引数付きで表示する\r
2650 void PrintArgs(char *fmt, va_list args)\r
2651 {\r
2652         wchar_t *ret;\r
2653         wchar_t *fmt_wchar;\r
2654         char *tmp;\r
2655         // 引数チェック\r
2656         if (fmt == NULL)\r
2657         {\r
2658                 return;\r
2659         }\r
2660 \r
2661         fmt_wchar = CopyStrToUni(fmt);\r
2662         ret = InternalFormatArgs(fmt_wchar, args, true);\r
2663 \r
2664         tmp = CopyUniToStr(ret);\r
2665         PrintStr(tmp);\r
2666         Free(tmp);\r
2667 \r
2668         Free(ret);\r
2669         Free(fmt_wchar);\r
2670 }\r
2671 \r
2672 // 文字列を表示する\r
2673 void Print(char *fmt, ...)\r
2674 {\r
2675         va_list args;\r
2676         if (fmt == NULL)\r
2677         {\r
2678                 return;\r
2679         }\r
2680 \r
2681         va_start(args, fmt);\r
2682         PrintArgs(fmt, args);\r
2683         va_end(args);\r
2684 }\r
2685 \r
2686 // デバッグ文字列を引数付きで表示する\r
2687 void DebugArgs(char *fmt, va_list args)\r
2688 {\r
2689         // 引数チェック\r
2690         if (fmt == NULL)\r
2691         {\r
2692                 return;\r
2693         }\r
2694         if (g_debug == false)\r
2695         {\r
2696                 return;\r
2697         }\r
2698 \r
2699         PrintArgs(fmt, args);\r
2700 }\r
2701 \r
2702 // デバッグ文字列を表示する\r
2703 void Debug(char *fmt, ...)\r
2704 {\r
2705         va_list args;\r
2706         // 引数チェック\r
2707         if (fmt == NULL)\r
2708         {\r
2709                 return;\r
2710         }\r
2711         if (g_debug == false)\r
2712         {\r
2713                 return;\r
2714         }\r
2715 \r
2716         va_start(args, fmt);\r
2717 \r
2718         DebugArgs(fmt, args);\r
2719 \r
2720         va_end(args);\r
2721 }\r
2722 \r
2723 // 文字列をフォーマットして結果を返す\r
2724 char *CopyFormat(char *fmt, ...)\r
2725 {\r
2726         char *buf;\r
2727         char *ret;\r
2728         UINT size;\r
2729         va_list args;\r
2730         // 引数チェック\r
2731         if (fmt == NULL)\r
2732         {\r
2733                 return NULL;\r
2734         }\r
2735 \r
2736         size = MAX(StrSize(fmt) * 10, MAX_SIZE * 10);\r
2737         buf = Malloc(size);\r
2738 \r
2739         va_start(args, fmt);\r
2740         FormatArgs(buf, size, fmt, args);\r
2741 \r
2742         ret = CopyStr(buf);\r
2743         Free(buf);\r
2744 \r
2745         va_end(args);\r
2746         return ret;\r
2747 }\r
2748 \r
2749 // 文字列をフォーマットする\r
2750 void Format(char *buf, UINT size, char *fmt, ...)\r
2751 {\r
2752         va_list args;\r
2753         // 引数チェック\r
2754         if (buf == NULL || fmt == NULL)\r
2755         {\r
2756                 return;\r
2757         }\r
2758 \r
2759         va_start(args, fmt);\r
2760         FormatArgs(buf, size, fmt, args);\r
2761         va_end(args);\r
2762 }\r
2763 \r
2764 // 文字列をフォーマットする (引数リスト)\r
2765 void FormatArgs(char *buf, UINT size, char *fmt, va_list args)\r
2766 {\r
2767         wchar_t *tag;\r
2768         wchar_t *ret;\r
2769         // 引数チェック\r
2770         if (buf == NULL || fmt == NULL)\r
2771         {\r
2772                 return;\r
2773         }\r
2774 \r
2775         tag = CopyStrToUni(fmt);\r
2776         ret = InternalFormatArgs(tag, args, true);\r
2777 \r
2778         UniToStr(buf, size, ret);\r
2779         Free(ret);\r
2780         Free(tag);\r
2781 }\r
2782 \r
2783 // 文字列を大文字・小文字を区別せずに比較する\r
2784 int StrCmpi(char *str1, char *str2)\r
2785 {\r
2786         UINT i;\r
2787         // 引数チェック\r
2788         if (str1 == NULL && str2 == NULL)\r
2789         {\r
2790                 return 0;\r
2791         }\r
2792         if (str1 == NULL)\r
2793         {\r
2794                 return 1;\r
2795         }\r
2796         if (str2 == NULL)\r
2797         {\r
2798                 return -1;\r
2799         }\r
2800 \r
2801         // 文字列比較\r
2802         i = 0;\r
2803         while (true)\r
2804         {\r
2805                 char c1, c2;\r
2806                 c1 = ToUpper(str1[i]);\r
2807                 c2 = ToUpper(str2[i]);\r
2808                 if (c1 > c2)\r
2809                 {\r
2810                         return 1;\r
2811                 }\r
2812                 else if (c1 < c2)\r
2813                 {\r
2814                         return -1;\r
2815                 }\r
2816                 if (str1[i] == 0 || str2[i] == 0)\r
2817                 {\r
2818                         return 0;\r
2819                 }\r
2820                 i++;\r
2821         }\r
2822 }\r
2823 \r
2824 // 文字列を比較する\r
2825 int StrCmp(char *str1, char *str2)\r
2826 {\r
2827         // 引数チェック\r
2828         if (str1 == NULL && str2 == NULL)\r
2829         {\r
2830                 return 0;\r
2831         }\r
2832         if (str1 == NULL)\r
2833         {\r
2834                 return 1;\r
2835         }\r
2836         if (str2 == NULL)\r
2837         {\r
2838                 return -1;\r
2839         }\r
2840 \r
2841         return strcmp(str1, str2);\r
2842 }\r
2843 \r
2844 // 文字列を小文字にする\r
2845 void StrLower(char *str)\r
2846 {\r
2847         UINT len, i;\r
2848         // 引数チェック\r
2849         if (str == NULL)\r
2850         {\r
2851                 return;\r
2852         }\r
2853 \r
2854         len = StrLen(str);\r
2855         for (i = 0;i < len;i++)\r
2856         {\r
2857                 str[i] = ToLower(str[i]);\r
2858         }\r
2859 }\r
2860 \r
2861 // 文字列を大文字にする\r
2862 void StrUpper(char *str)\r
2863 {\r
2864         UINT len, i;\r
2865         // 引数チェック\r
2866         if (str == NULL)\r
2867         {\r
2868                 return;\r
2869         }\r
2870 \r
2871         len = StrLen(str);\r
2872         for (i = 0;i < len;i++)\r
2873         {\r
2874                 str[i] = ToUpper(str[i]);\r
2875         }\r
2876 }\r
2877 \r
2878 // 文字を小文字にする\r
2879 char ToLower(char c)\r
2880 {\r
2881         if ('A' <= c && c <= 'Z')\r
2882         {\r
2883                 c += 'z' - 'Z';\r
2884         }\r
2885         return c;\r
2886 }\r
2887 \r
2888 // 文字を大文字にする\r
2889 char ToUpper(char c)\r
2890 {\r
2891         if ('a' <= c && c <= 'z')\r
2892         {\r
2893                 c += 'Z' - 'z';\r
2894         }\r
2895         return c;\r
2896 }\r
2897 \r
2898 // 文字列を結合\r
2899 UINT StrCat(char *dst, UINT size, char *src)\r
2900 {\r
2901         UINT len1, len2, len_test;\r
2902         // 引数チェック\r
2903         if (dst == NULL || src == NULL)\r
2904         {\r
2905                 return 0;\r
2906         }\r
2907 \r
2908         // KS\r
2909         KS_INC(KS_STRCAT_COUNT);\r
2910 \r
2911         if (size == 0)\r
2912         {\r
2913                 // 長さを無視\r
2914                 size = 0x7fffffff;\r
2915         }\r
2916 \r
2917         len1 = StrLen(dst);\r
2918         len2 = StrLen(src);\r
2919         len_test = len1 + len2 + 1;\r
2920         if (len_test > size)\r
2921         {\r
2922                 if (len2 <= (len_test - size))\r
2923                 {\r
2924                         return 0;\r
2925                 }\r
2926                 len2 -= len_test - size;\r
2927         }\r
2928         Copy(dst + len1, src, len2);\r
2929         dst[len1 + len2] = 0;\r
2930 \r
2931         return len1 + len2;\r
2932 }\r
2933 UINT StrCatLeft(char *dst, UINT size, char *src)\r
2934 {\r
2935         char *s;\r
2936         // 引数チェック\r
2937         if (dst == NULL || src == NULL)\r
2938         {\r
2939                 return 0;\r
2940         }\r
2941 \r
2942         s = CopyStr(dst);\r
2943         StrCpy(dst, size, src);\r
2944         StrCat(dst, size, s);\r
2945 \r
2946         Free(s);\r
2947 \r
2948         return StrLen(dst);\r
2949 }\r
2950 \r
2951 // 文字列をコピー\r
2952 UINT StrCpy(char *dst, UINT size, char *src)\r
2953 {\r
2954         UINT len;\r
2955         // 引数チェック\r
2956         if (dst == src)\r
2957         {\r
2958                 return StrLen(src);\r
2959         }\r
2960         if (dst == NULL || src == NULL)\r
2961         {\r
2962                 if (src == NULL && dst != NULL)\r
2963                 {\r
2964                         if (size >= 1)\r
2965                         {\r
2966                                 dst[0] = '\0';\r
2967                         }\r
2968                 }\r
2969                 return 0;\r
2970         }\r
2971         if (size == 1)\r
2972         {\r
2973                 dst[0] = '\0';\r
2974                 return 0;\r
2975         }\r
2976         if (size == 0)\r
2977         {\r
2978                 // 長さを無視\r
2979                 size = 0x7fffffff;\r
2980         }\r
2981 \r
2982         // 長さをチェック\r
2983         len = StrLen(src);\r
2984         if (len <= (size - 1))\r
2985         {\r
2986                 Copy(dst, src, len + 1);\r
2987         }\r
2988         else\r
2989         {\r
2990                 len = size - 1;\r
2991                 Copy(dst, src, len);\r
2992                 dst[len] = '\0';\r
2993         }\r
2994 \r
2995         // KS\r
2996         KS_INC(KS_STRCPY_COUNT);\r
2997 \r
2998         return len;\r
2999 }\r
3000 \r
3001 // 文字列バッファが指定されたサイズに収まっているかどうかを確認\r
3002 bool StrCheckSize(char *str, UINT size)\r
3003 {\r
3004         // 引数チェック\r
3005         if (str == NULL || size == 0)\r
3006         {\r
3007                 return false;\r
3008         }\r
3009 \r
3010         return StrCheckLen(str, size - 1);\r
3011 }\r
3012 \r
3013 // 文字列が指定された長さ以内であることを確認\r
3014 bool StrCheckLen(char *str, UINT len)\r
3015 {\r
3016         UINT count = 0;\r
3017         UINT i;\r
3018         // 引数チェック\r
3019         if (str == NULL)\r
3020         {\r
3021                 return false;\r
3022         }\r
3023 \r
3024         // KS\r
3025         KS_INC(KS_STRCHECK_COUNT);\r
3026 \r
3027         for (i = 0;;i++)\r
3028         {\r
3029                 if (str[i] == '\0')\r
3030                 {\r
3031                         return true;\r
3032                 }\r
3033                 count++;\r
3034                 if (count > len)\r
3035                 {\r
3036                         return false;\r
3037                 }\r
3038         }\r
3039 }\r
3040 \r
3041 // 文字列を格納するために必要なメモリサイズを取得\r
3042 UINT StrSize(char *str)\r
3043 {\r
3044         // 引数チェック\r
3045         if (str == NULL)\r
3046         {\r
3047                 return 0;\r
3048         }\r
3049 \r
3050         return StrLen(str) + 1;\r
3051 }\r
3052 \r
3053 // 文字列の長さを取得\r
3054 UINT StrLen(char *str)\r
3055 {\r
3056         // 引数チェック\r
3057         if (str == NULL)\r
3058         {\r
3059                 return 0;\r
3060         }\r
3061 \r
3062         // KS\r
3063         KS_INC(KS_STRLEN_COUNT);\r
3064 \r
3065         return (UINT)strlen(str);\r
3066 }\r
3067 \r
3068 \r