Strx.c
[大目次 | 目次 | 関数 | マクロ]
1|/**************************************************************************
2| 1. <<< 文字列の拡張 (StrX) >>>
3|
4| 2. <<< 標準ライブラリの簡易ヘルプ >>>
5|・大文字小文字変換 _strlwr, _strupr
6|***************************************************************************/
7|
8|#include "mixer_precomp.h" /* Auto precompiled header, Look at mixer-... folder */
9|// #pragma hdrstop
10|
11|#include <string.h>
12|#include <stdio.h>
13|#include <stdlib.h>
14|#include <ctype.h>
15|#if defined(_MSC_VER) && !defined(UNDER_CE)
16| #include <mbctype.h>
17| #include <direct.h>
18|#endif
19|
20|#if defined(_WIN32) && !defined(__BORLANDC__)
21| #include "windows.h"
22|#endif
23|
24|#if defined(USES_MXP_AUTOINC)
25| #include "strx.ah" /* Auto include header, Look at mixer-... folder */
26|#endif
27|
28|#if defined(FOR_WIN32) || defined(FOR_DOS32)
29|#include <locale.h>
30|#endif
31|
32|#ifdef FOR_WINCE
33| #define stricmp _stricmp
34| #define strnicmp _strnicmp
35|#endif
36|
37|#ifdef STRX_USES_MALLOC
38|#ifndef USES_STDPLUS
39|#error need StdPlus
40|#endif
41|#endif
42|
43|
44|/***********************************************************************
45| 3. <<< (_ismbblead) WINCE用ダミー関数 >>>
46|************************************************************************/
47|#ifdef FOR_WINCE
48|int _ismbblead( unsigned int c )
49|{
50| ASSERT(1);
51| return 0;
52|}
53|#endif
54|
55|/***********************************************************************
56| 4. <<< main の引数を表示する [StrX_printMainArg()] >>>
57|************************************************************************/
58|#ifndef FOR_WINCE
59|void StrX_printMainArg( int argc, char* argv[] )
60|{
61| int i;
62|
63| printf( "argc = %d\n", argc );
64| for ( i = 0; i < argc; i++ )
65| printf( "argv[%d] = %s\n", i, argv[i] );
66|}
67|#endif
68|
69|
70|
71|/*-------------------------------------------------------------------------*/
72|/* ◆5. <<<< (StrX) char* 型の文字列(コピー・連結) >>>> */
73|/*-------------------------------------------------------------------------*/
74|
75|
76|
77|/***********************************************************************
78| 5-1. <<< [StrX_cpy] 文字列のあふれチェック付き strcpy >>>
79|【引数】
80| ・char* dst; コピー先の文字列格納領域のアドレス(出力)
81| ・char* src; コピー元の文字列格納領域のアドレス(入力)
82| ・int dst_size : dst のメモリサイズ(バイト)
83|【補足】
84|・あふれた分はカットされます。
85|・アドレスが dst < src の場合 memmove 関数を使わなくても正しく移動します。
86|************************************************************************/
87|char* StrX_cpy( char* dst, const char* src, int dst_size )
88|{
89| int src_len = strlen( src );
90|
91| if ( src_len >= dst_size - 1 ) {
92| if ( dst_size > 0 ) {
93| memcpy( dst, src, dst_size - 1 );
94| dst[dst_size - 1] = '\0';
95| }
96| return dst;
97| }
98| else
99| return strcpy( dst, src );
100|}
101|
102|
103|
104|/***********************************************************************
105| 5-2. <<< [StrX_ncpy] 文字列のあふれチェック付き strncpy >>>
106|【引数】
107| ・int dst_maxLen : dst(出力)に格納できる最大の文字数(byte)
108|【補足】
109|・あふれた分はカットされます。
110|************************************************************************/
111|char* StrX_ncpy( char* dst, char* src, int n, int dst_maxLen )
112|{
113| int src_len = strlen( src );
114| int len;
115|
116| len = ( dst_maxLen < src_len ) ? dst_maxLen : src_len;
117| if ( n < len ) len = n;
118|
119| strncpy( dst, src, len );
120| dst[len] = '\0';
121|
122| return dst;
123|}
124|
125|
126|
127|
128|/***********************************************************************
129| 5-3. <<< [StrX_wordCpy] ワード・コピー、term 文字の直前までコピー >>>
130| src の term 文字の直前までコピーします。
131| 返り値:dec
132|************************************************************************/
133|void StrX_wordCpy( char* dec, int dec_len, const char* src, char term )
134|{
135| char* dec_over = dec + dec_len;
136|
137| while ( dec < dec_over ) {
138| if ( *src == term || *src == '\0' ) {
139| *dec = '\0'; return;
140| }
141| *dec++ = *src++;
142| }
143| *dec = '\0';
144|}
145|
146|
147|
148|/**************************************************************************
149| 5-4. <<< [StrX_toCSV] CSV 形式の1項目を作る >>>
150|【機能】
151|・必要に応じて "" で囲んだり " 文字を "" にします。
152|【引数】
153| ・int dst_maxLen; 格納できる最大の文字数('\0'除く)
154|【補足】
155|・','や'\n'を出力しないので、別に行ってください。
156|・"" で囲む条件は、文字列中に ',' または '"' がある場合、または、
157| 頭か末尾に空白がある場合です。
158|**************************************************************************/
159|char* StrX_toCSV( char* dst, const char* src, int dst_maxLen )
160|{
161| char* ret = dst;
162| char* dst_over = dst + dst_maxLen;
163| int kakomu; /* "" で囲むか (bool) */
164|
165| kakomu = ( strchr( src, ',' ) || strchr( src, '"' ) ||
166| src[0] == ' ' || src[strlen(src)-1] == ' ' );
167|
168| if ( kakomu ) {
169| if ( dst < dst_over ) { *dst = '"'; dst ++; }
170| }
171|
172| while ( *src != '\0' && dst < dst_over ) {
173| if ( *src == '"' ) {
174| *dst = '"'; dst ++;
175| if ( dst < dst_over ) { *dst = '"'; dst ++; }
176| }
177| else {
178| *dst = *src; dst ++;
179| }
180| src++;
181| }
182|
183| if ( kakomu ) {
184| if ( dst < dst_over ) { *dst = '"'; dst ++; }
185| }
186|
187| *dst = '\0';
188|
189| return ret;
190|}
191|
192|
193|
194|/**************************************************************************
195| 5-5. <<< [StrX_meltCSV] CSV 形式の1項目を取り出し、通常の文字列に戻す >>>
196|【引数】
197| ・char* t; 通常の文字列を格納するアドレス
198| ・char* s; CSV 形式の文字列
199| ・char* 返り値; 次(右)の CSV 項目へのアドレス
200|【補足】
201|・"" で囲まない場合、両端の空白を取り除きます。
202|・t の領域サイズは、s と同じかそれ以上にしてください。
203| t は s と同じでも構いません。
204|・(abc,,def)のように、次の CSV 項目の内容が無い場合、
205| 返り値 ret は *ret == NULL です。
206|・(abc)のように、次の CSV 項目が無い場合、返り値 は NULL です。
207|【例】
208|・s = (abc, def) なら t=(abc), ret=( def)
209|・s = ("abc:""def""",ghi) なら t=(abc:"def"), ret=(ghi)
210|・s = ( abc ) なら t=(abc), ret=NULL
211|・プログラミング例
212| p = csv_string;
213| if ( *p != '\0' ) {
214| do {
215| p = StrX_meltCSV( s, p );
216| :
217| } while ( p != NULL );
218| }
219|*************************************************************************/
220|char* StrX_meltCSV( char* t, const char* s )
221|{
222| /* 頭の空白を除く */
223| while ( *s == ' ' ) s++;
224|
225| switch ( *s ) {
226|
227| /* "" で囲まれている場合 */
228| case '"':
229| s++;
230| while ( *s != '"' || *(s+1) == '"' ) { /* " 文字まで */
231| if ( *s == *(s+1) && *s == '"' ) s++; /* " 文字 */
232| *t = *s; t++; s++;
233| if ( *s == '\0' ) break;
234| }
235| *t = '\0';
236|
237| s++;
238| for (;;) {
239| if ( *s == ',' ) return (char*)s+1;
240| if ( *s == '\0' ) return NULL;
241| s++;
242| }
243|
244| /* 空の項目の場合 */
245| case ',':
246| *t = '\0';
247| return (char*)s+1;
248|
249| case '\0':
250| *t = '\0';
251| return NULL;
252|
253| /* "" で囲まれていない場合 */
254| default: {
255| char* sp = NULL; /* 最後の連続した空白の先頭 */
256|
257| while ( *s != ',' && *s != '\0' && *s != '\r' && *s != '\n' ) { /* , 文字まで */
258|
259| /* sp を設定する */
260| if ( *s == ' ' ) {
261| if ( sp == NULL ) sp = t;
262| }
263| else sp = NULL;
264|
265| /* コピーする */
266| *t = *s; t++; s++;
267| }
268|
269| /* 返り値を決定する */
270| if ( *s == ',' ) s = s + 1;
271| else s = NULL;
272|
273| /* 末尾の空白を取り除く */
274| if ( sp != NULL ) *sp = '\0';
275| else *t = '\0';
276|
277| return (char*)s;
278| }
279| }
280|}
281|
282|
283|
284|/**************************************************************************
285| 5-6. <<< [StrX_cpyToCSymbol] ファイルパスを C 言語のシンボルにする >>>
286|【補足】
287|・ファイル名の部分を、C 言語のシンボルで使えるようにします。
288|・2バイト文字は1バイトずつコードを判定します。
289|・dst と src は、別の文字列領域を指定してください。
290|***************************************************************************/
291|char* StrX_cpyToCSymbol( char* dst, const char* src )
292|{
293| char* p;
294|
295| StrX_cpyFName( dst, src );
296| StrX_chgExt( dst, "" );
297| StrX_cutLastOf2( dst, '.' );
298|
299| if ( isdigit( dst[0] ) )
300| StrX_ins( dst, "_" );
301| for ( p = dst; *p != '\0'; p++ ) {
302| if ( ! isalpha( *p ) && ! isdigit( *p ) ) *p = '_';
303| }
304|
305| return dst;
306|}
307|
308|
309|/**************************************************************************
310| 5-7. <<< [StrX_getCmdWord] スペース区切り& "" 囲みのワードをコピー >>>
311|【引数】
312| ・char* t; 文字列を格納するアドレス
313| ・char* s; コマンド文字列中の解析し始める位置
314| ・char* 返り値; 次(右)のワードのアドレス
315|【補足】
316|・"" で囲まない場合、両端の空白を取り除きます。
317|・t の領域サイズは、s と同じかそれ以上にしてください。
318| t は s と同じでも構いません。
319|・返り値のさす文字が '\0' のとき、次のワードはありません(最後のワードの次)
320|**************************************************************************/
321|char* StrX_getCmdWord( char* t, const char* s )
322|{
323| while ( *s == ' ' ) s++;
324| if ( *s == '\0' ) return (char*)s;
325|
326| /* " " で囲まれている場合、'"' までをワードにする */
327| if ( *s == '"' ) {
328| s++;
329| while ( *s != '"' ) {
330| if ( *s == '\0' )
331| { *t = '\0'; return (char*)s; }
332| *t = *s;
333| t++; s++;
334| }
335| *t = '\0';
336| s++;
337| return (char*)s;
338| }
339|
340| /* " " で囲まれていない場合、' ' までをワードにする */
341| else {
342| while ( *s != ' ' ) {
343| if ( *s != '\0' )
344| { *t = '\0'; return (char*)s; }
345| *t = *s;
346| t++; s++;
347| }
348| *t = '\0';
349| s++;
350| return (char*)s;
351| }
352|}
353|
354|
355|
356|/***********************************************************************
357| 5-8. <<< [StrX_cat] 文字列のあふれチェック付き strcat >>>
358| ・dst_maxLen : dst(出力)に格納できる最大の文字数(byte)
359| あふれ分はカットされる
360|************************************************************************/
361|char* StrX_cat( char* dst, const char* add, int dst_maxLen )
362|{
363| int dst_len = strlen( dst );
364|
365| if ( dst_len + (int)strlen( add ) > dst_maxLen ) {
366| memcpy( &dst[dst_len], add, dst_maxLen - dst_len );
367| dst[dst_maxLen] = '\0';
368| return dst;
369| }
370| return strcat( dst, add );
371|}
372|
373|
374|
375|/***********************************************************************
376| 5-9. <<< [StrX_catR] s2 の記憶領域に s1 + s2 を格納する >>>
377| 格納された s2 も返します
378| 例: char buf[60]; strcpy( buf, "cde" ); なら
379| StrX_catR( "ab", buf, 60 ) == buf == "abcde"
380|************************************************************************/
381|char* StrX_catR( const char* s1, char* s2, int s2_size )
382|{
383| int s1_len = strlen( s1 );
384| int s2_len = strlen( s2 );
385|
386| if ( s1_len + s2_len < s2_size ) {
387| memmove( s2 + s1_len, s2, s2_len + 1 );
388| memcpy( s2, s1, s1_len );
389| }
390| else {
391| memmove( s2 + s1_len, s2, s2_size - s1_len - 1 );
392| s2[s2_size - 1] = '\0';
393| if ( s1_len < s2_size )
394| memcpy( s2, s1, s1_len );
395| else
396| memcpy( s2, s1, s2_size - 1 );
397| }
398| return s2;
399|}
400|
401|
402|
403|/*************************************************************************
404| 5-10. <<< [StrX_cpyWild] ワイルドカードに対応する部分をコピーする >>>
405|【引数】
406| ・char* 返り値; dst と同じ(内容は、コピーされたもの)
407| (その他は例を参考)
408|【補足】
409|・dst の埋め込む部分を '*' ワイルドカードで指定します。
410|(以下は未対応)
411|・'?' ワイルドカードは n 個目の '?' と対応します。対応する '?' がない場合、
412| 何も埋め込まれません。
413|・dst_wild, src_wild のワイルドカード以外の部分が dst, src に対応していない
414| 場合、動作は不明です。
415|【例】
416|・dst_wild="[*]", src="abcdef", src_wild="abc*" ... dst="[def]"
417|(以下は未対応)
418|・dst_wild="[?,?,?]", src="abcdefgh", src_wild="ab?d*g?" ... dst="[c,h,]"
419|**************************************************************************/
420|char* StrX_cpyWild( char* dst, const char* dst_wild, const char* src,
421| const char* src_wild )
422|{
423| char* d;
424| const char* dw;
425| const char* s;
426| const char* src_fst; /* ワイルドカードに対応する src 内の先頭アドレス */
427| const char* src_lst; /* ワイルドカードに対応する src 内の末尾アドレス */
428|
429| /* dst_wild の '*'ワイルドカードより前を dst へコピーする */
430| d = dst; dw = dst_wild;
431| while ( *dw != '*' ) {
432| *d = *dw;
433| if ( *dw == '\0' ) return dst;
434| d++; dw++;
435| }
436|
437| /* ワイルドカードに対応する src 内のアドレス src_fst, src_lst を取得する */
438| {
439| char* src_wild_aster = strchr( src_wild, '*' );
440| char* src_wild_zero = strchr( src_wild, '\0' );
441| char* src_zero = strchr( src, '\0' );
442|
443| src_fst = src + (src_wild_aster - src_wild);
444| src_lst = src_zero - (src_wild_zero - src_wild_aster);
445| }
446|
447| /* src の '*'ワイルドカードに対応する部分を dst(d) にコピーする */
448| s = src_fst;
449| while ( s <= src_lst ) {
450| *d = *s;
451| d++; s++;
452| }
453|
454| /* dst_wild の '*'ワイルドカードより後を dst(d) へコピーする */
455| dw ++; /* skip '*' */
456| while ( *dw != '\0' ) {
457| *d = *dw;
458| d++; dw++;
459| }
460| *d = '\0';
461|
462| return dst;
463|}
464|
465|
466|
467|/*************************************************************************
468| 5-11. <<< [StrX_ins] 文字列を挿入する >>>
469|【引数】
470| ・char* dst; 挿入する位置
471| ・char* src; 挿入する文字列
472| ・char* 返り値; dst
473|【補足】
474|・文字列の途中に挿入する場合、次のようにポインタ演算してください。
475| char* str = "abc";
476| StrX_ins( str+1, "X" );
477|**************************************************************************/
478|char* StrX_ins( char* dst, const char* src )
479|{
480| int len = strlen(src);
481| memmove( dst + len, dst, strlen(dst) + 1 );
482| memcpy( dst, src, len );
483| return dst;
484|}
485|
486|
487|
488|/***********************************************************************
489| 5-12. <<< [StrX_setLast] 末尾の文字が c でないなら追加する >>>
490| 返り値 : 追加した文字列
491|************************************************************************/
492|#ifndef K_AND_R
493|char* StrX_setLast( char* s, char c )
494|#else
495|char* StrX_setLast( s, c )
496| char* s; char c;
497|#endif
498|{
499| char* p = s;
500| int bLastHit; /* 直前の文字が c かどうか */
501|
502| while ( *p != '\0' ) {
503| if ( _ismbblead( *p ) ) { p++; bLastHit = 0; }
504| else bLastHit = ( *p == c );
505| p++;
506| }
507| if ( ! bLastHit ) { *p = c; p++; *p = '\0'; }
508|
509| return s;
510|}
511|
512|
513|
514|/*-------------------------------------------------------------------------*/
515|/* ◆6. <<<< (StrX) char* 型の文字列(削除) >>>> */
516|/*-------------------------------------------------------------------------*/
517|
518|
519|
520|/***********************************************************************
521| 6-1. <<< [StrX_bs] バックスペース、末尾の 1 バイトを除く >>>
522|【引数】
523| ・char* s; 末尾を除く文字列
524| ・char* 返り値; 除いた文字列
525|************************************************************************/
526|#ifndef K_AND_R
527|char* StrX_bs( char* s )
528|#else
529|char* StrX_bs( s )
530| char* s;
531|#endif
532|{
533| int len = strlen( s );
534|
535| s[ len - 1 ] = '\0';
536|
537| return s;
538|}
539|
540|
541|
542|/***********************************************************************
543| 6-2. <<< [StrX_bs2] バックスペース、末尾の n バイトを除く >>>
544|【引数】
545| ・char* s; 末尾を除く文字列
546| ・int n; 削除するバイト数
547| ・char* 返り値; 除いた文字列
548|************************************************************************/
549|#ifndef K_AND_R
550|char* StrX_bs2( char* s, int n )
551|#else
552|char* StrX_bs2( s, n )
553| char* s;
554| int n;
555|#endif
556|{
557| int len = strlen( s );
558|
559| ASSERT( len - n >= 0 );
560|
561| s[ len - n ] = '\0';
562|
563| return s;
564|}
565|
566|
567|
568|/************************************************************************
569| 6-3. <<< [StrX_del] 文字列中の s の位置から n 文字だけ削除する >>>
570|【引数】
571| ・char* s; 削除を開始する文字列中のアドレス
572| ・int n; 削除するバイト数
573| ・char* 返り値; 除いた文字列
574|*************************************************************************/
575|void StrX_del( char* s, int n )
576|{
577| ASSERT( (unsigned)n <= strlen( s ) );
578|
579| memmove( s, s+n, strlen(s)-n+1 );
580|}
581|
582|
583|
584|/***********************************************************************
585| 6-4. <<< [StrX_trim] 文字列の両端の空白、タブ、改行を取り除く >>>
586|【引数】
587| ・char* s; 両端の空白を削除する文字列
588| ・char* 返り値; 取り除いた文字列
589|************************************************************************/
590|char* StrX_trim( char* s )
591|{
592| char* left;
593| char* right;
594|
595| /* 空白、タブ、改行を除いた、文字列 s の先頭の位置 left を得る */
596| left = s;
597| while ( StrX_isSpace(*left) ) left ++;
598|
599| /* 空白、タブ、改行を除いた、文字列 s の末尾の位置 right を得る */
600| right = left + strlen( left ) - 1;
601| while ( StrX_isSpace(*right) && right >= s ) right --;
602|
603| /* 両端の空白、タブ、改行を取り除いた文字列 s に変える */
604| right[1] = '\0';
605| memmove( s, left, strlen( left ) + 1 );
606|
607| return s;
608|}
609|
610|
611|
612|/***********************************************************************
613| 6-5. <<< [StrX_trim2] 文字列の両端の空白、タブ、改行、'"'を取り除く >>>
614| 返り値 : 取り除いた文字列
615|************************************************************************/
616|char* StrX_trim2( char* s )
617|{
618| char* left;
619| char* right;
620|
621| StrX_trim( s );
622|
623| /* 空白、タブ、改行を除いた、文字列 s の先頭の位置 left を得る */
624| left = s;
625| while ( *left == '"' ) left ++;
626|
627| /* 空白、タブ、改行を除いた、文字列 s の末尾の位置 right を得る */
628| right = left + strlen( left ) - 1;
629| while ( *right == '"' && right >= s ) right --;
630|
631| /* 両端の空白、タブ、改行を取り除いた文字列 s に変える */
632| right[1] = '\0';
633| memmove( s, left, strlen( left ) + 1 );
634|
635| return s;
636|}
637|
638|
639|
640|/***********************************************************************
641| 6-6. <<< [StrX_cutHtmlTag] 文字列中の HTML タグを取り除く >>>
642|************************************************************************/
643|void StrX_cutHtmlTag( char* s )
644|{
645| char* s2 = s; /* s=コピー元、s2=コピー先 */
646|
647| while ( *s != '\0' ) {
648| if ( _ismbblead( *s ) ) {
649| *s2 = *s;
650| *(s2 + 1) = *(s + 1);
651| s += 2; s2 += 2;
652| }
653| else {
654| if ( *s == '<' ) {
655| s++;
656| do {
657| while ( _ismbblead( *s ) ) s += 2;
658| s++;
659| } while ( *s != '>' && *s != '\0' );
660| s++;
661| }
662| else {
663| *s2 = *s;
664| s ++; s2 ++;
665| }
666| }
667| }
668| *s2 = '\0';
669|}
670|
671|
672|/***********************************************************************
673| 6-7. <<< [StrX_cutRet] 文字列中のリターン文字とタブ文字を取り除く >>>
674|【引数】
675| ・char* 返り値; s の値
676|【補足】
677|・'\r'と'\n'と'\t' 文字を取り除きます。
678|・行が文の区切りのときに、複数行の1つの文を出力するために使います。
679|************************************************************************/
680|char* StrX_cutRet( char* s )
681|{
682| char* x = s;
683| char* y = s;
684|
685| while ( *x != '\0' ) {
686| if ( *x == '\r' || *x == '\n' || *x == '\t' );
687| else *y++ = *x;
688| x++;
689| }
690| *y = '\0';
691|
692| return s;
693|}
694|
695|
696|
697|/***********************************************************************
698| 6-8. <<< [StrX_cutLastOf] 末尾の文字が c なら取り除く(日本語非対応) >>>
699| 返り値 : 取り除いた文字列
700|************************************************************************/
701|#ifndef K_AND_R
702|char* StrX_cutLastOf( char* s, char c )
703|#else
704|char* StrX_cutLastOf( s, c )
705| char* s; char c;
706|#endif
707|{
708| int len = strlen( s );
709|
710| if ( s[ len - 1 ] == c ) {
711| s[ len - 1 ] = '\0';
712| }
713|
714| return s;
715|}
716|
717|
718|
719|/***********************************************************************
720| 6-9. <<< [StrX_cutLastOf2] 末尾の文字が c なら取り除く(日本語対応) >>>
721|************************************************************************/
722|char* StrX_cutLastOf2( char* s, char c )
723|{
724| char* p;
725| int f = 1;
726|
727| /* 最後の文字が日本語かどうか判定して結果を f へ */
728| for ( p = s; *p != '\0'; p++ ) {
729| if ( _ismbblead( *p ) ) { p++; f = 0; }
730| else f = 1;
731| }
732|
733| /* 末尾の文字が c なら取り除く */
734| if ( f ) {
735| p--;
736| if ( *p == c ) *p = '\0';
737| }
738|
739| return s;
740|}
741|
742|
743|
744|/***********************************************************************
745| 6-10. <<< [StrX_cutLastOf_2byteFirst] 末尾の文字が全角文字の最初のバイトなら取り除く >>>
746|************************************************************************/
747|char* StrX_cutLastOf_2byteFirst( char* s )
748|{
749| char* p = strchr( s, '\0' ) - 1;
750|
751| if ( _ismbblead( *p ) ) *p = '\0';
752|
753| return s;
754|}
755|
756|
757|/*-------------------------------------------------------------------------*/
758|/* ◆7. <<<< (StrX) char* 型の文字列(検索・参照) >>>> */
759|/*-------------------------------------------------------------------------*/
760|
761|
762|
763|/***********************************************************************
764| 7-1. <<< [StrX_getLast] 末尾の文字を得る >>>
765|************************************************************************/
766|#ifndef K_AND_R
767|char StrX_getLast( const char* s )
768|#else
769|char StrX_getLast( s )
770| const char* s;
771|#endif
772|{
773| return s[ strlen( s ) - 1 ];
774|}
775|
776|
777|
778|/***********************************************************************
779| 7-2. <<< [StrX_strchrs] 複数の文字を OR 検索する >>>
780|【引数】
781| ・char* s; 検索される文字列
782| ・char* key; 検索文字を並べた文字列
783| ・char* 返り値; 見つかった文字のアドレス(s の中のアドレス)
784|************************************************************************/
785|char* StrX_strchrs( const char* s, const char* key )
786|{
787| for ( ; *s != '\0'; s++ ) {
788| if ( strchr( key, *s ) != NULL )
789| return (char*)s;
790| }
791| return NULL;
792|}
793|
794|
795|
796|/***********************************************************************
797| 7-3. <<< [StrX_strchr2] 日本語中の半角文字を検索する >>>
798|【補足】
799| ・全角文字の2バイト目に誤ってヒットしないようになっています。
800|************************************************************************/
801|char* StrX_strchr2( const char* s, int k )
802|{
803| while ( *s != '\0' ) {
804| if ( _ismbblead( *s ) ) {
805| s += 2;
806| }
807| else {
808| if ( *s == k )
809| return (char*)s;
810| s++;
811| }
812| }
813| return NULL;
814|}
815|
816|
817|/***********************************************************************
818| 7-4. <<< [StrX_strchrs2] 日本語中の複数の半角文字を OR 検索する >>>
819|【補足】
820| ・全角文字の2バイト目に誤ってヒットしないようになっています。
821|************************************************************************/
822|char* StrX_strchrs2( const char* s, const char* key )
823|{
824| int i;
825|
826| for ( i = 0; s[i] != '\0'; i++ ) {
827| if ( _ismbblead( s[i] ) ) i++;
828| else {
829| if ( strchr( key, s[i] ) != NULL )
830| return (char*)s + i;
831| }
832| }
833| return NULL;
834|}
835|
836|
837|
838|/***********************************************************************
839| 7-5. <<< [StrX_strchrs_not] 複数の文字のどれでもない文字を検索する >>>
840|【引数】
841| ・char* s; 検索される文字列
842| ・char* key; not 検索文字を並べた文字列
843| ・char* 返り値; 見つかった文字のアドレス(s の中のアドレス)
844|************************************************************************/
845|char* StrX_strchrs_not( const char* s, const char* key )
846|{
847| for ( ; *s != '\0'; s++ ) {
848| if ( strchr( key, *s ) == NULL )
849| return (char*)s;
850| }
851| return NULL;
852|}
853|
854|
855|
856|/***********************************************************************
857| 7-6. <<< [StrX_RSearchC] 文字を逆順サーチ >>>
858|【補足】
859|・strchr() の検索を文字列の末尾から行ないます。
860|・標準ライブラリに strrchr があります。
861|************************************************************************/
862|#ifndef K_AND_R
863|char* StrX_RSearchC( const char* s, char key )
864|#else
865|char* StrX_RSearchC( s, key )
866| const char* s; char key;
867|#endif
868|{
869| const char* top = s;
870|
871| s = s + strlen( s );
872| while ( s >= top ) {
873| if ( *s == key )
874| return (char*)s;
875| s--;
876| }
877| return NULL;
878|}
879|
880|
881|
882|/***********************************************************************
883| 7-7. <<< [StrX_RSearchC2] 文字を逆順サーチ(日本語対応) >>>
884|************************************************************************/
885|char* StrX_RSearchC2( const char* s, int key )
886|{
887| const char* ss;
888| int f = 0;
889|
890| for (;;) {
891| ss = StrX_strchr2( s, key );
892| if ( ss == NULL ) return ( f ? (char*)s - 1 : NULL );
893| s = ss + 1;
894| f = 1;
895| }
896|}
897|
898|
899|
900|/***********************************************************************
901| 7-8. <<< [StrX_RSearch] 文字列を逆順サーチ >>>
902|【補足】
903|・strstr() の検索を文字列の末尾から行なう
904|************************************************************************/
905|#ifndef K_AND_R
906|char* StrX_RSearch( char* s, char* key )
907|#else
908|char* StrX_RSearch( s, key )
909| char* s; char* key;
910|#endif
911|{
912| char* top = s;
913| int len = strlen( key );
914|
915| s = s + strlen( s );
916| while ( s >= top ) {
917| if ( strncmp( s, key, len ) == 0 )
918| return s;
919| s--;
920| }
921| return NULL;
922|}
923|
924|
925|
926|/***********************************************************************
927| 7-9. <<< [StrX_stristr] 文字列を大文字小文字区別なく検索する >>>
928|************************************************************************/
929|char* StrX_stristr( const char* s, const char* key )
930|{
931| const char* pS;
932| const char* pKey;
933|
934| while ( *s != '\0' ) {
935| if ( toupper(*s) == toupper(*key) ) {
936| pS = s+1; pKey = key+1;
937| if ( *pKey == '\0' ) return (char*)s;
938| while ( toupper(*pS) == toupper(*pKey) ) {
939| pS++; pKey ++;
940| if ( *pKey == '\0' ) return (char*)s;
941| }
942| }
943| s++;
944| }
945| return NULL;
946|}
947|
948|
949|
950|/***********************************************************************
951| 7-10. <<< [StrX_stristr3] 文字列を大文字小文字区別なく検索する(漢字、連結) >>>
952|【引数】
953| ・char* s; 検索される文字列
954| ・char* key; 検索するキーワード
955| ・bool bCase; 大文字小文字を区別するかどうか
956| ・int* hitCount; (入出力)前回の検索で途中までヒットしていたバイト数(→補足)
957| ・char* 返り値; ヒットした位置(→補足)
958|【補足】
959|・連結(複数の文字列領域にまたがったキーワードもヒット)します。
960|・初めてこの関数を使うときは、*hitCount = 0 としてください。
961| s に前回の s の続きの文字列領域を指定した場合、
962| hitCount の変数に格納された値をそのまま使用してください。
963| ただし、*hitCount は、返り値が NULL だったときのみ設定されます。
964|・複数の文字列領域にまたがったキーワードがヒットしたときは、s よりも
965| 前のアドレスが返り値になるので注意してください。
966|【内部補足】
967|・前回の文字列領域の最後が日本語文字の1バイト目なら *hitCount == -1 です。
968|************************************************************************/
969|char* StrX_stristr3( const char* s, const char* key, bool bCase,
970| int* hitCount )
971|{
972| int hitCount2 = *hitCount;
973| const char* p;
974| int key_len = strlen( key );
975| char* s_overKey = strchr( s, '\0' ) - key_len + 1;
976| int (*ncmp)( const char*, const char*, size_t n );
977|
978| ncmp = ( bCase ? strncmp : strnicmp );
979|
980| /* 前の文字列領域とまたがったキーワードを検索する */
981| while ( hitCount2 > 0 ) {
982| if ( (*ncmp)( s, key + hitCount2, key_len - hitCount2 ) == 0 )
983| return (char*)s - hitCount2; /* Hit! */
984|
985| for ( p = key + 1, hitCount2 --;
986| hitCount2 > 0;
987| p++, hitCount2 -- ) {
988| if ( (*ncmp)( key, p, hitCount2 ) == 0 )
989| break;
990| if ( _ismbblead( *p ) ) { p++, hitCount2 --; }
991| }
992| }
993|
994| /* 文字列領域に完全に含まれるキーワードを検索する */
995| for ( p = s - hitCount2; p < s_overKey; p++ ) {
996| if ( (*ncmp)( p, key, key_len ) == 0 ) return (char*)p; /* hit! */
997| if ( _ismbblead( *p ) ) p++;
998| }
999|
1000| /* 次の文字列領域とまたがったキーワードがある可能性を残す */
1001| for ( hitCount2 = key_len - 1; hitCount2 > 0; hitCount2 --, p++ ) {
1002| if ( (*ncmp)( p, key, hitCount2 ) == 0 )
1003| break;
1004| if ( _ismbblead( *p ) ) { p++, hitCount2 --; }
1005| }
1006| *hitCount = hitCount2;
1007|
1008| return NULL;
1009|}
1010|
1011|
1012|/***********************************************************************
1013| 7-11. <<< [StrX_searchWord] ワードを検索する >>>
1014|【補足】
1015|・英文字、数字、アンダーラインが連続したものをワードとします。
1016|・大文字小文字を区別します。
1017|・日本語には対応していません。
1018|・ワードが見つからない場合、NULL を返します。
1019|【例】
1020|・s="abc defInfo def-info", k="def", 返り値="def-info" の d のアドレス
1021|************************************************************************/
1022|char* StrX_searchWord( const char* s, const char* k )
1023|{
1024| char* p;
1025| int len = strlen( k );
1026|
1027| for (;;) {
1028| p = strstr( s, k );
1029| if ( p == NULL )
1030| break;
1031| if ( ( s == p || StrX_isTerm(*(p-1)) ) && StrX_isTerm(*(p+len)) )
1032| break;
1033| s = p+1;
1034| }
1035| return p;
1036|}
1037|
1038|
1039|
1040|/***********************************************************************
1041| 7-12. <<< [StrX_getWordTop] 指定位置のワードの先頭のアドレスを返す >>>
1042|【引数】
1043| ・s : バッファ(文字列)全体の先頭へのアドレス
1044| ・p : ワードのどこかの位置
1045| ・term : ワード区切り文字
1046| 例: s="abc; def; g", p=s+6('e'), term=';' なら返り値=s+4(' ')
1047|************************************************************************/
1048|char* StrX_getWordTop( char* s, char* p, char term )
1049|{
1050| while ( p > s ) {
1051| if ( *p == term )
1052| return p+1;
1053| p--;
1054| }
1055| return s;
1056|}
1057|
1058|
1059|
1060|/***********************************************************************
1061| 7-13. <<< [StrX_getCmdParam] コマンドラインのパラメータを取得する >>>
1062|【引数】
1063| ・char* cmdline; パラメータ列の先頭(先頭の空白があってもよい)
1064| ・char* param; パラメータの格納先アドレス
1065| ・int param_size; param のメモリサイズ
1066| ・char* 返り値; 次のパラメータの先頭、無ければ NULL
1067|【補足】
1068|・ダブルクォーテーション("")で囲まれたものは1つのパラメータとします。
1069|【例】
1070|・以下の例では、文字列の境界を[ ]で表示しています。
1071|・cmdline=[file.exe 10 abc], param=[file.exe], 返り値=[10 abc]
1072|・cmdline=[ "10 abc"], param=[10 abc], 返り値=NULL
1073|・cmdline=[ ], param=[], 返り値=NULL
1074|************************************************************************/
1075|char* StrX_getCmdParam( const char* cmdline, char* param, int param_size )
1076|{
1077| const char* c = cmdline;
1078| char* p = param;
1079| char* p_over = param + param_size - 1;
1080|
1081| /* 先頭の空白をスキップする */
1082| while ( *c == ' ' ) p++;
1083| if ( *c == '\0' ) { param[0] = '\0'; return NULL; }
1084|
1085| /* "" で囲まれたパラメータのとき */
1086| if ( *c == '\"' ) {
1087| for ( c = c+1; *c != '\0' && *c != '\"' && p < p_over; p++, c++ ) {
1088| if ( _ismbblead(*p) )
1089| { *p = *c; p++; c++; *p = *c; }
1090| else
1091| *p = *c;
1092| }
1093| c++;
1094| }
1095|
1096| /* "" で囲まれていないパラメータのとき */
1097| else {
1098| for ( c = c+1; *c != '\0' && *c != ' ' && p < p_over; p++, c++ ) {
1099| if ( _ismbblead(*p) )
1100| { *p = *c; p++; c++; *p = *c; }
1101| else
1102| *p = *c;
1103| }
1104| }
1105|
1106| *p = '\0';
1107|
1108| /* 次のパラメータを探す */
1109| while ( *c == ' ' ) p++;
1110| if ( *c == '\0' ) return NULL;
1111| else return (char*)c;
1112|}
1113|
1114|
1115|/***********************************************************************
1116| 7-14. <<< [StrX_getCSV] CSV 形式の指定カラムの文字列を取得する >>>
1117|【引数】
1118| ・char* s; CSV 形式の行
1119| ・int iColumn; カラム番号(1〜)
1120| ・char* out; 文字列を格納するアドレス(s とは違う領域に)
1121| ・int out_size; out のメモリサイズ
1122| ・char* 返り値; out と同じ, iColumn が大きいすぎる場合は NULL
1123|【補足】
1124|・out_size は、s のメモリサイズと同じかそれ以上にしてください。
1125|・iColumn が大きすぎる場合、out には最後の項目が格納されます。
1126|・CSV 形式の行 s が "" の場合、iColumn == 1 でも NULL が返ります。
1127|************************************************************************/
1128|char* StrX_getCSV( const char* s, int iColumn, char* out, int out_size )
1129|{
1130| const char* p = s;
1131|
1132| ASSERT( (unsigned)out_size > strlen(s) );
1133| ASSERT( iColumn >= 1 );
1134|
1135| if ( s[0] == '\0' ) return NULL;
1136|
1137| while ( iColumn > 1 ) {
1138| p = StrX_meltCSV( out, p );
1139| if ( p == NULL ) return NULL;
1140| iColumn --;
1141| }
1142| StrX_meltCSV( out, p );
1143|
1144| return out;
1145|}
1146|
1147|
1148|
1149|/***********************************************************************
1150| 7-15. <<< [StrX_findInCSV] CSV 形式の中から一致する文字列を検索する >>>
1151|【引数】
1152| ・char* s; CSV 形式の行
1153| ・char* key; キー文字列
1154| ・bool bCase; 大文字小文字を区別するかどうか
1155| ・char* 返り値; 一致した文字列の項目番号(1〜)、見つからない=-1
1156|************************************************************************/
1157|int StrX_findInCSV( const char* s, const char* key, bool bCase )
1158|{
1159| enum { ss_size = 256 };
1160| int iCol;
1161| char ss[ss_size];
1162|
1163| ASSERT( strlen(key) < ss_size );
1164|
1165| if ( bCase ) {
1166| for ( iCol = 1; ; iCol++ ) {
1167| if ( StrX_getCSV( s, iCol, ss, ss_size ) == NULL ) return -1;
1168| if ( strcmp( ss, key ) == 0 ) return iCol;
1169| }
1170| }
1171| else {
1172| for ( iCol = 1; ; iCol++ ) {
1173| if ( StrX_getCSV( s, iCol, ss, ss_size ) == NULL ) return -1;
1174| if ( stricmp( ss, key ) == 0 ) return iCol;
1175| }
1176| }
1177|}
1178|
1179|
1180|/***********************************************************************
1181| 7-16. <<< [StrX_getCSVColumn] CSV 形式の指定位置のカラム番号を取得する >>>
1182|【引数】
1183| ・char* s; CSV 形式の行
1184| ・char* pos; カラム番号を調べる文字の位置
1185| ・char* 返り値; カラム番号(1〜)
1186|************************************************************************/
1187|int StrX_getCSVColumn( const char* s, const char* pos )
1188|{
1189| int iColumn = 0;
1190| const char* p = s;
1191| static char ss[256];
1192|
1193| while ( p != NULL && pos >= p ) {
1194| p = StrX_meltCSV( ss, p );
1195| iColumn ++;
1196| }
1197|
1198| return iColumn;
1199|}
1200|
1201|
1202|/***********************************************************************
1203| 7-17. <<< [StrX_getCSVNColumn] CSV 形式のカラム数を取得する >>>
1204|【引数】
1205| ・char* s; CSV 形式の行
1206| ・bool bCountSpace; 末尾の空白や空のカラムをカウントするかどうか
1207| ・char* 返り値; カラム数
1208|************************************************************************/
1209|int StrX_getCSVNColumn( const char* s, bool bCountSpace )
1210|{
1211| int iColumn = 0;
1212| const char* p;
1213| int nn = 0; /* 連続した空白カラムの数 */
1214| static char ss[256];
1215|
1216| p = s;
1217| while ( p != NULL ) {
1218| p = StrX_meltCSV( ss, p );
1219|
1220| if ( ! bCountSpace ) {
1221| StrX_trim( ss );
1222| if ( ss[0] == '\0' ) nn++; else nn=0;
1223| }
1224| iColumn ++;
1225| }
1226|
1227| return iColumn - nn;
1228|}
1229|
1230|
1231|/**************************************************************************
1232| 7-18. <<< [StrX_getCIdent] C 言語の識別子を検索して格納する >>>
1233|【引数】
1234| ・char* src; ワードを含む検索対象の文字列
1235| ・char* ident; 読み込んだ識別子を格納するアドレス
1236| ・size_t ident_sizeof; ident のメモリサイズ
1237| ・char* 返り値; ident の次の src 中の位置
1238|【補足】
1239|・C 言語の識別子が無かったら NULL が返ります。
1240|【例】
1241|・"123_abc-def" なら、ident=="_abc", 返り値==&"-def"
1242|**************************************************************************/
1243|char* StrX_getCIdent( const char* src, char* ident, int ident_sizeof )
1244|{
1245| char* ident_last = ident + ident_sizeof - 1;
1246|
1247| /* s を C言語の識別子の先頭にポイントする */
1248| while ( (! isalpha( *src ) && *src != '_') || _ismbblead( *src ) ) {
1249| if ( *src == '\0' ) return NULL;
1250| if ( _ismbblead( *src ) ) src++;
1251| src ++;
1252| }
1253|
1254| /* ident に識別子を格納する */
1255| while ( ident < ident_last ) {
1256| *ident = *src;
1257| ident ++; src ++;
1258| if ( ! isalpha( *src ) && ! isdigit( *src ) && *src != '_' )
1259| break;
1260| }
1261|
1262| /* ident の最後に '\0' 文字を付ける */
1263| *ident = '\0';
1264|
1265| return (char*)src;
1266|}
1267|
1268|
1269|
1270|/**************************************************************************
1271| 7-19. <<< [StrX_getCIdent2] 文字列中の C 言語識別子か漢字を検索して格納する >>>
1272|【引数】
1273| ・char* src; ワードを含む検索対象の文字列
1274| ・char* ident; 読み込んだ識別子を格納するアドレス
1275| ・size_t ident_sizeof; ident のメモリサイズ
1276| ・char* 返り値; src の中の拡張ワードの直後のアドレス
1277|【補足】
1278|・本関数が検索する「ワード」は、C 言語識別子か全角文字(1文字)です。
1279| C 言語識別子と全角文字が連続している場合、別のワードになります。
1280|・拡張ワードが無かったら NULL が返ります。
1281|【例】
1282|・"123_abc-def" なら、ident=="_abc", 返り値=="-def"
1283|・"X123_abc-def" なら、ident=="X123_abc", 返り値=="-def)"
1284|・"*(123_abc-def)" なら、ident=="def", 返り値==")"
1285|・" word next " なら、ident=="word", 返り値==" next"
1286|・"漢字kan2、ok" なら、ident=="漢", 返り値=="字kan2、ok"
1287|**************************************************************************/
1288|char* StrX_getCIdent2( const char* src, char* ident, int ident_sizeof )
1289|{
1290| char* ident_last = ident + ident_sizeof - 1;
1291|
1292| /* s をワードの先頭にポイントする */
1293| while ( ! isalpha( *src ) && *src != '_' && ! _ismbblead( *src ) ) {
1294| if ( *src == '\0' ) return NULL;
1295| src ++;
1296| }
1297|
1298| /* ident に C 言語識別子を格納する */
1299| if ( isalpha( *src ) || *src == '_' ) {
1300|
1301| while ( ident < ident_last ) {
1302| *ident = *src;
1303| ident ++; src ++;
1304| if ( ! isalpha( *src ) && ! isdigit( *src ) && *src != '_' )
1305| break;
1306| }
1307| *ident = '\0';
1308| }
1309|
1310| /* ident に漢字を格納する */
1311| else {
1312| if ( ident + 2 <= ident_last ) {
1313| *ident++ = *src++;
1314| *ident++ = *src++;
1315| *ident = '\0';
1316| }
1317| }
1318|
1319| return (char*)src;
1320|}
1321|
1322|
1323|
1324|/**************************************************************************
1325| 7-20. <<< [StrX_getToken] 文字列中のトークンか漢字を検索して格納する >>>
1326|【引数】
1327| ・char* src; ワードを含む検索対象の文字列
1328| ・char* token; 読み込んだ識別子を格納するアドレス
1329| ・size_t token_sizeof; token のメモリサイズ
1330| ・char* 返り値; src の中の拡張ワードの直後のアドレス
1331|【補足】
1332|・非トークンは、空白、タブ、改行、制御文字(0x01〜0x1F)です。
1333|・複数のトークンの取得は、StrX_getIdiom2 関数を使います。
1334|【例】
1335|・" word next " なら、token=="word", 返り値==" next"(トークン)
1336|・"123_abc-def" なら、token=="123", 返り値=="_abc-def"(数字)
1337|・" 0x123_abc-def" なら、token=="0x123", 返り値=="_abc-def"(16進数)
1338|・"\nX123_abc-def" なら、token=="X123_abc", 返り値=="-def)"(識別子)
1339|・"*(123_abc-def)" なら、token=="*", 返り値=="(123_abc-def)"(記号)
1340|・" 漢字kan2、ok" なら、token=="漢", 返り値=="字kan2、ok"(漢字)
1341|**************************************************************************/
1342|char* StrX_getToken( const char* src, char* token, int token_sizeof )
1343|{
1344| char* token_last = token + token_sizeof - 1;
1345|
1346| /* s をトークンの先頭にポイントする */
1347| while ( *src <= ' ' && *src > '\0' ) {
1348| src ++;
1349| }
1350| if ( *src == '\0' ) return NULL;
1351|
1352|
1353| /* token にトークンを格納する */
1354| if ( src[0] == '0' && src[1] == 'x' ) { /* 16進数 */
1355| if ( token + 2 <= token_last ) {
1356| token[0] = '0'; token[1] = 'x';
1357| src += 2;
1358| while ( token < token_last && isdigit( *src ) ) {
1359| *token = *src;
1360| token ++; src ++;
1361| }
1362| *token = '\0';
1363| }
1364| }
1365| else if ( isdigit( *src ) ) { /* 数値 */
1366| if ( token + 1 <= token_last ) {
1367| do {
1368| *token = *src;
1369| token ++; src ++;
1370| } while ( token < token_last && isdigit( *src ) );
1371| *token = '\0';
1372| }
1373| }
1374| else if ( _ismbblead( *src ) ) { /* 漢字 */
1375| if ( token + 2 <= token_last ) {
1376| *token++ = *src++;
1377| *token++ = *src++;
1378| *token = '\0';
1379| }
1380| }
1381| else if ( isalpha( *src ) || *src == '_' || *src == '~' ) { /* C言語識別子 */
1382| char* nami = (*src == '~') ? token : NULL;
1383|
1384| while ( token < token_last ) {
1385| *token = *src;
1386| token ++; src ++;
1387| if ( ! isalpha( *src ) && ! isdigit( *src ) && *src != '_' )
1388| break;
1389| }
1390| *token = '\0';
1391| if ( nami != NULL && *src != '(' && *src != '\0' )
1392| *(nami + 1) = '\0';
1393| }
1394| else { /* 記号 */
1395| if ( token + 1 <= token_last ) {
1396| *token = *src;
1397| token ++; src ++;
1398| *token = '\0';
1399| }
1400| }
1401|
1402| return (char*)src;
1403|}
1404|
1405|
1406|
1407|/***********************************************************************
1408| 7-21. <<< [StrX_getCSSValueOfInt] CSSのパラメータの値を整数型で取得する >>>
1409|【引数】
1410| ・char* css; CSSのパラメータ文の列
1411| ・char* attr_name; 属性の名前
1412| ・int* pValue; 属性の値を格納するアドレス
1413| ・bool 返り値; 指定の名前の属性があったかどうか
1414|【補足】
1415|・CSS は、Cascading Style Sheet の略です。
1416|・CSS の例:"fill:rgb(192,192,255);stroke:rgb(0,0,128);stroke-width:1"
1417|・CSS は、属性名と値の間に':', 文と文の間に';' を記述します。
1418|・指定の名前の属性がなかったら *pValue の値は変わりません。
1419|************************************************************************/
1420|bool StrX_getCSSValueOfInt( const char* css, const char* attr_name,
1421| int* pValue )
1422|{
1423| bool ret;
1424| char str[16];
1425|
1426| ret = StrX_getCSSValueOfStr( css, attr_name, str, sizeof(str) );
1427| if ( ret ) *pValue = atoi( str );
1428|
1429| return ret;
1430|}
1431|
1432|
1433|
1434|
1435|/***********************************************************************
1436| 7-22. <<< [StrX_getCSSValueOfStr] CSSのパラメータの値を文字列で取得する >>>
1437|【引数】
1438| ・char* css; CSSのパラメータ文の列
1439| ・char* attr_name; 属性の名前
1440| ・char* str; 属性の値を格納するアドレス
1441| ・int str_size; str のサイズ(バイト)
1442| ・bool 返り値; 指定の名前の属性があったかどうか
1443|【補足】
1444|・StrX_getCSSValueOfInt の文字列版です。
1445|************************************************************************/
1446|bool StrX_getCSSValueOfStr( const char* css, const char* attr_name,
1447| char* str, int str_size )
1448|{
1449| char* p = (char*)css;
1450| char* p2;
1451| int attr_name_len = strlen( attr_name );
1452|
1453| for (;;) {
1454| while ( isspace( *p ) ) p++;
1455| if ( strnicmp( p, attr_name, attr_name_len ) != 0 ) goto next_param;
1456|
1457| p += attr_name_len;
1458| while ( isspace( *p ) ) p++;
1459| if ( *p != ':' ) goto next_param;
1460|
1461| p++;
1462| while ( isspace( *p ) ) p++;
1463| p2 = p;
1464| while ( *p2 != ';' && *p2 != '\0' ) p2++;
1465| do {
1466| p2--;
1467| } while ( isspace( *p2 ) );
1468|
1469| p2 ++;
1470| if ( p2 - p >= str_size ) /* p2 - p > str_size - 1 */
1471| p2 = p + str_size - 1;
1472| strncpy( str, p, p2 - p );
1473| str[ p2 - p ] = '\0';
1474| return true;
1475|
1476| next_param:
1477| while ( *p != ';' ) {
1478| if ( *p == '\0' ) return false;
1479| p++;
1480| }
1481| p++;
1482| }
1483|}
1484|
1485|
1486|/***********************************************************************
1487| 7-23. <<< [StrX_getCSSValueOfColor] CSSのパラメータの値を色で取得する >>>
1488|【引数】
1489| ・char* css; CSSのパラメータ文の列
1490| ・char* attr_name; 属性の名前
1491| ・Color_WinRGB* pColor; 属性の値を格納するアドレス
1492| ・bool 返り値; 指定の名前の属性があったかどうか
1493|【補足】
1494|・StrX_getCSSValueOfInt の色指定版です。
1495|・色は、次のフォーマットで指定します。"rgb(R,G,B)", "rgb(192,192,255)"
1496|************************************************************************/
1497|#ifdef USES_COLOR
1498|bool StrX_getCSSValueOfColor( const char* css, const char* attr_name,
1499| Color_WinRGB* pColor )
1500|{
1501| bool ret;
1502| char str[32];
1503|
1504| ret = StrX_getCSSValueOfStr( css, attr_name, str, sizeof(str) );
1505| if ( ret ) {
1506| *pColor = StrX_getColorValue( str );
1507| }
1508|
1509| return ret;
1510|}
1511|#endif
1512|
1513|/***********************************************************************
1514| 7-24. <<< [StrX_getSVGPoints] SVG の polygon の points 属性を解析する >>>
1515|【引数】
1516| ・char* points; SVG の polygon の points 属性
1517| ・int* xs, ys; (出力)座標の配列
1518| ・int n; xs, ys の最大可能要素数
1519| ・bool 返り値; 頂点数
1520|【補足】
1521|・points の例:"10,10 20,20 30,30" ... 3頂点
1522|・points が n より多い頂点数のとき、n 個の頂点まで xs, ys に格納され、
1523| 返り値は、points に格納されている頂点数になります。
1524|************************************************************************/
1525|int StrX_getSVGPoints( const char* points, int* xs, int* ys, int n )
1526|{
1527| const char* p = points;
1528| int np = 0;
1529|
1530| while ( isdigit( *p ) ) {
1531| if ( np < n ) *xs = atoi( p );
1532| p = strchr( p, ',' ); if ( p == NULL ) break;
1533| p = StrX_strchrs_not( p, " \t\r\n" ); if ( p == NULL ) break;
1534| if ( np < n ) *ys = atoi( p+1 );
1535| p = StrX_strchrs( p, " \t\r\n" );
1536| xs++; ys++; np++;
1537| if ( p == NULL ) break;
1538| p = StrX_strchrs_not( p, " \t\r\n" );
1539| if ( p == NULL ) break;
1540| }
1541|
1542| return np;
1543|}
1544|
1545|/**************************************************************************
1546| 7-25. <<< [StrX_getIdiom2] 文字列中のイディオムを検索して指定ワード数まで格納する >>>
1547|【引数】
1548| ・char* src; イディオムを含む検索対象の文字列
1549| ・int mWord; 最大のワード数
1550| ・int* nWord; (出力)格納したワード数
1551| ・char* idiom; イディオムを格納するアドレス
1552| ・int idiom_size; idiom のメモリサイズ
1553| ・int 返り値; src 中のイディオムの直後のアドレス
1554|【補足】
1555|・ここで言う「イディオム」は、英熟語だけでなく、漢字(2バイト文字)文字列も
1556| 含みます。イディオムを構成するワードについては、StrX_getToken
1557| 関数を参照してください。
1558|・半角空白文字は、イディオムの区切りにはなりません。
1559|・半角文字と全角文字が混ざったものも1つのイディオムになります。
1560|**************************************************************************/
1561|char* StrX_getIdiom2( const char* src, int mWord, int* pnWord,
1562| char* idiom, int idiom_size )
1563|{
1564| int n;
1565| int nWord = 0;
1566|
1567| while ( idiom_size > 0 && nWord < mWord ) {
1568|
1569| /* 1ワード格納する */
1570| src = StrX_getToken( src, idiom, idiom_size );
1571| if ( src == NULL ) {
1572| break;
1573| }
1574| nWord ++;
1575| n = strlen( idiom ); idiom += n; idiom_size -= n;
1576|
1577| /* 次のイディオムへ */
1578| if ( *src == ' ' ) {
1579| if ( idiom_size == 0 ) break;
1580| src ++;
1581| *idiom = ' '; idiom ++;
1582| idiom_size --;
1583| }
1584| else if ( *src >= '\0' && *src < ' ' )
1585| break;
1586| }
1587|
1588| /* ワードが取得できなかったとき、末尾に加えた */
1589| /* ワードの区切り空白文字をカットする */
1590| if ( nWord >= 1 ) {
1591| do {
1592| idiom --;
1593| } while ( *idiom == ' ' );
1594| *( idiom + 1 ) = '\0';
1595| }
1596| *pnWord = nWord;
1597|
1598| return (char*)src;
1599|}
1600|
1601|
1602|
1603|/**************************************************************************
1604| 7-26. <<< [StrX_getCppIdiom] 文字列中のイディオムとC++言語トークンを検索して格納する >>>
1605|【引数】
1606| ・char* src; イディオムを含む検索対象の文字列
1607| ・int mWord; 最大のワード数
1608| ・int* nWord; (出力)格納したワード数
1609| ・char* idiom; イディオムを格納するアドレス
1610| ・int idiom_size; idiom のメモリサイズ
1611| ・int 返り値; src 中のイディオムの直後のアドレス
1612|【補足】
1613|・StrX_getIdiom2 を C++ のテンプレートに対応したバージョンです。
1614|・テンプレート関数名 Class<type,type>::method を Class::method で idiom に
1615| 格納します。このとき、4ワードになります。
1616|**************************************************************************/
1617|char* StrX_getCppIdiom( const char* src, int mWord, int* pnWord,
1618| char* idiom, int idiom_size )
1619|{
1620| char className[256];
1621| char ident[256];
1622| char* next;
1623|
1624| /* テンプレート関数名の形式ならば、加工して idiom に格納する(→補足) */
1625| StrX_getCIdent( src, className, sizeof(className) );
1626| next = StrX_getToken( src, idiom, idiom_size );
1627| if ( strcmp( idiom, className ) == 0 ) {
1628| if ( next == NULL || *next != '<' ) goto endif1; /* テンプレートのパラメータの始まり */
1629|
1630| do {
1631|
1632| StrX_getCIdent( next + 1, ident, sizeof(ident) );
1633| next = StrX_getToken( next + 1, idiom, idiom_size );
1634| if ( strcmp( idiom, ident ) != 0 ) goto endif1;
1635|
1636| } while ( *next == ',' );
1637| if ( strncmp( next, ">::", 3 ) != 0 ) goto endif1;
1638|
1639| StrX_getCIdent( next + 3, ident, sizeof(ident) );
1640| next = StrX_getToken( next + 3, idiom, idiom_size );
1641| if ( strcmp( idiom, ident ) != 0 ) goto endif1;
1642|
1643| sprintf( idiom, "%s::%s", className, ident );
1644| *pnWord = 4;
1645| return next;
1646| }
1647| endif1:
1648|
1649|
1650| /* テンプレート関数名ではないとき */
1651| return StrX_getIdiom2( src, mWord, pnWord, idiom, idiom_size );
1652|}
1653|
1654|
1655|
1656|/**************************************************************************
1657| 7-27. <<< [StrX_searchInArr] 文字列配列の中から検索する >>>
1658|【引数】
1659| ・char* s; 検索する文字列
1660| ・char** arr; 文字列配列の先頭アドレス(char* [] のアドレス)
1661| ・int arr_n; 配列 arr の要素数
1662| ・char** 返り値; 見つかった文字列へのアドレス(arr 配列内), NULL=ない
1663|***************************************************************************/
1664|#if 0
1665|char** StrX_searchInArr( const char* s, char** arr, int arr_n )
1666|{
1667| while ( arr_n > 0 ) {
1668| if ( strcmp( s, *arr ) == 0 ) return arr;
1669| arr ++;
1670| arr_n --;
1671| }
1672| return NULL;
1673|}
1674|#endif
1675|
1676|
1677|/**************************************************************************
1678| 7-28. <<< [StrX_searchInArr2] 文字列配列の中から検索する >>>
1679|【引数】
1680| ・char* s; 検索する文字列
1681| ・char** arr; 文字列配列の先頭アドレス(char* [] のアドレス)
1682| ・int arr_size; ポインタ配列 arr のメモリサイズ
1683| ・char** 返り値; 見つかった文字列へのアドレス(arr 配列内), NULL=ない
1684|***************************************************************************/
1685|char** StrX_searchInArr2( const char* s, const char** arr, int arr_size )
1686|{
1687| const char** arr_over = (const char**)( (const char*)arr + arr_size );
1688| ASSERT( arr_size > 0 );
1689|
1690| do {
1691| if ( strcmp( s, *arr ) == 0 ) return (char**)arr;
1692| arr ++;
1693| } while ( arr < arr_over );
1694|
1695| return NULL;
1696|}
1697|
1698|
1699|/*-------------------------------------------------------------------------*/
1700|/* ◆8. <<<< (StrX) char* 型の文字列(置換・文字コード変換) >>>> */
1701|/*-------------------------------------------------------------------------*/
1702|
1703|
1704|
1705|/***********************************************************************
1706| 8-1. <<< [StrX_rep1] 1文字同士を置換する >>>
1707|【引数】
1708| ・char* s; 置換される文字列
1709| ・char f; 置換前の文字
1710| ・char t; 置換後の文字
1711| ・char* 返り値; s と同じ
1712|【補足】
1713|・2バイト文字の場合、StrX_rep1b を用いてください。
1714|************************************************************************/
1715|char* StrX_rep1( char* s, char f, char t )
1716|{
1717| char* ret = s;
1718|
1719| while ( *s != '\0' ) {
1720| if ( *s == f ) *s = t;
1721| s++;
1722| }
1723|
1724| return ret;
1725|}
1726|
1727|
1728|
1729|/***********************************************************************
1730| 8-2. <<< [StrX_rep1b] 1文字同士を置換する(2バイト文字対応)>>>
1731|【引数】
1732| ・char* s; 置換される文字列
1733| ・char f; 置換前の文字
1734| ・char t; 置換後の文字
1735| ・char* 返り値; s と同じ
1736|************************************************************************/
1737|char* StrX_rep1b( char* s, char f, char t )
1738|{
1739| char* ret = s;
1740|
1741| while ( *s != '\0' ) {
1742| if ( _ismbblead( *s ) ) s++;
1743| else if ( *s == f ) *s = t;
1744| s++;
1745| }
1746|
1747| return ret;
1748|}
1749|
1750|
1751|
1752|/***********************************************************************
1753| 8-3. <<< [StrX_rep] 文字列同士を置換する >>>
1754|【引数】
1755| ・char* s; 内容を置換する文字列
1756| ・int s_sizeof; s のメモリサイズ
1757| ・char* f; 置換前の文字列
1758| ・char* t; 置換後の文字列
1759| ・char* 返り値; s と同じ
1760|************************************************************************/
1761|char* StrX_rep( char* s, int s_sizeof, const char* f, const char* t )
1762|{
1763| int f_len = strlen( f );
1764| int t_len = strlen( t );
1765| int diff = t_len - f_len; /* 文字列長の差(増えるなら+)*/
1766| int left = s_sizeof - strlen(s) - 1; /* 残りメモリ・サイズ */
1767| char* p = s;
1768| char* p2;
1769| int move_len;
1770|
1771| while ( *p != '\0' ) {
1772| if ( strncmp( p, f, f_len ) == 0 ) { /* 置換する文字列を見つけたら */
1773|
1774| /* 置換する文字より後の文字をスクロールする */
1775| p2 = p + f_len;
1776| move_len = strlen(p2) + 1;
1777| if ( left < diff ) { /* s のメモリ領域を超える場合 */
1778| s[s_sizeof - 1] = '\0';
1779| move_len += left - diff - 1;
1780| }
1781| if ( move_len > 0 )
1782| memmove( p2 + diff, p2, move_len );
1783| left -= diff;
1784|
1785| /* 文字列を置換する */
1786| if ( (p - s) + t_len < s_sizeof ) {
1787| memcpy( p, t, t_len );
1788| p += t_len;
1789| }
1790| else
1791| break;
1792| }
1793| else
1794| p++;
1795| }
1796| return s;
1797|}
1798|
1799|
1800|
1801|/***********************************************************************
1802| 8-4. <<< [StrX_repi] 数値を指定して置換する >>>
1803|【引数】
1804| ・char* s; 置換される文字列
1805| ・int s_sizeof; s のメモリサイズ
1806| ・char* f; 置換前の文字列
1807| ・int t; 置換後の文字列にする数値
1808| ・char* 返り値; s と同じ
1809|************************************************************************/
1810|char* StrX_repi( char* s, int s_sizeof, const char* f, int t )
1811|{
1812| static char num[20];
1813|
1814| sprintf( num, "%d", t );
1815| return StrX_rep( s, s_sizeof, f, num );
1816|}
1817|
1818|
1819|
1820|/***********************************************************************
1821| 8-5. <<< [StrX_repEx] 文字列を複数項目の文字列に置換する >>>
1822|【引数】
1823| ・char* s; 内容を置換する文字列, 区切り文字は CSV形式
1824| ・int s_sizeof; s のメモリサイズ
1825| ・char* f; 置換前の文字列(区切り文字の指定位置に %i を指定)
1826| ・char* t; 置換後の文字列の集合(CSV 形式)
1827| ・StrX_ConvFunc term_conv_func; 区切り文字変換関数(→補足、NULL可)
1828| ・void* obj; term_conv_func の第1引数
1829| ・char* work; ワーク領域
1830| ・int work_size; work のメモリサイズ(→補足)
1831| ・char* 返り値; s と同じ, NULL=s 中の f がおかしい
1832|【補足】
1833|・term_conv_func は、スキャンした区切り文字を変換する関数です。
1834| たとえば、区切り文字に変数名を指定することができるようになります。
1835| NULL にすると、変換関数を呼び出しません(変換しません)。
1836| term_conv_func の関数の型は次のとおりです。
1837| void term_conv_func( char* term, int term_size );
1838|・work_size は、(f の文字数+1) * 2 + (置換後の CSV 文字列の項目の
1839| うち、最大の文字数 + 1)が必要です。不足したときはエラーになります。
1840|【例】
1841| StrX_repEx( "zzzz$(\"; \")zzzz", 256, "$(%i)", "abc,123" );
1842| 置換後... "zzzzabc; 123zzzz"
1843|************************************************************************/
1844|char* StrX_repEx( char* s, int s_sizeof, const char* f, const char* t,
1845| StrX_ConvFunc term_conv_func, void* obj, char* work, int work_size )
1846|{
1847| char* key1; /* f の %1 以前の文字列 */
1848| int key_size;
1849| int key1_len;
1850| char* key2; /* f の %1 以後の文字列 */
1851| int key2_len;
1852| char* t_elem; /* 置換後の1項目の文字列 */
1853| int t_elem_size;
1854| char* term; /* 区切り文字 */
1855| int term_size;
1856|
1857| ASSERT( ! ( f[0] == '%' && f[1] == 'i' ) );
1858|
1859| key1 = work;
1860| key_size = strlen( f ) + 1;
1861| work += key_size;
1862| key2 = work; work += key_size;
1863| term = work; work += key_size;
1864| term_size = key_size;
1865| t_elem = work;
1866| t_elem_size = work_size - 3 * key_size;
1867|
1868| {
1869| char* kp; /* key's pointer */
1870| const char* fp1; /* f's pointer 1 */
1871| const char* fp2; /* f's pointer 2 */
1872|
1873| /* f の %1 より前の文字列を検索文字列 key1 とする */
1874| kp = key1;
1875| fp1 = f;
1876| for (;;) {
1877| fp2 = StrX_strchr2( fp1, '%' );
1878| ASSERT( fp2 != NULL );
1879| strncpy( kp, fp1, fp2 - fp1 );
1880|
1881| kp += fp2 - fp1;
1882| if ( *(fp2 + 1) != '%' ) break;
1883| *kp = '%';
1884| kp++;
1885| fp1 = fp2 + 2;
1886| }
1887| ASSERT( *(fp2 + 1) == 'i' );
1888| *kp = '\0';
1889| key1_len = kp - key1;
1890|
1891| /* f の %1 より後の文字列を検索文字列 key2 とする */
1892| kp = key2;
1893| fp1 = fp2 + 2;
1894| while ( *fp1 != '\0' ) {
1895| if ( *fp1 == '%' && *(fp1 + 1) == '%' ) fp1++;
1896| *kp = *fp1;
1897| kp++; fp1++;
1898| }
1899| *kp = '\0';
1900| key2_len = kp - key2;
1901| }
1902|
1903| /* 置換を行う */
1904| {
1905| int left = s_sizeof - strlen(s) - 1; /* 残りメモリ・サイズ */
1906| int term_len;
1907| char* sp; /* s's pointer */
1908| char* sp2;
1909| int zeroCh;
1910| int diff;
1911| int move_len;
1912| int i;
1913|
1914| sp = s;
1915| while ( *sp != '\0' ) {
1916| if ( strncmp( sp, key1, key1_len ) == 0 ) { /* 検索文字列を見つけたら */
1917|
1918| /* 区切り文字を term に代入する */
1919| sp2 = strstr( sp, key2 ); if ( sp2 == NULL ) return NULL;
1920| term_len = (sp2 - sp) - key1_len;
1921| if ( term_len >= term_size ) term_len = term_size - 1;
1922| strncpy( term, sp + key1_len, term_len );
1923| *( term + term_len ) = '\0';
1924| StrX_meltCSV( term, term );
1925| if ( term_conv_func != NULL )
1926| term_conv_func( obj, term, term_size );
1927| term_len = strlen( term );
1928|
1929| /* 置換後の文字列の長さを diff に代入する */
1930| diff = 0;
1931| for ( i = 1; ; i++ ) {
1932| if ( StrX_getCSV( t, i, t_elem, t_elem_size ) == NULL )
1933| break;
1934| if ( i >= 2 ) diff += term_len;
1935| diff += strlen( t_elem );
1936| }
1937|
1938| /* 置換する文字より後の文字をスクロールする */
1939| sp2 += key2_len;
1940| diff -= sp2 - sp;
1941| move_len = strlen(sp2) + 1;
1942| if ( left < diff ) { /* s のメモリ領域を超える場合 */
1943| s[s_sizeof - 1] = '\0';
1944| move_len += left - diff - 1;
1945| }
1946| memmove( sp2 + diff, sp2, move_len );
1947| left -= diff;
1948| sp2 += diff;
1949| zeroCh = *sp2;
1950|
1951| /* 文字列を置換する */
1952| for ( i = 1; ; i++ ) {
1953| if ( StrX_getCSV( t, i, t_elem, t_elem_size ) == NULL )
1954| break;
1955| if ( i >= 2 )
1956| { strncpy( sp, term, term_len ); sp += term_len; }
1957| strcpy( sp, t_elem );
1958| sp = strchr( sp, '\0' );
1959| }
1960| *sp = zeroCh;
1961| }
1962| else
1963| sp++;
1964| }
1965| }
1966| return s;
1967|}
1968|
1969|
1970|
1971|/*********************************************************************
1972| 8-6. <<< [StrX_sjis2jis] JIS外字コードへの変換 >>>
1973| 作成日 1995.12.28
1974| 関数名 sjistojis
1975| 機能 拡張シフトJISコード→JIS外字コードへの変換
1976| 引数 int code シフトJISコード
1977| 返り値 JISコード
1978| ※半角コード、記号コードは同じコードを返す
1979|*********************************************************************/
1980|unsigned short StrX_sjis2jis( unsigned short code )
1981|{
1982| register unsigned char ah, al;
1983| register unsigned short ax;
1984| ah = (unsigned char)(code >> 8);
1985| al = (unsigned char)(code & 0xff);
1986| ah = ah +ah;
1987| al -= 0x1f;
1988| if( !(al & 0x80) ) {
1989| if( al <= 0x5f && al >= 0x21 ) {
1990| al++;
1991| }
1992| al += 0xde;
1993| }
1994| ax = ( ah << 8 ) + al;
1995| ax = ax + 0x1fa1;
1996| ax = ax & 0x7f7f;
1997| return (ax);
1998|}
1999|
2000|
2001|
2002|/************************************************************************
2003| 8-7. <<< [StrX_getCodeT] 漢字コードの種類を返す >>>
2004|【引数】
2005| ・const unsigned char* s; 漢字コードの種類を判定する文字列の先頭アドレス
2006| ・int 返り値; 漢字コードの種類(StrX_CodeT型)
2007|【機能】
2008|・文字列 s の漢字コードの種類を返します。
2009|【補足】
2010|・返り値は、StrX_Ascii, StrX_Jis, StrX_ShiftJis, StrX_Euc のうちどれかが
2011| 返ります。
2012|・作成日:97.12.27
2013|*************************************************************************/
2014|int StrX_getCodeT( const unsigned char* s )
2015|{
2016| while ( *s != '\0' ) {
2017|
2018| if ( *s == StrX_ESC ) {
2019| if ( *(s+1) == '$' &&
2020| ( *(s+2)=='@' || *(s+2)=='B' ) )
2021| return StrX_Jis;
2022|
2023| if ( *(s+1) == '(' && *(s+2)=='I' )
2024| return StrX_Euc;
2025| }
2026| else if ( *s == 0x8E ) {
2027| if ( 0x40 <= *(s+1) && *(s+1) <= 0xEC && *(s+1) != 0x7F )
2028| return StrX_ShiftJis;
2029| else
2030| return StrX_Euc;
2031| }
2032| else if ( 0x80 <= *s && *s <= 0x9F )
2033| return StrX_ShiftJis;
2034|
2035| else if ( 0xA0 <= *s )
2036| return StrX_Euc;
2037|
2038| s++;
2039| }
2040| return StrX_Ascii;
2041|}
2042|
2043|
2044|
2045|/************************************************************************
2046| 8-8. <<< [StrX_toSJIS] 任意の漢字コードを shift JIS に変換する >>>
2047|【引数】
2048| ・char* out; shift JIS の文字列を格納するアドレス
2049| ・const char* in; 任意の漢字コードの文字列
2050| ・char* 返り値; out と同じ
2051|【補足】
2052|・out の領域は、in と同じかそれ以上のサイズにします。
2053|*************************************************************************/
2054|char* StrX_toSJIS( char* out, const char* in )
2055|{
2056| bool bSISO = false, bKanji = false;
2057|
2058| switch ( StrX_getCodeT( (const unsigned char*)in ) ) {
2059| case StrX_Ascii:
2060| case StrX_ShiftJis:
2061| strcpy( out, in );
2062| break;
2063| case StrX_Jis:
2064| StrX_jis2sjis( (unsigned char*)out, (const unsigned char*)in,
2065| &bSISO, &bKanji );
2066| break;
2067| case StrX_Euc:
2068| StrX_euc2sjis( (unsigned char*)out, (const unsigned char*)in,
2069| &bSISO );
2070| break;
2071| }
2072| return out;
2073|}
2074|
2075|
2076|
2077|/************************************************************************
2078| 8-9. <<< [StrX_jis2sjis] JIS 漢字コードを shift JIS に変換する >>>
2079|【引数】
2080| ・unsigned char* out; shift JIS 漢字コードの文字列を格納する先頭アドレス
2081| ・unsigned char* in; JIS 漢字コードの文字列
2082| ・bool* bSISO; SI/SO 状態(入出力), SI から SO の間なら true
2083| ・bool* bKanji; 漢字 IN/OUT 状態(入出力), 漢字なら true
2084| ・int 返り値; in の未処理バイト数
2085|【機能】
2086|・JIS コードの文字列 in を shift JIS コードに変換した文字列を out に
2087| 格納します。
2088|【補足】
2089|・out の領域は、in と同じかそれ以上のサイズにします。
2090|・返り値は、in の末尾に、漢字 IN/OUT コードの一部や、2バイトコードの
2091| 一部があるときに、0 より大きい値が返ります。
2092|・bSISO, bKanji は、どちらも false から始めます。
2093|・作成日:97.12.27
2094|*************************************************************************/
2095|int StrX_jis2sjis( unsigned char* out, const unsigned char* in,
2096| bool* bSISO, bool* bKanji )
2097|{
2098| unsigned char in0, in1, in2;
2099| const unsigned char* prev_in;
2100|
2101| /* EUC 文字列の上を in が走査しながら変換する */
2102| while ( *in != '\0' ) {
2103|
2104| /* SI/SO, 漢字 IN/OUT コードを続けて処理する */
2105| do {
2106| prev_in = in;
2107|
2108| /* in のシフトビットを取り除いたものを in0〜in2 へ取得する */
2109| in0 = in[0] & 0x7F; in1 = in[1] & 0x7F; in2 = in[2] & 0x7F;
2110|
2111| switch ( in0 ) {
2112|
2113| /* SI/SO コードを処理する */
2114| case StrX_SI: *bSISO = true; *bKanji = false; in++; break;
2115| case StrX_SO: *bSISO = false; *bKanji = false; in++; break;
2116|
2117| /* 漢字 IN/OUT コードを処理する */
2118| case StrX_ESC:
2119| if ( in1 == '$' ) {
2120| if ( in2=='@' || in2=='B' )
2121| { *bSISO = false; *bKanji = true; in+=3; }
2122| else if ( in[2] == '\0' )
2123| { *out = '\0'; return 2; }
2124| }
2125| else if ( in1 == '(' ) {
2126| if ( in2 == 'H' || in2 == 'B' || in2 == 'J' )
2127| { *bSISO = false; *bKanji = false; in+=3; }
2128| else if ( in2 == 'I' )
2129| { *bSISO = true; *bKanji = false; in+=3; }
2130| else if ( in[2] == '\0' )
2131| { *out = '\0'; return 2; }
2132| }
2133| else if ( in[1] == '\0' )
2134| { *out = '\0'; return 1; }
2135|
2136| break;
2137| }
2138| } while ( in != prev_in );
2139|
2140| /* 1バイト出力 */
2141| if ( ! *bKanji ) {
2142| if ( *bSISO && ( in0 > 0x20 && in0 < 0x60 ) )
2143| *out = in0 | 0x80;
2144| else *out = in0;
2145| in ++; out ++;
2146| }
2147| else if ( in0 < 0x21 || in0 > 0x7e )
2148| { *out = in0; in++; out++; }
2149|
2150| /* 2バイト出力 */
2151| else {
2152| unsigned char preCode, postCode;
2153| unsigned int code;
2154|
2155| if ( in[1] == '\0' )
2156| { *out = '\0'; return 1; }
2157|
2158| code = ( (in0 - 0x21)* 0x5E ) + in1 - 0x21;
2159| preCode = code / 0xBC + 0x81; if ( preCode > 0x9F ) preCode += 0x40;
2160| postCode = code % 0xBC + 0x40; if ( postCode > 0x7E ) postCode ++;
2161|
2162| *out = preCode; out++; *out = postCode; out++;
2163| in +=2;
2164| }
2165| }
2166|
2167| *out = '\0';
2168| return 0;
2169|}
2170|
2171|
2172|
2173|/***************************************************************************
2174| 8-10. <<< [StrX_euc2sjis] EUC 漢字コードを shift JIS 変換する >>>
2175|【引数】
2176| ・unsigned char* out; shift JIS 漢字コードの文字列を格納する先頭アドレス
2177| ・unsigned char* in; EUC 漢字コードの文字列
2178| ・bool* bSISO; SI/SO 状態(入出力), SI から SO の間なら true
2179| ・int 返り値; in の未処理バイト数
2180|【機能】
2181|・EUC コードの文字列 in を shift JIS コードに変換した文字列を out に
2182| 格納します。
2183|【補足】
2184|・out の領域は、in と同じかそれ以上のサイズにします。
2185|・返り値は、in の末尾に、漢字 IN/OUT コードの一部や、2バイトコードの
2186| 一部や 0x8E コードがあるときに、0 より大きい値が返ります。
2187|・bSISO は、false から始めます。
2188|・作成日:97.12.27
2189|***************************************************************************/
2190|int StrX_euc2sjis( unsigned char* out, const unsigned char* in,
2191| bool* bSISO )
2192|{
2193| unsigned char in0, in1, in2;
2194| const unsigned char* prev_in;
2195|
2196| /* EUC 文字列の上を in が走査しながら変換する */
2197| while ( *in != '\0' ) {
2198|
2199| /* SI/SO, 漢字 IN/OUT コードを続けて処理する */
2200| do {
2201| prev_in = in;
2202| in0 = in[0]; in1 = in[1]; in2 = in[2];
2203|
2204| switch ( in0 ) {
2205|
2206| /* SI/SO コードを処理する */
2207| case StrX_SI: *bSISO = true; in++; break;
2208| case StrX_SO: *bSISO = false; in++; break;
2209|
2210| /* 漢字 IN/OUT コードを処理する */
2211| case StrX_ESC:
2212| if ( in1 == '(' ) { /* '(' = 0x28 */
2213| if ( in2 == 'I' ) { *bSISO = true; in +=3; }
2214| else if ( in2 == 'J' ) { *bSISO = false; in +=3; }
2215| else if ( in2 == '\0' )
2216| { *out = '\0'; return 2; }
2217| }
2218| else if ( in1 == '\0' )
2219| { *out = '\0'; return 1; }
2220| break;
2221| }
2222| } while ( in != prev_in );
2223|
2224| /* 0x8E コードの処理 */
2225| if ( in0 == 0x8E && (in1 > 0xA0 && in1 < 0xE0) )
2226| in++;
2227| else if ( in0 == 0x8E && in1 == '\0' )
2228| { *out = '\0'; return 1; }
2229|
2230| /* 1バイト出力 */
2231| else if ( *bSISO && in0 < 0x80 ) {
2232| if ( in0 > 0x20 && in0 < 0x60 )
2233| { *out = in0 | 0x80; out++; in++; }
2234| else
2235| { *out = in0; out++; in++; }
2236| }
2237| else if ( in0 < 0xA1 || in0 > 0xFE )
2238| { *out = in0 & 0x7F; out++; in++; }
2239|
2240| /* 2バイト出力 */
2241| else {
2242| unsigned char preCode, postCode;
2243| unsigned int code;
2244| unsigned char in0x = in0 & 0x7F;
2245| unsigned char in1x = in1 & 0x7F;
2246|
2247| if ( in1 == '\0' )
2248| { *out = '\0'; return 1; }
2249|
2250| code = ( (in0x - 0x21)* 0x5E ) + in1x - 0x21;
2251| preCode = code / 0xBC + 0x81; if ( preCode > 0x9F ) preCode += 0x40;
2252| postCode = code % 0xBC + 0x40; if ( postCode > 0x7E ) postCode ++;
2253|
2254| *out = preCode; out++; *out = postCode; out++;
2255| in +=2;
2256| }
2257| }
2258|
2259| *out = '\0';
2260| return 0;
2261|}
2262|
2263|
2264|
2265|/*************************************************************************
2266| 8-11. <<< [StrX_getJisIO] JIS 漢字 IN/OUT コードを判定する >>>
2267|【引数】
2268| ・char* s; JIS 漢字 IN/OUT コードか判定する文字の先頭アドレス
2269| ・int 返り値; 漢字 IN/OUT コードかどうかの判定(StrX_CodeT型)
2270|【補足】
2271|・返り値は、漢字 IN の場合 StrX_JisIn,漢字 OUT の場合 StrX_JisOut,
2272| その他の場合、0 です。
2273|・漢字 IN コードは、3バイトです。
2274|・漢字 OUT コードは、3バイトです。
2275|**************************************************************************/
2276|int StrX_getJisIOType( const char* s )
2277|{
2278| if ( *s == StrX_ESC ) {
2279| s++;
2280| if ( *s == '$' ) {
2281| s++;
2282| if ( *s == '@' || *s == 'B' )
2283| return StrX_JisIn;
2284| }
2285| else if ( *s == '(' ) {
2286| s++;
2287| if ( *s == 'H' || *s == 'B' || *s == 'J' || *s == 'I' )
2288| return StrX_JisOut;
2289| }
2290| }
2291| return 0;
2292|}
2293|
2294|
2295|
2296|/***************************************************************************
2297| 8-12. <<< [StrX_sjis2unicode] shift JIS 漢字コードを UNICODE へ変換する >>>
2298|【引数】
2299| ・unsigned short* unicodeStr; (出力)UNICODE 漢字コードの文字列を格納する先頭アドレス
2300| ・unsigned char* shiftJisStr; shift JIS 漢字コードの文字列
2301| ・int unicodeStr_size; unicodeStr の領域のメモリサイズ(バイト)
2302|【補足】
2303|・unicodeStr_size は、shiftJisStr の文字数またはバイト数の2倍あれば十分です。
2304|・shiftJisStr の最後が、2バイト文字の1バイト目で終わらないように注意してください。
2305|***************************************************************************/
2306|#if defined(FOR_WIN32) || defined(FOR_DOS32)
2307|void StrX_sjis2unicode( unsigned short* unicodeStr, const char* shiftJisStr,
2308| int unicodeStr_size )
2309|{
2310| setlocale(LC_ALL, "Japanese");
2311| MultiByteToWideChar( CP_OEMCP, MB_PRECOMPOSED, shiftJisStr, -1,
2312| unicodeStr, unicodeStr_size );
2313|}
2314|#endif
2315|
2316|/***************************************************************************
2317| 8-13. <<< [StrX_unicode2sjis] UNICODE 漢字コードを shift JIS へ変換する >>>
2318|【引数】
2319| ・unsigned char* shiftJisStr; (出力)shift JIS 漢字コードの文字列
2320| ・unsigned short* unicodeStr; UNICODE 漢字コードの文字列を格納する先頭アドレス
2321| ・int shiftJisStr_size; shiftJisStr の領域のメモリサイズ(バイト)
2322|【補足】
2323|・shiftJisStr_size は、unicodeStr と同じバイト数だけあれば十分です。
2324|・unicodeStr の最後が、文字の1バイト目で終わらないように注意してください。
2325|***************************************************************************/
2326|#if defined(FOR_WIN32) || defined(FOR_DOS32)
2327|void StrX_unicode2sjis( unsigned char* shiftJisStr, const unsigned short* unicodeStr,
2328| int shiftJisStr_size )
2329|{
2330| setlocale(LC_ALL, "Japanese");
2331| WideCharToMultiByte( CP_OEMCP, 0, unicodeStr, -1,
2332| shiftJisStr, shiftJisStr_size, NULL, NULL );
2333|}
2334|#endif
2335|
2336|/*************************************************************************
2337| 8-14. <<< [StrX_getHash] ハッシュ値を返す(大文字小文字を区別する) >>>
2338|【引数】
2339| ・char* s; ハッシュする文字列
2340| ・int width; ハッシュ値の幅
2341| ・int 返り値; ハッシュ値
2342|【補足】
2343|・返り値は、0〜(width-1) の範囲の整数です。
2344|・ハッシュ値は次のように用います。
2345| ・ハッシュテーブルに追加するとき
2346| int hash = StrX_getHash( obj->str, 100 ); // ハッシュ値を求めて
2347| Container_add( con[hash], obj ); // ハッシュ値番目のコンテナに入れる
2348| ・ハッシュテーブルから検索するとき
2349| int hash = StrX_getHash( obj->str, 100 ); // ハッシュ値を求めて
2350| Container_search( con[hash], key ); // ハッシュ値番目のコンテナを探す
2351|**************************************************************************/
2352|int StrX_getHash( const char* s, int width )
2353|{
2354| unsigned int hash = 0;
2355| int i = 0; /* (-1)文字目 */
2356|
2357| while ( s[i] != '\0' ) {
2358| hash += (int)(unsigned char)(s[i]) * (i+1);
2359| i++;
2360| }
2361|
2362| return hash % width;
2363|}
2364|
2365|
2366|
2367|/*************************************************************************
2368| 8-15. <<< [StrX_getHashI] ハッシュ値を返す(大文字小文字を区別しない) >>>
2369|【引数】
2370| ・char* s; ハッシュする文字列
2371| ・int width; ハッシュ値の幅
2372| ・int 返り値; ハッシュ値
2373|【補足】
2374|・大文字小文字の違いがあっても同じハッシュ値を返す StrX_getHash() です。
2375|**************************************************************************/
2376|int StrX_getHashI( const char* s, int width )
2377|{
2378| unsigned int hash = 0;
2379| int i = 0; /* (-1)文字目 */
2380| int c;
2381|
2382| while ( s[i] != '\0' ) {
2383| c = s[i];
2384| if ( c <= 'Z' && c >= 'A' ) c += 0x20;
2385| hash += c * (i+1);
2386| i++;
2387| }
2388|
2389| return hash % width;
2390|}
2391|
2392|
2393|
2394|/*************************************************************************
2395| 8-16. <<< [StrX_toHtmlTxt] HTML 用のテキストに変換する >>>
2396|【引数】
2397| ・char* src; 元テキスト
2398| ・char* dst; HTML テキストを格納する領域の先頭アドレス
2399| ・int dst_size; dst の領域のサイズ
2400| ・char* 返り値; dst
2401|【補足】
2402|・HTML タグ文字である '<', '>', '&' を "<", ">", "&" に変換します。
2403|・src と dst は別の領域にしてください。
2404|・dst の領域を越える場合、残りは切り捨てます。
2405| その際、"<", ">", "&" の一部が残らないようにします。
2406|**************************************************************************/
2407|char* StrX_toHtmlTxt( const char* src, char* dst, int dst_size )
2408|{
2409| char* dst_first = dst;
2410| char* dst_over = dst + dst_size;
2411|
2412| ASSERT( src < dst || src >= dst_over );
2413|
2414| while ( *src != '\0' ) {
2415| switch ( *src ) {
2416| case '<':
2417| if ( dst + 4 >= dst_over ) goto exit_for;
2418| *dst = '&'; dst++; *dst = 'l'; dst++;
2419| *dst = 't'; dst++; *dst = ';'; dst++;
2420| break;
2421| case '>':
2422| if ( dst + 4 >= dst_over ) goto exit_for;
2423| *dst = '&'; dst++; *dst = 'g'; dst++;
2424| *dst = 't'; dst++; *dst = ';'; dst++;
2425| break;
2426| case '&':
2427| if ( dst + 5 >= dst_over ) goto exit_for;
2428| *dst = '&'; dst++; *dst = 'a'; dst++;
2429| *dst = 'm'; dst++; *dst = 'p'; dst++;
2430| *dst = ';'; dst++;
2431| break;
2432| default:
2433| if ( dst + 1 >= dst_over ) goto exit_for;
2434| if ( _ismbblead( *src ) )
2435| { *dst = *src; dst++; src++; }
2436| *dst = *src; dst++;
2437| break;
2438| }
2439| src ++;
2440| }
2441|exit_for:
2442| *dst ='\0';
2443|
2444| return dst_first;
2445|}
2446|
2447|
2448|
2449|/*************************************************************************
2450| 8-17. <<< [StrX_cpyLower] 文字列を小文字にする >>>
2451|【引数】
2452| ・char* dst; 小文字にした文字列を格納する領域
2453| ・char* src; 元テキスト(dst と同じでもOK)
2454|**************************************************************************/
2455|void StrX_cpyLower( char* dst, const char* src )
2456|{
2457| while ( *src != '\0' ) {
2458| if ( _ismbblead( *src ) ) {
2459| *dst = *src; dst++; src++;
2460| *dst = *src;
2461| }
2462| else if ( isupper( *src ) ) {
2463| *dst = tolower( *src );
2464| }
2465| else {
2466| *dst = *src;
2467| }
2468| dst++; src++;
2469| }
2470| *dst = '\0';
2471|}
2472|
2473|
2474|/*************************************************************************
2475| 8-18. <<< [StrX_cpyUpper] 文字列を大文字にする >>>
2476|【引数】
2477| ・char* dst; 大文字にした文字列を格納する領域
2478| ・char* src; 元テキスト(dst と同じでもOK)
2479|**************************************************************************/
2480|void StrX_cpyUpper( char* dst, const char* src )
2481|{
2482| while ( *src != '\0' ) {
2483| if ( _ismbblead( *src ) ) {
2484| *dst = *src; dst++; src++;
2485| *dst = *src;
2486| }
2487| else if ( islower( *src ) ) {
2488| *dst = toupper( *src );
2489| }
2490| else {
2491| *dst = *src;
2492| }
2493| dst++; src++;
2494| }
2495| *dst = '\0';
2496|}
2497|
2498|
2499|/***********************************************************************
2500| 8-19. <<< [StrX_getTableXY] 表計算での位置表記から X,Y 座標値を得る >>>
2501|【引数】
2502| ・char* xy; 表計算アプリでの位置表記
2503| ・int* x, y; (出力)X,Y 座標値
2504|【補足】
2505|・例:"A1"... *x=1, *y=1, "AB712"... *x=28, *y=712
2506|************************************************************************/
2507|void StrX_getTableXY( const char* xy, int* x, int* y )
2508|{
2509| *x = 0;
2510| for (;;) {
2511| if ( *xy >= 'A' && *xy <= 'Z' ) *x = *x * 26 + *xy - 'A' + 1;
2512| else if ( *xy >= 'a' && *xy <= 'z' ) *x = *x * 26 + *xy - 'a' + 1;
2513| else break;
2514| xy++;
2515| }
2516| *y = atoi( xy );
2517|}
2518|
2519|
2520|/*-------------------------------------------------------------------------*/
2521|/* ◆9. <<<< (StrX) char* 型の文字列(判断・正規化) >>>>
2522|/*-------------------------------------------------------------------------*/
2523|
2524|
2525|
2526|/***********************************************************************
2527| 9-1. <<< [StrX_isSJis2byte] 指定位置の文字が日本語の2バイト目かどうか判定する >>>
2528|【引数】
2529| ・char* char_top; pChar を含む文字列の先頭アドレス
2530| ・char* pChar; 2バイト目かどうか判定する文字のアドレス
2531| ・int 返り値; 2バイト目かどうか( yes=1, no=0 )
2532|************************************************************************/
2533|int StrX_isSJis2byte( const char* char_top, const char* pChar )
2534|{
2535| const char* p;
2536|
2537| for ( p = char_top; *p != '\0'; p++ ) {
2538| if ( p == pChar ) return 0;
2539| if ( _ismbblead( *p ) ) {
2540| p++;
2541| if ( p == pChar ) return 1;
2542| }
2543| }
2544| error();
2545| return 0;
2546|}
2547|
2548|
2549|
2550|/***********************************************************************
2551| 9-2. <<< [StrX_isExist2byte] 2バイト文字が含まれているかどうか判定する >>>
2552|【引数】
2553| ・char* s; 判定する文字列
2554| ・int 返り値; 2バイト文字が含まれているかどうか
2555|************************************************************************/
2556|int StrX_isExist2byte( const char* s )
2557|{
2558| const char* p;
2559|
2560| for ( p = s; *p != '\0'; p++ ) {
2561| if ( _ismbblead( *p ) ) return 1;
2562| }
2563| return 0;
2564|}
2565|
2566|
2567|
2568|/***********************************************************************
2569| 9-3. <<< [StrX_isSpace] 空白かどうか判断する >>>
2570| isspace では 8bit キャラクタに対応していないが、これは対応している
2571|************************************************************************/
2572|bool StrX_isSpace( int c )
2573|{
2574| if ( c < 0 ) return 0;
2575| else return isspace( c ) != 0;
2576|}
2577|
2578|
2579|
2580|/***********************************************************************
2581| 9-4. <<< [StrX_isAlpha] アルファベットかどうか判断する >>>
2582|************************************************************************/
2583|bool StrX_isAlpha( int c )
2584|{
2585| return ( c >= 'A' && c <= 'Z' ) || ( c >= 'a' && c <= 'z' );
2586|}
2587|
2588|
2589|
2590|/***********************************************************************
2591| 9-5. <<< [StrX_isDigit] 数字かどうか判断する >>>
2592|************************************************************************/
2593|bool StrX_isDigit( int c )
2594|{
2595| return ( c >= '0' && c <= '9' );
2596|}
2597|
2598|
2599|
2600|/***********************************************************************
2601| 9-6. <<< [StrX_isSpcTabRet] 空白、タブ、改行かどうか判断する >>>
2602|************************************************************************/
2603|bool StrX_isSpcTabRet( int c )
2604|{
2605| return c == ' ' || c == '\n' || c == '\r' || c == '\t';
2606|}
2607|
2608|
2609|
2610|/***********************************************************************
2611| 9-7. <<< [StrX_isSpaceStr] 空白文字列かどうか判断する >>>
2612|************************************************************************/
2613|int StrX_isSpaceStr( const char* c )
2614|{
2615| while ( *c != '\0' )
2616| if ( ! StrX_isSpace(*c) ) return 0;
2617| return 1;
2618|}
2619|
2620|
2621|
2622|/***********************************************************************
2623| 9-8. <<< [StrX_isTerm] 区切り文字か判断する >>>
2624|【引数】
2625| ・int 返り値; 区切り文字=1、その他=0
2626|************************************************************************/
2627|int StrX_isTerm( char c )
2628|{
2629| return ! ( isalpha(c) || c == '_' );
2630|}
2631|
2632|
2633|
2634|/***********************************************************************
2635| 9-9. <<< [StrX_isFName] ファイル名として有効かどうか判断する >>>
2636|************************************************************************/
2637|bool StrX_isFName( const char* name )
2638|{
2639| if ( StrX_strchrs( name, "\\/:,;*?\"<>|" ) != NULL ) return false;
2640| if ( name[0]=='.' ) return false;
2641| return true;
2642|}
2643|
2644|
2645|
2646|/*************************************************************************
2647| 9-10. <<< [StrX_cmpWild] ワイルドカードを持った文字列を比較する(大文字小文字を区別) >>>
2648|【補足】
2649|・ワイルドカードは、wild 引数にのみ指定できます。
2650| ・'?' ワイルドカードは、任意の1文字と対応します。空文字には対応しません。
2651| ・'*' ワイルドカードは、任意長の文字列と対応します。ただし、'*' は1つ
2652| しか指定できません。
2653| ・ワイルドカードは指定しなくても構いません
2654|・大文字と小文字は区別します。
2655|・複数のワイルドカードを使うときは、StrX_Set_searchWild2 関数を使用し
2656| てください。
2657|【例】
2658|・wild="abc*", str="abcdef" ... ret == 0
2659|・wild="abc?", str="abcdef" ... ret < 0 ('e' を比較)
2660|・wild="abc*e", str="abcdef" ... ret > 0 (後ろの 'f' を比較)
2661|・wild="*.c", str="main.c" ... ret == 0
2662|**************************************************************************/
2663|int StrX_cmpWild( const char* wild, const char* str )
2664|{
2665| const char* w;
2666| const char* s;
2667| int diff;
2668| #ifndef NDEBUG
2669| const char* ww; /* '*' が2つあるかチェックするため */
2670| #endif
2671|
2672| /* '*'ワイルドカードまで比較する */
2673| w = wild; s = str;
2674| while ( *w != '\0' && *w != '*' ) {
2675| if ( *w != *s && *w != '?' ) {
2676| return *w - *s;
2677| }
2678| w++; s++;
2679| }
2680|
2681| /* '*'ワイルドカードが無ければ、文字数を確認して終了する */
2682| if ( *w == '\0' ) {
2683| return - *s;
2684| }
2685|
2686| /* '*'ワイルドカードより後を、後ろから比較する */
2687| #ifndef NDEBUG
2688| ww = w; /* あとで、'*' が2つあるかチェックする */
2689| #endif
2690| w = strchr( w, '\0' ) - 1;
2691| s = strchr( s, '\0' ) - 1;
2692| diff = 0;
2693| while ( *w != '*' ) {
2694| if ( *w != *s && *w != '?' ) {
2695| diff = *w - *s;
2696| }
2697| w--; s--;
2698| }
2699|
2700| #ifndef NDEBUG
2701| if ( ww != w ) error(); /* '*' が2つある */
2702| #endif
2703|
2704| return diff;
2705|}
2706|
2707|
2708|
2709|/*************************************************************************
2710| 9-11. <<< [StrX_cmpWildI] ワイルドカードを持った文字列を比較する(大文字小文字を区別しない) >>>
2711|【補足】
2712|・大文字と小文字を区別しない StrX_cmpWild です。
2713|・'*' は2つ以上指定できます。
2714|**************************************************************************/
2715|int StrX_cmpWildI( const char* wild, const char* str )
2716|{
2717| const char* w;
2718| const char* s;
2719|
2720|#if 1
2721| w = wild; s = str;
2722| while ( *w != '\0' ) {
2723|
2724| if ( *w == '*' ) {
2725| const char* w_start; /* ワイルドカードの後に続くキーワードの開始位置 */
2726| const char* w_over; /* 同、終了位置 */
2727|
2728| /* w_start, w_over の取得 */
2729| w ++; w_start = w;
2730| while ( *w != '*' && *w != '?' && *w != '\0' )
2731| w++;
2732| w_over = w;
2733|
2734| /* ワイルドカード分をスキップする */
2735| w = w_start;
2736| while ( *s != '\0' ) {
2737| if ( tolower( *w ) == tolower( *s ) ) {
2738| w++;
2739| if ( w == w_over )
2740| { s++; break; }
2741| }
2742| else {
2743| w = w_start;
2744| }
2745| s++;
2746| }
2747| }
2748|
2749| else if ( *w == '?' ) {
2750| if ( *s == '\0' )
2751| return +1;
2752| w++; s++;
2753| }
2754|
2755| else {
2756| if ( tolower( *w ) != tolower( *s ) )
2757| return *w - *s;
2758| w++; s++;
2759| }
2760| }
2761|
2762| return -*s;
2763|#else
2764| int diff;
2765| #ifndef NDEBUG
2766| const char* ww; /* '*' が2つあるかチェックするため */
2767| #endif
2768|
2769| /* '*'ワイルドカードまで比較する */
2770| w = wild; s = str;
2771| while ( *w != '\0' && *w != '*' ) {
2772|
2773| if ( tolower( *w ) != tolower( *s ) && *w != '?' ) {
2774| return *w - *s;
2775| }
2776| w++; s++;
2777| }
2778|
2779| /* '*'ワイルドカードが無ければ、文字数を確認して終了する */
2780| if ( *w == '\0' ) {
2781| return - *s;
2782| }
2783|
2784| /* '*'ワイルドカードより後を、後ろから比較する */
2785| #ifndef NDEBUG
2786| ww = w; /* あとで、'*' が2つあるかチェックする */
2787| #endif
2788| w = strchr( w, '\0' ) - 1;
2789| s = strchr( s, '\0' ) - 1;
2790| diff = 0;
2791| while ( *w != '*' ) {
2792| if ( tolower( *w ) != tolower( *s ) && *w != '?' ) {
2793| diff = *w - *s;
2794| }
2795| w--; s--;
2796| }
2797|
2798| #ifndef NDEBUG
2799| if ( ww != w ) error(); /* '*' が2つある */
2800| #endif
2801|
2802| return diff;
2803|#endif
2804|}
2805|
2806|
2807|
2808|/***********************************************************************
2809| 9-12. <<< [StrX_isMatchMask] ワイルドカードにマッチするか判断する >>>
2810|【補足】
2811|・ワイルドカードは、'*'(いくつかの任意の文字)と'?'(任意の1文字)のことを
2812| いい、たとえば、*.c は main.c や sub.c などの文字列とマッチします。
2813|************************************************************************/
2814|#if 0
2815|bool StrX_isMatchMask( const char* target, const char* wildcard )
2816|{
2817| return StrX_cmpWild( wildcard, target ) == 0;
2818|}
2819|#endif
2820|
2821|
2822|
2823|/*-------------------------------------------------------------------------*/
2824|/* ◆10. <<<< (StrX) char* 型の文字列(ファイル名、ファイルパス) >>>> */
2825|/*・ファイル名に関する処理は、このエリア以外にもあります。 */
2826|/*-------------------------------------------------------------------------*/
2827|
2828|
2829|
2830|/***********************************************************************
2831| 10-1. <<< [StrX_getRunFullPath] 実行しているディレクトリからフルパスを得る >>>
2832|【引数】
2833| ・fullPath : フルパス(出力)
2834| ・stepPath : 相対パス、fullPath と同じでもよい
2835| ・fullPath_len : フルパスに格納できる最大の文字数(byte)
2836|【補足】
2837|・標準関数に _fullpath 関数があります。
2838|・stepPath の ".\" や "..\" は、まとめられます。
2839|・ルート・ディレクトリよりも親へ指定しないこと(b:\..\a.txt など)
2840| 例 : 実行dir="b:\curdir", stepPath="..\a.dat" なら
2841| fullPath="b:\a.dat"
2842|************************************************************************/
2843|#if defined(_MSC_VER) && !defined(FOR_WINCE)
2844|char* StrX_getRunFullPath( char* fullPath, const char* stepPath,
2845| int fullPath_len )
2846|{
2847| char s[_MAX_PATH];
2848|
2849| _getcwd( s, 254 );
2850| if ( fullPath != stepPath ) strcpy( fullPath, stepPath );
2851| StrX_toAbsPath( fullPath, fullPath_len, s );
2852|
2853| return fullPath;
2854|}
2855|#endif /* _MSC_VER */
2856|
2857|
2858|
2859|/***********************************************************************
2860| 10-2. <<< [StrX_getExeFullPath] 実行ファイルのディレクトリからフルパスを得る >>>
2861|【引数】
2862| ・char* 返り値; fullPath
2863|【補足】
2864|・main で StrX_argv0 = argv[0] を設定してから使うこと。
2865| (MFC では、StrX_argv0 = AfxGetApp()->m_pszHelpFilePath;)
2866| (または GetModuleFileName( AfxGetApp()->m_hInstance, s, 255 );)
2867|・ベースのディレクトリが異なること以外は、StrX_getRunFullPath と同じ
2868|・fullPath と stepPath が同じアドレスでも構いません。
2869|************************************************************************/
2870|#ifdef _MSC_VER
2871|const char* StrX_argv0 = NULL; /* main() の argv[0] 引数をポイントすること */
2872|
2873|char* StrX_getExeFullPath( char* fullPath, const char* stepPath,
2874| int fullPath_len )
2875|{
2876| char s[_MAX_PATH];
2877|
2878| /* stepPath が絶対パスなら、そのままコピー */
2879| if ( stepPath[0] == '\\' || stepPath[1] == ':' ) {
2880| strcpy( fullPath, stepPath );
2881| return fullPath;
2882| }
2883|
2884| /* "b:\exedir\stepPath" を s に得る */
2885| ASSERT( StrX_argv0 != NULL );
2886| strcpy( s, StrX_argv0 );
2887| *( strrchr( s, StrX_DirMark_char ) + 1 ) = '\0';
2888| StrX_cat( s, stepPath, 256 );
2889|
2890| /* ".\" や "..\" をまとめて、fullPath に得る */
2891| StrX_toRegularPath( s );
2892| StrX_cpy( fullPath, s, fullPath_len );
2893|
2894| return fullPath;
2895|}
2896|#endif /* _MSC_VER */
2897|
2898|
2899|
2900|/***********************************************************************
2901| 10-3. <<< [StrX_isAbsPath] 絶対パスかどうか判定する >>>
2902|【引数】
2903| ・char* path; 判定する文字列
2904| ・bool 返り値; 絶対パスかどうか
2905|************************************************************************/
2906|bool StrX_isAbsPath( const char* path )
2907|{
2908| char* p = strchr( path, '\\' );
2909| char* p2 = strchr( path, '/' );
2910|
2911| if ( p == NULL && p2 == NULL ) return false;
2912|
2913| if ( p != NULL && p2 != NULL ) {
2914| if ( p > p2 ) p = p2;
2915| }
2916|
2917| return ( p == path || *(p - 1) == ':' );
2918|}
2919|
2920|
2921|
2922|/***********************************************************************
2923| 10-4. <<< [StrX_isUrl] Netscape URL かどうか判定する >>>
2924|【引数】
2925| ・char* url; 判定する文字列
2926| ・bool 返り値; Netscape URL かどうか
2927|【補足】
2928|・Windows ファイルパスか Netscape URL かのみを比較しています。
2929|************************************************************************/
2930|bool StrX_isUrl( const char* url )
2931|{
2932| if ( ( url[0] == '/' && url[1] == '/' ) ||
2933| ( url[0] == '\\' && url[1] == '\\' ) ) {
2934| return false;
2935| }
2936| if ( url[1] == ':' )
2937| return false;
2938|
2939| return true;
2940|}
2941|
2942|
2943|
2944|/***********************************************************************
2945| 10-5. <<< [StrX_chgPathToUrl] Windows パスを Netscape URL に変換する >>>
2946|【引数】
2947| ・char* url; URL に変換した文字列を格納するアドレス
2948| ・char* path; パス文字列(フルパス)
2949| ・char* 返り値; url と同じ
2950|【補足】
2951|・url と path が同じアドレスでも構いません。
2952|・url のメモリサイズは、_MAX_PATH 以上にしてください。
2953|・path のディレクトリ区切り文字は、'/' でも '\' でも構いません。
2954|【例】
2955|・path = "\\pc01\c\file.txt" → url = "file://pc01/c/file.txt"
2956|・path = "c:\file.txt" → url = "file:///c|/file.txt"
2957|************************************************************************/
2958|char* StrX_chgPathToUrl( char* url, const char* path )
2959|{
2960| /* Microsoft ネットワーク・パスの場合 */
2961| if ( ( path[0] == '/' && path[1] == '/' ) ||
2962| ( path[0] == '\\' && path[1] == '\\' ) ) {
2963| ASSERT( strlen(path) < _MAX_PATH - 6 );
2964|
2965| memmove( url + 7, path + 2, strlen(path)-1 );
2966| StrX_rep1b( url + 7, '\\', '/' );
2967| memcpy( url, "file://", 7 );
2968| }
2969|
2970| /* ローカル・ファイルパスの場合 */
2971| else {
2972| ASSERT( path[1] == ':' );
2973| ASSERT( path[2] == '/' || path[2] == '\\' );
2974| ASSERT( strlen(path) < _MAX_PATH - 9 );
2975|
2976| memmove( url + 8, path, strlen(path) + 1 );
2977| StrX_rep1b( url + 8, '\\', '/' );
2978| memcpy( url, "file:///", 8 );
2979| url[9] = '|';
2980| }
2981|
2982| StrX_rep( url, _MAX_PATH, " ", "%20" );
2983|
2984| return url;
2985|}
2986|
2987|
2988|
2989|/***********************************************************************
2990| 10-6. <<< [StrX_toRegularPath] ファイル名の ".\" や "..\" を、取り除く >>>
2991| ルート・ディレクトリよりも親へ指定しないこと(b:\..\a.txt など)
2992| 戻り値 : s
2993| 例 : 実行dir="b:\curdir", stepPath="..\a.dat" なら
2994| fullPath="b:\a.dat"
2995|************************************************************************/
2996|char* StrX_toRegularPath( char* s )
2997|{
2998| char* p0; /* 先頭の "..\" の次のアドレス */
2999| char *p, *p2;
3000|
3001| /* 先頭の "..\" はスキップする, p0 を設定する */
3002| p0 = s;
3003| while ( strncmp( p0, "..\\", 3 ) == 0 ) p0 += 3;
3004|
3005| /* s から "parentdir\..\" を取り除く */
3006| p = p0;
3007| while ( ( p2 = strstr( p, ".." StrX_DirMark_str ) ) != NULL ) {
3008| *(p2 - 1) = '\0';
3009| p = strrchr( s, StrX_DirMark_char ) + 1;
3010| if ( p - 1 == NULL )
3011| error2_0( StrX_Err_NoMoreParentDir, "親ディレクトリ指定\"..\\\"が多すぎます。" );
3012| memmove( p, p2+3, strlen( p2+3 ) + 1 );
3013| }
3014|
3015| /* s から ".\" を取り除く */
3016| p = p0;
3017| while ( ( p2 = strstr( p, "." StrX_DirMark_str ) ) != NULL ) {
3018| if ( p2 != strstr( p, ".." StrX_DirMark_str ) +1 )
3019| memmove( p2, p2+2, strlen( p2+2 ) + 1 );
3020| p = p2+1;
3021| }
3022|
3023| return s;
3024|}
3025|
3026|
3027|
3028|/***********************************************************************
3029| 10-7. <<< [StrX_toAbsPath] 相対パスを絶対パスにする >>>
3030|【引数】
3031| ・char* path; 相対パス(絶対パスでも可、ただし何もしない)
3032| ・int maxlen; path に格納できる最大の文字数('\0'含まない)
3033| ・char* base; 基準パス
3034| ・char* 戻り値; path
3035|【補足】
3036|・ルート・ディレクトリよりも親へ指定しないこと(b:\..\a.txt など)
3037|・例 : base="b:\curdir", path="..\a.dat" なら
3038| ret="b:\a.dat"
3039|・path に http://〜 を指定した場合、何もしません。
3040|************************************************************************/
3041|char* StrX_toAbsPath( char* path, int path_maxlen, const char* base )
3042|{
3043| if ( path[0] == '\0' ) return path;
3044|
3045| /* path が絶対パスの場合、なにもしない */
3046| if ( path[0] == '/' || path[0] == '\\' || path[1] == ':' ||
3047| strncmp( path, "file:", 5 ) == 0 ||
3048| strncmp( path, "http:", 5 ) == 0 ) {
3049| return path;
3050| }
3051|
3052| /* path が相対パスの場合、絶対パスにする */
3053| {
3054| char path2[512];
3055| char* p;
3056|
3057| strcpy( path2, base );
3058| if ( StrX_getLast( path2 ) != '/' )
3059| StrX_setLast( path2, '\\' );
3060| strcat( path2, path );
3061| StrX_toRegularPath( path2 );
3062| if ( path_maxlen < (int)strlen( path2 ) && path_maxlen < 512 )
3063| path2[path_maxlen] = '\0';
3064| strcpy( path, path2 );
3065|
3066| p = strchr( path, '\0' );
3067| if ( ( *( p - 2 ) == '\\' || *( p - 2 ) == '/' ) && *( p - 1 ) == '.' )
3068| *( p - 1 ) = '\0';
3069|
3070| return path;
3071| }
3072|}
3073|
3074|
3075|
3076|/***********************************************************************
3077| 10-8. <<< [StrX_toAbsPath2] 相対パスを絶対パスにする(ファイル指定) >>>
3078|【引数】
3079| ・char* path; 相対パス(絶対パスでも可、ただし何もしない)
3080| ・int maxlen; path に格納できる最大の文字数('\0'含まない)
3081| ・char* base; 基準ファイルパス
3082| ・char* 戻り値; path
3083|【補足】
3084|・StrX_toAbsPath の base 引数がフォルダではなくファイルになっています。
3085|************************************************************************/
3086|char* StrX_toAbsPath2( char* path, int path_maxlen, const char* base )
3087|{
3088| char s[_MAX_PATH];
3089|
3090| if ( path[0] == '\0' ) return path;
3091|
3092| StrX_cpyFolder( s, base );
3093| StrX_toAbsPath( path, path_maxlen, s );
3094|
3095| return path;
3096|}
3097|
3098|
3099|/***********************************************************************
3100| 10-9. <<< [StrX_cpyAbsPath2CSV] CSV 形式のパス列をすべて絶対パスにする >>>
3101|************************************************************************/
3102|#ifdef USES_BIGSTACK
3103|char* StrX_cpyAbsPath2CSV( char* absp, const char* stepp, int absp_size,
3104| const char* base )
3105|{
3106| char path2[_MAX_PATH];
3107| char* p = absp;
3108| int i;
3109|
3110| ASSERT( stepp != absp );
3111|
3112| for ( i = 1; ; i++ ) {
3113| if ( StrX_getCSV( stepp, i, path2, _MAX_PATH ) == NULL )
3114| break;
3115| if ( i == 1 && path2[0] == '\0' ) { absp[0] = '\0'; return absp; }
3116| StrX_toAbsPath2( path2, _MAX_PATH, base );
3117| StrX_toCSV( p, path2, absp + absp_size - p - 1 );
3118| p = strchr( p, '\0' );
3119| p[0] = ','; p[1] = ' '; p += 2;
3120| if ( p >= absp + absp_size ) error();
3121| }
3122| if ( i >= 2 ) p -= 2;
3123| *p = '\0';
3124|
3125| return absp;
3126|}
3127|#endif
3128|
3129|/***********************************************************************
3130| 10-10. <<< [StrX_toStepPath] 絶対パスを相対パスにする(フォルダ指定) >>>
3131|【引数】
3132| ・char* path; 変換する絶対パス
3133| ・int path_sizeof; path のメモリサイズ('\0'含む)
3134| ・char* base; 基準フォルダパス(絶対パス)
3135| ・char* 戻り値; path(相対パス)
3136|【補足】
3137|・区切り記号は '\' でも '/' でも構いません。
3138|・exe ファイルにドラッグ&ドロップしたファイルのパスは DOS8.3 形式なので、
3139| 長いファイル名のもう片方の path か base に指定すると正しく処理できません。
3140|【例】
3141| path="b:\curdir\sub\a.txt", base="b:\curdir" なら ret="sub\a.txt"
3142| path="b:\curdir\sub\a.txt", base="a:\curdir" なら ret="b:\curdir\sub\a.txt"
3143| path="/sub/a.txt", base="/dir/" なら ret="../sub/a.txt"
3144|************************************************************************/
3145|char* StrX_toStepPath( char* path, int path_sizeof, const char* base )
3146|{
3147| static char path2[512];
3148| char* ret = path;
3149| char* pPath = path2;
3150| const char* pBase = base;
3151| char* pDirMarkInPath = NULL;
3152| const char* pDirMarkInBase = NULL;
3153| char* ret_over = ret + path_sizeof;
3154| int lastCh = *( strchr( path, '\0' ) - 1 );
3155|
3156| #ifndef NDEBUG
3157| char path_backup[256];
3158| char base_backup[256];
3159| strcpy( path_backup, path );
3160| strcpy( base_backup, base );
3161| #endif
3162|
3163| #ifndef NDEBUG
3164| #if _MAX_PATH > 512
3165| #error
3166| #endif
3167| #endif
3168|
3169| ASSERT( strchr( base, '\\' ) != NULL );
3170|
3171| if ( path[0] == '\0' ) return path;
3172|
3173| strcpy( path2, path );
3174| *ret = '\0';
3175|
3176| /* ドライブが同じならドライブ指定を無くす */
3177| if ( path2[1] == ':' ) {
3178| if ( base[1] == ':' ) {
3179| if ( tolower(path2[0]) != tolower(base[0]) ) {
3180| strcpy( path, path2 );
3181| return path;
3182| }
3183| pBase += 2;
3184| }
3185| pPath += 2;
3186| }
3187| else if ( base[1] == ':' ) {
3188| strcpy( path, path2 );
3189| return path;
3190| #if 0
3191| *ret = *pBase;
3192| *(ret + 1) = ':';
3193| ret += 2;
3194| pBase += 2;
3195| #endif
3196| }
3197|
3198| /* 親フォルダが同じ間、スキップする */
3199| while ( tolower(*pPath) == tolower(*pBase) ) {
3200|
3201| #ifndef NDEBUG
3202| if ( *pPath == '\0' ) return path;
3203| #endif
3204|
3205| /* 最後のフォルダ区切り記号の位置を取っておく */
3206| if ( *pPath == '\\' || *pPath == '/' ) {
3207| pDirMarkInPath = pPath;
3208| pDirMarkInBase = pBase;
3209| }
3210|
3211| pPath ++; pBase ++;
3212| }
3213|
3214| if ( *pPath == '\0' && ( *pBase == '\\' || *pBase == '/' ) ) {
3215| pDirMarkInPath = pPath;
3216| pDirMarkInBase = pBase;
3217| }
3218|
3219| ASSERT( pDirMarkInPath != NULL );
3220|
3221| /* base フォルダの最後に \ を付ける */
3222| if ( (*pBase == '\0') &&
3223| (*pPath == '\\' || *pPath == '/') ) {
3224| if ( ret != path && *(ret - 1) != ':' )
3225| { *ret = *pPath; ret ++; }
3226| pDirMarkInPath = pPath;
3227| }
3228|
3229| /* 親フォルダへ戻る記号 "..\" を付ける */
3230| else {
3231| pBase = pDirMarkInBase;
3232| while ( *(pBase + 1) != '\0' ) {
3233| if ( *pBase == '\\' || *pBase == '/' ) {
3234| if ( ret +3 >= ret_over ) { *ret = '\0'; return path; }
3235| *ret = '.'; ret++;
3236| *ret = '.'; ret++;
3237| *ret = *pBase; ret++;
3238| }
3239| pBase ++;
3240| }
3241| }
3242|
3243| /* のこりの相対パスを付ける */
3244| if ( *pDirMarkInPath == '\0' ) {
3245| *(ret - 1) = '\0';
3246| }
3247| else {
3248| pPath = pDirMarkInPath + 1;
3249| if ( ret + strlen( pPath ) >= ret_over )
3250| *(pPath + (ret_over - ret) - 1) = '\0';
3251| strcpy( ret, pPath );
3252| }
3253|
3254| /* path と base が同じだったら、"." を返す */
3255| if ( path[0] == '\0' ) {
3256| if ( lastCh == '\\' || lastCh == '/' ) sprintf( path, ".%c", lastCh );
3257| else strcpy( path, "." );
3258| }
3259|
3260| return path;
3261|}
3262|
3263|
3264|
3265|/***********************************************************************
3266| 10-11. <<< [StrX_toStepPath2] 絶対パスを相対パスにする(ファイル指定) >>>
3267|【引数】
3268| ・char* path; 変換する絶対パス
3269| ・int path_sizeof; path のメモリサイズ('\0'含む)
3270| ・char* file; 基準ファイルパス(絶対パス)
3271| ・char* 戻り値; path(相対パス)
3272|【補足】
3273|・StrX_toStepPath の base 引数がフォルダではなくファイルになっています。
3274|************************************************************************/
3275|#ifdef USES_BIGSTACK
3276|char* StrX_toStepPath2( char* path, int path_sizeof, const char* file )
3277|{
3278| char* s;
3279|
3280| BigStack_start();
3281| s = BigStack_alloc( _MAX_PATH );
3282|
3283| StrX_cpyFolder( s, file );
3284| StrX_toStepPath( path, path_sizeof, s );
3285|
3286| BigStack_end();
3287|
3288| return path;
3289|}
3290|#endif /* #ifdef USES_BIGSTACK */
3291|
3292|
3293|/***********************************************************************
3294| 10-12. <<< [StrX_cpyStepPath2CSV] CSV 形式のパス列をすべて相対パスにする >>>
3295|************************************************************************/
3296|#ifdef USES_BIGSTACK
3297|char* StrX_cpyStepPath2CSV( char* stepp, const char* absp, int stepp_size,
3298| const char* base )
3299|{
3300| char path2[_MAX_PATH];
3301| char* p = stepp;
3302| int i;
3303|
3304| for ( i = 1; ; i++ ) {
3305| if ( StrX_getCSV( absp, i, path2, _MAX_PATH ) == NULL )
3306| break;
3307| if ( i == 1 && path2[0] == '\0' ) { stepp[0] = '\0'; return stepp; }
3308| StrX_toStepPath2( path2, _MAX_PATH, base );
3309| StrX_toCSV( p, path2, stepp + stepp_size - p - 1 );
3310| p = strchr( p, '\0' );
3311| p[0] = ','; p[1] = ' '; p += 2;
3312| if ( p >= stepp + stepp_size ) error();
3313| }
3314| if ( i >= 2 ) p -= 2;
3315| *p = '\0';
3316|
3317| return stepp;
3318|}
3319|#endif
3320|
3321|/***********************************************************************
3322| 10-13. <<< [StrX_toStepURL] 絶対 URL を相対 URL にする >>>
3323|【引数】
3324| ・char* url; 絶対 URL
3325| ・int url_sizeof; url のメモリサイズ('\0'含む)
3326| ・char* base; 基準 URL(絶対 URL)
3327| ・char* 戻り値; url
3328|【補足】
3329|・base は、基準となる HTML ファイルを指定します。格納されている
3330| ディレクトリではありません。
3331|・区切り記号は '\' でも '/' でも構いません。
3332|【例】
3333| url="b:\sub\a.htm#1", base="b:\sub\a.htm" なら ret="#1"
3334| url="http://sub/bb.htm#1", base="http://sub/a.htm" なら ret="bb.htm#1"
3335| url="bb.htm#1", base="bb.htm#2" なら ret="#1"
3336| url="/sub/ccc.htm", base="/dir/a.htm" なら ret="../sub/ccc.htm"
3337|************************************************************************/
3338|char* StrX_toStepURL( char* url, int url_sizeof, const char* base )
3339|{
3340| char* p;
3341| int len;
3342| static char baseDir[_MAX_PATH];
3343|
3344| p = strchr( url, '#' );
3345| len = p - url;
3346| if ( p != NULL && memcmp( url, base, len ) == 0 &&
3347| ( *(base + len) == '\0' || *(base + len) == '#' ) ) {
3348| memmove( url, p, strlen(p)+1 );
3349| }
3350| else {
3351| strcpy( baseDir, base );
3352| StrX_cutFName( baseDir );
3353| StrX_toStepPath( url, url_sizeof, baseDir );
3354| }
3355|
3356| return url;
3357|}
3358|
3359|
3360|
3361|/***********************************************************************
3362| 10-14. <<< [StrX_toAbsURL] 相対 URL を絶対 URL にする >>>
3363|【引数】
3364| ・char* url; (入力)相対 URL、(出力)絶対 URL
3365| ・int url_sizeof; url のメモリサイズ('\0'含む)
3366| ・char* base; 基準 URL(絶対 URL)
3367| ・char* 戻り値; url
3368|************************************************************************/
3369|char* StrX_toAbsURL( char* url, int url_maxlen, const char* base )
3370|{
3371| if ( url[0] == '#' ) {
3372| int base_len = strlen( base );
3373| int url_len = strlen( url );
3374|
3375| if ( base_len + url_len > url_maxlen - 1 )
3376| url_len = url_maxlen - 1 - base_len;
3377|
3378| memmove( url + base_len, url, url_len + 1 );
3379| strncpy( url, base, base_len );
3380| }
3381| else
3382| StrX_toAbsPath( url, url_maxlen, base );
3383|
3384| return url;
3385|}
3386|
3387|
3388|
3389|/***********************************************************************
3390| 10-15. <<< [StrX_movePath] フォルダ間を移動するようにパスを変換する >>>
3391|【引数】
3392| ・char* src; 変換前のファイルの絶対パス
3393| ・char* from_folder; 基準フォルダの移動前の絶対パス
3394| ・char* to_folder; 基準フォルダの移動後の絶対パス
3395| ・char* dst; 変換後のファイルの絶対パス
3396| ・char* dst_size; dst のメモリ領域サイズ
3397|************************************************************************/
3398|void StrX_movePath( const char* src,
3399| const char* from_folder, const char* to_folder,
3400| char* dst, int dst_size )
3401|{
3402| int from_len = strlen( from_folder );
3403| int to_len = strlen( to_folder );
3404|
3405| if ( from_folder[from_len - 1] != '\\' ) from_len ++;
3406|
3407| ASSERT( strncmp( src, from_folder, from_len ) );
3408| ASSERT( to_len < dst_size );
3409|
3410| strcpy( dst, to_folder );
3411| dst += to_len;
3412| if ( *(dst - 1) != '\\' ) {
3413| *dst = '\\'; dst++;
3414| }
3415| if ( to_len + (int)strlen( src + from_len ) >= dst_size )
3416| error();
3417| strcpy( dst, src + from_len );
3418|}
3419|
3420|/**************************************************************************
3421| 10-16. <<< [StrX_getSpacedPath] 文字列の先頭から、空白を含んだファイルパスを取得する >>>
3422|【引数】
3423| ・char* str; ファイルパスを含んだ文字列
3424| ・char* path; ファイルパスを格納する領域(サイズは_MAX_PATH)
3425| ・char** param; str の中のパラメータの先頭位置を格納するアドレス(NULL可)
3426|【補足】
3427|・たとえば、"c:\Program Files\a.exe %1" から "c:\Program Files\a.exe" を
3428| 取得します。このとき、Program と Files の間の空白と、.exe の後の空白の違いを
3429| 存在するファイルのパスを参照して区別します。
3430|・str が "c:\Program Files\a.exe %1 %2" のとき、*param は、"%1 %2" になります。
3431|・空白を含んでいなくてもファイルパスを取得できます。
3432|***************************************************************************/
3433|#if defined(USES_FILEX) && !defined(FOR_WINCE)
3434|void StrX_getSpacedPath( const char* str, char* path, char** param )
3435|{
3436| char* p;
3437|
3438| /* ファイルパスが "" で囲まれているとき */
3439| if ( str[0] == '\"' ) {
3440| p = StrX_strchr2( str + 1, '\"' );
3441| if ( p == NULL ) {
3442| strcpy( path, p + 1 );
3443| if ( param != NULL ) *param = strchr( str + 1, '\0' );
3444| }
3445| else {
3446| strncpy( path, str + 1, p - str - 1 );
3447| do {
3448| p++;
3449| } while ( *p == ' ' );
3450| if ( param != NULL ) *param = p;
3451| }
3452| }
3453|
3454| /* ファイルパスが "" で囲まれていないとき */
3455| else {
3456| p = StrX_strchr2( str, ' ' );
3457| while ( p != NULL ) {
3458| *p = '\0';
3459| if ( FileX_isExist( str ) ) {
3460| strcpy( path, str );
3461| *p = ' ';
3462| if ( param != NULL ) *param = p + 1;
3463| break;
3464| }
3465| *p = ' ';
3466| p = StrX_strchr2( p + 1, ' ' );
3467| }
3468| if ( p == NULL ) {
3469| strcpy( path, str );
3470| if ( param != NULL ) *param = strchr( str, '\0' );
3471| }
3472| }
3473|}
3474|#endif
3475|
3476|
3477|/***********************************************************************
3478| 10-17. <<< [StrX_toLongPath] 長いファイル名に変更する >>>
3479|【補足】
3480|・存在していないファイルを指定した場合、ファイル名は未定です。
3481|・相対パスを指定しないでください。
3482|・ネットワーク上のファイルパスには、使えません。
3483|・短いファイル名にするときは、API に GetShortPathName があります。
3484|************************************************************************/
3485|#if defined(USES_BIGSTACK) && defined(USES_FILEX) && defined(USES_EXCEPT3)
3486|#if defined(FOR_WIN32) || defined(FOR_DOS32)
3487|char* StrX_toLongPath( char* longPath, const char* shortPath )
3488|{
3489| WIN32_FIND_DATA find;
3490| const char* p;
3491| char* workPath; /* ルートから子フォルダをたどるパス */
3492| const char* sp; /* shortPath をたどる */
3493| char* lp; /* longPath をたどる */
3494| char* wp; /* workPath をたどる */
3495| HANDLE h;
3496|
3497| ASSERT( FileX_isExist(shortPath) ); /* 引数に "" が無い可能性があります。*/
3498|
3499| if ( strncmp( shortPath, "\\\\", 2 ) == 0 ) { /* "\\" で始まるネットワークパス */
3500| strcpy( longPath, shortPath );
3501| return longPath;
3502| }
3503|
3504| BigStack_start();
3505| sp = shortPath;
3506| lp = longPath;
3507| workPath = wp = BigStack_alloc( _MAX_PATH );
3508|
3509| /* ルートフォルダまで(ドライブ名など)をコピーする */
3510| p = strchr( sp, '\\' );
3511| ASSERT( p != NULL );
3512| for ( sp = shortPath; sp <= p; sp++ ) {
3513| *wp = *sp; wp++;
3514| *lp = *sp; lp++;
3515| }
3516|
3517| /* ファイル名の追加 */
3518| for(;;) {
3519|
3520| /* 次の workPath を作る */
3521| p = strchr( sp, '\\' ); if ( p == NULL ) break;
3522| for ( ; sp < p; sp++ ) {
3523| *wp = *sp; wp++;
3524| }
3525| *wp = '\0';
3526|
3527| /* 長いファイル名を追加する */
3528| FindFirstFile( workPath, &find );
3529| for ( p = find.cFileName; *p != '\0'; p++ ) {
3530| *lp = *p; lp++;
3531| }
3532| sp++;
3533| *wp = '\\'; wp++;
3534| *lp = '\\'; lp++;
3535| }
3536| h = FindFirstFile( shortPath, &find );
3537| ASSERT( h != INVALID_HANDLE_VALUE ); /*ときどき判断しないぞ*/
3538| for ( p = find.cFileName; *p != '\0'; p++ ) {
3539| *lp = *p; lp++;
3540| }
3541| *lp = '\0';
3542|
3543| BigStack_end();
3544| return longPath;
3545|}
3546|#endif
3547|#endif
3548|
3549|
3550|
3551|/***********************************************************************
3552| 10-18. <<< [StrX_refFName] パス中のファイル名を参照する >>>
3553|【引数】
3554| ・char* path; パス(フォルダ指定付き)
3555| ・char* 返り値; ファイル名(フォルダ指定なし)
3556|【補足】
3557|・内容は、StrX_cpyFName 関数とほとんど同じですが、path の末尾に
3558| '\'が付いている場合、返り値にも'\' が付くので注意してください。
3559| 例:path="sub\file\" ... 返り値="file\"
3560|・返り値の内容は、path と同じ領域を参照しています。
3561|************************************************************************/
3562|char* StrX_refFName( const char* path )
3563|{
3564| char* p = strchr( path, '\0' ) - 1;
3565|
3566| if ( *p == StrX_DirMark_char ) {
3567| char* p2;
3568|
3569| *p = '\0';
3570| p2 = StrX_RSearchC2( path, StrX_DirMark_char );
3571| *p = StrX_DirMark_char;
3572| return p2 + 1;
3573| }
3574| else {
3575| p = StrX_RSearchC2( path, StrX_DirMark_char );
3576| if ( p == NULL ) return (char*)path;
3577| else return p + 1;
3578| }
3579|}
3580|
3581|
3582|
3583|/***********************************************************************
3584| 10-19. <<< [StrX_cpyFName] パス中のファイル名をコピーする >>>
3585|【引数】
3586| ・char* fname; ファイル名を格納するアドレス
3587| ・char* 返り値; fname と同じ
3588|【補足】
3589|・fname のサイズは、path と同じサイズにします。
3590|・fname と path が同じアドレスでも構いません。
3591|【例】
3592|・path="b:\dir\fname.txt" なら fname="fname.txt"
3593|・path="b:\dir\subdir\" なら fname="subdir"
3594|・path="step\" なら fname="step"
3595|・path="step" なら fname="step"
3596|************************************************************************/
3597|char* StrX_cpyFName( char* fname, const char* path )
3598|{
3599| char* path_last = strchr( path, '\0' ) - 1;
3600| char* p;
3601| char* p2;
3602|
3603| /* path の末尾がフォルダ区切り記号でない場合 */
3604| if ( (*path_last != '/' && *path_last != '\\') ||
3605| StrX_isSJis2byte( path, path_last ) ) {
3606|
3607| /* 最後のフォルダ区切り記号から path の末尾までコピーする */
3608| p = StrX_RSearchC2( path, '/' );
3609| p2 = StrX_RSearchC2( path, '\\' );
3610| if ( p < p2 ) p = p2;
3611| if ( p == NULL ) return strcpy( fname, path );
3612| else return strcpy( fname, p+1 );
3613| }
3614|
3615| /* そうでない場合、 */
3616| else {
3617| /* 一度、末尾に文字列終端文字を置いて、同様にコピーする */
3618| *path_last = '\0';
3619| p = StrX_RSearchC2( path, '/' );
3620| p2 = StrX_RSearchC2( path, '\\' );
3621| if ( p < p2 ) p = p2;
3622| if ( p == NULL ) strcpy( fname, path );
3623| else strcpy( fname, p+1 );
3624| *path_last = StrX_DirMark_char; /* 戻す */
3625| return fname;
3626| }
3627|}
3628|
3629|
3630|
3631|/***********************************************************************
3632| 10-20. <<< [StrX_cpyFolder] パス中のファイル名以外をコピーする >>>
3633|【引数】
3634| ・char* folder; フォルダパスを格納するアドレス
3635| ・char* 返り値; folder と同じ
3636|【補足】
3637|・folder のサイズは、path と同じサイズにします。
3638|・folder と path が同じアドレスでも構いません。
3639|************************************************************************/
3640|char* StrX_cpyFolder( char* folder, const char* path )
3641|{
3642| strcpy( folder, path );
3643| StrX_cutFName( folder );
3644| return folder;
3645|}
3646|
3647|
3648|
3649|/***********************************************************************
3650| 10-21. <<< [StrX_cutFName] パス中のファイル名を削除する >>>
3651|【引数】
3652| ・char* 返り値; path と同じ
3653|【補足】
3654|・フォルダの区切り記号は '\' でも '/' でも構いません
3655|【例】
3656|・path="b:\dir\fname.txt" なら "b:\dir"
3657|・path="b:\dir\subdir\" なら "b:\dir"
3658|・path="step\" なら ""
3659|・path="step" なら ""
3660|************************************************************************/
3661|char* StrX_cutFName( char* path )
3662|{
3663| char* p;
3664| char* p_last;
3665| char* lastTerm = NULL;
3666|
3667| /* 末尾のディレクトリ区切り記号を取り除く */
3668| p = strchr( path, '\0' ) - 1;
3669| if ( *p == '\\' || *p == '/' ) {
3670| *p = '\0';
3671| }
3672| else
3673| p++;
3674|
3675| /* ルートでない限り、いちばん後ろのディレクトリ区切り記号を '\0'にする */
3676| p_last = p;
3677| p = path;
3678| while ( p <= p_last ) {
3679| if ( *p == '\\' || *p == '/' ) {
3680| lastTerm = p;
3681| }
3682| else if ( _ismbblead( *p ) )
3683| p++;
3684| p++;
3685| }
3686| if ( lastTerm == NULL ) {
3687| *path = '\0';
3688| }
3689| else {
3690| if ( lastTerm == path + 2 && *(path + 1) == ':' )
3691| lastTerm ++;
3692| *lastTerm = '\0';
3693| }
3694|
3695| return path;
3696|}
3697|
3698|
3699|
3700|/***********************************************************************
3701| 10-22. <<< [StrX_addFName] パスにファイル名を追加する >>>
3702|【引数】
3703| ・char* 返り値; path と同じ
3704|【補足】
3705|・path の領域サイズに注意してください。
3706|・fname に、相対パスを指定した場合、後で、StrX_toRegularPath 関数を
3707| 呼び出してください。
3708|【例】
3709|・path="b:\subdir\" に "fname.txt" を追加したら "b:\subdir\fname.txt"
3710|・path="b:\f.txt" に "fname.txt" を追加したら "b:\f.txt\fname.txt"
3711|・path="" に "fname.txt" を追加したら "fname.txt"
3712|・path="b:\sub\f.txt" に "a:\fname.txt" を追加したら "a:\fname.txt"
3713|************************************************************************/
3714|char* StrX_addFName( char* path, const char* fname )
3715|{
3716| if ( *path == '\0' || fname[1] == ':' ) {
3717| strcpy( path, fname );
3718| }
3719| else {
3720| StrX_setLast( path, StrX_DirMark_char );
3721| strcat( path, fname );
3722| }
3723| return path;
3724|}
3725|
3726|
3727|
3728|/***********************************************************************
3729| 10-23. <<< [StrX_insLastOfFName] ファイル名の末尾に文字列を挿入する(拡張子はそのまま) >>>
3730|************************************************************************/
3731|char* StrX_insLastOfFName( char* path, char* ins )
3732|{
3733| char* ext = StrX_refExt( path );
3734| int len = strlen(ins);
3735|
3736| if ( *ext == '\0' )
3737| strcat( path, ins );
3738| else {
3739| memmove( ext + len - 1, ext - 1, strlen( ext ) + 2 );
3740| strncpy( ext - 1, ins, len );
3741| }
3742| return path;
3743|}
3744|
3745|/***********************************************************************
3746| 10-24. <<< [StrX_cdFName] パスのディレクトリを変更する >>>
3747|【引数】
3748| ・char* cd; ディレクトリの変更先(相対パス可)
3749| ・char* 返り値; path と同じ、内容は変更後のパス
3750|【補足】
3751|・path の領域サイズに注意してください。
3752|【例】
3753|・path="b:\subdir\fname.txt", cd="sub" なら "b:\subdir\sub\fname.txt"
3754|・path="..\subdir\fname.txt", cd="sub" なら "..\subdir\sub\fname.txt"
3755|・path="fname.txt", cd="\sub" なら "\sub\fname.txt"
3756|・path="..\subdir\fname.txt", cd="c:\sub" なら "c:\sub\fname.txt"
3757|************************************************************************/
3758|#ifndef FOR_WINCE
3759|char* StrX_cdFName( char* path, const char* cd )
3760|{
3761| static char fname[_MAX_FNAME];
3762|
3763| if ( cd[0] == '\\' || cd[1] == ':' ) {
3764| StrX_cpyFName( fname, path );
3765| strcpy( path, cd );
3766| StrX_addFName( path, fname );
3767| }
3768| else {
3769| StrX_cpyFName( fname, path );
3770| StrX_cutFName( path );
3771| StrX_addFName( path, cd );
3772| StrX_toRegularPath( path );
3773| StrX_addFName( path, fname );
3774| }
3775|
3776| return path;
3777|}
3778|#endif
3779|
3780|
3781|
3782|/***********************************************************************
3783| 10-25. <<< [StrX_cdURL] 相対 URL のディレクトリを変更する >>>
3784|************************************************************************/
3785|char* StrX_cdURL( char* url, const char* cd )
3786|{
3787| /* 作成中 */
3788| cd; /* avoid warning */
3789| return url;
3790|}
3791|
3792|
3793|
3794|/***********************************************************************
3795| 10-26. <<< [StrX_refExt] 拡張子を参照する >>>
3796|【補足】
3797|・返り値は変更しないでください。
3798|************************************************************************/
3799|char* StrX_refExt( const char* path )
3800|{
3801| char* p = strrchr( path, '.' );
3802|
3803| if ( p == NULL ) return strchr( path, '\0' );
3804| else return (char*)p+1;
3805|}
3806|
3807|
3808|
3809|/***********************************************************************
3810| 10-27. <<< [StrX_chgExt] 拡張子を変更する >>>
3811|【引数】
3812| ・char* path; ファイル名またはファイルパス
3813| ・char* ext; 変更後の拡張子
3814| ・char* 返り値; path(変更したファイル名またはファイルパス)
3815|【補足】
3816|・ext = "" と指定すると、拡張子を区切る "." も無くなります。
3817|************************************************************************/
3818|char* StrX_chgExt( char* path, const char* ext )
3819|{
3820| char* p = strrchr( path, '.' );
3821|
3822| if ( p == NULL ) {
3823| if ( ext[0] != '\0' ) {
3824| strcat( path, "." );
3825| strcat( path, ext );
3826| }
3827| }
3828| else {
3829| if ( ext[0] == '\0' )
3830| *p = '\0';
3831| else
3832| strcpy( p+1, ext );
3833| }
3834| return path;
3835|}
3836|
3837|
3838|
3839|/***********************************************************************
3840| 10-28. <<< [StrX_cmpNoExt] 拡張子以外を比較する >>>
3841|【引数】
3842| ・char* path1; ファイル名またはファイルパス
3843| ・char* path2; ファイル名またはファイルパス
3844| ・int 返り値; 0より大小による比較結果
3845|【補足】
3846|・拡張子が異なっていても、ファイル名が同じときは0を返します。
3847|************************************************************************/
3848|int StrX_cmpNoExt( const char* path1, const char* path2 )
3849|{
3850| const char* tree = path1;
3851| const char* period = path1;
3852|
3853| while ( toupper(*path1) == toupper(*path2) ) {
3854| switch ( *path1 ) {
3855| case '\\': tree = path1; break;
3856| case '.': period = path1; break;
3857| case '\0': return 0;
3858| }
3859| path1++; path2++;
3860| }
3861| if ( tree < period ) return 0;
3862| else return *path1 - *path2;
3863|}
3864|
3865|
3866|/***********************************************************************
3867| 10-29. <<< [StrX_cpyWithoutURLSubName] URL のパスの後の名前をカットしてコピーする >>>
3868|【引数】
3869| ・char* path; URL のパスの後の名前をカットしたものを格納するアドレス
3870| ・char* url; URL
3871| ・char* 返り値; path
3872|【補足】
3873|・url = http://www.a.com/index.htm#name なら
3874| path = http://www.a.com/index.htm にします。
3875|・#name がなかったらそのままコピーします。
3876|************************************************************************/
3877|char* StrX_cpyWithoutURLSubName( char* path, const char* url )
3878|{
3879| char* subName = StrX_refURLSubName( url );
3880|
3881| if ( *subName == '\0' )
3882| strcpy( path, url );
3883| else {
3884| int n = subName - url - 1;
3885| strncpy( path, url, n );
3886| path[n] = '\0';
3887| }
3888|
3889| return path;
3890|}
3891|
3892|
3893|/***********************************************************************
3894| 10-30. <<< [StrX_refURLSubName] URL のパスの後の名前を参照する >>>
3895|【引数】
3896| ・char* url; URL
3897| ・char* 返り値; URL のパスの後の名前(なし="")
3898|【補足】
3899|・URL のパスの後の名前とは、http://www.a.com/index.htm#name の name のこと。
3900|************************************************************************/
3901|char* StrX_refURLSubName( const char* url )
3902|{
3903| char* p = StrX_RSearchC2( url, '.' );
3904| char* s = StrX_RSearchC2( url, '#' );
3905|
3906| if ( s == NULL || s < p ) {
3907| return "";
3908| }
3909| else {
3910| return s + 1;
3911| }
3912|}
3913|
3914|
3915|
3916|/*-------------------------------------------------------------------------*/
3917|/* ◆11. <<<< (StrX) char* 型の文字列(数値との変換・n進数) >>>> */
3918|/*-------------------------------------------------------------------------*/
3919|
3920|
3921|
3922|/***********************************************************************
3923| 11-1. <<< 整数を 4桁の16進数に変換して文字列に格納する [StrX_initByInt16s()] >>>
3924|【引数】
3925| ・char* str 変換した16進数を格納する文字列のアドレス
3926| ・unsigned int n 変換する整数
3927|【補足】
3928|・変換した 16 進数の A〜F は大文字になります。
3929|・3桁以下の場合、先頭に 0 が付きます。例 "012F", "004A"
3930|・str のポイント先は 4byte以上確保してあること。
3931|・int は 16bit であること。
3932|************************************************************************/
3933|void StrX_initByInt16s( char* str, unsigned int n )
3934|{
3935| unsigned int n1;
3936|
3937| n1 = n >> 12;
3938| if ( n1 <= 9 ) *str = '0' + n1;
3939| else *str = 'A' - 10 + n1;
3940| str ++;
3941|
3942| n1 = ( n << 4 ) >> 12;
3943| if ( n1 <= 9 ) *str = '0' + n1;
3944| else *str = 'A' - 10 + n1;
3945| str ++;
3946|
3947| n1 = ( n << 8 ) >> 12;
3948| if ( n1 <= 9 ) *str = '0' + n1;
3949| else *str = 'A' - 10 + n1;
3950| str ++;
3951|
3952| n1 = ( n & 0xF );
3953| if ( n1 <= 9 ) *str = '0' + n1;
3954| else *str = 'A' - 10 + n1;
3955| str ++;
3956|
3957| *str = '\0';
3958|}
3959|
3960|
3961|
3962|/***********************************************************************
3963| 11-2. <<< 整数を 2桁の16進数に変換する [StrX_initByInt16s_2()] >>>
3964|【引数】
3965| ・char* str 変換した16進数を格納する文字列のアドレス
3966| ・unsigned int n 変換する整数
3967|【補足】
3968|・変換した 16 進数の A〜F は大文字になります。
3969|・1桁の場合、先頭に 0 が付きます。例 "0F"
3970|・str のポイント先は 2byte以上確保してあること。
3971|・int は 16bit であること。
3972|************************************************************************/
3973|void StrX_initByInt16s_2( char* str, unsigned int n )
3974|{
3975| unsigned int n1;
3976|
3977| n = n & 0xFF;
3978|
3979| n1 = n >> 4;
3980| if ( n1 <= 9 ) *str = '0' + n1;
3981| else *str = 'A' - 10 + n1;
3982| str ++;
3983|
3984| n1 = ( n & 0xF );
3985| if ( n1 <= 9 ) *str = '0' + n1;
3986| else *str = 'A' - 10 + n1;
3987| str ++;
3988|
3989| *str = '\0';
3990|}
3991|
3992|
3993|
3994|/***********************************************************************
3995| 11-3. <<< 整数を 8桁の16進数に変換する [StrX_initByLong16s()] >>>
3996|【引数】
3997| ・char* str 変換した16進数を格納する文字列のアドレス
3998| ・unsigned long n 変換する整数
3999|【補足】
4000|・変換した 16 進数の A〜F は大文字になります。
4001|・7桁以下の場合、先頭に 0 が付きます。例 "012F", "004A"
4002|・str のポイント先は 9byte以上確保してあること。
4003|・int は 16bit であること。
4004|************************************************************************/
4005|void StrX_initByLong16s( char* str, unsigned long n )
4006|{
4007| int i;
4008| unsigned int n1;
4009|
4010| for ( i = 0; i < 8; i ++ ) {
4011| n1 = (int)(n >> 28);
4012| if ( n1 <= 9 ) *str = '0' + n1;
4013| else *str = 'A' - 10 + n1;
4014| str ++;
4015| n <<= 4;
4016| }
4017|
4018| *str = '\0';
4019|}
4020|
4021|
4022|
4023|/***********************************************************************
4024| 11-4. <<< 整数を文字列に変換して格納する [StrX_initByInt()] >>>
4025|【引数】
4026| ・char* str 変換した10進数を格納する文字列のアドレス
4027| ・int str_len str に格納できる最大の文字数 [byte]
4028| ・int n 変換する整数(負または正または0)
4029|【補足】
4030|・変換した整数は 10 進数で表現されます。
4031|・str_len を超える桁数の場合、上位 str_len 桁が格納されます。
4032|・桁数が超えたかどうかは確認できません。
4033|***********************************************************************/
4034|void StrX_initByInt( char* str, int str_len, int n )
4035|{
4036| int n1; /* 一桁の数字 */
4037| int base = 10000;
4038| int setF = 0; /* 数字を1つでも格納したかどうか 1=した、0=しない */
4039| char* str_over = str + str_len; /* str_len 文字を超えた str の位置 */
4040|
4041| /* 負の符号を格納する */
4042| if ( n < 0 ) {
4043| *str = '-'; str++;
4044| n = -n;
4045| }
4046|
4047| /* 上位から数字を格納する */
4048| if ( n != 0 && n != -32768 ) {
4049| do {
4050| n1 = n / base;
4051| if ( n1 != 0 || setF == 1 ) {
4052| *str = '0' + n1; str++;
4053| if ( str == str_over ) break; /* 桁あふれ */
4054| setF = 1;
4055| }
4056| n -= n1 * base;
4057| base /= 10;
4058| } while ( base > 0 );
4059| }
4060| else if ( n == 0 ) {
4061| *str = '0'; str++;
4062| }
4063| else /* if ( n == 32768 ) */ {
4064| *str = '3'; str++;
4065| if ( str == str_over ) goto endif1; /* 桁あふれ */
4066| *str = '2'; str++;
4067| if ( str == str_over ) goto endif1; /* 桁あふれ */
4068| *str = '7'; str++;
4069| if ( str == str_over ) goto endif1; /* 桁あふれ */
4070| *str = '6'; str++;
4071| if ( str == str_over ) goto endif1; /* 桁あふれ */
4072| *str = '8'; str++;
4073| endif1:;
4074| }
4075|
4076| *str = '\0';
4077|}
4078|
4079|
4080|
4081|/***********************************************************************
4082| 11-5. <<< 文字列から整数を取得する [StrX_scanInt()] >>>
4083|【引数】
4084| ・char* str 10進数が格納された文字列
4085| ・int n 取得した数値を格納する変数のアドレス
4086| ・char* 返り値; 数値の次の文字のアドレス
4087|【補足】
4088|・str のアドレスの内容は、数字か + か - である必要があります。
4089|・返り値が要らない場合、atoi があります。
4090|***********************************************************************/
4091|char* StrX_scanInt( const char* str, int* n )
4092|{
4093| int flag = 1;
4094| int num = 0;
4095|
4096| if ( *str == '+' ) str++;
4097| while ( *str == '-' ) { str++; flag = -flag; }
4098|
4099| while ( *str >= '0' && *str <= '9' ) {
4100| num = num * 10 + (*str - '0');
4101| str++;
4102| }
4103|
4104| *n = flag * num;
4105|
4106| return (char*)str;
4107|}
4108|
4109|
4110|
4111|/***********************************************************************
4112| 11-6. <<< long 型の n から s へ2進数を格納する [StrX_get2s_fromLong()] >>>
4113|【引数】
4114| ・char* s; 2進数の文字列を格納するアドレス(33〜36byte)
4115| ・unsigned long n; long 型の数値
4116| ・char term; 8桁ごとの区切り文字, '\0' なら区切らない
4117| ・char* 返り値; s と同じ
4118|【補足】
4119|・s のエディアンは n と同じ
4120|・例:n=0x1234, term=':' なら s = "00000000:00000000:00010010:00110100"
4121|・例:n=0x1234, term='\0' なら s = "00000000000000000001001000110100"
4122|************************************************************************/
4123|char* StrX_get2s_fromLong( char* s, unsigned long n, char term )
4124|{
4125| int i;
4126| char* sp = s;
4127| const char* p;
4128| const static char* dig[0x10] = {
4129| "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
4130| "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" };
4131|
4132| for ( i = 0; i < 4; i++ ) {
4133| p = dig[n >> 28];
4134| *sp++ = *p++; *sp++ = *p++; *sp++ = *p++; *sp++ = *p;
4135| n <<= 4;
4136| p = dig[n >> 28];
4137| *sp++ = *p++; *sp++ = *p++; *sp++ = *p++; *sp++ = *p;
4138| n <<= 4;
4139| if ( term != '\0' && i < 3 ) *sp++ = term;
4140| }
4141| *sp = '\0';
4142|
4143| return s;
4144|}
4145|
4146|
4147|
4148|/***********************************************************************
4149| 11-7. <<< 2進数の文字列 s の数値を long 型で返す [StrX_getLong_from2s()] >>>
4150|【引数】
4151| ・char* s; 2進数の文字列へのアドレス
4152| ・long 返り値; 数値
4153|【補足】
4154|・s に区切り文字('0','1'以外)があっても構わない。
4155|・例:s = "00000000:00000000:00010010:00110100" なら 返り値=0x1234
4156|・例:s = "00000000000000000001001000110100" なら 返り値=0x1234
4157|・s は、8の倍数の桁数でなくてもよい。
4158| 例:s = "10010:00110100" なら 返り値=0x1234
4159|・32桁以上指定しないでください
4160|***********************************************************************/
4161|long StrX_getLong_from2s( char* s )
4162|{
4163| long result = 0;
4164| long base = 0x0001;
4165| char* sp;
4166|
4167| /* sp を下の桁にポイントする */
4168| for ( sp = s; *sp != '\0'; sp++ );
4169|
4170| /* 下の桁から変換する */
4171| for ( ; sp > s; sp-- ) {
4172| switch ( *sp ) {
4173| case '0': base <<= 1; break;
4174| case '1': result += base; base <<= 1; break;
4175| default: break;
4176| }
4177| }
4178|
4179| return result;
4180|}
4181|
4182|
4183|
4184|/***********************************************************************
4185| 11-8. <<< [StrX_getColorValue] カラー文字列から数値を得る >>>
4186|【引数】
4187| ・char* color_str; カラー文字列、"rgb(R,G,B)", 例:"rgb(192,192,255)"
4188| ・Color_WinRGB 返り値; カラーの数値
4189|************************************************************************/
4190|#ifdef USES_COLOR
4191|Color_WinRGB StrX_getColorValue( const char* color_str )
4192|{
4193| const char* p;
4194| Color_WinRGB color;
4195|
4196| p = strchr( color_str, '(' );
4197| if ( p == NULL ) return false;
4198| color = atoi( p + 1 ); /* RED */
4199| p = strchr( p, ',' );
4200| if ( p == NULL ) return false;
4201| color |= atoi( p + 1 ) << 8; /* GREEN */
4202| p = strchr( p + 1, ',' );
4203| if ( p == NULL ) return false;
4204| color |= atoi( p + 1 ) << 16; /* BLUE */
4205|
4206| return color;
4207|}
4208|#endif
4209|
4210|
4211|/***********************************************************************
4212| 11-9. <<< [StrX_getColorStr] カラーの数値からカラー文字列を取得する >>>
4213|【引数】
4214| ・char* color_str; (出力)カラー文字列を格納する領域の先頭アドレス
4215| ・Color_WinRGB value; カラーの数値
4216|【補足】
4217|・関連:StrX_getColorValue
4218|・color_str は、17バイト以上の領域を指定してください。
4219|・color_str は、次のフォーマットで格納されます。"rgb(R,G,B)", 例:"rgb(192,192,255)"
4220|************************************************************************/
4221|#ifdef USES_COLOR
4222|void StrX_getColorStr( char* color_str, Color_WinRGB value )
4223|{
4224| sprintf( color_str, "rgb(%d,%d,%d)",
4225| Color_WinRGB_getR( value ), Color_WinRGB_getG( value ),
4226| Color_WinRGB_getB( value ) );
4227|}
4228|#endif
4229|
4230|/***********************************************************************
4231| 11-10. <<< [StrX_getFontValue] フォント文字列から各属性を取得する >>>
4232|【引数】
4233| ・char* font_str; フォント文字列、"face, size, bold, italic"
4234| ・char* face; (出力)フォント名(font_str のより大きいこと)
4235| ・char* size10; (出力)フォントサイズの10倍
4236| ・bool* bBold; (出力)太字かどうか
4237| ・bool* bItalic; (出力)斜め文字かどうか
4238|【補足】
4239|・フォント文字列の中のフォントサイズは、10倍ではなく小数で記述します。
4240|・フォント文字列の中の bool 値は、1 or 0 で記述します。
4241|************************************************************************/
4242|void StrX_getFontValue( const char* font_str, char* face, int* size10,
4243| bool* bBold, bool* bItalic )
4244|{
4245| int font_str_size = strlen(font_str) + 1;
4246| char s[256];
4247|
4248| StrX_getCSV( font_str, 1, face, font_str_size );
4249| StrX_getCSV( font_str, 2, s, font_str_size );
4250| *size10 = atoi( s ) * 10;
4251| StrX_getCSV( font_str, 3, s, font_str_size );
4252| *bBold = s[0] != '0';
4253| StrX_getCSV( font_str, 4, s, font_str_size );
4254| *bItalic = s[0] != '0';
4255|}
4256|
4257|
4258|
4259|
4260|/***********************************************************************
4261| 11-11. <<< [StrX_getFontStr] フォント文字列を作成する >>>
4262|【引数】
4263| ・char* font_str; (出力)フォント文字列、"face, size, bold, italic"
4264| ・char* face; フォント名
4265| ・char size10; フォントサイズの10倍
4266| ・bool bBold; 太字かどうか
4267| ・bool bItalic; 斜め文字かどうか
4268|【補足】
4269|・フォント文字列の中のフォントサイズは、10倍ではなく小数で記述します。
4270|・フォント文字列の中の bool 値は、1 or 0 で記述します。
4271|************************************************************************/
4272|void StrX_getFontStr( char* font_str, const char* face, int size10,
4273| bool bBold, bool bItalic )
4274|{
4275| sprintf( font_str, "%s, %d, %d, %d", face, size10 / 10, bBold != 0, bItalic != 0 );
4276|}
4277|
4278|/*-------------------------------------------------------------------------*/
4279|/* ◆12. <<<< (StrX_ListElem) リストの要素になる文字列 >>>> */
4280|/*-------------------------------------------------------------------------*/
4281|
4282|
4283|#ifdef USES_LISTX
4284|
4285|#ifdef USES_SYM
4286|SYM_STRUCT_START( StrX_ListElem )
4287|SYM_STRUCT_MEMB( StrX_ListElem, char*, p )
4288|SYM_STRUCT_END( StrX_ListElem )
4289|#endif
4290|
4291|/***********************************************************************
4292| 12-1. <<< [StrX_ListElem_finish2] リスト要素の文字列を後始末する >>>
4293|************************************************************************/
4294|void StrX_ListElem_finish2( StrX_ListElem* m )
4295|{
4296| free( m->p );
4297|}
4298|
4299|#endif
4300|
4301|/*-------------------------------------------------------------------------*/
4302|/* ◆13. <<<< (StrX_Mem) 文字列領域 >>>> */
4303|/*-------------------------------------------------------------------------*/
4304|
4305|
4306|
4307|/**************************************************************************
4308| 13-1. <<< [StrX_Mem_init] 初期化する >>>
4309|【補足】
4310|・buf に malloc したアドレスを指定した場合、StrX_Mem_getTopAdr で取得
4311| できるアドレスを free することを忘れないでください。
4312|**************************************************************************/
4313|void StrX_Mem_init( StrX_Mem* m, char* buf, size_t buf_sizeof )
4314|{
4315| m->buf = buf;
4316| m->buf_over = buf + buf_sizeof;
4317| m->pBuf = buf;
4318| *buf = '\0';
4319|}
4320|
4321|
4322|
4323|/**************************************************************************
4324| 13-2. <<< [StrX_Mem_toEmpty] 記憶領域に入っているすべての文字列を消去する >>>
4325|**************************************************************************/
4326|void StrX_Mem_toEmpty( StrX_Mem* m )
4327|{
4328| m->pBuf = m->buf;
4329| *m->buf = '\0';
4330|}
4331|
4332|
4333|
4334|/**************************************************************************
4335| 13-3. <<< [StrX_Mem_alloc] 記憶領域を確保する >>>
4336|【補足】
4337|・空き領域が無ければ、 NULL を返します。
4338|・この関数によって返されたアドレスには、1つの文字列しか格納できません。
4339| 2つ目の文字列を格納する前に、再び alloc してください。
4340|・alloc した領域に文字列を格納する前に、次の alloc をすることはできません。
4341| つまり、alloc を連続して2回呼び出して、あとからその2つの領域に
4342| 格納することは出来ません。alloc してすぐに格納してください。
4343|【内部補足】
4344|・内部バッファは次のように変化していきます。(\='\0')
4345| \ init pBuf=0, left=9
4346| \\ alloc pBuf=1, left=9
4347| \abc\ strcpy pBuf=1, left=5
4348| \abc\\ alloc pBuf=5, left=5
4349| \abc\123\ strcpy pBuf=5, left=1
4350|**************************************************************************/
4351|char* StrX_Mem_alloc( StrX_Mem* m )
4352|{
4353| m->pBuf = strchr( m->pBuf, '\0' ) + 1;
4354|
4355| if ( m->pBuf >= m->buf_over ) {
4356| error2_0( StrX_Err_MemEmpty, "アプリ内部のメモリ領域が足りません" );
4357| }
4358|
4359| *m->pBuf = '\0';
4360|
4361| return m->pBuf;
4362|}
4363|
4364|
4365|
4366|/**************************************************************************
4367| 13-4. <<< [StrX_Mem_alloc2] 記憶領域を初期化して確保する >>>
4368|【引数】
4369| ・const char* str; 初期化する内容
4370| ・char* 返り値; 確保した領域のアドレス
4371|【補足】
4372|・空き領域が無ければ、 NULL を返します。
4373|・空き領域が少なければ、入るだけ入れます。
4374|**************************************************************************/
4375|char* StrX_Mem_alloc2( StrX_Mem* m, const char* str )
4376|{
4377| size_t size, len;
4378| char* p;
4379|
4380| /* 記憶領域を確保する ★ */
4381| p = StrX_Mem_alloc( m );
4382| if ( p == NULL ) return p;
4383|
4384| /* 初期化する */
4385| len = strlen( str );
4386| size = StrX_Mem_getLeftSize( m );
4387| if ( len < size ) strcpy( p, str );
4388| else { strncpy( p, str, size-1 ); p[size-1] = '\0'; }
4389|
4390| return p;
4391|}
4392|
4393|
4394|
4395|/**************************************************************************
4396| 13-5. <<< [StrX_Mem_alloc3] 記憶領域を効率よく初期化して確保する >>>
4397|【機能】
4398|・前回代入した文字列と同じ内容で初期化する場合、記憶領域を確保しないで、
4399| 前回返したアドレスを再び返します。
4400|【引数】
4401| ・const char* str; 初期化する内容
4402| ・char* 返り値; 確保した領域のアドレス
4403|【補足】
4404|・同じ内容の場合、同じ領域を参照することになるので、なるべく内容を変更しない
4405| ようにしてください。
4406|・空き領域が無ければ、NULL を返します。
4407|・空き領域が少なければ、入るだけ入れます。
4408|・前々回以前の文字列に対しても効率よく行う場合は Dic コンポーネントを
4409| 使ってください。
4410|**************************************************************************/
4411|char* StrX_Mem_alloc3( StrX_Mem* m, const char* str )
4412|{
4413| if ( strcmp( str, m->pBuf ) == 0 ) return m->pBuf;
4414| else return StrX_Mem_alloc2( m, str );
4415|}
4416|
4417|
4418|
4419|/**************************************************************************
4420| 13-6. <<< [StrX_Mem_copyAlloc] 文字列領域を確保して、初期値を代入する >>>
4421|【引数】
4422| ・char* str; 初期値文字列
4423| ・char* 返り値; 確保した文字列領域の先頭アドレス
4424|【補足】
4425|・文字列領域は、StrX_Mem_alloc3 と同じ様に効率よく確保します。
4426|**************************************************************************/
4427|char* StrX_Mem_copyAlloc( StrX_Mem* m, const char* str )
4428|{
4429| if ( strcmp( str, m->pBuf ) == 0 ) return strcpy( m->pBuf, str );
4430| else return StrX_Mem_alloc2( m, str );
4431|}
4432|
4433|
4434|
4435|/**************************************************************************
4436| 13-7. <<< [StrX_Mem_free] 前回 StrX_Mem_alloc した領域を次回も使うようにする >>>
4437|【引数】
4438| ・const char* adr; 解放するメモリ領域のアドレス
4439|【補足】
4440|・adr には、直前の StrX_Mem_alloc 関数で返されたアドレスを指定します。
4441|・連続して free する場合、スタックのように alloc した逆の順番に指定して
4442| いきます。
4443|【内部補足】
4444|・内部バッファは次のように変化していきます。(\='\0')
4445| strcpy後 \abc\123\ pBuf=5, left=1
4446| \abc\ pBuf=4, left=5
4447| \ pBuf=0, left=9
4448| alloc後 \abc\\ pBuf=5, left=5
4449| \abc\ pBuf=4, left=5
4450|**************************************************************************/
4451|void StrX_Mem_free( StrX_Mem* m, const char* adr )
4452|{
4453| if ( m->pBuf == m->buf )
4454| return;
4455|
4456| do {
4457| m->pBuf --;
4458| } while( *m->pBuf != '\0' );
4459| ASSERT( m->pBuf + 1 == adr );
4460|}
4461|
4462|
4463|
4464|/**************************************************************************
4465| 13-8. <<< [StrX_Mem_getLeftSize] 残りメモリサイズを返す >>>
4466|**************************************************************************/
4467|size_t StrX_Mem_getLeftSize( StrX_Mem* m )
4468|{
4469| if ( m->buf_over == m->pBuf ) {
4470| #ifndef NDEBUG
4471| error();
4472| #endif
4473| return 0;
4474| }
4475| return m->buf_over - m->pBuf - strlen( m->pBuf ) - 1;
4476|}
4477|
4478|/**************************************************************************
4479| 13-9. <<< [StrX_Mem_getNext] 文字列を先頭から順番にたどる >>>
4480|【引数】
4481| ・char* cur; 現在の文字列のアドレス(NULL=先頭の文字列を返す)
4482| ・char* 返り値; 次の文字列のアドレス(NULL=次は無い)
4483|**************************************************************************/
4484|char* StrX_Mem_getNext( StrX_Mem* m, char* cur )
4485|{
4486| if ( cur == NULL ) {
4487| if ( m->pBuf == m->buf ) return NULL;
4488| else return m->buf + 1;
4489| }
4490| else {
4491| if ( cur >= m->pBuf ) return NULL;
4492| else return strchr( cur, '\0' ) + 1;
4493| }
4494|}
4495|
4496|
4497|
4498|/**************************************************************************
4499| 13-10. <<< [StrX_Mem_print] デバッグ表示する >>>
4500|**************************************************************************/
4501|#ifndef ERRORS_CUT_DEBUG_TOOL
4502|void StrX_Mem_print( StrX_Mem* m, const char* title )
4503|{
4504| Errors_printf( "%sStrX_Mem[%p] buf=%p, buf_over = %p, pBuf = %p, checked = %d",
4505| title, m, m->buf, m->buf_over, m->pBuf, m->checked );
4506|}
4507|#endif /* #ifndef ERRORS_CUT_DEBUG_TOOL */
4508|
4509|
4510|/**************************************************************************
4511| 13-11. <<< [StrX_Mem_printAll] すべての文字列を表示する >>>
4512|**************************************************************************/
4513|#ifndef ERRORS_CUT_DEBUG_TOOL
4514|void StrX_Mem_printAll( StrX_Mem* m )
4515|{
4516| char* s;
4517|
4518| Errors_printf( "StrX_Mem:" );
4519| for ( StrX_Mem_forEach( m, &s ) ) {
4520| Errors_printf( " %s", s );
4521| }
4522|}
4523|#endif /* #ifndef ERRORS_CUT_DEBUG_TOOL */
4524|
4525|
4526|/*-------------------------------------------------------------------------*/
4527|/* ◆14. <<<< (StrX_Set) 文字列の記憶領域の部分集合 >>>> */
4528|/*-------------------------------------------------------------------------*/
4529|
4530|
4531|
4532|/**************************************************************************
4533| 14-1. <<< [StrX_Set_printAll] 部分集合に含まれるすべての文字列を表示する >>>
4534|**************************************************************************/
4535|#ifdef USES_STDLIBS
4536|#ifndef ERRORS_CUT_DEBUG_TOOL
4537|void StrX_Set_printAll( StrX_Set* m )
4538|{
4539| char* s;
4540|
4541| Errors_printf( "StrX_Set:" );
4542| for ( StrX_Set_forEach( m, &s ) ) {
4543| Errors_printf( " %s", s );
4544| }
4545|}
4546|#endif /* #ifndef ERRORS_CUT_DEBUG_TOOL */
4547|#endif
4548|
4549|
4550|/**************************************************************************
4551| 14-2. <<< [StrX_Set_searchWild] ワイルドカードで文字列を検索する >>>
4552|【引数】
4553| ・SetX_Set* m; 文字列の集合
4554| ・char* wildkey; 検索キー(ワイルドカード可)
4555| ・int 返り値; 番号(0〜)、見つからない=−1
4556|【補足】
4557|・返り値は、StrX_Mem_alloc で最初に格納した文字列が検索されたときが0、
4558| 次に格納した文字列では1、続いて 2,3... となります。
4559|**************************************************************************/
4560|#ifdef USES_STDLIBS
4561|int StrX_Set_searchWild( StrX_Set* m, const char* wildkey )
4562|{
4563| char* s;
4564| int i = 0;
4565|
4566| for ( StrX_Set_forEach( m, &s ) ) {
4567| if ( StrX_cmpWild( wildkey, s ) == 0 )
4568| return i;
4569| i++;
4570| }
4571| return -1;
4572|}
4573|#endif
4574|
4575|/**************************************************************************
4576| 14-3. <<< [StrX_Set_searchWild2] 文字列に一致するワイルドカードを検索する >>>
4577|【引数】
4578| ・SetX_Set* wilds; ワイルドカードを含む文字列の集合
4579| ・char* key; 検索キー(ワイルドカード不可)
4580| ・int 返り値; 番号(0〜)、見つからない=−1
4581|【補足】
4582|・返り値は、StrX_Set_searchWild 関数と同じです。
4583|**************************************************************************/
4584|#ifdef USES_STDLIBS
4585|int StrX_Set_searchWild2( StrX_Set* wilds, const char* key )
4586|{
4587| char* s;
4588| int i = 0;
4589|
4590| for ( StrX_Set_forEach( wilds, &s ) ) {
4591| if ( StrX_cmpWild( s, key ) == 0 )
4592| return i;
4593| i++;
4594| }
4595| return -1;
4596|}
4597|#endif
4598|
4599|/*-------------------------------------------------------------------------*/
4600|/* ◆15. <<<< (StrX_MemV) 文字列の記憶領域(malloc 使用)>>>> */
4601|/*-------------------------------------------------------------------------*/
4602|
4603|
4604|/***********************************************************************
4605| 15-1. <<< [StrX_MemV_init] 初期化する >>>
4606|************************************************************************/
4607|#ifdef STRX_USES_MALLOC
4608|#ifdef USES_LISTX
4609|void StrX_MemV_init( StrX_MemV* m )
4610|{
4611| StrX_MemVE* ve = (StrX_MemVE*)malloc( sizeof(StrX_MemVE) );
4612| void* memX = malloc( StrX_MemV_unitSize );
4613|
4614| /* malloc できないとき、エラーにする */
4615| StdPlus_chkMalloc( ve, memX, StdPlus_End );
4616|
4617| ERRORS_FINISHCHK_FOR_INIT( StrX_MemV_finish );
4618|
4619| /* 初期化する */
4620| ListX_init( &m->mems );
4621| ListX_addFirst( &m->mems, ve );
4622| StrX_Mem_init( &ve->mem, memX, StrX_MemV_unitSize );
4623|
4624| m->mem_last = ve;
4625| m->maxLen = StrX_MemV_maxLen;
4626|}
4627|#endif
4628|#endif
4629|
4630|
4631|
4632|/***********************************************************************
4633| 15-2. <<< [StrX_MemV_finish] 後始末する >>>
4634|************************************************************************/
4635|#ifdef STRX_USES_MALLOC
4636|#ifdef USES_LISTX
4637|void StrX_MemV_finish( StrX_MemV* m )
4638|{
4639| StrX_MemVE* ve;
4640| StrX_MemVE* ve2;
4641|
4642| for ( ListX_forEachFree( &m->mems, &ve, StrX_MemVE, &ve2, free ) ) {
4643| StdPlus_free( StrX_Mem_getTopAdr( &ve->mem ) );
4644| }
4645| ERRORS_FINISHCHK_FOR_FINISH( StrX_MemV_finish );
4646|}
4647|#endif
4648|#endif
4649|
4650|
4651|/***********************************************************************
4652| 15-3. <<< [StrX_MemV_alloc] メモリ領域を確保する >>>
4653|【補足】
4654|・返り値によって得られたアドレスのさす領域は、m->maxLen の大きさだけ
4655| 保証されています。
4656|・過去に取得した返り値(アドレス)は、StrX_MemV_alloc の内部で
4657| realloc されたときに無効になります。
4658|************************************************************************/
4659|#ifdef STRX_USES_MALLOC
4660|#ifdef USES_LISTX
4661|char* StrX_MemV_alloc( StrX_MemV* m )
4662|{
4663| StrX_Mem* mem = &m->mem_last->mem;
4664|
4665| /* 確保したメモリ領域が不足してきたとき、メモリ領域を追加確保する */
4666| if ( (int)StrX_Mem_getLeftSize( mem ) <= m->maxLen ) {
4667| StrX_MemVE* ve = (StrX_MemVE*)malloc( sizeof(StrX_MemVE) );
4668| void* memX = malloc( StrX_MemV_unitSize );
4669|
4670| StdPlus_chkMalloc( mem, ve, StdPlus_End );
4671|
4672| /* リスト要素を初期化する */
4673| ListX_Elem_insertNext( m->mem_last, ve );
4674| StrX_Mem_init( &ve->mem, memX, StrX_MemV_unitSize );
4675| m->mem_last = ve;
4676|
4677| mem = &ve->mem;
4678| ASSERT( (int)StrX_Mem_getLeftSize( mem ) > m->maxLen );
4679| }
4680|
4681| return StrX_Mem_alloc( mem );
4682|}
4683|#endif
4684|#endif
4685|
4686|
4687|/*-------------------------------------------------------------------------*/
4688|/* ◆16. <<<< (StrX_MemV2) 文字列の記憶領域(malloc & ハッシュ 使用)>>>> */
4689|/*-------------------------------------------------------------------------*/
4690|
4691|
4692|#if defined(USES_INF) && defined(USES_ARRX) && defined(USES_LISTX) && defined(USES_STDPLUS)
4693|
4694|/***********************************************************************
4695| 16-1. <<< [StrX_MemV2_init] 初期化する >>>
4696|【引数】
4697| ・int width; 内部で使用するハッシュテーブルの幅
4698| ・StrX_HashFunc hash; ハッシュ関数(StrX_getHash, StrX_getHashI など)
4699| ・bool bCase; 大文字小文字を区別する
4700|【補足】
4701|・bCase によって hash を変える必要がある可能性があります。
4702|************************************************************************/
4703|void StrX_MemV2_init( StrX_MemV2* m, int width, StrX_HashFunc hash,
4704| bool bCase )
4705|{
4706| ERRORS_INITCHK( m, 0 );
4707|
4708| Offset_Key_init( &m->key, StrX_MemV2E, p,
4709| ( bCase ? Offset_CStringP : Offset_CStringPI ), 0 );
4710| ListX_Dic_init( &m->dic, width, StrX_MemV2E, &m->key, hash );
4711| ListX_init( &m->symbols );
4712|}
4713|
4714|
4715|/***********************************************************************
4716| 16-2. <<< [StrX_MemV2_setSymbol] アドレス指定文字列を設定する >>>
4717|【引数】
4718| ・char* setStr; アドレス指定文字列
4719|【補足】
4720|・setStr と同じ内容の文字列を StrX_MemV2_alloc() した場合に
4721| strStr のアドレスを返すようにします。
4722|・NULL 文字列や汎用文字列などに使用します。
4723|************************************************************************/
4724|void StrX_MemV2_setSymbol( StrX_MemV2* m, const char* setStr )
4725|{
4726| ERRORS_INITCHK( m, 0 );
4727|
4728| ListX_addFirstMalloc( &m->symbols, StrX_MemV2E )->p = (char*)setStr;
4729|}
4730|
4731|
4732|/***********************************************************************
4733| 16-3. <<< [StrX_MemV2_alloc] 指定の文字列領域を確保する >>>
4734|【補足】
4735|・引数 str と同じ内容の文字列領域を確保または再利用し、その文字列の
4736| 先頭アドレスを返します。
4737|・str に NULL または Errors_null が指定されたら、それをそのまま返します。
4738|************************************************************************/
4739|char* StrX_MemV2_alloc( StrX_MemV2* m, const char* str )
4740|{
4741| StrX_MemV2E* p;
4742|
4743| ERRORS_INITCHK( m, 1 );
4744|
4745| if ( str == NULL || str == Errors_null ) return (char*)str;
4746|
4747| p = ListX_search_s( &m->symbols, &m->key, str, StrX_MemV2E );
4748|
4749| if ( p == NULL ) {
4750| p = ListX_Dic_alloc( &m->dic, str, StrX_MemV2E );
4751| if ( p != NULL ) StrX_MemV2E_init( p, (void*)str );
4752| else p = ListX_Dic_search( &m->dic, str, StrX_MemV2E );
4753| }
4754|
4755| return p->p;
4756|}
4757|
4758|/***********************************************************************
4759| 16-4. <<< [StrX_MemV2_print] デバッグ表示する >>>
4760|************************************************************************/
4761|#ifndef ERRORS_CUT_DEBUG_TOOL
4762|void StrX_MemV2_print( StrX_MemV2* m, const char* title )
4763|{
4764| ERRORS_INITCHK( m, 1 );
4765|
4766| ListX_Dic_print( &m->dic, title );
4767| Offset_Key_print( &m->key, title );
4768|}
4769|#endif
4770|
4771|/***********************************************************************
4772| 16-5. <<< [StrX_MemV2E_finish] 文字列領域をヒープへ開放する >>>
4773|************************************************************************/
4774|void StrX_MemV2E_finish( StrX_MemV2E* m )
4775|{
4776| free( m->p );
4777|}
4778|
4779|#endif
4780|
4781|/*-------------------------------------------------------------------------*/
4782|/* ◆17. <<<< (StrX_SetV) 文字列の記憶領域の部分集合 >>>> */
4783|/*-------------------------------------------------------------------------*/
4784|
4785|
4786|
4787|/**************************************************************************
4788| 17-1. <<< [StrX_SetV_forEach_imp] StrX_SetV_forEach の実装 >>>
4789|**************************************************************************/
4790|#ifdef STRX_USES_MALLOC
4791|#ifdef USES_LISTX
4792|char* StrX_SetV_forEach_imp( StrX_SetV* m, char* p )
4793|{
4794| if ( p < m->pVE->mem.pBuf ) return strchr( p, '\0' ) + 1;
4795| else {
4796| m->pVE = m->pVE->ListX_Elem_extend;
4797| if ( m->pVE == NULL ) return NULL;
4798| else return m->pVE->mem.buf + 1;
4799| }
4800|}
4801|#endif
4802|#endif
4803|
4804|/*-------------------------------------------------------------------------*/
4805|/* ◆18. <<<< (StrX_Pathes) 右クリック『送る』のファイルパス >>>> */
4806|/*-------------------------------------------------------------------------*/
4807|
4808|
4809|#ifdef USES_BIGSTACK
4810|#if defined(USES_FILEX) && defined(USES_EXCEPT3)
4811|#if defined(FOR_WIN32) || defined(FOR_DOS32)
4812|
4813|
4814|/***********************************************************************
4815| 18-1. <<< [StrX_Pathes_set] 内部用 >>>
4816|************************************************************************/
4817|static void StrX_Pathes_set( StrX_Pathes* m )
4818|{
4819| if ( *m->curPath == '"' ) {
4820| StrX_wordCpy( m->longPath, _MAX_PATH - 1, m->curPath + 1, '"' );
4821| }
4822| else {
4823| char s[_MAX_PATH];
4824|
4825| StrX_wordCpy( s, _MAX_PATH - 1, m->curPath, ' ' );
4826| StrX_toLongPath( m->longPath, s );
4827| }
4828|}
4829|
4830|/***********************************************************************
4831| 18-2. <<< [StrX_Pathes_init] 初期化する >>>
4832|【引数】
4833| ・char* cmdline; 短いファイルパス(空白区切り)
4834|【補足】
4835|・cmdline には、オプションをスキップしてファイルパスの始まる位置の
4836| アドレスを指定してください。例:AfxGetApp()->m_lpCmdLine = "-x a.txt"
4837| のときは、"a.txt" のアドレスを指定します。
4838|・長いファイル名を指定するときは、"" で囲んでください。
4839|・StrX_Pathes_next を呼び出す前に最初のファイルパスを StrX_Pathes_getCurPath
4840| で参照することが出来ます。
4841|************************************************************************/
4842|void StrX_Pathes_init( StrX_Pathes* m, const char* cmdline )
4843|{
4844| m->pathes = (char*)cmdline;
4845| m->curPath = (char*)cmdline;
4846| StrX_Pathes_set( m );
4847|}
4848|
4849|/***********************************************************************
4850| 18-3. <<< [StrX_Pathes_reset] 最初のパスを参照するようにする >>>
4851|************************************************************************/
4852|void StrX_Pathes_reset( StrX_Pathes* m )
4853|{
4854| m->curPath = m->pathes;
4855| StrX_Pathes_set( m );
4856|}
4857|
4858|
4859|/***********************************************************************
4860| 18-4. <<< [StrX_Pathes_getCurPath] 現在ポイントしているパスを参照する >>>
4861|************************************************************************/
4862|char* StrX_Pathes_getCurPath( StrX_Pathes* m )
4863|{
4864| return m->longPath;
4865|}
4866|
4867|
4868|/***********************************************************************
4869| 18-5. <<< [StrX_Pathes_next] 次のパスをポイントする >>>
4870|【引数】
4871| ・bool 返り値; 次があるかどうか(ある=true)
4872|************************************************************************/
4873|bool StrX_Pathes_next( StrX_Pathes* m )
4874|{
4875| char* p;
4876|
4877| if ( *m->curPath == '"' ) {
4878| p = strchr( m->curPath + 1, '"' );
4879| if ( p != NULL && *(p + 1) != '\0' && *(p + 2) != '\0' ) {
4880| m->curPath = p + 2;
4881| StrX_Pathes_set( m );
4882| return true;
4883| }
4884| return false;
4885| }
4886| else {
4887| p = strchr( m->curPath, ' ' );
4888| if ( p != NULL ) {
4889| m->curPath = p + 1;
4890| StrX_Pathes_set( m );
4891| return true;
4892| }
4893| else
4894| return false;
4895| }
4896|}
4897|
4898|
4899|/***********************************************************************
4900| 18-6. <<< [StrX_Pathes_getN] 要素数を返す >>>
4901|************************************************************************/
4902|int StrX_Pathes_getN( StrX_Pathes* m )
4903|{
4904| int nPath;
4905| char* curPath_back = m->curPath;
4906|
4907| m->curPath = m->pathes;
4908|
4909| nPath = 1;
4910| while ( StrX_Pathes_next( m ) ) {
4911| nPath ++;
4912| }
4913|
4914| m->curPath = curPath_back;
4915| StrX_Pathes_set( m );
4916|
4917| return nPath;
4918|}
4919|
4920|
4921|#endif
4922|#endif
4923|#endif
4924|
4925|