source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Mayaqua/Str.c @ 86521dd

trunk
Last change on this file since 86521dd was a1bae3e, checked in by mitty <mitty@…>, 12 years ago
  • copy vendor drop to trunk

git-svn-id: https://lab.mitty.jp/svn/lab/trunk@147 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

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