source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Mayaqua/Internat.c @ 04eb6d7

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