水無瀬の部屋 > Programming > sample > tools > toolbase.cpp |
---|
1: //*********************************************************
2: // プロジェクト: TOOLS
3: // ファイル名: toolbase.cpp
4: //*********************************************************
5: #include <header/toolbase.h> //
6: #include <header/tooldbg.h> // ASSERT(),
7: #include <limits.h> //
8:
9:
10: //---------------------------------------------------------
11: // テスト関数 の 宣言
12: //---------------------------------------------------------
13: DECLARE_TESTPROC( test_bitcount ); // bitcount, bitcount8, bitcount16, bitcount32, bitcount64
14: DECLARE_TESTPROC( test_str );
15: DECLARE_TESTPROC( test_pathname );
16: DECLARE_TESTPROC( test_time );
17: DECLARE_TESTPROC( test_memmem );
18: DECLARE_TESTPROC( test_IsValidArgcArgv );
19:
20:
21: //---------------------------------------------------------
22: // マクロ の 定義
23: //---------------------------------------------------------
24: //
25: #define MEMMAP_SIZE ( 256 / CHAR_BIT )
26: #define STRMAP_SIZE ( 256 / CHAR_BIT )
27:
28: // 使用禁止文字
29: #define INVALID_COMMANDLINECHARS "\a\b\t\n\v\f\r" // コマンドライン で使わせない文字
30: #define INVALID_PATHMASKCHARS "\"<>|" INVALID_COMMANDLINECHARS // パスマスク で使わせない文字
31: #define INVALID_PATHCHARS "*?" INVALID_PATHMASKCHARS // パス名 で使わせない文字
32:
33: //
34: #define IS_VALID_DBCS_CHAR_CODE( c ) (0 == (~0xFFFF & (c)))
35: #define IS_VALID_CHAR_CODE( c ) (0 == (~0xFF & (c)))
36:
37: // const int index = c / CHAR_BIT;
38: // const int bit = c % CHAR_BIT;
39: // map[ index ] |= BIT( bit );
40: #define SET_MEMMAP_BIT( map, c ) ((map)[ static_cast<BYTE>( c ) / CHAR_BIT ] |= BIT( static_cast<BYTE>( c ) % CHAR_BIT ))
41:
42: // const int index = c / CHAR_BIT;
43: // const int bit = c % CHAR_BIT;
44: // map[ index ] & BIT( bit );
45: #define GET_MEMMAP_BIT( map, c ) ((map)[ static_cast<BYTE>( c ) / CHAR_BIT ] & BIT( static_cast<BYTE>( c ) % CHAR_BIT ))
46:
47: // const int index = c / CHAR_BIT;
48: // const int bit = c % CHAR_BIT;
49: // map[ index ] |= BIT( bit );
50: #define SET_STRMAP_BIT( map, c ) ((map)[ static_cast<BYTE>( c ) / CHAR_BIT ] |= BIT( static_cast<BYTE>( c ) % CHAR_BIT ))
51:
52: // const int index = c / CHAR_BIT;
53: // const int bit = c % CHAR_BIT;
54: // map[ index ] & BIT( bit );
55: #define GET_STRMAP_BIT( map, c ) ((map)[ static_cast<BYTE>( c ) / CHAR_BIT ] & BIT( static_cast<BYTE>( c ) % CHAR_BIT ))
56:
57:
58: //---------------------------------------------------------
59: // ファイルスコープ関数 の 宣言
60: //---------------------------------------------------------
61: static bool make_memmap( BYTE *map, size_t size, const char *ctrl, size_t count );
62: static bool make_strmap( BYTE *map, size_t size, const char *ctrl );
63:
64:
65: //------------------------------------------------------------------------------------------------------------------
66: // a
67: //------------------------------------------------------------------------------------------------------------------
68:
69: //------------------------------------------------------------------------------------------------------------------
70: // b
71: //------------------------------------------------------------------------------------------------------------------
72: //*********************************************************
73: // bitcount()
74: // 立っている ビットの数 を数える。
75: // 値 b を2進表記した場合に現れる 1 の数を返す。
76: //
77: // BYTE b
78: // 立っている ビットの数 を数える 1 byte の値。
79: //
80: //*********************************************************
81: int // 立っている ビットの数
82: bitcount
83: (
84: BYTE b // 1 byte 値
85: )
86: {
87: CALLONCE_TESTPROC( test_bitcount ); // [テスト]
88:
89: int bit = 0;
90: while( 0 != b )
91: {
92: if ( 0 != (b & 0x01) )
93: {
94: ++bit;
95: }
96:
97: b >>= 1;
98: }
99:
100: ASSERT( (0 <= bit) && (bit <= CHAR_BIT) );
101:
102: return bit;
103: }//bitcount
104:
105: //*********************************************************
106: // bitcount8()
107: // 立っている ビットの数 を数える。
108: // 値 b8 を2進表記した場合に現れる 1 の数を返す。
109: //
110: // BYTE b8
111: // 立っている ビットの数 を数える 8 bits の値。
112: //
113: //*********************************************************
114: int // 立っている ビットの数
115: bitcount8
116: (
117: BYTE b8 // 8 bits 値
118: )
119: {
120: CALLONCE_TESTPROC( test_bitcount ); // [テスト]
121:
122: // 8 bits 限定アルゴリズムを利用している
123: COMPILE_ASSERT( 8 == (CHAR_BIT * sizeof( b8 )) );
124:
125: b8 = static_cast<BYTE>( ((b8 & 0xAA) >> 1) + (b8 & 0x55) );
126: b8 = static_cast<BYTE>( ((b8 & 0xCC) >> 2) + (b8 & 0x33) );
127: b8 = static_cast<BYTE>( ((b8 & 0xF0) >> 4) + (b8 & 0x0F) );
128:
129: ASSERT( (0 <= b8) && (b8 <= CHAR_BIT) );
130:
131: return b8;
132: }//bitcount8
133:
134: //*********************************************************
135: // bitcount16()
136: // 立っている ビットの数 を数える。
137: // 値 w16 を2進表記した場合に現れる 1 の数を返す。
138: //
139: // WORD w16
140: // 立っている ビットの数 を数える 16 bits の値。
141: //
142: //*********************************************************
143: int // 立っている ビットの数
144: bitcount16
145: (
146: WORD w16 // 16 bits 値
147: )
148: {
149: CALLONCE_TESTPROC( test_bitcount ); // [テスト]
150:
151: // 16 bits 限定アルゴリズムを利用している
152: COMPILE_ASSERT( 16 == (CHAR_BIT * sizeof( w16 )) );
153:
154: w16 = static_cast<WORD>( ((w16 & 0xAAAA) >> 1) + (w16 & 0x5555) );
155: w16 = static_cast<WORD>( ((w16 & 0xCCCC) >> 2) + (w16 & 0x3333) );
156: w16 = static_cast<WORD>( ((w16 & 0xF0F0) >> 4) + (w16 & 0x0F0F) );
157: w16 = static_cast<WORD>( ((w16 & 0xFF00) >> 8) + (w16 & 0x00FF) );
158:
159: ASSERT( (0 <= w16) && (w16 <= (CHAR_BIT * sizeof( WORD ))) );
160:
161: return w16;
162: }//bitcount16
163:
164: //*********************************************************
165: // bitcount32()
166: // 立っている ビットの数 を数える。
167: // 値 dw32 を2進表記した場合に現れる 1 の数を返す。
168: //
169: // DWORD dw32
170: // 立っている ビットの数 を数える 32 bits の値。
171: //
172: //*********************************************************
173: int // 立っている ビットの数
174: bitcount32
175: (
176: DWORD dw32 // 32 bits 値
177: )
178: {
179: CALLONCE_TESTPROC( test_bitcount ); // [テスト]
180:
181: // 32 bits 限定アルゴリズムを利用している
182: COMPILE_ASSERT( 32 == (CHAR_BIT * sizeof( dw32 )) );
183:
184: dw32 = ((dw32 & 0xAAAAAAAA) >> 1) + (dw32 & 0x55555555);
185: dw32 = ((dw32 & 0xCCCCCCCC) >> 2) + (dw32 & 0x33333333);
186: dw32 = ((dw32 & 0xF0F0F0F0) >> 4) + (dw32 & 0x0F0F0F0F);
187: dw32 = ((dw32 & 0xFF00FF00) >> 8) + (dw32 & 0x00FF00FF);
188: dw32 = ((dw32 & 0xFFFF0000) >> 16) + (dw32 & 0x0000FFFF);
189:
190: ASSERT( (0 <= dw32) && (dw32 <= (CHAR_BIT * sizeof( DWORD ))) );
191:
192: return dw32;
193: }//bitcount32
194:
195: //*********************************************************
196: // bitcount64()
197: // 立っている ビットの数 を数える。
198: // 値 dw64 を2進表記した場合に現れる 1 の数を返す。
199: //
200: // DWORD64 dw64
201: // 立っている ビットの数 を数える 64 bits の値。
202: //
203: //*********************************************************
204: int // 立っている ビットの数
205: bitcount64
206: (
207: DWORD64 dw64 // 64 bits 値
208: )
209: {
210: CALLONCE_TESTPROC( test_bitcount ); // [テスト]
211:
212: // 64 bits 限定アルゴリズムを利用している
213: COMPILE_ASSERT( 64 == (CHAR_BIT * sizeof( dw64 )) );
214:
215: dw64 = ((dw64 & 0xAAAAAAAAAAAAAAAA) >> 1) + (dw64 & 0x5555555555555555);
216: dw64 = ((dw64 & 0xCCCCCCCCCCCCCCCC) >> 2) + (dw64 & 0x3333333333333333);
217: dw64 = ((dw64 & 0xF0F0F0F0F0F0F0F0) >> 4) + (dw64 & 0x0F0F0F0F0F0F0F0F);
218: dw64 = ((dw64 & 0xFF00FF00FF00FF00) >> 8) + (dw64 & 0x00FF00FF00FF00FF);
219: dw64 = ((dw64 & 0xFFFF0000FFFF0000) >> 16) + (dw64 & 0x0000FFFF0000FFFF);
220: dw64 = ((dw64 & 0xFFFFFFFF00000000) >> 32) + (dw64 & 0x00000000FFFFFFFF);
221:
222: ASSERT( (0 <= dw64) && (dw64 <= (CHAR_BIT * sizeof( DWORD64 ))) );
223:
224: return static_cast<int>( dw64 );
225: }//bitcount64
226:
227: //*********************************************************
228: // bool_inverse
229: //*********************************************************
230: void
231: bool_inverse
232: (
233: bool *pb
234: )
235: {
236: // パラメタの仮定
237: ASSERT( IsValidPtr( pb, sizeof( *pb ) ) );
238:
239: *pb = !(*pb);
240: }//bool_inverse
241:
242:
243: //------------------------------------------------------------------------------------------------------------------
244: // c
245: //------------------------------------------------------------------------------------------------------------------
246: //*********************************************************
247: // chreql
248: //*********************************************************
249: bool
250: chreql
251: (
252: int c1,
253: int c2
254: )
255: {
256: CALLONCE_TESTPROC( test_str ); // [テスト]
257:
258: // パラメタの仮定
259: ASSERT( IS_VALID_DBCS_CHAR_CODE( c1 ) );
260: ASSERT( IS_VALID_DBCS_CHAR_CODE( c2 ) );
261:
262: return c1 == c2;
263: }//chreql
264:
265: //*********************************************************
266: // chreqli
267: //*********************************************************
268: bool
269: chreqli
270: (
271: int c1,
272: int c2
273: )
274: {
275: CALLONCE_TESTPROC( test_str ); // [テスト]
276:
277: // パラメタの仮定
278: ASSERT( IS_VALID_DBCS_CHAR_CODE( c1 ) );
279: ASSERT( IS_VALID_DBCS_CHAR_CODE( c2 ) );
280:
281: //
282: if ( c1 == c2 )
283: {
284: return true;
285: }
286:
287: //
288: if ( ! IS_VALID_CHAR_CODE( c1 )
289: || ! IS_VALID_CHAR_CODE( c2 ) )
290: {
291: return false;
292: }
293:
294: ASSERT( IS_VALID_CHAR_CODE( c1 ) );
295: ASSERT( IS_VALID_CHAR_CODE( c2 ) );
296: return ToLower( c1 ) == ToLower( c2 );
297: }//chreqli
298:
299: //*********************************************************
300: // CutFileExtension
301: // パス path から拡張子を切り取る
302: // 拡張子 ".ext" の先頭文字 'e' へのポインタを返す
303: // 拡張子が無い場合には文字列終端 '\0' へのポインタを返す
304: // [path\file.ext] -> [path\file], ext
305: //*********************************************************
306: char *
307: CutFileExtension
308: (
309: char *path
310: )
311: {
312: CALLONCE_TESTPROC( test_pathname ); // [テスト]
313:
314: // パラメタの仮定
315: ASSERT( IsValidLocalPathString( path ) );
316: ASSERT( IsValidStringBufferPtr( path, 1 + strlen( path ) ) );
317:
318: // 拡張子を探す
319: char *ext = GetFileExtensionPtr( path );
320: ASSERT( ('.' == *ext) || ('\0' == *ext) );
321:
322: // 拡張子なし
323: if ( '\0' == *ext )
324: {
325: return ext;
326: }
327: ASSERT( '.' == *ext );
328:
329: // 拡張子の切り落とし
330: *ext = '\0';
331:
332: //
333: ASSERT( IsValidLocalPathString( path ) );
334: return ext + 1;
335: }//CutFileExtension
336:
337: //*********************************************************
338: // CutFileName
339: // フルパス名からファイル名を切り取る
340: // [path\file.ext] -> [path], file.ext
341: //*********************************************************
342: char *
343: CutFileName
344: (
345: char *path
346: )
347: {
348: CALLONCE_TESTPROC( test_pathname ); // [テスト]
349:
350: // パラメタの仮定
351: ASSERT( IsValidLocalPathString( path ) );
352: ASSERT( IsValidStringBufferPtr( path, 1 + strlen( path ) ) );
353:
354: //
355: char *separator = jmsrchr( path, '\\' );
356: if ( !separator )
357: {
358: // '\'がなかった
359: ASSERT( ! strchri( path, '\\' ) );
360: return path;
361: }
362: ASSERT( '\\' == *separator );
363:
364: //
365: *separator = '\0';
366:
367: //
368: ASSERT( IsValidLocalPathString( path ) );
369: return separator + 1;
370: }//CutFileName
371:
372:
373: //------------------------------------------------------------------------------------------------------------------
374: // d
375: //------------------------------------------------------------------------------------------------------------------
376:
377: //------------------------------------------------------------------------------------------------------------------
378: // e
379: //------------------------------------------------------------------------------------------------------------------
380:
381: //------------------------------------------------------------------------------------------------------------------
382: // f
383: //------------------------------------------------------------------------------------------------------------------
384: //*********************************************************
385: // fgetsz
386: // ストリームから最初の '\0' までを読み込む
387: //*********************************************************
388: bool
389: fgetsz
390: (
391: char *buf,
392: int bufsize,
393: FILE *fp
394: )
395: {
396: // パラメタの仮定
397: ASSERT( 0 < bufsize );
398: ASSERT( IsValidStringBufferPtr( buf, bufsize ) );
399: ASSERT( IsValidFilePtr( fp ) );
400: ASSERT( fp != stdin );
401: DESTROY_TEXT_BUFFER( buf, bufsize ); // [破壊]
402:
403: int i;
404: int c; // 読み込んだ文字
405: {for( i = 0; i < bufsize-1; ++i )
406: {
407: ASSERT( i >= 0 );
408: ASSERT( i < bufsize );
409:
410: c = fgetc( fp );
411: buf[i] = (char)((c==EOF)?'\0':c); // [未確認][キャスト][警告の回避]
412:
413: if ( buf[i] == '\0' )
414: return !((i==0)&&(c==EOF));
415:
416: ASSERT( c != EOF );
417: ASSERT( c != '\0' );
418: }}
419:
420: ASSERT( i >= 0 );
421: ASSERT( i < bufsize );
422:
423: c = fgetc( fp );
424:
425: if ((c!=EOF)&&(c!='\0'))
426: ungetc( c, fp );
427:
428: buf[i] = '\0';
429: return true;
430: }//fgetsz
431:
432: //*********************************************************
433: // fputeuc
434: //*********************************************************
435: void
436: fputeuc
437: (
438: int euc,
439: FILE *fp
440: )
441: {
442: // パラメタの仮定
443: // ASSERT( is_euc( euc ) );
444: ASSERT( IsValidFilePtr( fp ) );
445:
446: if ( 0 < HIBYTE( euc ) )
447: {
448: fputc( HIBYTE( euc ), fp );
449: }
450:
451: fputc( LOBYTE( euc ), fp );
452:
453: }//fputeuc
454:
455: //*********************************************************
456: // fputf
457: //*********************************************************
458: void
459: fputf
460: (
461: FILE *fw,
462: FILE *fr
463: )
464: {
465: // パラメタの仮定
466: ASSERT( IsValidFilePtr( fw ) );
467: ASSERT( IsValidFilePtr( fr ) );
468: ASSERT( fw != fr );
469:
470: int c;
471: while( EOF != (c = fgetc( fr )) )
472: {
473: fputc( c, fw );
474: }
475:
476: }//fputf
477:
478: //*********************************************************
479: // fputjms
480: //*********************************************************
481: void
482: fputjms
483: (
484: int jms,
485: FILE *fp
486: )
487: {
488: // パラメタの仮定
489: ASSERT( IsValidFilePtr( fp ) );
490: ASSERT( (EOF == jms) || IS_VALID_DBCS_CHAR_CODE( jms ) );
491:
492: if ( 0 < HIBYTE( jms ) )
493: {
494: fputc( HIBYTE( jms ), fp );
495: }
496:
497: fputc( LOBYTE( jms ), fp );
498:
499: }//fputjms
500:
501: //*********************************************************
502: // fputsz
503: //*********************************************************
504: bool
505: fputsz
506: (
507: const char *string,
508: FILE *fp
509: )
510: {
511: // パラメタの仮定
512: ASSERT( IsValidStringPtr( string ) );
513: ASSERT( IsValidFilePtr( fp ) );
514: ASSERT( fp != stdout );
515: ASSERT( fp != stderr );
516:
517: return ( 0 <= fputs( string, fp ) )
518: && ( '\0' == fputc( '\0', fp ) );
519: }//fputsz
520:
521:
522: //------------------------------------------------------------------------------------------------------------------
523: // g
524: //------------------------------------------------------------------------------------------------------------------
525: //*********************************************************
526: // GetDayOfWeek()
527: // 指定された 年月日 が 何曜日 かを求める。
528: // 何曜日かを示す 曜日番号 を返す。
529: // [0 = 日, 1 = 月, 2 = 火, 3 = 水, 4 = 木, 5 = 金, 6 = 土]
530: //
531: // int year
532: // 年 を 西暦 で与える。
533: //
534: // int month
535: // 月 を 1 〜 12 の範囲で指定する。
536: //
537: // int day
538: // 日 を 1 〜 31 の範囲で指定する。
539: //
540: //*********************************************************
541: int // 曜日番号 0-6
542: GetDayOfWeek
543: (
544: int year, // 年 西暦
545: int month, // 月 1-12
546: int day // 日 1-31
547: )
548: {
549: CALLONCE_TESTPROC( test_time ); // [テスト]
550:
551: // パラメタの仮定
552: ASSERT( IsValidDate( year, month, day ) );
553:
554: // 1月 と 2月 を前年の 13月 と 14月 として扱う
555: if ( month <= 2 )
556: {
557: year -= 1;
558: month += 12;
559: }
560:
561: // 曜日番号を返す
562: return (day + ((8 + (13 * month)) / 5) + (year + (year / 4) - (year / 100) + (year / 400))) % 7;
563: }//GetDayOfWeek
564:
565: //*********************************************************
566: // GetFileExtensionPtr
567: // フルパス名の拡張子開始位置を取得
568: // [filename.ext] → [.ext]
569: // 拡張子が無い場合には文字列終端 '\0' を指す
570: //*********************************************************
571: char *
572: GetFileExtensionPtr
573: (
574: const char *path
575: )
576: {
577: CALLONCE_TESTPROC( test_pathname ); // [テスト]
578:
579: // パラメタの仮定
580: ASSERT( IsValidLocalPathString( path ) );
581:
582: //
583: const char *extension = jmsrchr( path, '.' );
584: if ( !extension || jmschr( extension, '\\' ) )
585: {
586: // 拡張子なし
587: return strtail( path );
588: }
589:
590: //
591: ASSERT( '.' == *extension );
592: return const_cast<char *>( extension );
593: }//GetFileExtensionPtr
594:
595: //*********************************************************
596: // GetFileLocation
597: // フルパスからファイルの場所のみを抜き出す
598: //*********************************************************
599: bool
600: GetFileLocation
601: (
602: const char *path, // d:\dir\filename.ext
603: char *buf, // d:\dir
604: size_t bufsize //
605: )
606: {
607: CALLONCE_TESTPROC( test_pathname ); // [テスト]
608:
609: // パラメタの仮定
610: ASSERT( IsEnoughPathBufferSize( bufsize ) ); // [WARN]
611: ASSERT( IsValidLocalPathString( path ) );
612: ASSERT( IsValidStringBufferPtr( buf, bufsize ) );
613: DESTROY_TEXT_BUFFER( buf, bufsize ); // [破壊]
614: ASSERT( (buf > strtail(path))
615: || (path > buf + bufsize) );
616:
617: //
618: char *separator = jmsrchr( path, '\\' );
619: if ( ! separator )
620: {
621: strcopy( buf, bufsize, "" );
622: }
623: else
624: {
625: ASSERT( '\\' == *separator );
626: strsub( buf, bufsize, path, separator );
627: }
628:
629: ASSERT( IsValidLocalPathString( buf ) );
630: ASSERT( strlen( buf ) < bufsize );
631: return true;
632: }//GetFileLocation
633:
634: //*********************************************************
635: // GetFileNamePtr
636: // フルパス名のファイル名開始位置を取得
637: // [path\filename.ext] → [filename.ext]
638: // ファイル名が無い( '\' で終了する)場合には文字列終端 '\0' を指す
639: //*********************************************************
640: char *
641: GetFileNamePtr
642: (
643: const char *path
644: )
645: {
646: CALLONCE_TESTPROC( test_pathname ); // [テスト]
647:
648: // パラメタの仮定
649: ASSERT( IsValidLocalPathString( path ) );
650:
651: //
652: const char *separator = jmsrchr( path, '\\' );
653: if ( separator )
654: {
655: ASSERT( '\\' == *separator );
656: return const_cast<char *>( separator + 1 );
657: }
658:
659: // '\'がなかった
660: ASSERT( ! strchri( path, '\\' ) );
661: return const_cast<char *>( path );
662: }//GetFileNamePtr
663:
664: //*********************************************************
665: // GetMonthDays()
666: // 1ヶ月 が 何日 あるかを求める。
667: // 指定された 月 の 総日数 を返す。
668: // 指定された月が不正な場合 -1 を返す。
669: //
670: // int year
671: // 総日数を求める月のある年を 西暦 で与える。
672: //
673: // int month
674: // 日数を調べたい月を 1 〜 12 の範囲で指定する。
675: //
676: //*********************************************************
677: int // 日数
678: GetMonthDays
679: (
680: int year, // 年 西暦
681: int month // 月 1-12
682: )
683: {
684: CALLONCE_TESTPROC( test_time ); // [テスト]
685:
686: // パラメタの仮定
687: ASSERT( (1 <= month) && (month <= 12) );
688:
689: // 閏年の2月
690: if ( (2 == month) && IsLeapYear( year ) )
691: {
692: return 29;
693: }
694:
695: // 閏年でない場合の1ヶ月の総日数
696: const int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
697: COMPILE_ASSERT( 12 == numof( days ) );
698:
699: ASSERT( (0 <= (month-1)) && ((month-1) < numof( days )) );
700: return days[ month-1 ];
701: }//GetMonthDays
702:
703:
704: //------------------------------------------------------------------------------------------------------------------
705: // h
706: //------------------------------------------------------------------------------------------------------------------
707:
708: //------------------------------------------------------------------------------------------------------------------
709: // i
710: //------------------------------------------------------------------------------------------------------------------
711: //*********************************************************
712: // IsBackslash
713: //*********************************************************
714: bool
715: IsBackslash
716: (
717: const char *string,
718: size_t pos
719: )
720: {
721: // パラメタの仮定
722: ASSERT( IsValidStringPtr( string ) );
723: ASSERT( (0 <= pos) && (pos < strlen(string)) );
724:
725: return ('\\' == string[ pos ]) && !isJMS( string, pos );
726: }//IsBackslash
727:
728: //*********************************************************
729: // isJMS
730: // 文字列 string の string[nPos] について
731: // 1バイト文字か2バイト文字の一部であるかを判定する。
732: //
733: // 戻り値:
734: // 0 …… 1バイト文字
735: // 1 …… 2バイト文字の第1バイト
736: // 2 …… 2バイト文字の第2バイト
737: //*********************************************************
738: int
739: isJMS
740: (
741: const char *string,
742: size_t pos
743: )
744: {
745: // パラメタの仮定
746: ASSERT( IsValidStringPtr( string ) );
747: // ASSERT( (0 <= pos) && (pos < strlen(string)) );
748:
749: int state = 0; // { 0, 1, 2 } = { 1バイト文字, 2バイト文字の第1バイト, 2バイト文字の第2バイト }
750: {for( const char *p = string; '\0' != *p; ++p, --pos )
751: {
752: ASSERT( (0 == state)
753: || (1 == state)
754: || (2 == state) );
755:
756: if ( ( 0 == state ) && ( jms1( *p ) ) ) state = 1; // 0 -> 1
757: else if ( ( 1 == state ) && ( jms2( *p ) ) ) state = 2; // 1 -> 2
758: else if ( ( 2 == state ) && ( jms1( *p ) ) ) state = 1; // 2 -> 1
759: else state = 0; // 2 -> 0, その他
760:
761: // 指定の位置の状態を返す
762: if ( pos <= 0 )
763: {
764: return state;
765: }
766: }}
767:
768: return 0;
769: }//isJMS
770:
771: //*********************************************************
772: // IsLeapYear()
773: // 指定された 年 が 閏年 であるか調べる。
774: // 閏年 であれば 真 を返す。
775: //
776: // int year
777: // 閏年かどうか調べたい年を 西暦 で指定する。
778: //
779: //*********************************************************
780: bool // 閏年 であれば 真
781: IsLeapYear
782: (
783: int year // 西暦
784: )
785: {
786: CALLONCE_TESTPROC( test_time ); // [テスト]
787:
788: // パラメタの仮定
789: ASSERT( 0 <= year );
790:
791: // << 閏年の決まり方 >>
792: // 1.400 の倍数 であれば閏年
793: // 2.100 の倍数 であれば閏年ではない
794: // 3. 4 の倍数 であれば閏年
795: // 4.その他の年 は閏年ではない
796:
797: // 400 の倍数であれば閏年
798: if ( 0 == (year % 400) )
799: return true;
800:
801: // 100 の倍数であれば閏年ではない
802: if ( 0 == (year % 100) )
803: return false;
804:
805: // 4 の倍数であれば閏年
806: if ( 0 == (year % 4) )
807: return true;
808:
809: // その他の年は閏年ではない
810: return false;
811: }//IsLeapYear
812:
813: //*********************************************************
814: // IsPathDescendant
815: //*********************************************************
816: bool
817: IsPathDescendant
818: (
819: const char *descendant, // 子孫
820: const char *ancestor // 先祖
821: )
822: {
823: CALLONCE_TESTPROC( test_pathname ); // [テスト]
824:
825: // パラメタの仮定
826: ASSERT( IsValidLocalPathString( descendant ) );
827: ASSERT( IsValidLocalPathString( ancestor ) );
828:
829: //
830: if ( ! strhstri( descendant, ancestor ) )
831: {
832: return false;
833: }
834:
835: //
836: if ( streqli( descendant, ancestor ) )
837: {
838: return false;
839: }
840:
841: //
842: if ( IsPathTailSeparator( ancestor ) )
843: {
844: return true;
845: }
846:
847: //
848: const char *next = descendant + strlen( ancestor );
849: if ( ('\\' == next[ 0 ])
850: && ('\0' != next[ 1 ]) )
851: {
852: return true;
853: }
854:
855: return false;
856: }//IsPathDescendant
857:
858: //*********************************************************
859: // IsPathTailSeparator
860: //*********************************************************
861: bool
862: IsPathTailSeparator
863: (
864: const char *path
865: )
866: {
867: CALLONCE_TESTPROC( test_pathname ); // [テスト]
868:
869: // パラメタの仮定
870: ASSERT( IsValidLocalPathString( path ) );
871:
872: return !! strtstr( path, "\\" );
873: }//IsPathTailSeparator
874:
875: //*********************************************************
876: // IsSortedArray()
877: // 配列が整列されているか調べる。
878: // 配列 array[] が整列されていれば 真 を返す。
879: //
880: // const void *array
881: // 配列が整列されているか調べる配列へのポインタ
882: //
883: // size_t num
884: // 配列 array[] の 要素数
885: //
886: // size_t size
887: // 配列 array[] の各要素の バイト数
888: //
889: // int (*comp)( const void *, const void * )
890: // 配列 array[] を整列した比較関数
891: //
892: //
893: // [参照]
894: // qsort() …… 配列を整列する。
895: // bsearch() …… 整列済み配列から要素を検索する。
896: // unique() …… 整列済み配列の重複する要素を1つにまとめる。
897: //
898: //*********************************************************
899: bool // 整列されていれば 真
900: IsSortedArray
901: (
902: const void *array, // 整列されているか調べる配列
903: size_t num, // 要素数
904: size_t size, // 各要素のバイト数
905: int (*comp)( const void *, const void * ) // 比較関数
906: )
907: {
908: // パラメタの仮定
909: ASSERT( 0 < num ); // 0 == num だと size*(num-1) で不具合
910: ASSERT( 0 < size );
911: ASSERT( IsValidReadPtr( array, size * num ) );
912: ASSERT( IsValidCodePtr( comp ) );
913:
914: const BYTE *start = static_cast<const BYTE *>( array );
915: const BYTE *stop = start + (size * (num - 1));
916: {for( const BYTE *p = start; p < stop; p += size )
917: {
918: // 逆順を発見
919: if ( 0 < comp( p, p+size ) )
920: {
921: return false;
922: }
923: }}
924:
925: return true;
926: }//IsSortedArray
927:
928: //*********************************************************
929: // IsValidArgcArgv()
930: // 引数文字列配列が 標準形式 であれば 真 を返す。
931: // ・引数文字列配列 argv が argc 個の文字列を指すポインタ変数からなる配列である
932: // ・配列の最後に null が付加されている
933: //
934: // int argc
935: // 引数文字列配列 argv に含まれる引数の数。
936: // 引数文字列配列 argv の要素数より常に 1 小さい。
937: //
938: // char **argv
939: // argv[ argc ] は null であること。
940: //
941: // 使用例:
942: // ASSERT( IsValidArgcArgv( argc, argv ) );
943: //
944: //*********************************************************
945: bool // 標準形式 であれば 真
946: IsValidArgcArgv
947: (
948: int argc, // 引数文字列配列 argv に含まれる引数の数
949: char **argv // 引数文字列へのポインタからなる配列へのポインタ
950: )
951: {
952: CALLONCE_TESTPROC( test_IsValidArgcArgv ); // [テスト]
953:
954: VALID_TEST( 0 <= argc );
955: VALID_TEST( IsValidPtr( argv, (1 + argc) * sizeof( *argv ) ) );
956: VALID_TEST( !argv[ argc ] );
957:
958: //
959: {for( int i = 0; i < argc; ++i )
960: {
961: VALID_TEST( IsValidStringPtr( argv[ i ] ) );
962: }}
963:
964: return true;
965: }//IsValidArgcArgv
966:
967: //*********************************************************
968: // IsValidCodePtr
969: //*********************************************************
970: bool
971: IsValidCodePtr
972: (
973: void *proc
974: )
975: {
976: VALID_TEST( proc );
977: VALID_TEST( !IsBadCodePtr( static_cast<FARPROC>( proc ) ) );
978:
979: return true;
980: }//IsValidCodePtr
981:
982: //*********************************************************
983: // IsValidCommandLineString
984: //*********************************************************
985: bool
986: IsValidCommandLineString
987: (
988: const char *string
989: )
990: {
991: CALLONCE_TESTPROC( test_pathname ); // [テスト]
992:
993: VALID_TEST( IsValidStringPtr( string ) );
994: // VALID_TEST( strlen(string) <= MAX_CMDLINE );
995: VALID_TEST( ! jmspbrk( string, INVALID_COMMANDLINECHARS ) );
996:
997: return true;
998: }//IsValidCommandLineString
999:
1000: //*********************************************************
1001: // IsValidDate
1002: //*********************************************************
1003: bool // 妥当であれば 真
1004: IsValidDate
1005: (
1006: int year, // 年 西暦
1007: int month, // 月 1-12
1008: int day // 日 1-31
1009: )
1010: {
1011: CALLONCE_TESTPROC( test_time ); // [テスト]
1012:
1013: // 月が妥当か
1014: VALID_TEST( (1 <= month) && (month <= 12) );
1015:
1016: // 日が妥当か
1017: const int days = GetMonthDays( year, month );
1018: VALID_TEST( (1 <= day) && (day <= days) );
1019:
1020: return true;
1021: }//IsValidDate
1022:
1023: //*********************************************************
1024: // IsValidFilePtr
1025: //*********************************************************
1026: bool
1027: IsValidFilePtr
1028: (
1029: FILE *fp
1030: )
1031: {
1032: VALID_TEST( IsValidPtr( fp, sizeof( *fp ) ) );
1033:
1034: return true;
1035: }//IsValidFilePtr
1036:
1037: //*********************************************************
1038: // IsValidLengthStringPtr
1039: //*********************************************************
1040: bool
1041: IsValidLengthStringPtr
1042: (
1043: const char *str,
1044: size_t // length
1045: )
1046: {
1047: VALID_TEST( str );
1048: // VALID_TEST( !IsBadStringPtr( str, length ) );
1049:
1050: return true;
1051: }//IsValidLengthStringPtr
1052:
1053: //*********************************************************
1054: // IsValidLocalPathMaskString
1055: //*********************************************************
1056: bool
1057: IsValidLocalPathMaskString
1058: (
1059: const char *mask
1060: )
1061: {
1062: CALLONCE_TESTPROC( test_pathname ); // [テスト]
1063:
1064: VALID_TEST( IsValidStringPtr( mask ) );
1065: VALID_TEST( strlen( mask ) <= MAX_PATH );
1066: VALID_TEST( IsValidCommandLineString( mask ) );
1067: VALID_TEST( ! jmspbrk( mask, INVALID_PATHMASKCHARS ) );
1068:
1069: return true;
1070: }//IsValidLocalPathMaskString
1071:
1072: //*********************************************************
1073: // IsValidLocalPathString
1074: //*********************************************************
1075: bool
1076: IsValidLocalPathString
1077: (
1078: const char *path
1079: )
1080: {
1081: CALLONCE_TESTPROC( test_pathname ); // [テスト]
1082:
1083: VALID_TEST( IsValidStringPtr( path ) );
1084: VALID_TEST( strlen( path ) <= MAX_PATH );
1085: VALID_TEST( IsValidCommandLineString( path ) );
1086: VALID_TEST( IsValidLocalPathMaskString( path ) );
1087: VALID_TEST( ! jmspbrk( path, INVALID_PATHCHARS ) );
1088:
1089: return true;
1090: }//IsValidLocalPathString
1091:
1092: //*********************************************************
1093: // IsValidPtr
1094: //*********************************************************
1095: bool
1096: IsValidPtr
1097: (
1098: void *ptr, //
1099: size_t size // バイト数
1100: )
1101: {
1102: VALID_TEST( ptr );
1103: VALID_TEST( IsValidReadPtr( ptr, size ) );
1104: VALID_TEST( IsValidWritePtr( ptr, size ) );
1105:
1106: return true;
1107: }//IsValidPtr
1108:
1109: //*********************************************************
1110: // IsValidReadPtr
1111: //*********************************************************
1112: bool
1113: IsValidReadPtr
1114: (
1115: const void *ptr, //
1116: size_t size // バイト数
1117: )
1118: {
1119: VALID_TEST( ptr );
1120: VALID_TEST( !IsBadReadPtr( ptr, size ) );
1121:
1122: return true;
1123: }//IsValidReadPtr
1124:
1125: //*********************************************************
1126: // IsValidStringBufferPtr
1127: // 大概は DESTROY_TEXT_BUFFER() とセットで使うことになる
1128: //*********************************************************
1129: bool
1130: IsValidStringBufferPtr
1131: (
1132: char *ptr, //
1133: size_t count // 要素数
1134: )
1135: {
1136: VALID_TEST( IsValidPtr( ptr, count * sizeof( *ptr ) ) );
1137:
1138: return true;
1139: }//IsValidStringBufferPtr
1140:
1141: //*********************************************************
1142: // IsValidStringPtr
1143: //*********************************************************
1144: bool
1145: IsValidStringPtr
1146: (
1147: const char *str
1148: )
1149: {
1150: VALID_TEST( str );
1151: VALID_TEST( IsValidLengthStringPtr( str, SCHAR_MAX ) );
1152:
1153: return true;
1154: }//IsValidStringPtr
1155:
1156: //*********************************************************
1157: // IsValidWritePtr
1158: //*********************************************************
1159: bool
1160: IsValidWritePtr
1161: (
1162: void *ptr, //
1163: size_t size // バイト数
1164: )
1165: {
1166: VALID_TEST( ptr );
1167: VALID_TEST( !IsBadWritePtr( ptr, size ) );
1168:
1169: // 実際に書き込んでみてエラーが起きないか様子を見る
1170: { BYTE *p = static_cast<BYTE *>( ptr ); {for( size_t n = size; 0 < n; --n ){ *p++ ^= 0xFF; }} }
1171:
1172: // 元に戻す
1173: { BYTE *p = static_cast<BYTE *>( ptr ); {for( size_t n = size; 0 < n; --n ){ *p++ ^= 0xFF; }} }
1174:
1175: return true;
1176: }//IsValidWritePtr
1177:
1178:
1179: //------------------------------------------------------------------------------------------------------------------
1180: // j
1181: //------------------------------------------------------------------------------------------------------------------
1182: //*********************************************************
1183: // jmscode
1184: // 文字 p の文字コード値を取得
1185: //*********************************************************
1186: int
1187: jmscode
1188: (
1189: const char *p
1190: )
1191: {
1192: CALLONCE_TESTPROC( test_str ); // [テスト]
1193:
1194: // パラメタの仮定
1195: ASSERT( IsValidStringPtr( p ) );
1196:
1197: if ( jms1( p[ 0 ] ) && ('\0' != p[ 1 ]) )
1198: {
1199: return MAKEDBC( p[ 0 ], p[ 1 ] );
1200: }
1201:
1202: ASSERT( !IsDBCSLeadByte( (BYTE)p[ 0 ] ) || ('\0' == p[ 1 ]) );
1203: return static_cast<unsigned char>( p[ 0 ] );
1204: }//jmscode
1205:
1206: //*********************************************************
1207: // jmsmatch
1208: // ワイルドカードが利用可能な文字列比較関数
1209: //*********************************************************
1210: bool
1211: jmsmatch
1212: (
1213: const char *ptn,
1214: const char *str
1215: )
1216: {
1217: CALLONCE_TESTPROC( test_str ); // [テスト]
1218:
1219: // パラメタの仮定
1220: ASSERT( IsValidStringPtr( ptn ) );
1221: ASSERT( IsValidStringPtr( str ) );
1222: // ASSERT( (str > strtail(ptn)) || (ptn > strtail(str)) );
1223:
1224: switch( jmscode(ptn) )
1225: {
1226: case '\0':
1227: return '\0' == *str;
1228: case '*':
1229: return jmsmatch( jmsnext(ptn), str ) || (('\0' != *str) && jmsmatch( ptn, jmsnext(str) ));
1230: case '?':
1231: return ('\0' != *str) && jmsmatch( jmsnext(ptn), jmsnext(str) );
1232: default:
1233: return (jmscode(ptn) == jmscode(str)) && jmsmatch( jmsnext(ptn), jmsnext(str) );
1234: }
1235: }//jmsmatch
1236:
1237: //*********************************************************
1238: // jmsnext
1239: // 文字 p の次の文字へのポインタを取得
1240: // 文字 p が文字列終端文字 '\0' である場合は '\0' へのポインタ返します
1241: //*********************************************************
1242: char *
1243: jmsnext
1244: (
1245: const char *p
1246: )
1247: {
1248: CALLONCE_TESTPROC( test_str ); // [テスト]
1249:
1250: // パラメタの仮定
1251: ASSERT( IsValidStringPtr( p ) );
1252:
1253: // 文字列終端文字 '\0' であれば '\0' へのポインタを返す
1254: if ( '\0' == *p )
1255: {
1256: return const_cast<char *>( p );
1257: }
1258:
1259: // 2バイト文字であれば2バイト進める
1260: if ( jms1( p[0] ) && ('\0' != p[1]) )
1261: {
1262: return const_cast<char *>(p + 2);
1263: }
1264:
1265: // 2バイト文字でなければ1バイト進める
1266: ASSERT( !IsDBCSLeadByte( (BYTE)p[0] ) || ('\0' == p[1]) );
1267: return const_cast<char *>(p + 1);
1268: }//jmsnext
1269:
1270: //*********************************************************
1271: // jmschr()
1272: // 文字列 から 文字 を検索する。
1273: // 最初 に現れた文字への ポインタ を返す。
1274: // 文字が見つからない場合は null を返す。
1275: // 文字列終端文字 '\0' も検索対象となる。
1276: //
1277: // const char *string
1278: // 検索対象となる文字列
1279: //
1280: // int c
1281: // 文字列から検索する文字
1282: //
1283: //*********************************************************
1284: char * // 文字へのポインタ
1285: jmschr
1286: (
1287: const char *string, // 検索対象文字列
1288: int c // 検索文字
1289: )
1290: {
1291: CALLONCE_TESTPROC( test_str ); // [テスト]
1292:
1293: // パラメタの仮定
1294: ASSERT( IsValidStringPtr( string ) );
1295: ASSERT( IS_VALID_DBCS_CHAR_CODE( c ) );
1296:
1297: // 検索文字を見つけるまでポインタを進める
1298: const char *p = string;
1299: while( ! chreql( c, strcode( p ) ) )
1300: {
1301: if ( '\0' == *p )
1302: {
1303: ASSERT( p == strtail( string ) );
1304: return null;
1305: }
1306:
1307: p = strnext( p );
1308: ASSERT( (string < p) && (p <= strtail( string )) );
1309: }
1310:
1311: ASSERT( (string <= p) && (p <= strtail( string )) );
1312: ASSERT( chreql( c, strcode( p ) ) );
1313: return const_cast<char *>( p );
1314: }//jmschr
1315:
1316: //*********************************************************
1317: // jmsrchr()
1318: // 文字列 から 文字 を検索する。
1319: // 最後 に現れた文字への ポインタ を返す。
1320: // 文字が見つからない場合は null を返す。
1321: // 文字列終端文字 '\0' も検索対象となる。
1322: //
1323: // const char *string
1324: // 検索対象となる文字列
1325: //
1326: // int c
1327: // 文字列から検索する文字
1328: //
1329: //*********************************************************
1330: char * // 文字へのポインタ
1331: jmsrchr
1332: (
1333: const char *string, // 検索対象文字列
1334: int c // 検索文字
1335: )
1336: {
1337: CALLONCE_TESTPROC( test_str ); // [テスト]
1338:
1339: // パラメタの仮定
1340: ASSERT( IsValidStringPtr( string ) );
1341: ASSERT( IS_VALID_DBCS_CHAR_CODE( c ) );
1342:
1343: // 文字列終端に達するまで検索を繰り返す。
1344: const char *last = null;
1345: {for( const char *p = string; null != (p = jmschr( p, c )); )
1346: {
1347: ASSERT( (string <= p) && (p <= strtail( string )) );
1348: last = p;
1349:
1350: if ( '\0' == *p )
1351: {
1352: ASSERT( '\0' == c );
1353: ASSERT( p == strtail( string ) );
1354: ASSERT( (string <= last) && (last == p) );
1355: return const_cast<char *>( last );
1356: }
1357:
1358: p = strnext( p );
1359: ASSERT( (string <= last) && (last < p) && (p <= strtail( string )) );
1360: }}
1361:
1362: ASSERT( !last || ((string <= last) && (last <= strtail( string ))) );
1363: ASSERT( !last || chreql( c, strcode( last ) ) );
1364: return const_cast<char *>( last );
1365: }//jmsrchr
1366:
1367: //*********************************************************
1368: // jmsstr()
1369: // 文字列 から 文字列 を検索する。
1370: // 最初 に現れた文字列の先頭を指す ポインタ を返す。
1371: // 文字列が見つからない場合は null を返す。
1372: // pattern が 空文字列 の場合は常に string を返す。
1373: // 文字列終端文字 '\0' は検索対象とならない。
1374: //
1375: // const char *string
1376: // 検索対象となる文字列
1377: //
1378: // const char *pattern
1379: // 文字列から検索する文字列
1380: //
1381: //*********************************************************
1382: char * // 文字列へのポインタ
1383: jmsstr
1384: (
1385: const char *string, // 検索対象文字列
1386: const char *pattern // 検索する文字列
1387: )
1388: {
1389: CALLONCE_TESTPROC( test_str ); // [テスト]
1390:
1391: // パラメタの仮定
1392: ASSERT( IsValidStringPtr( string ) );
1393: ASSERT( IsValidStringPtr( pattern ) );
1394:
1395: // pattern が空文字列の場合は string を返す。
1396: if ( '\0' == pattern[ 0 ] )
1397: {
1398: return const_cast<char *>( string );
1399: }
1400:
1401: // 最初に現れた pattern へのポインタを返す。
1402: const size_t length = strlen( pattern );
1403: {for( const char *p = string; null != (p = jmschr( p, strcode( pattern ) )); )
1404: {
1405: ASSERT( (string <= p) && (p < strtail( string )) );
1406:
1407: if ( strneql( p, pattern, length ) )
1408: {
1409: ASSERT( (string <= p) && (p + length <= strtail( string )) );
1410: return const_cast<char *>( p );
1411: }
1412:
1413: p = strnext( p );
1414: ASSERT( (string < p) && (p <= strtail( string )) );
1415: }}
1416:
1417: // pattern が見つからない場合は null を返す。
1418: return null;
1419: }//jmsstr
1420:
1421: //*********************************************************
1422: // jmspbrk()
1423: // 文字列 から 文字 を検索する。
1424: // 最初 に現れた文字群 ctrl に含まれる文字への ポインタ を返す。
1425: // 文字が見つからない場合は null を返す。
1426: // 文字列終端文字 '\0' は検索対象とならない。
1427: //
1428: // const char *base
1429: // 検索対象となる文字列。
1430: //
1431: // const char *ctrl
1432: // 検索する 文字群 を並べた文字列。
1433: // 文字列終端文字 '\0' は 文字群 に含まれない。
1434: //
1435: //*********************************************************
1436: char * // 文字へのポインタ
1437: jmspbrk
1438: (
1439: const char *base, // 検索対象文字列
1440: const char *ctrl // 検索文字群
1441: )
1442: {
1443: CALLONCE_TESTPROC( test_str ); // [テスト]
1444:
1445: // パラメタの仮定
1446: ASSERT( IsValidStringPtr( base ) );
1447: ASSERT( IsValidStringPtr( ctrl ) );
1448:
1449: // バイト列の長さが 0 であれば常に null を返す
1450: const size_t length = strlen( base );
1451: if ( length <= 0 )
1452: {
1453: return null;
1454: }
1455:
1456: // バイト列 ctrl に属さないバイトの長さ
1457: const size_t span = jmscspn( base, ctrl );
1458: if ( length <= span )
1459: {
1460: return null; // バイト列 base の全バイトがバイト列 ctrl に属さない
1461: }
1462:
1463: //
1464: return const_cast<char *>( base + span );
1465: }//jmspbrk
1466:
1467: //*********************************************************
1468: // jmscspn()
1469: // 文字列 から 文字 を検索する。
1470: // 最初 に現れた文字群 ctrl に含まれる文字までの バイト数 を返す。
1471: // 文字が見つからない場合は 文字列終端までのバイト数 を返す。
1472: // 文字列終端文字 '\0' は検索対象とならない。
1473: //
1474: // const char *base
1475: // 検索対象となる文字列。
1476: //
1477: // const char *ctrl
1478: // 検索する 文字群 を並べた文字列。
1479: // 文字列終端文字 '\0' は 文字群 に含まれない。
1480: //
1481: //*********************************************************
1482: size_t // 文字までのバイト数
1483: jmscspn
1484: (
1485: const char *base, // 検索対象文字列
1486: const char *ctrl // 検索文字群
1487: )
1488: {
1489: CALLONCE_TESTPROC( test_str ); // [テスト]
1490:
1491: // パラメタの仮定
1492: ASSERT( IsValidStringPtr( base ) );
1493: ASSERT( IsValidStringPtr( ctrl ) );
1494:
1495: //
1496: BYTE map[ STRMAP_SIZE ];
1497: make_strmap( map, sizeof( map ), ctrl );
1498:
1499: //
1500: const char *p = base;
1501: while( '\0' != *p )
1502: {
1503: const int c = strcode( p );
1504: if ( IS_VALID_CHAR_CODE( c )
1505: && (0 != GET_STRMAP_BIT( map, c )) )
1506: {
1507: return p - base;
1508: }
1509:
1510: p = strnext( p );
1511: }
1512:
1513: return p - base;
1514: }//jmscspn
1515:
1516: //*********************************************************
1517: // jmsspn()
1518: // 文字列 から 文字 を検索する。
1519: // 最初 に現れた文字群 ctrl に含まれない文字までの バイト数 を返す。
1520: // 文字が見つからない場合は 文字列終端までのバイト数 を返す。
1521: // 文字列終端文字 '\0' は検索対象とならない。
1522: //
1523: // const char *base
1524: // 検索対象となる文字列。
1525: //
1526: // const char *ctrl
1527: // 検索する 文字群 を並べた文字列。
1528: // 文字列終端文字 '\0' は 文字群 に含まれない。
1529: //
1530: //*********************************************************
1531: size_t // 文字までのバイト数
1532: jmsspn
1533: (
1534: const char *base, // 検索対象文字列
1535: const char *ctrl // 検索文字群
1536: )
1537: {
1538: CALLONCE_TESTPROC( test_str ); // [テスト]
1539:
1540: // パラメタの仮定
1541: ASSERT( IsValidStringPtr( base ) );
1542: ASSERT( IsValidStringPtr( ctrl ) );
1543:
1544: //
1545: BYTE map[ STRMAP_SIZE ];
1546: make_strmap( map, sizeof( map ), ctrl );
1547:
1548: //
1549: const char *p = base;
1550: while( '\0' != *p )
1551: {
1552: const int c = strcode( p );
1553: if ( ! IS_VALID_CHAR_CODE( c )
1554: || (0 == GET_STRMAP_BIT( map, c )) )
1555: {
1556: return p - base;
1557: }
1558:
1559: p = strnext( p );
1560: }
1561:
1562: return p - base;
1563: }//jmsspn
1564:
1565:
1566: //------------------------------------------------------------------------------------------------------------------
1567: // k
1568: //------------------------------------------------------------------------------------------------------------------
1569:
1570: //------------------------------------------------------------------------------------------------------------------
1571: // l
1572: //------------------------------------------------------------------------------------------------------------------
1573:
1574: //------------------------------------------------------------------------------------------------------------------
1575: // m
1576: //------------------------------------------------------------------------------------------------------------------
1577: //*********************************************************
1578: // MakeFullPath
1579: // path と filename からフルパス fullpath を作る
1580: //*********************************************************
1581: bool
1582: MakeFullPath
1583: (
1584: char *buffer,
1585: size_t bufsize,
1586: const char *base,
1587: const char *sub
1588: )
1589: {
1590: CALLONCE_TESTPROC( test_pathname ); // [テスト]
1591:
1592: // パラメタの仮定
1593: ASSERT( IsEnoughPathBufferSize( bufsize ) ); // [WARN]
1594: ASSERT( IsValidStringBufferPtr( buffer, bufsize ) );
1595: DESTROY_TEXT_BUFFER( buffer, bufsize ); // [破壊]
1596: ASSERT( IsValidLocalPathString( base ) );
1597: ASSERT( IsValidLocalPathMaskString( sub ) );
1598: ASSERT( ( strtail( base ) < buffer ) || ( buffer + bufsize <= base ) );
1599: ASSERT( ( strtail( sub ) < buffer ) || ( buffer + bufsize <= sub ) );
1600:
1601:
1602: //
1603: strcopy( buffer, bufsize, base );
1604: // MakeFullPath( buffer, bufsize, "", base );
1605:
1606: //
1607: char *buf = buffer;
1608: { char *tail = strrstr( buffer, "\\" ); buf = tail ? tail : buffer; }
1609:
1610: //
1611: const char *p = sub;
1612: const char *q = p;
1613: do
1614: {
1615: //
1616: ASSERT( p <= strtail( sub ) );
1617: q = p + jmscspn( p, "/\\" );
1618: ASSERT( ('\0' == *q) || ('\\' == *q) || ('/' == *q) );
1619: ASSERT( (p <= q) && (q <= strtail( sub )) );
1620:
1621: if ( (p < q) && strneql( ".", p, q-p ) )
1622: {
1623: nop();
1624: }
1625: else if ( (p < q) && strneql( "..", p, q-p ) )
1626: {
1627: //
1628: {
1629: char *backslash = strtstr( buf, "\\" );
1630: if ( backslash )
1631: {
1632: *backslash = '\0';
1633: }
1634: }
1635:
1636: //
1637: if ( '\0' == buffer[ 0 ] )
1638: {
1639: // これ以上は駆け上がることができない
1640: DESTROY_TEXT_BUFFER( buffer, bufsize ); // [破壊]
1641: return false;
1642: }
1643: else
1644: {
1645: char *backslash = strrstr( buffer, "\\" );
1646: if ( backslash )
1647: {
1648: *backslash = '\0';
1649: }
1650: else
1651: {
1652: buffer[ 0 ] = '\0';
1653: }
1654: }
1655:
1656: //
1657: { char *tail = strrstr( buffer, "\\" ); buf = tail ? tail : buffer; }
1658: }
1659: else
1660: {
1661: //
1662: if ( ('\0' != buffer[ 0 ]) && !IsPathTailSeparator( buf ) )
1663: {
1664: char *tail = strtail( buf );
1665: strcopy( tail, bufsize - (tail - buffer), "\\" );
1666: }
1667:
1668: //
1669: {
1670: char *tail = strtail( buf );
1671: strncopy( tail, bufsize - (tail - buffer), p, q - p );
1672: // tail[ min( ((size_t)(q - p)), (bufsize - (tail - buffer)) ) ]
1673: }
1674: }
1675:
1676: p = q + 1;
1677: }while( '\0' != *q );
1678:
1679: ASSERT( IsValidLocalPathMaskString( buffer ) );
1680: ASSERT( strlen( buffer ) < bufsize );
1681: return true;
1682: }//MakeFullPath
1683:
1684: //*********************************************************
1685: // memdup()
1686: // バイト列 base から size バイトを複製する。
1687: //*********************************************************
1688: void *
1689: memdup
1690: (
1691: const void *base,
1692: size_t size
1693: )
1694: {
1695: // パラメタの仮定
1696: ASSERT( 0 < size );
1697: ASSERT( IsValidReadPtr( base, size ) );
1698:
1699: void *p = (void *)malloc( size );
1700: if ( !p )
1701: {
1702: return null;
1703: }
1704:
1705: memmove( p, base, size );
1706:
1707: ASSERT( IsValidPtr( p, size ) );
1708: ASSERT( memeql( p, base, size ) );
1709: return p;
1710: }//memdup
1711:
1712: //*********************************************************
1713: // memeql()
1714: // バイト列 と バイト列 を比較する。
1715: // バイト列 p, q が一致すれば 真 を返す。
1716: //
1717: // const void *p
1718: // 比較するバイト列
1719: //
1720: // const void *q
1721: // 比較するバイト列
1722: //
1723: // size_t size
1724: // 比較するバイト長
1725: //
1726: //*********************************************************
1727: bool // 一致すれば 真
1728: memeql
1729: (
1730: const void *p,
1731: const void *q,
1732: size_t size
1733: )
1734: {
1735: CALLONCE_TESTPROC( test_memmem ); // [テスト]
1736:
1737: // パラメタの仮定
1738: // ASSERT( 0 < size );
1739: ASSERT( IsValidReadPtr( p, size ) );
1740: ASSERT( IsValidReadPtr( q, size ) );
1741:
1742: return 0 == memcmp( p, q, size );
1743: }//memeql
1744:
1745: //*********************************************************
1746: // memmem()
1747: // バイト列 から バイト列 を検索する。
1748: // 最初 に現れたバイト列の先頭を指す ポインタ を返す。
1749: // バイト列が見つからない場合は null を返す。
1750: // 検索バイト数が 0 の場合は常に null を返す。
1751: // 検索バイト列 pattern のバイト長が 0 の場合は常に base を返す。
1752: //
1753: // const char *base
1754: // 検索対象となる バイト列
1755: //
1756: // size_t count
1757: // 最大検索バイト数
1758: //
1759: // const void *pattern
1760: // 検索する バイト列
1761: //
1762: // size_t length
1763: // バイト列 pattern の バイト長
1764: //
1765: //*********************************************************
1766: void * // バイト列へのポインタ
1767: memmem
1768: (
1769: const void *base, // 検索対象バイト列
1770: size_t count, // 検索対象バイト数
1771: const void *pattern, // 検索するバイト列
1772: size_t length // バイト列 pattern のバイト長
1773: )
1774: {
1775: CALLONCE_TESTPROC( test_memmem ); // [テスト]
1776:
1777: // パラメタの仮定
1778: ASSERT( IsValidReadPtr( base, count ) );
1779: ASSERT( IsValidReadPtr( pattern, length ) );
1780:
1781: // 検索バイト数 0 では検索は常に失敗する。
1782: if ( count <= 0 )
1783: {
1784: return null;
1785: }
1786:
1787: // 最初に一致する位置を探す
1788: const BYTE *start = static_cast<const BYTE *>( base );
1789: {for( const BYTE *p = start; p + length <= start + count; ++p )
1790: {
1791: if ( memeql( p, pattern, length ) )
1792: {
1793: return const_cast<BYTE *>( p );
1794: }
1795: }}
1796:
1797: return null;
1798: }//memmem
1799:
1800: //*********************************************************
1801: // mempbrk()
1802: // バイト列 から 文字 を検索する。
1803: // 最初 に現れた文字群 ctrl に含まれる文字への ポインタ を返す。
1804: // 文字が見つからない場合は null を返す。
1805: // 文字列先頭から length バイト目までを検索する。
1806: // 検索バイト数が 0 の場合は常に null を返す。
1807: //
1808: // const char *base
1809: // 検索対象となる バイト列
1810: //
1811: // size_t length
1812: // 最大検索バイト数
1813: //
1814: // const char *ctrl
1815: // 検索する 文字群 を並べた バイト列
1816: //
1817: // size_t count
1818: // バイト列 ctrl[] の 要素数
1819: //
1820: //*********************************************************
1821: void * // バイトへのポインタ
1822: mempbrk
1823: (
1824: const void *base, // 検索対象バイト列
1825: size_t length, // 検索対象バイト数
1826: const char *ctrl, // 検索バイト群
1827: size_t count // バイト群 ctrl の 要素数
1828: )
1829: {
1830: CALLONCE_TESTPROC( test_memmem ); // [テスト]
1831:
1832: // パラメタの仮定
1833: ASSERT( IsValidReadPtr( base, length ) );
1834: ASSERT( IsValidReadPtr( ctrl, count ) );
1835:
1836: // バイト列の長さが 0 であれば常に null を返す
1837: if ( length <= 0 )
1838: {
1839: return null;
1840: }
1841:
1842: // バイト列 ctrl に属さないバイトの長さ
1843: const size_t span = memcspn( base, length, ctrl, count );
1844: if ( length <= span )
1845: {
1846: return null; // バイト列 base の全バイトがバイト列 ctrl に属さない
1847: }
1848:
1849: //
1850: const BYTE *p = static_cast<const BYTE *>( base );
1851: return const_cast<BYTE *>( p + span );
1852: }//mempbrk
1853:
1854: //*********************************************************
1855: // memcspn()
1856: // バイト列 から 文字 を検索する。
1857: // 最初 に現れた文字群 ctrl に含まれる文字までの バイト数 を返す。
1858: // 文字が見つからない場合は length を返す。
1859: // 文字列先頭から length バイト目までを検索する。
1860: //
1861: // const char *base
1862: // 検索対象となる バイト列
1863: //
1864: // size_t length
1865: // 最大検索バイト数
1866: //
1867: // const char *ctrl
1868: // 検索する 文字群 を並べた バイト列
1869: //
1870: // size_t count
1871: // バイト列 ctrl[] の 要素数
1872: //
1873: //*********************************************************
1874: size_t // 文字までのバイト数
1875: memcspn
1876: (
1877: const void *base, // 検索対象バイト列
1878: size_t length, // 検索対象バイト数
1879: const char *ctrl, // 検索バイト群
1880: size_t count // バイト群 ctrl の 要素数
1881: )
1882: {
1883: CALLONCE_TESTPROC( test_memmem ); // [テスト]
1884:
1885: // パラメタの仮定
1886: ASSERT( IsValidReadPtr( base, length ) );
1887: ASSERT( IsValidReadPtr( ctrl, count ) );
1888:
1889: //
1890: BYTE map[ MEMMAP_SIZE ];
1891: make_memmap( map, sizeof( map ), ctrl, count );
1892:
1893: //
1894: const BYTE *p = static_cast<const BYTE *>( base );
1895: {for( size_t n = length; 0 < n; --n, ++p )
1896: {
1897: const BYTE c = *p;
1898: if ( 0 != GET_MEMMAP_BIT( map, c ) )
1899: {
1900: ASSERT( ((BYTE *)base <= p) && (p < ((BYTE *)base) + length) );
1901: return p - (BYTE *)base;
1902: }
1903: }}
1904:
1905: return length;
1906: }//memcspn
1907:
1908: //*********************************************************
1909: // memspn()
1910: // バイト列 から 文字 を検索する。
1911: // 最初 に現れた文字群 ctrl に含まれない文字までの バイト数 を返す。
1912: // 文字が見つからない場合は length を返す。
1913: // 文字列先頭から length バイト目までを検索する。
1914: //
1915: // const char *base
1916: // 検索対象となる バイト列
1917: //
1918: // size_t length
1919: // 最大検索バイト数
1920: //
1921: // const char *ctrl
1922: // 検索する 文字群 を並べた バイト列
1923: //
1924: // size_t count
1925: // バイト列 ctrl[] の 要素数
1926: //
1927: //*********************************************************
1928: size_t // 文字までのバイト数
1929: memspn
1930: (
1931: const void *base, // 検索対象バイト列
1932: size_t length, // 検索対象バイト数
1933: const char *ctrl, // 検索バイト群
1934: size_t count // バイト群 ctrl の 要素数
1935: )
1936: {
1937: CALLONCE_TESTPROC( test_memmem ); // [テスト]
1938:
1939: // パラメタの仮定
1940: ASSERT( IsValidReadPtr( base, length ) );
1941: ASSERT( IsValidReadPtr( ctrl, count ) );
1942:
1943: //
1944: BYTE map[ MEMMAP_SIZE ];
1945: make_memmap( map, sizeof( map ), ctrl, count );
1946:
1947: //
1948: const BYTE *p = static_cast<const BYTE *>( base );
1949: {for( size_t n = length; 0 < n; --n, ++p )
1950: {
1951: const BYTE c = *p;
1952: if ( 0 == GET_MEMMAP_BIT( map, c ) )
1953: {
1954: ASSERT( ((BYTE *)base <= p) && (p < ((BYTE *)base) + length) );
1955: return p - (BYTE *)base;
1956: }
1957: }}
1958:
1959: return length;
1960: }//memspn
1961:
1962: //*********************************************************
1963: // memswap()
1964: // 2つのオブジェクト va, vb の内容を交換する。
1965: // 重複する領域の交換は未定義。
1966: //
1967: // void *va
1968: // オブジェクトへのポインタ
1969: //
1970: // void *vb
1971: // オブジェクトへのポインタ
1972: //
1973: // size_t size
1974: // オブジェクトのサイズを バイト数 で指定する。
1975: //
1976: //*********************************************************
1977: void
1978: memswap
1979: (
1980: void *va, // オブジェクトへのポインタ
1981: void *vb, // オブジェクトへのポインタ
1982: size_t size // オブジェクトのバイト数
1983: )
1984: {
1985: // パラメタの仮定
1986: ASSERT( IsValidPtr( va, size ) );
1987: ASSERT( IsValidPtr( vb, size ) );
1988: ASSERT( ( ((BYTE *)va + size) <= (BYTE *)vb )
1989: || ( ((BYTE *)vb + size) <= (BYTE *)va ) );
1990:
1991: BYTE *ca = static_cast<BYTE *>( va );
1992: BYTE *cb = static_cast<BYTE *>( vb );
1993: {for( ; 0 < size; --size, ++ca, ++cb )
1994: {
1995: // バイト値を交換する
1996: BYTE tmp = *ca;
1997: *ca = *cb;
1998: *cb = tmp;
1999: }}
2000:
2001: }//memswap
2002:
2003: //*********************************************************
2004: // memzero()
2005: // バッファ p の先頭 size バイトを値 0 で初期化する。
2006: // 初期化した配列末尾の直後への ポインタ を返す。
2007: //
2008: // void *p
2009: // バッファへのポインタ
2010: //
2011: // size_t size
2012: // 初期化するバイト数
2013: //
2014: //*********************************************************
2015: void *
2016: memzero
2017: (
2018: void *p, // バッファへのポインタ
2019: size_t size // 初期化するバイト数
2020: )
2021: {
2022: // パラメタの仮定
2023: ASSERT( 0 < size );
2024: ASSERT( IsValidPtr( p, size ) );
2025:
2026: memset( p, 0, size );
2027:
2028: return static_cast<BYTE *>( p ) + size;
2029: }//memzero
2030:
2031: //*********************************************************
2032: // memreverse()
2033: // 配列 array[] の要素を逆順に並べ替える。
2034: // 転置後の要素で配列 array[] を上書きする。
2035: // 置換した配列末尾の直後への ポインタ を返す。
2036: //
2037: // void *array
2038: // 並べ替える配列へのポインタ。
2039: // 転置後の配列を受け取るバッファ。
2040: //
2041: // size_t num
2042: // 配列 array[] の 要素数 。
2043: //
2044: // size_t size
2045: // 配列 array[] の各要素の バイト数 。
2046: //
2047: //*********************************************************
2048: void * // 配列直後へのポインタ
2049: memreverse
2050: (
2051: void *array, // 並べ替える配列
2052: size_t num, // 要素数
2053: size_t size // 各要素のバイト数
2054: )
2055: {
2056: // パラメタの仮定
2057: ASSERT( 0 < num );
2058: ASSERT( 0 < size );
2059: ASSERT( IsValidPtr( array, num * size ) );
2060:
2061: BYTE *l = static_cast<BYTE *>( array );
2062: BYTE *r = static_cast<BYTE *>( array ) + (size * (num-1));
2063: while( l < r )
2064: {
2065: memswap( l, r, size );
2066: l += size;
2067: r -= size;
2068: }
2069:
2070: return static_cast<BYTE *>( array ) + (num * size);
2071: }//memreverse
2072:
2073: //*********************************************************
2074: // memlrotate()
2075: // 配列 array の要素を左方向に要素 shift 個分だけ回転移動する
2076: // 配列は大きさ size の要素 num 個で構成される
2077: //*********************************************************
2078: void
2079: memlrotate
2080: (
2081: void *array,
2082: size_t shift,
2083: size_t num,
2084: size_t size
2085: )
2086: {
2087: // パラメタの仮定
2088: ASSERT( 0 < num );
2089: ASSERT( 0 < size );
2090: ASSERT( (0 < shift) && (shift < num) );
2091: ASSERT( IsValidPtr( array, num * size ) );
2092:
2093: memreverse( array, shift, size );
2094: memreverse( (BYTE *)array + (size * shift), num - shift, size );
2095: memreverse( array, num, size );
2096: }//memlrotate
2097:
2098: //*********************************************************
2099: // memrrotate()
2100: // 配列 array の要素を右方向に要素 shift 個分だけ回転移動する
2101: // 配列は大きさ size の要素 num 個で構成される
2102: //*********************************************************
2103: void
2104: memrrotate
2105: (
2106: void *array,
2107: size_t shift,
2108: size_t num,
2109: size_t size
2110: )
2111: {
2112: // パラメタの仮定
2113: ASSERT( 0 < num );
2114: ASSERT( 0 < size );
2115: ASSERT( (0 < shift) && (shift < num) );
2116: ASSERT( IsValidPtr( array, num * size ) );
2117:
2118: memreverse( array, num, size );
2119: memreverse( array, shift, size );
2120: memreverse( (BYTE *)array + (size * shift), num - shift, size );
2121: }//memrrotate
2122:
2123:
2124: //------------------------------------------------------------------------------------------------------------------
2125: // n
2126: //------------------------------------------------------------------------------------------------------------------
2127:
2128: //------------------------------------------------------------------------------------------------------------------
2129: // o
2130: //------------------------------------------------------------------------------------------------------------------
2131:
2132: //------------------------------------------------------------------------------------------------------------------
2133: // p
2134: //------------------------------------------------------------------------------------------------------------------
2135:
2136: //------------------------------------------------------------------------------------------------------------------
2137: // q
2138: //------------------------------------------------------------------------------------------------------------------
2139:
2140: //------------------------------------------------------------------------------------------------------------------
2141: // r
2142: //------------------------------------------------------------------------------------------------------------------
2143: //------------------------------------------------------------------------------------------------------------------
2144: // s
2145: //------------------------------------------------------------------------------------------------------------------
2146: //*********************************************************
2147: // strcode
2148: //*********************************************************
2149: int
2150: strcode
2151: (
2152: const char *string
2153: )
2154: {
2155: CALLONCE_TESTPROC( test_str ); // [テスト]
2156:
2157: // パラメタの仮定
2158: ASSERT( IsValidStringPtr( string ) );
2159:
2160: const int code = jmscode( string );
2161: ASSERT( IS_VALID_DBCS_CHAR_CODE( code ) );
2162: return code;
2163: }//strcode
2164:
2165: //*********************************************************
2166: // strnext
2167: //*********************************************************
2168: char *
2169: strnext
2170: (
2171: const char *string
2172: )
2173: {
2174: CALLONCE_TESTPROC( test_str ); // [テスト]
2175:
2176: // パラメタの仮定
2177: ASSERT( IsValidStringPtr( string ) );
2178:
2179: return jmsnext( string );
2180: }//strnext
2181:
2182: //*********************************************************
2183: // strputc
2184: //*********************************************************
2185: size_t
2186: strputc
2187: (
2188: char *buffer,
2189: size_t bufsize,
2190: size_t offset,
2191: int c
2192: )
2193: {
2194: CALLONCE_TESTPROC( test_str ); // [テスト]
2195:
2196: // パラメタの仮定
2197: ASSERT( buffer || (0 == bufsize) );
2198: ASSERT( !buffer || (offset <= bufsize) );
2199: ASSERT( !buffer || IsValidStringBufferPtr( buffer, bufsize ) );
2200: ASSERT( IS_VALID_DBCS_CHAR_CODE( c ) );
2201:
2202: //
2203: size_t count = 0;
2204:
2205: //
2206: if ( !buffer )
2207: {
2208: count += 1;
2209: }
2210: else if ( offset < bufsize )
2211: {
2212: // 領域の破壊検査
2213: DESTROY_TEXT_BUFFER( buffer + offset, bufsize - offset ); // [破壊]
2214:
2215: buffer[ offset ] = static_cast<char>( c );
2216: count += 1;
2217: }
2218:
2219: //
2220: ASSERT( !buffer || (offset + count <= bufsize) || ((0 == count) && (offset == bufsize)) );
2221: ASSERT( !buffer || IsValidStringPtr( buffer ) );
2222: ASSERT( !buffer
2223: || (count == strputc( null, 0, offset, c ))
2224: || (bufsize <= offset + strputc( null, 0, offset, c )) );
2225: return count;
2226: }//strputc
2227:
2228: //*********************************************************
2229: // strputs
2230: // 終端文字は含まない
2231: //*********************************************************
2232: size_t
2233: strputs
2234: (
2235: char *buffer,
2236: size_t bufsize,
2237: size_t offset,
2238: const char *string
2239: )
2240: {
2241: CALLONCE_TESTPROC( test_str ); // [テスト]
2242:
2243: // パラメタの仮定
2244: ASSERT( IsValidStringPtr( string ) );
2245: ASSERT( buffer || (0 == bufsize) );
2246: ASSERT( !buffer || (offset <= bufsize) );
2247: ASSERT( !buffer || IsValidStringBufferPtr( buffer, bufsize ) );
2248: // ASSERT( !buffer || (DESTROY_TEXT_BUFFER( buffer, bufsize ), true) ); // [破壊] (offset == bufsize) で不適切
2249: ASSERT( !buffer
2250: || (strtail( string ) < buffer)
2251: || (buffer + bufsize < string) );
2252:
2253: //
2254: const size_t length = strlen( string );
2255: const size_t count = strnputs( buffer, bufsize, offset, string, length );
2256:
2257: ASSERT( !buffer || IsValidStringPtr( buffer ) );
2258: ASSERT( !buffer || (offset + count < bufsize) || ((0 == count) && (offset == bufsize)) );
2259: ASSERT( !buffer || (count == strlen( buffer + offset )) || ((0 == count) && (offset == bufsize)) );
2260: ASSERT( !buffer
2261: || (count == strputs( null, 0, offset, string ))
2262: || (bufsize <= offset + strputs( null, 0, offset, string )) );
2263: return count;
2264: }//strputs
2265:
2266: //*********************************************************
2267: // strnputs
2268: // 終端文字は含まない
2269: //*********************************************************
2270: size_t
2271: strnputs
2272: (
2273: char *buffer,
2274: size_t bufsize,
2275: size_t offset,
2276: const char *string,
2277: size_t n
2278: )
2279: {
2280: CALLONCE_TESTPROC( test_str ); // [テスト]
2281:
2282: // パラメタの仮定
2283: ASSERT( IsValidLengthStringPtr( string, n ) );
2284: ASSERT( buffer || (0 == bufsize) );
2285: ASSERT( !buffer || (offset <= bufsize) );
2286: ASSERT( !buffer || IsValidStringBufferPtr( buffer, bufsize ) );
2287: // ASSERT( !buffer || (DESTROY_TEXT_BUFFER( buffer, bufsize ), true) ); // [破壊] (offset == bufsize) で不適切
2288: ASSERT( !buffer
2289: || (strtail( string ) < buffer)
2290: || (buffer + bufsize < string) );
2291:
2292: //
2293: const size_t length = strnlen( string, n );
2294:
2295: //
2296: size_t count = 0;
2297: if ( !buffer )
2298: {
2299: count = length;
2300: }
2301: else if ( offset < bufsize )
2302: {
2303: // 領域の破壊検査
2304: DESTROY_TEXT_BUFFER( buffer + offset, bufsize - offset ); // [破壊]
2305:
2306: count = min( length, bufsize - offset - 1 );
2307: memmove( buffer + offset, string, count * sizeof( *buffer ) );
2308: buffer[ offset + count ] = '\0';
2309: }
2310:
2311: ASSERT( !buffer || IsValidStringPtr( buffer ) );
2312: ASSERT( !buffer || (offset + count < bufsize) || ((0 == count) && (offset == bufsize)) );
2313: // ASSERT( !buffer || (count == strlen( buffer + offset )) || ((0 == count) && (offset == bufsize)) );
2314: ASSERT( !buffer
2315: || (count == strnputs( null, 0, offset, string, n ))
2316: || (bufsize <= offset + strnputs( null, 0, offset, string, n )) );
2317: return count;
2318: }//strnputs
2319:
2320: //*********************************************************
2321: // strchop()
2322: // 文字列 string の最後の 1 byte を切り落とす
2323: // 切り落とした文字を返す
2324: // 文字列 string の長さが 0 であれば常に文字 '\0' を返す
2325: // [xyz] => [xy], z
2326: //*********************************************************
2327: int
2328: strchop
2329: (
2330: char *string
2331: )
2332: {
2333: CALLONCE_TESTPROC( test_str ); // [テスト]
2334:
2335: // パラメタの仮定
2336: ASSERT( IsValidStringPtr( string ) );
2337: ASSERT( IsValidStringBufferPtr( string, 1 + strlen(string) ) );
2338:
2339: const size_t length = strlen( string );
2340: if ( length <= 0 )
2341: {
2342: return '\0';
2343: }
2344:
2345: ASSERT( '\0' != string[ length-1 ] );
2346: const int c = string[ length-1 ];
2347: string[ length-1 ] = '\0';
2348:
2349: ASSERT( IsValidStringPtr( string ) );
2350: ASSERT( length == 1 + strlen( string ) );
2351: ASSERT( '\0' != c );
2352: return c;
2353: }//strchop
2354:
2355: //*********************************************************
2356: // strchri()
2357: // 文字列 から 文字 を検索する。
2358: // 最初 に現れた文字への ポインタ を返す。
2359: // 文字が見つからない場合は null を返す。
2360: // 文字列終端文字 '\0' も検索対象となる。
2361: // 半角英字 の 大文字と小文字 を区別しない。
2362: //
2363: // const char *string
2364: // 検索対象となる文字列
2365: //
2366: // int c
2367: // 文字列から検索する文字
2368: //
2369: //*********************************************************
2370: char * // 文字へのポインタ
2371: strchri
2372: (
2373: const char *string, // 検索対象文字列
2374: int c // 検索文字
2375: )
2376: {
2377: CALLONCE_TESTPROC( test_str ); // [テスト]
2378:
2379: // パラメタの仮定
2380: ASSERT( IsValidStringPtr( string ) );
2381: ASSERT( IS_VALID_DBCS_CHAR_CODE( c ) );
2382:
2383: // 検索文字を見つけるまでポインタを進める
2384: const char *p = string;
2385: while( ! chreqli( c, strcode( p ) ) )
2386: {
2387: ASSERT( (string <= p) && (p <= strtail( string )) );
2388:
2389: if ( '\0' == *p )
2390: {
2391: ASSERT( p == strtail( string ) );
2392: ASSERT( ! jmschr( string, c ) );
2393: return null;
2394: }
2395:
2396: p = strnext( p );
2397: ASSERT( (string < p) && (p <= strtail( string )) );
2398: }
2399:
2400: ASSERT( (string <= p) && (p <= strtail( string )) );
2401: ASSERT( chreqli( c, strcode( p ) ) );
2402: return const_cast<char *>( p );
2403: }//strchri
2404:
2405: //*********************************************************
2406: // strrchri()
2407: // 文字列 から 文字 を検索する。
2408: // 最後 に現れた文字への ポインタ を返す。
2409: // 文字が見つからない場合は null を返す。
2410: // 文字列終端文字 '\0' も検索対象となる。
2411: // 半角英字 の 大文字と小文字 を区別しない。
2412: //
2413: // const char *string
2414: // 検索対象となる文字列
2415: //
2416: // int c
2417: // 文字列から検索する文字
2418: //
2419: //*********************************************************
2420: char * // 文字へのポインタ
2421: strrchri
2422: (
2423: const char *string, // 検索対象文字列
2424: int c // 検索文字
2425: )
2426: {
2427: CALLONCE_TESTPROC( test_str ); // [テスト]
2428:
2429: // パラメタの仮定
2430: ASSERT( IsValidStringPtr( string ) );
2431: ASSERT( IS_VALID_DBCS_CHAR_CODE( c ) );
2432:
2433: // 文字列終端に達するまで検索を繰り返す。
2434: const char *last = null;
2435: {for( const char *p = string; null != (p = strchri( p, c )); )
2436: {
2437: ASSERT( (string <= p) && (p <= strtail( string )) );
2438: last = p;
2439:
2440: if ( '\0' == *p )
2441: {
2442: ASSERT( '\0' == c );
2443: ASSERT( p == strtail( string ) );
2444: ASSERT( (string <= last) && (last == p) );
2445: return const_cast<char *>( last );
2446: }
2447:
2448: p = strnext( p );
2449: ASSERT( (string <= last) && (last < p) && (p <= strtail( string )) );
2450: }}
2451:
2452: ASSERT( !last || ((string <= last) && (last <= strtail( string ))) );
2453: ASSERT( !last || chreqli( c, strcode( last ) ) );
2454: return const_cast<char *>( last );
2455: }//strrchri
2456:
2457: //*********************************************************
2458: // strcopy
2459: // 文字列 string を領域 buffer へ複写する
2460: // 領域 buffer に bufsize バイトを超えて複写することはない
2461: // 文字列の末尾には文字列終端文字 '\0' が付加される
2462: //*********************************************************
2463: void
2464: strcopy
2465: (
2466: char *buffer,
2467: size_t bufsize,
2468: const char *string
2469: )
2470: {
2471: CALLONCE_TESTPROC( test_str ); // [テスト]
2472:
2473: // パラメタの仮定
2474: ASSERT( IsValidStringPtr( string ) );
2475: ASSERT( IsValidStringBufferPtr( buffer, bufsize ) );
2476: ASSERT( ( strtail( string ) < buffer )
2477: || ( buffer + bufsize < string ) );
2478: DESTROY_TEXT_BUFFER( buffer, bufsize ); // [破壊]
2479:
2480: if ( 0 < bufsize )
2481: {
2482: if ( 2 == isJMS( string, bufsize-1 ) )
2483: {
2484: --bufsize;
2485: }
2486:
2487: if ( 0 < bufsize )
2488: {
2489: const size_t length = strnlen( string, bufsize - 1 );
2490: memmove( buffer, string, length * sizeof( *buffer ) );
2491: buffer[ length ] = '\0';
2492:
2493: ASSERT( IsValidStringPtr( buffer ) );
2494: ASSERT( strlen( buffer ) < bufsize );
2495: }
2496: }
2497:
2498: }//strcopy
2499:
2500: //*********************************************************
2501: // strncopy
2502: // 文字列 string を領域 buffer へ複写する
2503: // 領域 buffer に bufsize バイトを超えて複写することはない
2504: // 文字列の末尾には文字列終端文字 '\0' が付加される
2505: //*********************************************************
2506: void
2507: strncopy
2508: (
2509: char *buffer,
2510: size_t bufsize,
2511: const char *string,
2512: size_t count
2513: )
2514: {
2515: CALLONCE_TESTPROC( test_str ); // [テスト]
2516:
2517: // パラメタの仮定
2518: ASSERT( IsValidLengthStringPtr( string, count ) );
2519: ASSERT( IsValidStringBufferPtr( buffer, bufsize ) );
2520: ASSERT( ( strtail( string ) < buffer )
2521: || ( buffer + bufsize < string ) );
2522: DESTROY_TEXT_BUFFER( buffer, bufsize ); // [破壊]
2523:
2524: if ( 0 < bufsize )
2525: {
2526: if ( 2 == isJMS( string, bufsize-1 ) )
2527: {
2528: --bufsize;
2529: }
2530:
2531: if ( 0 < bufsize )
2532: {
2533: const size_t length = strnlen( string, min(count, bufsize - 1) );
2534: memmove( buffer, string, length * sizeof( *buffer ) );
2535: buffer[ length ] = '\0';
2536:
2537: ASSERT( IsValidStringPtr( buffer ) );
2538: ASSERT( strlen( buffer ) < bufsize );
2539: ASSERT( strlen( buffer ) <= count );
2540: }
2541: }
2542:
2543: }//strncopy
2544:
2545: //*********************************************************
2546: // strcount()
2547: // 文字列の 出現回数 を数える。
2548: // 文字列 string に現れる文字列 pattern の数を数える。
2549: //
2550: // const char *string
2551: // 検索対象となる文字列
2552: //
2553: // const char *pattern
2554: // 出現回数を数える文字
2555: //
2556: //*********************************************************
2557: int // 出現回数
2558: strcount
2559: (
2560: const char *string, // 検索対象文字列
2561: const char *pattern // 出現回数を数える文字
2562: )
2563: {
2564: CALLONCE_TESTPROC( test_str ); // [テスト]
2565:
2566: // パラメタの仮定
2567: ASSERT( IsValidStringPtr( string ) );
2568: ASSERT( IsValidStringPtr( pattern ) );
2569:
2570: const size_t length = strlen( pattern );
2571: if ( length <= 0 )
2572: {
2573: return 0;
2574: }
2575:
2576: int count = 0;
2577: while( null != (string = jmsstr( string, pattern )) )
2578: {
2579: ++count;
2580: string += length;
2581: }
2582:
2583: ASSERT( 0 <= count );
2584: return count;
2585: }//strcount
2586:
2587: //*********************************************************
2588: // StrAlloc
2589: //*********************************************************
2590: char *
2591: StrAlloc
2592: (
2593: const char *string
2594: )
2595: {
2596: CALLONCE_TESTPROC( test_str ); // [テスト]
2597:
2598: // パラメタの仮定
2599: ASSERT( IsValidStringPtr( string ) );
2600:
2601: const size_t bufsize = 1 + strlen( string );
2602: char *p = (char *)malloc( bufsize * sizeof( *p ) );
2603: if ( !p )
2604: {
2605: return null;
2606: }
2607:
2608: strcopy( p, bufsize, string );
2609:
2610: ASSERT( IsValidStringPtr( p ) );
2611: ASSERT( streql( p, string ) );
2612: return p;
2613: }//StrAlloc
2614:
2615: //*********************************************************
2616: // strndup()
2617: //*********************************************************
2618: char *
2619: strndup
2620: (
2621: const char *string,
2622: size_t count
2623: )
2624: {
2625: CALLONCE_TESTPROC( test_str ); // [テスト]
2626:
2627: // パラメタの仮定
2628: ASSERT( IsValidLengthStringPtr( string, count ) );
2629:
2630: const size_t length = strnlen( string, count );
2631: const size_t bufsize = 1 + length;
2632: char *p = (char *)malloc( bufsize * sizeof( *p ) );
2633: if ( !p )
2634: {
2635: return null;
2636: }
2637:
2638: strcopy( p, bufsize, string );
2639: ASSERT( '\0' == p[ length ] );
2640: p[ length ] = '\0';
2641:
2642: ASSERT( IsValidStringPtr( p ) );
2643: ASSERT( strlen( p ) <= count );
2644: ASSERT( strneql( p, string, count ) );
2645: return p;
2646: }//strndup
2647:
2648: //*********************************************************
2649: // streql()
2650: // 文字列 と 文字列 を比較する。
2651: // 文字列 str1, str2 が一致すれば 真 を返す。
2652: // 文字列終端文字 '\0' も比較対象となる。
2653: // 半角英字 の 大文字と小文字 を区別する。
2654: //
2655: // const char *str1
2656: // 比較する文字列
2657: //
2658: // const char *str2
2659: // 比較する文字列
2660: //
2661: //*********************************************************
2662: bool // 一致すれば 真
2663: streql
2664: (
2665: const char *str1, // 文字列
2666: const char *str2 // 文字列
2667: )
2668: {
2669: CALLONCE_TESTPROC( test_str ); // [テスト]
2670:
2671: // パラメタの仮定
2672: ASSERT( IsValidStringPtr( str1 ) );
2673: ASSERT( IsValidStringPtr( str2 ) );
2674:
2675: return 0 == strcmp( str1, str2 );
2676: }//streql
2677:
2678: //*********************************************************
2679: // streqli()
2680: // 文字列 と 文字列 を比較する。
2681: // 文字列 str1, str2 が一致すれば 真 を返す。
2682: // 文字列終端文字 '\0' も比較対象となる。
2683: // 半角英字 の 大文字と小文字 を区別しない。
2684: //
2685: // const char *str1
2686: // 比較する文字列
2687: //
2688: // const char *str2
2689: // 比較する文字列
2690: //
2691: //*********************************************************
2692: bool // 一致すれば 真
2693: streqli
2694: (
2695: const char *str1, // 文字列
2696: const char *str2 // 文字列
2697: )
2698: {
2699: CALLONCE_TESTPROC( test_str ); // [テスト]
2700:
2701: // パラメタの仮定
2702: ASSERT( IsValidStringPtr( str1 ) );
2703: ASSERT( IsValidStringPtr( str2 ) );
2704:
2705: return 0 == _stricmp( str1, str2 );
2706: }//streqli
2707:
2708: //*********************************************************
2709: // strhstr()
2710: // 文字列 と 文字列 を比較する。
2711: // 文字列 string が文字列 pattern で始まっているならば 真 を返す。
2712: // pattern が 空文字列 の場合は常に 真 を返す。
2713: // 文字列終端文字 '\0' は比較対象とならない。
2714: // 半角英字 の 大文字と小文字 を区別する。
2715: //
2716: //*********************************************************
2717: bool
2718: strhstr
2719: (
2720: const char *string,
2721: const char *pattern
2722: )
2723: {
2724: CALLONCE_TESTPROC( test_str ); // [テスト]
2725:
2726: // パラメタの仮定
2727: ASSERT( IsValidStringPtr( string ) );
2728: ASSERT( IsValidStringPtr( pattern ) );
2729:
2730: const char *p = string;
2731: const char *q = pattern;
2732: while( '\0' != *q )
2733: {
2734: if ( ! chreql( strcode( p ), strcode( q ) ) )
2735: {
2736: ASSERT( string != jmsstr( string, pattern ) );
2737: return false;
2738: }
2739:
2740: p = strnext( p );
2741: q = strnext( q );
2742: }
2743:
2744: ASSERT( string == jmsstr( string, pattern ) );
2745: ASSERT( static_cast<size_t>(p - string) == strlen( pattern ) );
2746: return true;
2747: }//strhstr
2748:
2749: //*********************************************************
2750: // strhstri()
2751: // 文字列 と 文字列 を比較する。
2752: // 文字列 string が文字列 pattern で始まっているならば 真 を返す。
2753: // pattern が 空文字列 の場合は常に 真 を返す。
2754: // 文字列終端文字 '\0' は比較対象とならない。
2755: // 半角英字 の 大文字と小文字 を区別しない。
2756: //
2757: //*********************************************************
2758: bool
2759: strhstri
2760: (
2761: const char *string,
2762: const char *pattern
2763: )
2764: {
2765: CALLONCE_TESTPROC( test_str ); // [テスト]
2766:
2767: // パラメタの仮定
2768: ASSERT( IsValidStringPtr( string ) );
2769: ASSERT( IsValidStringPtr( pattern ) );
2770:
2771: return string == strstri( string, pattern );
2772: }//strhstri
2773:
2774: //*********************************************************
2775: // StrLower
2776: //*********************************************************
2777: void
2778: StrLower
2779: (
2780: char *string
2781: )
2782: {
2783: CALLONCE_TESTPROC( test_str ); // [テスト]
2784:
2785: // パラメタの仮定
2786: ASSERT( IsValidStringPtr( string ) );
2787: ASSERT( IsValidStringBufferPtr( string, 1 + strlen(string) ) );
2788:
2789: // 2バイト文字対策は大丈夫だろうか?
2790: {for( char *p = string; '\0' != *p; p = jmsnext(p) )
2791: {
2792: if ( IsUpper( *p ) )
2793: {
2794: ASSERT( IS_VALID_CHAR_CODE( *p ) );
2795: *p = static_cast<char>( ToLower( *p ) );
2796: ASSERT( IS_VALID_CHAR_CODE( *p ) );
2797: ASSERT( ! IsUpper( *p ) );
2798: }
2799: }}
2800:
2801: ASSERT( IsValidStringPtr( string ) );
2802: }//StrLower
2803:
2804: //*********************************************************
2805: // strmatch()
2806: // ワイルドカードが利用可能な文字列比較関数
2807: //*********************************************************
2808: bool
2809: strmatch
2810: (
2811: const char *ptn,
2812: const char *str
2813: )
2814: {
2815: CALLONCE_TESTPROC( test_str ); // [テスト]
2816:
2817: // パラメタの仮定
2818: ASSERT( IsValidStringPtr( ptn ) );
2819: ASSERT( IsValidStringPtr( str ) );
2820: // ASSERT( (str > strtail(ptn)) || (ptn > strtail(str)) );
2821:
2822: switch( *ptn )
2823: {
2824: case '\0':
2825: return '\0' == *str;
2826: case '*':
2827: return strmatch( ptn+1, str ) || (('\0' != *str) && strmatch( ptn, str+1 ));
2828: case '?':
2829: return ('\0' != *str) && strmatch( ptn+1, str+1 );
2830: default:
2831: return (*ptn == *str) && strmatch( ptn+1, str+1 );
2832: }
2833: }//strmatch
2834:
2835: //*********************************************************
2836: // strmove()
2837: // 文字列を buf に複写します。
2838: //*********************************************************
2839: char *
2840: strmove
2841: (
2842: char *buf, // 複写先の領域
2843: const char *str // 複写する文字列
2844: )
2845: {
2846: CALLONCE_TESTPROC( test_str ); // [テスト]
2847:
2848: // パラメタの仮定
2849: ASSERT( IsValidStringPtr( str ) );
2850: ASSERT( IsValidStringBufferPtr( buf, 1 + strlen(str) ) );
2851:
2852: const size_t length = strlen( str );
2853: memmove( buf, str, (1 + length) * sizeof( *str ) );
2854: return buf + length;
2855: }//strmove
2856:
2857: //*********************************************************
2858: // strnchr()
2859: // 文字列 から 文字 を検索する。
2860: // 最初 に現れた文字への ポインタ を返す。
2861: // 文字が見つからない場合は null を返す。
2862: // 文字列先頭から n バイト目までを検索する。
2863: // 検索バイト数が 0 の場合は常に null を返す。
2864: // 文字列終端文字 '\0' も検索対象となる。
2865: // 半角英字 の 大文字と小文字 を区別する。
2866: //
2867: // const char *string
2868: // 検索対象となる文字列
2869: //
2870: // int c
2871: // 文字列から検索する文字
2872: //
2873: // size_t n
2874: // 検索する最大バイト数
2875: //
2876: //*********************************************************
2877: char * // 文字へのポインタ
2878: strnchr
2879: (
2880: const char *string, // 検索対象文字列
2881: int c, // 検索文字
2882: size_t count // 最大検索バイト数
2883: )
2884: {
2885: CALLONCE_TESTPROC( test_str ); // [テスト]
2886:
2887: // パラメタの仮定
2888: ASSERT( IsValidLengthStringPtr( string, count ) );
2889: ASSERT( IS_VALID_DBCS_CHAR_CODE( c ) );
2890:
2891: // 検索バイト数 0 では検索は常に失敗する。
2892: if ( count <= 0 )
2893: {
2894: return null;
2895: }
2896:
2897: // 検索文字を見つけるまでポインタを進める
2898: const char *p = string;
2899: while( ! chreql( c, strcode( p ) ) )
2900: // while( ! chreql( c, strncode( p, n - (p - string) ) ) )
2901: {
2902: ASSERT( (string <= p) && (p <= strtail( string )) );
2903: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) < count) );
2904:
2905: if ( '\0' == *p )
2906: {
2907: return null;
2908: }
2909:
2910: p = strnext( p );
2911: ASSERT( (string < p) && (p <= strtail( string )) );
2912:
2913: if ( count <= static_cast<size_t>(p - string) )
2914: {
2915: return null;
2916: }
2917: }
2918:
2919: ASSERT( chreql( c, strcode( p ) ) );
2920: ASSERT( p == jmschr( string, c ) );
2921: ASSERT( (string <= p) && (p <= strtail( string )) );
2922: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) < count) );
2923: return const_cast<char *>( p );
2924: }//strnchr
2925:
2926: //*********************************************************
2927: // strnchri()
2928: // 文字列 から 文字 を検索する。
2929: // 最初 に現れた文字への ポインタ を返す。
2930: // 文字が見つからない場合は null を返す。
2931: // 文字列先頭から n バイト目までを検索する。
2932: // 検索バイト数が 0 の場合は常に null を返す。
2933: // 文字列終端文字 '\0' も検索対象となる。
2934: // 半角英字 の 大文字と小文字 を区別しない。
2935: //
2936: // const char *string
2937: // 検索対象となる文字列
2938: //
2939: // int c
2940: // 文字列から検索する文字
2941: //
2942: // size_t n
2943: // 検索する最大バイト数
2944: //
2945: //*********************************************************
2946: char * // 文字へのポインタ
2947: strnchri
2948: (
2949: const char *string, // 検索対象文字列
2950: int c, // 検索文字
2951: size_t count // 最大検索バイト数
2952: )
2953: {
2954: CALLONCE_TESTPROC( test_str ); // [テスト]
2955:
2956: // パラメタの仮定
2957: ASSERT( IsValidLengthStringPtr( string, count ) );
2958: ASSERT( IS_VALID_DBCS_CHAR_CODE( c ) );
2959:
2960: // 検索バイト数 0 では検索は常に失敗する。
2961: if ( count <= 0 )
2962: {
2963: return null;
2964: }
2965:
2966: // 検索文字を見つけるまでポインタを進める
2967: const char *p = string;
2968: while( ! chreqli( c, strcode( p ) ) )
2969: {
2970: ASSERT( (string <= p) && (p <= strtail( string )) );
2971: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) < count) );
2972:
2973: if ( '\0' == *p )
2974: {
2975: return null;
2976: }
2977:
2978: p = strnext( p );
2979: ASSERT( (string < p) && (p <= strtail( string )) );
2980:
2981: if ( count <= static_cast<size_t>(p - string) )
2982: {
2983: return null;
2984: }
2985: }
2986:
2987: ASSERT( chreqli( c, strcode( p ) ) );
2988: ASSERT( p == strchri( string, c ) );
2989: ASSERT( (string <= p) && (p <= strtail( string )) );
2990: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) < count) );
2991: return const_cast<char *>( p );
2992: }//strnchri
2993:
2994: //*********************************************************
2995: // strnrchr()
2996: // 文字列 から 文字 を検索する。
2997: // 最後 に現れた文字への ポインタ を返す。
2998: // 文字が見つからない場合は null を返す。
2999: // 文字列先頭から n バイト目までを検索する。
3000: // 検索バイト数が 0 の場合は常に null を返す。
3001: // 文字列終端文字 '\0' も検索対象となる。
3002: // 半角英字 の 大文字と小文字 を区別する。
3003: //
3004: // const char *string
3005: // 検索対象となる文字列
3006: //
3007: // int c
3008: // 文字列から検索する文字
3009: //
3010: // size_t n
3011: // 検索する最大バイト数
3012: //
3013: //*********************************************************
3014: char * // 文字へのポインタ
3015: strnrchr
3016: (
3017: const char *string, // 検索対象文字列
3018: int c, // 検索文字
3019: size_t count // 最大検索バイト数
3020: )
3021: {
3022: CALLONCE_TESTPROC( test_str ); // [テスト]
3023:
3024: // パラメタの仮定
3025: ASSERT( IsValidLengthStringPtr( string, count ) );
3026: ASSERT( IS_VALID_DBCS_CHAR_CODE( c ) );
3027:
3028: // 文字列終端に達するまで検索を繰り返す。
3029: const char *p = string;
3030: const char *last = null;
3031: while( (static_cast<size_t>(p - string) < count)
3032: && (null != (p = strnchr( p, c, count - (p - string) ))) )
3033: {
3034: ASSERT( (string <= p) && (p <= strtail( string )) );
3035: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) < count) );
3036: last = p;
3037:
3038: if ( '\0' == *p )
3039: {
3040: ASSERT( '\0' == c );
3041: ASSERT( p == strtail( string ) );
3042: ASSERT( (string <= last) && (last == p) );
3043: return const_cast<char *>( last );
3044: }
3045:
3046: p = strnext( p );
3047: ASSERT( (string <= last) && (last < p) && (p <= strtail( string )) );
3048: }
3049:
3050: ASSERT( !last || ((string <= last) && (last <= strtail( string ))) );
3051: ASSERT( !last || ((0 <= (last - string)) && (static_cast<size_t>(last - string) < count)) );
3052: return const_cast<char *>( last );
3053: }//strnrchr
3054:
3055: //*********************************************************
3056: // strnrchri()
3057: // 文字列 から 文字 を検索する。
3058: // 最後 に現れた文字への ポインタ を返す。
3059: // 文字が見つからない場合は null を返す。
3060: // 文字列先頭から n バイト目までを検索する。
3061: // 検索バイト数が 0 の場合は常に null を返す。
3062: // 文字列終端文字 '\0' も検索対象となる。
3063: // 半角英字 の 大文字と小文字 を区別しない。
3064: //
3065: // const char *string
3066: // 検索対象となる文字列
3067: //
3068: // int c
3069: // 文字列から検索する文字
3070: //
3071: // size_t n
3072: // 検索する最大バイト数
3073: //
3074: //*********************************************************
3075: char * // 文字へのポインタ
3076: strnrchri
3077: (
3078: const char *string, // 検索対象文字列
3079: int c, // 検索文字
3080: size_t count // 最大検索バイト数
3081: )
3082: {
3083: CALLONCE_TESTPROC( test_str ); // [テスト]
3084:
3085: // パラメタの仮定
3086: ASSERT( IsValidLengthStringPtr( string, count ) );
3087: ASSERT( IS_VALID_DBCS_CHAR_CODE( c ) );
3088:
3089: // 文字列終端に達するまで検索を繰り返す。
3090: const char *p = string;
3091: const char *last = null;
3092: while( (static_cast<size_t>(p - string) < count)
3093: && (null != (p = strnchri( p, c, count - (p - string) ))) )
3094: {
3095: ASSERT( (string <= p) && (p <= strtail( string )) );
3096: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) < count) );
3097: last = p;
3098:
3099: if ( '\0' == *p )
3100: {
3101: ASSERT( '\0' == c );
3102: ASSERT( p == strtail( string ) );
3103: ASSERT( (string <= last) && (last == p) );
3104: return const_cast<char *>( last );
3105: }
3106:
3107: p = strnext( p );
3108: ASSERT( (string <= last) && (last < p) && (p <= strtail( string )) );
3109: }
3110:
3111: ASSERT( !last || ((string <= last) && (last <= strtail( string ))) );
3112: ASSERT( !last || ((0 <= (last - string)) && (static_cast<size_t>(last - string) < count)) );
3113: return const_cast<char *>( last );
3114: }//strnrchri
3115:
3116: //*********************************************************
3117: // strneql()
3118: // 文字列 と 文字列 を比較する。
3119: // 文字列 str1, str2 が一致すれば 真 を返す。
3120: // 文字列先頭から count バイト目までを比較する。
3121: // 文字列終端文字 '\0' も比較対象となる。
3122: // 半角英字 の 大文字と小文字 を区別する。
3123: //
3124: // const char *str1
3125: // 比較する文字列
3126: //
3127: // const char *str2
3128: // 比較する文字列
3129: //
3130: // size_t count
3131: // 比較する最大バイト数
3132: //
3133: //*********************************************************
3134: bool // 一致すれば 真
3135: strneql
3136: (
3137: const char *str1, // 文字列
3138: const char *str2, // 文字列
3139: size_t count // 比較するバイト数
3140: )
3141: {
3142: CALLONCE_TESTPROC( test_str ); // [テスト]
3143:
3144: // パラメタの仮定
3145: ASSERT( IsValidLengthStringPtr( str1, count ) );
3146: ASSERT( IsValidLengthStringPtr( str2, count ) );
3147:
3148: const char *p = str1;
3149: const char *q = str2;
3150: while( (static_cast<size_t>(p - str1) < count)
3151: && (static_cast<size_t>(q - str2) < count) )
3152: {
3153: ASSERT( (p - str1) == (q - str2) );
3154:
3155: if ( ! chreql( strcode( p ), strcode( q ) ) )
3156: {
3157: ASSERT( 0 != strncmp( str1, str2, count ) );
3158: return false;
3159: }
3160:
3161: // 文字列が完全に一致すれば 真 を返す
3162: if ( ( '\0' == *p )
3163: && ( '\0' == *q ) )
3164: {
3165: ASSERT( 0 == strncmp( str1, str2, count ) );
3166: return true;
3167: }
3168:
3169: //
3170: p = strnext( p );
3171: q = strnext( q );
3172: ASSERT( (p - str1) == (q - str2) );
3173: }
3174:
3175: ASSERT( 0 == strncmp( str1, str2, count ) );
3176: return true;
3177: }//strneql
3178:
3179: //*********************************************************
3180: // strneqli()
3181: // 文字列 と 文字列 を比較する。
3182: // 文字列 str1, str2 が一致すれば 真 を返す。
3183: // 文字列先頭から count バイト目までを比較する。
3184: // 文字列終端文字 '\0' も比較対象となる。
3185: // 半角英字 の 大文字と小文字 を区別しない。
3186: //
3187: // const char *str1
3188: // 比較する文字列
3189: //
3190: // const char *str2
3191: // 比較する文字列
3192: //
3193: // size_t count
3194: // 比較する最大バイト数
3195: //
3196: //*********************************************************
3197: bool // 一致すれば 真
3198: strneqli
3199: (
3200: const char *str1, // 文字列
3201: const char *str2, // 文字列
3202: size_t count // 比較するバイト数
3203: )
3204: {
3205: CALLONCE_TESTPROC( test_str ); // [テスト]
3206:
3207: // パラメタの仮定
3208: ASSERT( IsValidLengthStringPtr( str1, count ) );
3209: ASSERT( IsValidLengthStringPtr( str2, count ) );
3210:
3211: const char *p = str1;
3212: const char *q = str2;
3213: while( (static_cast<size_t>(p - str1) < count)
3214: && (static_cast<size_t>(q - str2) < count) )
3215: {
3216: ASSERT( (p - str1) == (q - str2) );
3217:
3218: if ( ! chreqli( strcode( p ), strcode( q ) ) )
3219: {
3220: ASSERT( 0 != _strnicmp( str1, str2, count ) );
3221: return false;
3222: }
3223:
3224: // 文字列が完全に一致すれば 真 を返す
3225: if ( ( '\0' == *p )
3226: && ( '\0' == *q ) )
3227: {
3228: ASSERT( 0 == _strnicmp( str1, str2, count ) );
3229: return true;
3230: }
3231:
3232: //
3233: p = strnext( p );
3234: q = strnext( q );
3235: ASSERT( (p - str1) == (q - str2) );
3236: }
3237:
3238: ASSERT( 0 == _strnicmp( str1, str2, count ) );
3239: return true;
3240: }//strneqli
3241:
3242: //*********************************************************
3243: // strnlen()
3244: // 文字列の長さを求める。
3245: // 文字列長を バイト数 で返す。
3246: // 文字列長に文字列終端文字 '\0' は含まれない。
3247: //
3248: // const char *string
3249: // 長さを求める文字列
3250: //
3251: // size_t count
3252: // 最大長
3253: //
3254: //*********************************************************
3255: size_t // 文字列のバイト長
3256: strnlen
3257: (
3258: const char *string, // 長さを求める文字列
3259: size_t count // 最大長
3260: )
3261: {
3262: CALLONCE_TESTPROC( test_str ); // [テスト]
3263:
3264: // パラメタの仮定
3265: ASSERT( IsValidReadPtr( string, count ) );
3266:
3267: size_t n = count;
3268: const char *p = string;
3269: while( (0 < n) && ('\0' != *p) )
3270: {
3271: ++p;
3272: --n;
3273: }
3274:
3275: ASSERT( string <= p );
3276: const size_t length = p - string;
3277:
3278: ASSERT( length <= count );
3279: ASSERT( (count == length)
3280: || ('\0' == string[ length ]) );
3281: return length;
3282: }//strnlen
3283:
3284: //*********************************************************
3285: // strnpbrk()
3286: // 文字列 から 文字 を検索する。
3287: // 最初 に現れた文字群 ctrl に含まれる文字への ポインタ を返す。
3288: // 文字が見つからない場合は null を返す。
3289: // 文字列先頭から count バイト目までを検索する。
3290: // 検索バイト数が 0 の場合は常に null を返す。
3291: // 文字列終端文字 '\0' は検索対象とならない。
3292: //
3293: // const char *base
3294: // 検索対象となる文字列。
3295: //
3296: // const char *ctrl
3297: // 検索する 文字群 を並べた文字列。
3298: // 文字列終端文字 '\0' は 文字群 に含まれない。
3299: //
3300: // size_t count
3301: // 検索する最大バイト数。
3302: //
3303: //*********************************************************
3304: char * // 文字へのポインタ
3305: strnpbrk
3306: (
3307: const char *base, // 検索対象文字列
3308: const char *ctrl, // 検索文字群
3309: size_t count // 最大検索文字数
3310: )
3311: {
3312: CALLONCE_TESTPROC( test_str ); // [テスト]
3313:
3314: // パラメタの仮定
3315: ASSERT( IsValidLengthStringPtr( base, count ) );
3316: ASSERT( IsValidStringPtr( ctrl ) );
3317:
3318: // バイト列の長さが 0 であれば常に null を返す
3319: const size_t length = strnlen( base, count );
3320: if ( length <= 0 )
3321: {
3322: return null;
3323: }
3324:
3325: // バイト列 ctrl に属さないバイトの長さ
3326: const size_t span = strncspn( base, ctrl, count );
3327: if ( length <= span )
3328: {
3329: return null; // バイト列 base の全バイトがバイト列 ctrl に属さない
3330: }
3331:
3332: //
3333: return const_cast<char *>( base + span );
3334: }//strnpbrk
3335:
3336: //*********************************************************
3337: // strncspn()
3338: // 文字列 から 文字 を検索する。
3339: // 最初 に現れた文字群 ctrl に含まれる文字までの バイト数 を返す。
3340: // 文字が見つからない場合は 文字列終端までのバイト数 を返す。
3341: // 文字列先頭から count バイト目までを検索する。
3342: // 文字列終端文字 '\0' は検索対象とならない。
3343: //
3344: // const char *base
3345: // 検索対象となる文字列。
3346: //
3347: // const char *ctrl
3348: // 検索する 文字群 を並べた文字列。
3349: // 文字列終端文字 '\0' は 文字群 に含まれない。
3350: //
3351: // size_t count
3352: // 検索する最大バイト数。
3353: //
3354: //*********************************************************
3355: size_t // 文字までのバイト数
3356: strncspn
3357: (
3358: const char *string, // 検索対象文字列
3359: const char *ctrl, // 検索文字群
3360: size_t count // 最大検索文字数
3361: )
3362: {
3363: CALLONCE_TESTPROC( test_str ); // [テスト]
3364:
3365: // パラメタの仮定
3366: ASSERT( IsValidLengthStringPtr( string, count ) );
3367: ASSERT( IsValidStringPtr( ctrl ) );
3368:
3369: //
3370: BYTE map[ STRMAP_SIZE ];
3371: make_strmap( map, sizeof( map ), ctrl );
3372:
3373: //
3374: const char *p = string;
3375: while( ( static_cast<size_t>(p - string) < count )
3376: && ( '\0' != *p ) )
3377: {
3378: ASSERT( (string <= p) && (p <= strtail( string )) );
3379: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) < count) );
3380:
3381: const int c = strcode( p );
3382: if ( IS_VALID_CHAR_CODE( c )
3383: && (0 != GET_STRMAP_BIT( map, c )) )
3384: {
3385: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) < count) );
3386: return p - string;
3387: }
3388:
3389: p = strnext( p );
3390: ASSERT( (string <= p) && (p <= strtail( string )) );
3391: }
3392:
3393: ASSERT( (string <= p) && (p <= strtail( string )) );
3394: return min( count, static_cast<size_t>(p - string) );
3395: }//strncspn
3396:
3397: //*********************************************************
3398: // strnspn()
3399: // 文字列 から 文字 を検索する。
3400: // 最初 に現れた文字群 ctrl に含まれない文字までの バイト数 を返す。
3401: // 文字が見つからない場合は 文字列終端までのバイト数 を返す。
3402: // 文字列先頭から count バイト目までを検索する。
3403: // 文字列終端文字 '\0' は検索対象とならない。
3404: //
3405: // const char *string
3406: // 検索対象となる文字列。
3407: //
3408: // const char *ctrl
3409: // 検索する 文字群 を並べた文字列。
3410: // 文字列終端文字 '\0' は 文字群 に含まれない。
3411: //
3412: // size_t count
3413: // 検索する最大バイト数。
3414: //
3415: //*********************************************************
3416: size_t // 文字までのバイト数
3417: strnspn
3418: (
3419: const char *string, // 検索対象文字列
3420: const char *ctrl, // 検索文字群
3421: size_t count // 最大検索文字数
3422: )
3423: {
3424: CALLONCE_TESTPROC( test_str ); // [テスト]
3425:
3426: // パラメタの仮定
3427: ASSERT( IsValidLengthStringPtr( string, count ) );
3428: ASSERT( IsValidStringPtr( ctrl ) );
3429:
3430: //
3431: BYTE map[ STRMAP_SIZE ];
3432: make_strmap( map, sizeof( map ), ctrl );
3433:
3434: //
3435: const char *p = string;
3436: while( ( static_cast<size_t>(p - string) < count )
3437: && ( '\0' != *p ) )
3438: {
3439: ASSERT( (string <= p) && (p <= strtail( string )) );
3440: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) < count) );
3441:
3442: const int c = strcode( p );
3443: if ( ! IS_VALID_CHAR_CODE( c )
3444: || (0 == GET_STRMAP_BIT( map, c )) )
3445: {
3446: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) < count) );
3447: return p - string;
3448: }
3449:
3450: p = strnext( p );
3451: ASSERT( (string <= p) && (p <= strtail( string )) );
3452: }
3453:
3454: ASSERT( (string <= p) && (p <= strtail( string )) );
3455: return min( count, static_cast<size_t>(p - string) );
3456: }//strnspn
3457:
3458: //*********************************************************
3459: // strnrstr()
3460: // 文字列 から 文字列 を検索する。
3461: // 最後 に現れた文字列の先頭を指す ポインタ を返す。
3462: // 文字列が見つからない場合は null を返す。
3463: // 検索バイト数が 0 の場合は常に null を返す。
3464: // pattern が 空文字列 の場合は常に 文字列終端 を返す。
3465: // 文字列先頭から count バイト目までを検索する。
3466: // 文字列終端文字 '\0' は検索対象とならない。
3467: // 半角英字 の 大文字と小文字 を区別する。
3468: //
3469: // const char *string
3470: // 検索対象となる文字列
3471: //
3472: // const char *pattern
3473: // 文字列から検索する文字列
3474: //
3475: // size_t count
3476: // 検索する最大バイト数
3477: //
3478: //*********************************************************
3479: char * // 文字列へのポインタ
3480: strnrstr
3481: (
3482: const char *string, // 検索対象文字列
3483: const char *pattern, // 検索文字列
3484: size_t count // 最大検索バイト数
3485: )
3486: {
3487: CALLONCE_TESTPROC( test_str ); // [テスト]
3488:
3489: // パラメタの仮定
3490: ASSERT( IsValidLengthStringPtr( string, count ) );
3491: ASSERT( IsValidStringPtr( pattern ) );
3492:
3493: // 検索バイト数 0 では検索は常に失敗する。
3494: if ( count <= 0 )
3495: {
3496: return null;
3497: }
3498:
3499: // 検索バイト数 が 検索する文字列長 未満では検索は常に失敗する。
3500: const size_t length = strlen( pattern );
3501: if ( count < length )
3502: {
3503: return null;
3504: }
3505: ASSERT( length <= count );
3506:
3507: // 文字列終端に達するまで検索を繰り返す。
3508: const char *p = string;
3509: const char *last = null;
3510: while( (static_cast<size_t>(p - string) <= (count - length))
3511: && (null != (p = strnstr( p, pattern, count - (p - string) )))
3512: && (static_cast<size_t>(p - string) <= (count - length)) )
3513: {
3514: ASSERT( (string <= p) && (p <= strtail( string )) );
3515: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) <= (count - length)) );
3516: last = p;
3517:
3518: if ( '\0' == *p )
3519: {
3520: ASSERT( '\0' == pattern[ 0 ] );
3521: ASSERT( p == strtail( string ) );
3522: ASSERT( (string <= last) && (last == p) );
3523: return const_cast<char *>( last );
3524: }
3525:
3526: p = strnext( p );
3527: ASSERT( (string < p) && (p <= strtail( string )) );
3528: }
3529:
3530: ASSERT( !last || ((string <= last) && (last <= strtail( string ))) );
3531: ASSERT( !last || ((0 <= (last - string)) && (static_cast<size_t>(last - string) <= (count - length))) );
3532: return const_cast<char *>( last );
3533: }//strnrstr
3534:
3535: //*********************************************************
3536: // strnrstri()
3537: // 文字列 から 文字列 を検索する。
3538: // 最後 に現れた文字列の先頭を指す ポインタ を返す。
3539: // 文字列が見つからない場合は null を返す。
3540: // 検索バイト数が 0 の場合は常に null を返す。
3541: // pattern が 空文字列 の場合は常に 文字列終端 を返す。
3542: // 文字列先頭から count バイト目までを検索する。
3543: // 文字列終端文字 '\0' は検索対象とならない。
3544: // 半角英字 の 大文字と小文字 を区別しない。
3545: //
3546: // const char *string
3547: // 検索対象となる文字列
3548: //
3549: // const char *pattern
3550: // 文字列から検索する文字列
3551: //
3552: // size_t count
3553: // 検索する最大バイト数
3554: //
3555: //*********************************************************
3556: char * // 文字列へのポインタ
3557: strnrstri
3558: (
3559: const char *string, // 検索対象文字列
3560: const char *pattern, // 検索文字列
3561: size_t count // 最大検索バイト数
3562: )
3563: {
3564: CALLONCE_TESTPROC( test_str ); // [テスト]
3565:
3566: // パラメタの仮定
3567: ASSERT( IsValidLengthStringPtr( string, count ) );
3568: ASSERT( IsValidStringPtr( pattern ) );
3569:
3570: // 検索バイト数 0 では検索は常に失敗する。
3571: if ( count <= 0 )
3572: {
3573: return null;
3574: }
3575:
3576: // 検索バイト数 が 検索する文字列長 未満では検索は常に失敗する。
3577: const size_t length = strlen( pattern );
3578: if ( count < length )
3579: {
3580: return null;
3581: }
3582: ASSERT( length <= count );
3583:
3584: // 文字列終端に達するまで検索を繰り返す。
3585: const char *p = string;
3586: const char *last = null;
3587: while( (static_cast<size_t>(p - string) <= (count - length))
3588: && (null != (p = strnstri( p, pattern, count - (p - string) )))
3589: && (static_cast<size_t>(p - string) <= (count - length)) )
3590: {
3591: ASSERT( (string <= p) && (p <= strtail( string )) );
3592: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) <= (count - length)) );
3593: last = p;
3594:
3595: if ( '\0' == *p )
3596: {
3597: ASSERT( '\0' == pattern[ 0 ] );
3598: ASSERT( p == strtail( string ) );
3599: ASSERT( (string <= last) && (last == p) );
3600: return const_cast<char *>( last );
3601: }
3602:
3603: p = strnext( p );
3604: ASSERT( (string < p) && (p <= strtail( string )) );
3605: }
3606:
3607: ASSERT( !last || ((string <= last) && (last <= strtail( string ))) );
3608: ASSERT( !last || ((0 <= (last - string)) && (static_cast<size_t>(last - string) <= (count - length))) );
3609: return const_cast<char *>( last );
3610: }//strnrstri
3611:
3612: //*********************************************************
3613: // strnstr()
3614: // 文字列 から 文字列 を検索する。
3615: // 最初 に現れた文字列の先頭を指す ポインタ を返す。
3616: // 文字列が見つからない場合は null を返す。
3617: // 検索バイト数が 0 の場合は常に null を返す。
3618: // pattern が 空文字列 の場合は常に string を返す。
3619: // 文字列先頭から count バイト目までを検索する。
3620: // 文字列終端文字 '\0' は検索対象とならない。
3621: // 半角英字 の 大文字と小文字 を区別する。
3622: //
3623: // const char *string
3624: // 検索対象となる文字列
3625: //
3626: // const char *pattern
3627: // 文字列から検索する文字列
3628: //
3629: // size_t count
3630: // 検索する最大バイト数
3631: //
3632: //*********************************************************
3633: char * // 文字列へのポインタ
3634: strnstr
3635: (
3636: const char *string, // 検索対象文字列
3637: const char *pattern, // 検索文字列
3638: size_t count // 最大検索バイト数
3639: )
3640: {
3641: CALLONCE_TESTPROC( test_str ); // [テスト]
3642:
3643: // パラメタの仮定
3644: ASSERT( IsValidLengthStringPtr( string, count ) );
3645: ASSERT( IsValidStringPtr( pattern ) );
3646:
3647: // 検索バイト数 0 では検索は常に失敗する。
3648: if ( count <= 0 )
3649: {
3650: return null;
3651: }
3652:
3653: // pattern が空文字列の場合は string を返す。
3654: if ( '\0' == pattern[ 0 ] )
3655: {
3656: return const_cast<char *>( string );
3657: }
3658:
3659: // 検索バイト数 が 検索する文字列長 未満では検索は常に失敗する。
3660: const size_t length = strlen( pattern );
3661: if ( count < length )
3662: {
3663: return null;
3664: }
3665: ASSERT( length <= count );
3666:
3667: // 最初に現れた pattern へのポインタを返す。
3668: const char *p = string;
3669: while( (static_cast<size_t>(p - string) <= (count - length))
3670: && (null != (p = strnchr( p, strcode( pattern ), count - (p - string) )))
3671: && (static_cast<size_t>(p - string) <= (count - length)) )
3672: {
3673: ASSERT( (string <= p) && (p < strtail( string )) );
3674: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) <= (count - length)) );
3675:
3676: if ( strneql( p, pattern, length ) )
3677: {
3678: ASSERT( (string <= p) && (p + length <= strtail( string )) );
3679: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) <= (count - length)) );
3680: return const_cast<char *>( p );
3681: }
3682:
3683: p = strnext( p );
3684: ASSERT( (string < p) && (p <= strtail( string )) );
3685: }
3686:
3687: // pattern が見つからない場合は null を返す。
3688: return null;
3689: }//strnstr
3690:
3691: //*********************************************************
3692: // strnstri()
3693: // 文字列 から 文字列 を検索する。
3694: // 最初 に現れた文字列の先頭を指す ポインタ を返す。
3695: // 文字列が見つからない場合は null を返す。
3696: // 検索バイト数が 0 の場合は常に null を返す。
3697: // pattern が 空文字列 の場合は常に string を返す。
3698: // 文字列先頭から count バイト目までを検索する。
3699: // 文字列終端文字 '\0' は検索対象とならない。
3700: // 半角英字 の 大文字と小文字 を区別しない。
3701: //
3702: // const char *string
3703: // 検索対象となる文字列
3704: //
3705: // const char *pattern
3706: // 文字列から検索する文字列
3707: //
3708: // size_t count
3709: // 検索する最大バイト数
3710: //
3711: //*********************************************************
3712: char * // 文字列へのポインタ
3713: strnstri
3714: (
3715: const char *string, // 検索対象文字列
3716: const char *pattern, // 検索文字列
3717: size_t count // 最大検索バイト数
3718: )
3719: {
3720: CALLONCE_TESTPROC( test_str ); // [テスト]
3721:
3722: // パラメタの仮定
3723: ASSERT( IsValidLengthStringPtr( string, count ) );
3724: ASSERT( IsValidStringPtr( pattern ) );
3725:
3726: // 検索バイト数 0 では検索は常に失敗する。
3727: if ( count <= 0 )
3728: {
3729: return null;
3730: }
3731:
3732: // pattern が空文字列の場合は string を返す。
3733: if ( '\0' == pattern[ 0 ] )
3734: {
3735: return const_cast<char *>( string );
3736: }
3737:
3738: // 検索バイト数 が 検索する文字列長 未満では検索は常に失敗する。
3739: const size_t length = strlen( pattern );
3740: if ( count < length )
3741: {
3742: return null;
3743: }
3744:
3745: // 最初に現れた pattern へのポインタを返す。
3746: const char *p = string;
3747: while( (static_cast<size_t>(p - string) <= (count - length))
3748: && (null != (p = strnchri( p, strcode( pattern ), count - (p - string) )))
3749: && (static_cast<size_t>(p - string) <= (count - length)) )
3750: {
3751: ASSERT( (string <= p) && (p < strtail( string )) );
3752: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) <= (count - length)) );
3753:
3754: if ( strneqli( p, pattern, length ) )
3755: {
3756: ASSERT( (string <= p) && (p + length <= strtail( string )) );
3757: ASSERT( (0 <= (p - string)) && (static_cast<size_t>(p - string) <= (count - length)) );
3758: return const_cast<char *>( p );
3759: }
3760:
3761: p = strnext( p );
3762: ASSERT( (string < p) && (p <= strtail( string )) );
3763: }
3764:
3765: // pattern が見つからない場合は null を返す。
3766: ASSERT( !strnstr( string, pattern, count ) );
3767: return null;
3768: }//strnstri
3769:
3770: //*********************************************************
3771: // strntail()
3772: // 文字列終端文字 '\0' への ポインタ を返す。
3773: //
3774: // const char *string
3775: // 終端を求める文字列へのポインタ
3776: //
3777: //*********************************************************
3778: char * // 文字列終端文字 '\0' へのポインタ
3779: strntail
3780: (
3781: const char *string, // 文字列へのポインタ
3782: size_t count
3783: )
3784: {
3785: CALLONCE_TESTPROC( test_str ); // [テスト]
3786:
3787: // パラメタの仮定
3788: ASSERT( IsValidLengthStringPtr( string, count ) );
3789:
3790: return const_cast<char *>( string + strnlen( string, count ) );
3791: }//strntail
3792:
3793: //*********************************************************
3794: // strrep()
3795: // string 中の From を To で置換します
3796: //*********************************************************
3797: char *
3798: strrep
3799: (
3800: char *string,
3801: const char *From,
3802: const char *To
3803: )
3804: {
3805: CALLONCE_TESTPROC( test_str ); // [テスト]
3806:
3807: // パラメタの仮定
3808: ASSERT( IsValidStringPtr( To ) );
3809: ASSERT( IsValidStringPtr( From ) );
3810: ASSERT( IsValidStringPtr( string ) );
3811: ASSERT( IsValidStringBufferPtr( string, 1 + strlen(string) ) );
3812: ASSERT( ( strtail( To ) < From )
3813: || ( strtail( From ) < To ) );
3814:
3815: size_t nToLen = strlen( To );
3816: size_t nFromLen = strlen( From );
3817: ptrdiff_t nShift = nToLen - nFromLen;
3818:
3819: char *p;
3820: char *start = string;
3821: char *stop = strtail( string );
3822: while( null != ( p = jmsstr( start, From ) ) )
3823: {
3824: ASSERT( '\0' == stop[ 0 ] );
3825: start = strshift( p + nFromLen, nShift );
3826: stop += nShift;
3827: ASSERT( '\0' == stop[ 0 ] );
3828:
3829: memmove( p, To, nToLen * sizeof( *p ) );
3830: }
3831:
3832: ASSERT( IsValidStringPtr( string ) );
3833: return string;
3834: }//strrep
3835:
3836: //*********************************************************
3837: // strrevj
3838: //*********************************************************
3839: char *
3840: strrevj
3841: (
3842: char *string
3843: )
3844: {
3845: CALLONCE_TESTPROC( test_str ); // [テスト]
3846:
3847: // パラメタの仮定
3848: ASSERT( IsValidStringPtr( string ) );
3849: ASSERT( IsValidStringBufferPtr( string, 1 + strlen(string) ) );
3850:
3851: {for( char *p = string; '\0' != *p; ++p )
3852: {
3853: if ( (p+1) != jmsnext(p) )
3854: {
3855: memswap( p, p + 1, sizeof( char ) );
3856: ++p;
3857: }
3858: }}
3859:
3860: ASSERT( IsValidStringPtr( string ) );
3861: return _strrev( string );
3862: }//strrevj
3863:
3864: //*********************************************************
3865: // strshift()
3866: // nShift が 負の場合は?
3867: //*********************************************************
3868: char *
3869: strshift
3870: (
3871: char *string,
3872: ptrdiff_t shift
3873: )
3874: {
3875: CALLONCE_TESTPROC( test_str ); // [テスト]
3876:
3877: // パラメタの仮定
3878: ASSERT( IsValidStringPtr( string ) );
3879: ASSERT( IsValidStringBufferPtr( string, 1 + strlen( string ) ) );
3880:
3881: char *start = string;
3882: char *stop = strtail( string );
3883:
3884: ASSERT( '\0' == stop[ 0 ] );
3885: memmove( start + shift, start, (stop - start + 1) * sizeof( *string ) );
3886: ASSERT( '\0' == stop[ shift ] );
3887:
3888: return string + shift;
3889: }//strshift
3890:
3891: //*********************************************************
3892: // strskip()
3893: // 文字列先頭にある 特定の文字群 を読み飛ばす。
3894: // 最初 に現れた文字群 skip に含まれない文字への ポインタ を返す。
3895: // 文字が見つからない場合は 文字列終端へのポインタ を返す。
3896: // 文字列終端文字 '\0' は 文字群 に含まれない。
3897: //
3898: // const char *string
3899: // 文字列
3900: //
3901: // const char *skip
3902: // 読み飛ばす 文字群 を並べた文字列。
3903: // 文字列終端文字 '\0' は 文字群 に含まれない。
3904: //
3905: //*********************************************************
3906: char * // 文字へのポインタ
3907: strskip
3908: (
3909: const char *string, // 文字列
3910: const char *skip // 読み飛ばす文字群
3911: )
3912: {
3913: CALLONCE_TESTPROC( test_str ); // [テスト]
3914:
3915: // パラメタの仮定
3916: ASSERT( IsValidStringPtr( string ) );
3917: ASSERT( IsValidStringPtr( skip ) );
3918:
3919: return const_cast<char *>( string + jmsspn( string, skip ) );
3920: }//strskip
3921:
3922: //*********************************************************
3923: // strrstr()
3924: // 文字列 から 文字列 を検索する。
3925: // 最後 に現れた文字列の先頭を指す ポインタ を返す。
3926: // 文字列が見つからない場合は null を返す。
3927: // pattern が 空文字列 の場合は常に 文字列終端 を返す。
3928: // 文字列終端文字 '\0' は検索対象とならない。
3929: // 半角英字 の 大文字と小文字 を区別する。
3930: //
3931: // const char *string
3932: // 検索対象となる文字列
3933: //
3934: // const char *pattern
3935: // 文字列から検索する文字列
3936: //
3937: //*********************************************************
3938: char * // 文字列へのポインタ
3939: strrstr
3940: (
3941: const char *string, // 検索対象文字列
3942: const char *pattern // 検索する文字列
3943: )
3944: {
3945: CALLONCE_TESTPROC( test_str ); // [テスト]
3946:
3947: // パラメタの仮定
3948: ASSERT( IsValidStringPtr( string ) );
3949: ASSERT( IsValidStringPtr( pattern ) );
3950:
3951: // 文字列終端に達するまで検索を繰り返す。
3952: const char *last = null;
3953: {for( const char *p = string; null != (p = jmsstr( p, pattern )); )
3954: {
3955: ASSERT( (string <= p) && (p <= strtail( string )) );
3956: last = p;
3957:
3958: if ( '\0' == *p )
3959: {
3960: ASSERT( '\0' == pattern[ 0 ] );
3961: ASSERT( p == strtail(string) );
3962: ASSERT( (string <= last) && (last <= p) );
3963: return const_cast<char *>( last );
3964: }
3965:
3966: p = strnext( p );
3967: ASSERT( (string < p) && (p <= strtail( string )) );
3968: }}
3969:
3970: ASSERT( !last || ((string <= last) && (last < strtail( string ))) );
3971: return const_cast<char *>( last );
3972: }//strrstr
3973:
3974: //*********************************************************
3975: // strrstri()
3976: // 文字列 から 文字列 を検索する。
3977: // 最後 に現れた文字列の先頭を指す ポインタ を返す。
3978: // 文字列が見つからない場合は null を返す。
3979: // pattern が 空文字列 の場合は常に 文字列終端 を返す。
3980: // 文字列終端文字 '\0' は検索対象とならない。
3981: // 半角英字 の 大文字と小文字 を区別しない。
3982: //
3983: // const char *string
3984: // 検索対象となる文字列
3985: //
3986: // const char *pattern
3987: // 文字列から検索する文字列
3988: //
3989: //*********************************************************
3990: char * // 文字列へのポインタ
3991: strrstri
3992: (
3993: const char *string, // 検索対象文字列
3994: const char *pattern // 検索する文字列
3995: )
3996: {
3997: CALLONCE_TESTPROC( test_str ); // [テスト]
3998:
3999: // パラメタの仮定
4000: ASSERT( IsValidStringPtr( string ) );
4001: ASSERT( IsValidStringPtr( pattern ) );
4002:
4003: // 文字列終端に達するまで検索を繰り返す。
4004: const char *last = null;
4005: {for( const char *p = string; null != (p = strstri( p, pattern )); )
4006: {
4007: ASSERT( (string <= p) && (p <= strtail( string )) );
4008: last = p;
4009:
4010: if ( '\0' == *p )
4011: {
4012: ASSERT( '\0' == pattern[ 0 ] );
4013: ASSERT( p == strtail( string ) );
4014: ASSERT( (string <= last) && (last <= p) );
4015: return const_cast<char *>( last );
4016: }
4017:
4018: p = strnext( p );
4019: ASSERT( (string < p) && (p <= strtail( string )) );
4020: }}
4021:
4022: ASSERT( !last || ((string <= last) && (last < strtail( string ))) );
4023: return const_cast<char *>( last );
4024: }//strrstri
4025:
4026: //*********************************************************
4027: // strstri()
4028: // 文字列 から 文字列 を検索する。
4029: // 最初 に現れた文字列の先頭を指す ポインタ を返す。
4030: // 文字列が見つからない場合は null を返す。
4031: // pattern が 空文字列 の場合は常に string を返す。
4032: // 文字列終端文字 '\0' は検索対象とならない。
4033: // 半角英字 の 大文字と小文字 を区別しない。
4034: //
4035: // const char *string
4036: // 検索対象となる文字列
4037: //
4038: // const char *pattern
4039: // 文字列から検索する文字列
4040: //
4041: //*********************************************************
4042: char * // 文字列へのポインタ
4043: strstri
4044: (
4045: const char *string, // 検索対象文字列
4046: const char *pattern // 検索する文字列
4047: )
4048: {
4049: CALLONCE_TESTPROC( test_str ); // [テスト]
4050:
4051: // パラメタの仮定
4052: ASSERT( IsValidStringPtr( string ) );
4053: ASSERT( IsValidStringPtr( pattern ) );
4054:
4055: // pattern が空文字列の場合は string を返す。
4056: if ( '\0' == pattern[ 0 ] )
4057: {
4058: return const_cast<char *>( string );
4059: }
4060:
4061: // 最初に現れた pattern へのポインタを返す。
4062: const size_t length = strlen( pattern );
4063: {for( const char *p = string; null != (p = strchri( p, strcode( pattern ) )); )
4064: {
4065: ASSERT( (string <= p) && (p < strtail( string )) );
4066:
4067: if ( strneqli( p, pattern, length ) )
4068: {
4069: ASSERT( (string <= p) && (p + length <= strtail( string )) );
4070: return const_cast<char *>( p );
4071: }
4072:
4073: p = strnext( p );
4074: ASSERT( (string < p) && (p <= strtail( string )) );
4075: }}
4076:
4077: // pattern が見つからない場合は null を返す。
4078: ASSERT( !jmsstr( string, pattern ) );
4079: return null;
4080: }//strstri
4081:
4082: //*********************************************************
4083: // strsub()
4084: // p...q-1 を buffer に取得
4085: //*********************************************************
4086: char *
4087: strsub
4088: (
4089: char *buffer,
4090: size_t bufsize,
4091: const char *p,
4092: const char *q
4093: )
4094: {
4095: CALLONCE_TESTPROC( test_str ); // [テスト]
4096:
4097: // パラメタの仮定
4098: ASSERT( 0 < bufsize );
4099: ASSERT( IsValidStringBufferPtr( buffer, bufsize ) );
4100: ASSERT( IsValidStringPtr( p ) );
4101: ASSERT( IsValidStringPtr( q ) );
4102: ASSERT( strtail( p ) == strtail( q ) );
4103: ASSERT( p <= q );
4104: DESTROY_TEXT_BUFFER( buffer, bufsize ); // [破壊]
4105: ASSERT( (buffer > strtail(q))
4106: || (q > buffer + bufsize) );
4107:
4108: // 複写する文字数
4109: const size_t copysize = min( bufsize-1, static_cast<size_t>(q - p) );
4110: ASSERT( 0 <= copysize );
4111:
4112: //
4113: memmove( buffer, p, copysize * sizeof( *buffer ) );
4114: buffer[ copysize ] = '\0';
4115:
4116: ASSERT( IsValidStringPtr( buffer ) );
4117: return buffer + copysize;
4118: }//strsub
4119:
4120: //*********************************************************
4121: // strtail()
4122: // 文字列終端文字 '\0' への ポインタ を返す。
4123: //
4124: // const char *string
4125: // 終端を求める文字列へのポインタ
4126: //
4127: //*********************************************************
4128: char * // 文字列終端文字 '\0' へのポインタ
4129: strtail
4130: (
4131: const char *string // 文字列へのポインタ
4132: )
4133: {
4134: CALLONCE_TESTPROC( test_str ); // [テスト]
4135:
4136: // パラメタの仮定
4137: ASSERT( IsValidStringPtr( string ) );
4138:
4139: return const_cast<char *>( string + strlen( string ) );
4140: }//strtail
4141:
4142: //*********************************************************
4143: // strtstr()
4144: // 文字列 string が文字列 pattern で終わっている場合に真を返す
4145: // 文字列 pattern が長さ 0 の文字列を指している場合は常に真を返す
4146: //*********************************************************
4147: char *
4148: strtstr
4149: (
4150: const char *string,
4151: const char *pattern
4152: )
4153: {
4154: CALLONCE_TESTPROC( test_str ); // [テスト]
4155:
4156: // パラメタの仮定
4157: ASSERT( IsValidStringPtr( string ) );
4158: ASSERT( IsValidStringPtr( pattern ) );
4159:
4160: const char *p = strrstr( string, pattern );
4161: return const_cast<char *>( (p && streql( p, pattern )) ? p : null );
4162: }//strtstr
4163:
4164: //*********************************************************
4165: // strtstri()
4166: // 文字列 string が文字列 pattern で終わっている場合に真を返す
4167: // 文字列 pattern が長さ 0 の文字列を指している場合は常に真を返す
4168: //*********************************************************
4169: char *
4170: strtstri
4171: (
4172: const char *string,
4173: const char *pattern
4174: )
4175: {
4176: CALLONCE_TESTPROC( test_str ); // [テスト]
4177:
4178: // パラメタの仮定
4179: ASSERT( IsValidStringPtr( string ) );
4180: ASSERT( IsValidStringPtr( pattern ) );
4181:
4182: const char *p = strrstri( string, pattern );
4183: return const_cast<char *>( (p && streqli( p, pattern )) ? p : null );
4184: }//strtstri
4185:
4186: //*********************************************************
4187: // StrUpper
4188: //*********************************************************
4189: void
4190: StrUpper
4191: (
4192: char *string
4193: )
4194: {
4195: CALLONCE_TESTPROC( test_str ); // [テスト]
4196:
4197: // パラメタの仮定
4198: ASSERT( IsValidStringPtr( string ) );
4199: ASSERT( IsValidStringBufferPtr( string, 1 + strlen(string) ) );
4200:
4201: // 2バイト文字対策は大丈夫だろうか?
4202: {for( char *p = string; '\0' != *p; p = jmsnext(p) )
4203: {
4204: if ( IsLower( *p ) )
4205: {
4206: ASSERT( IS_VALID_CHAR_CODE( *p ) );
4207: *p = static_cast<char>( ToUpper( *p ) );
4208: ASSERT( IS_VALID_CHAR_CODE( *p ) );
4209: ASSERT( ! IsLower( *p ) );
4210: }
4211: }}
4212:
4213: ASSERT( IsValidStringPtr( string ) );
4214: }//StrUpper
4215:
4216: //*********************************************************
4217: // SwapFileExtension()
4218: // パス名の拡張子を別の拡張子に入れ替える。
4219: //*********************************************************
4220: char *
4221: SwapFileExtension
4222: (
4223: char *path, // パス名
4224: size_t bufsize, //
4225: const char *extension // 新しい拡張子
4226: )
4227: {
4228: CALLONCE_TESTPROC( test_pathname ); // [テスト]
4229:
4230: // パラメタの仮定
4231: ASSERT( 0 < bufsize );
4232: ASSERT( IsValidStringBufferPtr( path, bufsize ) );
4233: ASSERT( IsValidLocalPathString( path ) );
4234: ASSERT( strlen( path ) < bufsize );
4235: ASSERT( IsValidLocalPathString( extension ) );
4236: ASSERT( '.' == extension[ 0 ] );
4237: ASSERT( (strtail(extension) < path)
4238: || (path + bufsize < extension) );
4239:
4240: // 古い拡張子を削除
4241: CutFileExtension( path );
4242:
4243: // 新しい拡張子を追加
4244: char *tail = strtail( path );
4245: strcopy( tail, bufsize - (tail - path), extension );
4246:
4247: //
4248: ASSERT( IsValidLocalPathString( path ) );
4249: ASSERT( strlen( path ) < bufsize );
4250: return tail;
4251: }//SwapFileExtension
4252:
4253:
4254: //------------------------------------------------------------------------------------------------------------------
4255: // t
4256: //------------------------------------------------------------------------------------------------------------------
4257:
4258: //------------------------------------------------------------------------------------------------------------------
4259: // u
4260: //------------------------------------------------------------------------------------------------------------------
4261: //*********************************************************
4262: // unique()
4263: // 整列済み配列 array[] の重複する要素を1つにまとめる。
4264: // 圧縮後の要素で配列 array[] を上書きする。
4265: // 圧縮後の 要素数 を返す。
4266: // [aabccdeee] -> [abcde], 5
4267: //
4268: // void *array
4269: // 圧縮する整列済み配列へのポインタ。
4270: // 圧縮後の配列を受け取るバッファ。
4271: //
4272: // size_t num
4273: // 配列 array[] の要素数。
4274: //
4275: // size_t size
4276: // 配列 array[] の各要素のバイト数。
4277: //
4278: // int (*comp)( const void *, const void * )
4279: // 整列済み配列 array[] を整列した比較関数。
4280: //
4281: //
4282: // [参照]
4283: // qsort() …… 配列を整列する。
4284: // bsearch() …… 整列済み配列から要素を検索する。
4285: // IsSortedArray() …… 配列が整列されているか調べる。
4286: //
4287: //*********************************************************
4288: size_t // 処理後の要素数
4289: unique
4290: (
4291: void *array, // 圧縮する配列
4292: size_t num, // 要素数
4293: size_t size, // 各要素のバイト数
4294: int (*comp)( const void *, const void * ) // 比較関数
4295: )
4296: {
4297: // パラメタの仮定
4298: ASSERT( 0 < num ); // 0 == num だと (size * (num-1)) で不具合
4299: ASSERT( 0 < size );
4300: ASSERT( IsValidPtr( array, size * num ) );
4301: ASSERT( IsValidCodePtr( comp ) );
4302: ASSERT( IsSortedArray( array, num, size, comp ) );
4303:
4304: // すべての要素を走査
4305: BYTE *start = static_cast<BYTE *>( array );
4306: BYTE *stop = start + (size * (num-1)); // ちょうど最後の要素
4307: ASSERT( start <= stop );
4308:
4309: BYTE *dst = start; // 書き込み位置
4310: BYTE *p = start; // 読み込み位置
4311: while( p <= stop )
4312: {
4313: ASSERT( (start <= dst )
4314: && (dst <= p )
4315: && (p <= stop) );
4316:
4317: // 重複ない要素列 p 〜 q の末尾 q を決定する
4318: BYTE *q = p;
4319: while( (q < stop) && (0 != comp( q, q+size )) )
4320: {
4321: q += size;
4322: }
4323: ASSERT( (q == stop) || (0 == comp( q, q+size )) );
4324: ASSERT( (p <= q) && (q <= stop) );
4325: ASSERT( 0 == (q - p) % size );
4326:
4327: // dst に p 〜 q を複写
4328: size_t elements = ((q - p)/size) + 1; // 複写する要素数を求める
4329: memmove( dst, p, size * elements ); // 要素を複写する
4330: dst += (size * elements); // 次の複写開始位置へ
4331:
4332: // q と重複する要素を全てスキップ
4333: p = q + size;
4334: while( (p <= stop) && (0 == comp( q, p )) )
4335: {
4336: p += size;
4337: }
4338: ASSERT( (p == stop+size) || (0 != comp( q, p )) );
4339: }
4340: ASSERT( p == (stop + size) );
4341:
4342: ASSERT( 0 == (dst-start) % size );
4343: ASSERT( 0 < (dst-start) / size );
4344: ASSERT( num >= (dst-start) / size );
4345: ASSERT( IsSortedArray( array, (dst-start)/size, size, comp ) );
4346: return (dst - start) / size;
4347: }//unique
4348:
4349:
4350: //------------------------------------------------------------------------------------------------------------------
4351: // v
4352: //------------------------------------------------------------------------------------------------------------------
4353:
4354: //------------------------------------------------------------------------------------------------------------------
4355: // w
4356: //------------------------------------------------------------------------------------------------------------------
4357:
4358: //------------------------------------------------------------------------------------------------------------------
4359: // x
4360: //------------------------------------------------------------------------------------------------------------------
4361:
4362: //------------------------------------------------------------------------------------------------------------------
4363: // y
4364: //------------------------------------------------------------------------------------------------------------------
4365:
4366: //------------------------------------------------------------------------------------------------------------------
4367: // z
4368: //------------------------------------------------------------------------------------------------------------------
4369:
4370:
4371: //******************************************************************************************************************
4372: // private
4373: //******************************************************************************************************************
4374: //*********************************************************
4375: // make_strmap()
4376: // 文字群に含まれる 文字 に対応するビットを立てる。
4377: // 文字 が文字群に含まれているか調べるには GET_STRMAP_BIT( map, code ) を使う。
4378: //
4379: // 使用例:
4380: // BYTE map[ STRMAP_SIZE ];
4381: // make_strmap( map, sizeof( map ), ctrl );
4382: // return 0 != GET_STRMAP_BIT( map, c ) ); // 含まれていれば 真
4383: //
4384: //*********************************************************
4385: static
4386: bool
4387: make_strmap
4388: (
4389: BYTE *map, //
4390: size_t size, //
4391: const char *ctrl // 検索文字群
4392: )
4393: {
4394: // パラメタの仮定
4395: ASSERT( STRMAP_SIZE <= size );
4396: ASSERT( IsValidReadPtr( map, size ) );
4397: ASSERT( IsValidStringPtr( ctrl ) );
4398:
4399: //
4400: memzero( map, size );
4401:
4402: //
4403: {for( const char *p = ctrl; '\0' != *p; ++p )
4404: {
4405: const BYTE c = static_cast<BYTE>( *p );
4406: SET_STRMAP_BIT( map, c );
4407: ASSERT( 0 != GET_STRMAP_BIT( map, c ) );
4408: }}
4409:
4410: return true;
4411: }//make_strmap
4412:
4413: //*********************************************************
4414: // make_memmap()
4415: //
4416: //
4417: //*********************************************************
4418: static
4419: bool
4420: make_memmap
4421: (
4422: BYTE *map, //
4423: size_t size, //
4424: const char *ctrl, // 検索バイト群
4425: size_t count // バイト群 ctrl の 要素数
4426: )
4427: {
4428: // パラメタの仮定
4429: ASSERT( MEMMAP_SIZE <= size );
4430: ASSERT( IsValidReadPtr( map, size ) );
4431: ASSERT( 0 <= count );
4432: ASSERT( IsValidReadPtr( ctrl, count ) );
4433:
4434: //
4435: memzero( map, size );
4436:
4437: //
4438: const BYTE *p = reinterpret_cast<const BYTE *>( ctrl );
4439: {for( ; 0 < count; --count, ++p )
4440: {
4441: const BYTE c = static_cast<BYTE>( *p );
4442: SET_MEMMAP_BIT( map, c );
4443: ASSERT( 0 != GET_MEMMAP_BIT( map, c ) );
4444: }}
4445:
4446: return true;
4447: }//make_memmap
4448:
4449:
4450: //******************************************************************************************************************
4451: // TEST
4452: //******************************************************************************************************************
4453:
4454:
4455: #ifdef _DEBUG // デバッグ時のみ
4456:
4457:
4458: #include <time.h> // { struct tm, mktime() }@test_time();
4459:
4460:
4461: //*********************************************************
4462: // test_bitcount()
4463: //*********************************************************
4464: DEFINE_TESTPROC( test_bitcount )
4465: {
4466: //---------------------------------------------------------
4467: // 定数 の テスト
4468: //---------------------------------------------------------
4469:
4470: //---------------------------------------------------------
4471: // ファイルスコープ関数 の テスト
4472: //---------------------------------------------------------
4473:
4474: //---------------------------------------------------------
4475: // 公開関数 の テスト
4476: //---------------------------------------------------------
4477:
4478: const int bits[] =
4479: {
4480: 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
4481: 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
4482: 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
4483: 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
4484: 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
4485: 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
4486: 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
4487: 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4488: 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
4489: 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
4490: 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
4491: 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4492: 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
4493: 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4494: 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
4495: 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
4496: };
4497: COMPILE_ASSERT( 256 == numof( bits ) );
4498:
4499: {for( int i = 0; i < numof( bits ); ++i )
4500: {
4501: BYTE b = static_cast<BYTE>( i );
4502:
4503: const int count = bitcount( b );
4504: VERIFY( count == bits[ i ] );
4505: VERIFY( count == bitcount8( b ) );
4506: VERIFY( count == bitcount16( b ) );
4507: VERIFY( count == bitcount32( b ) );
4508: VERIFY( count == bitcount64( b ) );
4509: }}
4510:
4511: //
4512: // MAKEDWORD64(a, b) について
4513: // [C4293] '<<' : シフト数が負の値であるか、大きすぎます。定義されていない動作です
4514: // 32bit 左シフト "<< 32" を行うと警告が出るので 16bit 左シフト "<< 16 << 16" で代用する。
4515: //
4516: #define HIDWORD(dw64) ((DWORD)((DWORD64)(dw64) >> 32))
4517: #define LODWORD(dw64) ((DWORD)((DWORD64)(dw64) & 0xFFFFFFFF))
4518: #define MAKEDWORD(a, b) ((DWORD)(((WORD)(((DWORD)(a)) & 0xFFFF)) | ((DWORD)(((WORD)(((DWORD)(b)) & 0xFFFF)) << 16))))
4519: #define MAKEDWORD64(a, b) ((DWORD64)(((DWORD)(((DWORD64)(a)) & 0xFFFFFFFF)) | ((DWORD64)((((DWORD)(((DWORD64)(b)) & 0xFFFFFFFF)) << 16) << 16))))
4520: {for( int i = 0; i < 256; ++i )
4521: {
4522: const DWORD64 dw64 = MAKEDWORD64( MAKEDWORD( MAKEWORD(i, i+1), MAKEWORD(i+2, i+3) ), MAKEDWORD( MAKEWORD(i+4, i+5), MAKEWORD(i+6, i+7) ) );
4523:
4524: VERIFY( bitcount64( dw64 )
4525: == bitcount32( LODWORD(dw64) ) + bitcount32( HIDWORD(dw64) ) );
4526: VERIFY( bitcount64( dw64 )
4527: == bitcount16( LOWORD(LODWORD(dw64)) ) + bitcount16( HIWORD(LODWORD(dw64)) )
4528: + bitcount16( LOWORD(HIDWORD(dw64)) ) + bitcount16( HIWORD(HIDWORD(dw64)) ) );
4529: VERIFY( bitcount64( dw64 )
4530: == bitcount8( LOBYTE(LOWORD(LODWORD(dw64))) ) + bitcount8( HIBYTE(LOWORD(LODWORD(dw64))) )
4531: + bitcount8( LOBYTE(HIWORD(LODWORD(dw64))) ) + bitcount8( HIBYTE(HIWORD(LODWORD(dw64))) )
4532: + bitcount8( LOBYTE(LOWORD(HIDWORD(dw64))) ) + bitcount8( HIBYTE(LOWORD(HIDWORD(dw64))) )
4533: + bitcount8( LOBYTE(HIWORD(HIDWORD(dw64))) ) + bitcount8( HIBYTE(HIWORD(HIDWORD(dw64))) ) );
4534: }}
4535: #undef HIDWORD
4536: #undef LODWORD
4537: #undef MAKEDWORD
4538: #undef MAKEDWORD64
4539:
4540: }//test_bitcount
4541:
4542: //*********************************************************
4543: // test_pathname()
4544: //*********************************************************
4545: DEFINE_TESTPROC( test_pathname )
4546: {
4547: //---------------------------------------------------------
4548: // 定数 の テスト
4549: //---------------------------------------------------------
4550:
4551: //---------------------------------------------------------
4552: // ファイルスコープ関数 の テスト
4553: //---------------------------------------------------------
4554:
4555: //---------------------------------------------------------
4556: // 公開関数 の テスト
4557: //---------------------------------------------------------
4558:
4559: // IsValidLocalPathString(), IsValidLocalPathMaskString()
4560: {
4561: const struct
4562: {
4563: bool path; //
4564: bool mask; //
4565: const char *string; //
4566: }
4567: testcase[] =
4568: {
4569: #define MAKE_TESTCASE( path, mask, string ) { path, mask, string }
4570: MAKE_TESTCASE( true, true, "" ),
4571: MAKE_TESTCASE( true, true, "a" ),
4572: MAKE_TESTCASE( true, true, "\\" ),
4573: MAKE_TESTCASE( false, true, "*" ),
4574: MAKE_TESTCASE( false, true, "?" ),
4575: MAKE_TESTCASE( false, false, "\"" ),
4576: MAKE_TESTCASE( false, false, "<" ),
4577: MAKE_TESTCASE( false, false, ">" ),
4578: MAKE_TESTCASE( false, false, "|" ),
4579: #undef MAKE_TESTCASE
4580: };
4581: {for( int i = 0; i < numof( testcase ); ++i )
4582: {
4583: VERIFY( testcase[ i ].path == IsValidLocalPathString( testcase[ i ].string ) );
4584: VERIFY( testcase[ i ].mask == IsValidLocalPathMaskString( testcase[ i ].string ) );
4585: }}
4586: }
4587:
4588: // IsPathTailSeparator()
4589: {
4590: const struct
4591: {
4592: bool result; //
4593: const char *path; //
4594: }
4595: testcase[] =
4596: {
4597: #define MAKE_TESTCASE( result, path ) { result, path }
4598: MAKE_TESTCASE( false, "" ),
4599: MAKE_TESTCASE( false, "a" ),
4600: MAKE_TESTCASE( true, "\\" ),
4601: MAKE_TESTCASE( false, "ソ" ),
4602: MAKE_TESTCASE( true, "a\\" ),
4603: MAKE_TESTCASE( true, "ソ\\" ),
4604: #undef MAKE_TESTCASE
4605: };
4606: {for( int i = 0; i < numof( testcase ); ++i )
4607: {
4608: VERIFY( testcase[ i ].result == IsPathTailSeparator( testcase[ i ].path ) );
4609: }}
4610: }
4611:
4612: // IsPathDescendant()
4613: {
4614: const struct
4615: {
4616: bool result; //
4617: const char *descendant; // 含む
4618: const char *ancestor; // 含まれる
4619: }
4620: testcase[] =
4621: {
4622: #define MAKE_TESTCASE( result, descendant, ancestor ) { result, descendant, ancestor }
4623: MAKE_TESTCASE( false, "a\\b\\", "a\\b\\" ),
4624: MAKE_TESTCASE( false, "a\\b", "a\\b\\" ),
4625: MAKE_TESTCASE( false, "a\\b\\", "a\\b" ),
4626: MAKE_TESTCASE( false, "a\\b", "a\\b" ),
4627:
4628: MAKE_TESTCASE( false, "a\\", "a\\b\\" ),
4629: MAKE_TESTCASE( false, "a", "a\\b\\" ),
4630: MAKE_TESTCASE( false, "a\\", "a\\b" ),
4631: MAKE_TESTCASE( false, "a", "a\\b" ),
4632:
4633: MAKE_TESTCASE( true, "a\\b\\", "a\\" ),
4634: MAKE_TESTCASE( true, "a\\b", "a\\" ),
4635: MAKE_TESTCASE( true, "a\\b\\", "a" ),
4636: MAKE_TESTCASE( true, "a\\b", "a" ),
4637: MAKE_TESTCASE( false, "aa\\b\\", "a" ),
4638: MAKE_TESTCASE( false, "aa\\b", "a" ),
4639:
4640: MAKE_TESTCASE( false, "a\\", "a\\" ),
4641: MAKE_TESTCASE( false, "a", "a\\" ),
4642: MAKE_TESTCASE( false, "a\\", "a" ),
4643: MAKE_TESTCASE( false, "a", "a" ),
4644: #undef MAKE_TESTCASE
4645: };
4646: {for( int i = 0; i < numof( testcase ); ++i )
4647: {
4648: VERIFY( testcase[ i ].result == IsPathDescendant( testcase[ i ].descendant, testcase[ i ].ancestor ) );
4649: }}
4650: }
4651:
4652: // GetFileLocation()
4653: {
4654: const struct
4655: {
4656: const char *location;
4657: const char *path;
4658: }
4659: testcase[] =
4660: {
4661: { "", "" },
4662: { "", "x" },
4663: { "", "xx" },
4664: { "", "ソ" },
4665: { "", "\\" },
4666: { "x", "x\\" },
4667: { "x", "x\\" },
4668: { "xx", "xx\\" },
4669: { "ソ", "ソ\\" },
4670: { "\\", "\\\\" },
4671: { "", "\\x" },
4672: { "", "\\xx" },
4673: { "", "\\ソ" },
4674: { "x", "x\\x" },
4675: { "xx", "xx\\xx" },
4676: { "ソ", "ソ\\ソ" },
4677: { "ソ\\ソ", "ソ\\ソ\\" },
4678: };
4679: {for( int i = 0; i < numof( testcase ); ++i )
4680: {
4681: char location[ MAX_PATH_BUF ];
4682: VERIFY( GetFileLocation( testcase[ i ].path, location, numof(location) ) );
4683: VERIFY( streql( location, testcase[ i ].location ) );
4684: }}
4685: }
4686:
4687: // GetFileNamePtr(), GetFileExtensionPtr()
4688: {
4689: const struct
4690: {
4691: int name;
4692: int ext;
4693: const char *path;
4694: }
4695: testcase[] =
4696: {
4697: { 0, 0, "" },
4698: { 0, 1, "f" },
4699: { 0, 0, "." },
4700: { 0, 0, ".e" },
4701: { 0, 0, ".ext" },
4702: { 0, 2, "ソ" }, // 2 バイト目に '\' がある文字
4703: { 0, 3, "ソf" }, // 2 バイト目に '\' がある文字
4704: { 0, 4, "file" },
4705: { 1, 1, "\\" },
4706: { 2, 2, "p\\" },
4707: { 5, 5, "path\\" },
4708: { 1, 5, "\\file" },
4709: { 2, 2, "p\\" },
4710: { 10, 14, "path\\path\\file" },
4711: { 10, 10, "path\\path\\" },
4712: { 11, 11, "path\\path\\\\" },
4713: { 2, 2, "\\\\" },
4714: { 2, 6, "\\\\file" },
4715: { 0, 5, ".body.ext" },
4716: { 0, 11, "body1.body2.ext" },
4717: { 6, 10, ".path\\body" },
4718: { 6, 10, "path.\\body" },
4719: { 5, 5, "path\\.ext" },
4720: { 6, 6, "path.\\.ext" },
4721: { 6, 6, "path.\\." },
4722: { 6, 6, "path.\\" },
4723: { 0, 4, "path.ソ" }, // 2 バイト目に '\' がある文字
4724: };
4725: {for( int i = 0; i < numof( testcase ); ++i )
4726: {
4727: const char *name = GetFileNamePtr( testcase[ i ].path );
4728: VERIFY( name == testcase[ i ].path + testcase[ i ].name );
4729:
4730: const char *ext = GetFileExtensionPtr( testcase[ i ].path );
4731: VERIFY( ext == testcase[ i ].path + testcase[ i ].ext );
4732: }}
4733: }
4734:
4735: // MakeFullPath()
4736: {
4737: const struct
4738: {
4739: bool b;
4740: const char *dir;
4741: const char *sub;
4742: const char *result;
4743: }
4744: testcase[] =
4745: {
4746: #define MAKE_TESTCASE( b, dir, sub, result ) { b, dir, sub, result }
4747: MAKE_TESTCASE( true, "a\\b\\c\\", "\\.\\d\\..\\xxx\\.\\yyy\\zzz\\", "a\\b\\c\\xxx\\yyy\\zzz\\" ),
4748: MAKE_TESTCASE( true, "a\\b\\c\\", "\\.\\xxx\\.\\yyy\\zzz\\", "a\\b\\c\\xxx\\yyy\\zzz\\" ),
4749: MAKE_TESTCASE( true, "a\\b\\c\\", "\\.\\xxx\\.\\yyy\\zzz", "a\\b\\c\\xxx\\yyy\\zzz" ),
4750: MAKE_TESTCASE( true, "a\\b\\c", "\\.\\xxx\\.\\yyy\\zzz", "a\\b\\c\\xxx\\yyy\\zzz" ),
4751:
4752: MAKE_TESTCASE( true, "", "", "" ),
4753: MAKE_TESTCASE( true, "", ".", "" ),
4754: MAKE_TESTCASE( true, "", "a", "a" ),
4755: MAKE_TESTCASE( true, "", "a\\", "a\\" ),
4756: MAKE_TESTCASE( true, "", "\\", "" ),
4757: MAKE_TESTCASE( true, "", "\\a", "a" ),
4758: MAKE_TESTCASE( true, "", "\\a\\", "a\\" ),
4759: MAKE_TESTCASE( true, "", ".\\", "" ),
4760: MAKE_TESTCASE( true, "", ".\\a", "a" ),
4761: MAKE_TESTCASE( true, "", ".\\a\\", "a\\" ),
4762: MAKE_TESTCASE( true, "", "\\.\\", "" ),
4763: MAKE_TESTCASE( true, "", "\\.\\a", "a" ),
4764: MAKE_TESTCASE( true, "", "\\.\\a\\", "a\\" ),
4765:
4766: MAKE_TESTCASE( true, "a", "", "a\\" ),
4767: MAKE_TESTCASE( true, "a", ".", "a" ),
4768: MAKE_TESTCASE( true, "a", "a", "a\\a" ),
4769: MAKE_TESTCASE( true, "a", "a\\", "a\\a\\" ),
4770: MAKE_TESTCASE( true, "a", "\\", "a\\" ),
4771: MAKE_TESTCASE( true, "a", "\\a", "a\\a" ),
4772: MAKE_TESTCASE( true, "a", "\\a\\", "a\\a\\" ),
4773: MAKE_TESTCASE( true, "a", ".\\", "a\\" ),
4774: MAKE_TESTCASE( true, "a", ".\\a", "a\\a" ),
4775: MAKE_TESTCASE( true, "a", ".\\a\\", "a\\a\\" ),
4776: MAKE_TESTCASE( true, "a", "\\.\\", "a\\" ),
4777: MAKE_TESTCASE( true, "a", "\\.\\a", "a\\a" ),
4778: MAKE_TESTCASE( true, "a", "\\.\\a\\", "a\\a\\" ),
4779:
4780: MAKE_TESTCASE( true, "ソ", "", "ソ\\" ),
4781: MAKE_TESTCASE( true, "ソ", ".", "ソ" ),
4782: MAKE_TESTCASE( true, "ソ", "ソ", "ソ\\ソ" ),
4783: MAKE_TESTCASE( true, "ソ", "ソ\\", "ソ\\ソ\\" ),
4784: MAKE_TESTCASE( true, "ソ", "\\", "ソ\\" ),
4785: MAKE_TESTCASE( true, "ソ", "\\ソ", "ソ\\ソ" ),
4786: MAKE_TESTCASE( true, "ソ", "\\ソ\\", "ソ\\ソ\\" ),
4787: MAKE_TESTCASE( true, "ソ", ".\\", "ソ\\" ),
4788: MAKE_TESTCASE( true, "ソ", ".\\ソ", "ソ\\ソ" ),
4789: MAKE_TESTCASE( true, "ソ", ".\\ソ\\", "ソ\\ソ\\" ),
4790: MAKE_TESTCASE( true, "ソ", "\\.\\", "ソ\\" ),
4791: MAKE_TESTCASE( true, "ソ", "\\.\\ソ", "ソ\\ソ" ),
4792: MAKE_TESTCASE( true, "ソ", "\\.\\ソ\\", "ソ\\ソ\\" ),
4793:
4794: MAKE_TESTCASE( true, "\\", "", "\\" ),
4795: MAKE_TESTCASE( true, "\\", ".", "\\" ),
4796: MAKE_TESTCASE( true, "\\", "a", "\\a" ),
4797: MAKE_TESTCASE( true, "\\", "a\\", "\\a\\" ),
4798: MAKE_TESTCASE( true, "\\", "\\", "\\" ),
4799: MAKE_TESTCASE( true, "\\", "\\a", "\\a" ),
4800: MAKE_TESTCASE( true, "\\", "\\a\\", "\\a\\" ),
4801: MAKE_TESTCASE( true, "\\", ".\\", "\\" ),
4802: MAKE_TESTCASE( true, "\\", ".\\a", "\\a" ),
4803: MAKE_TESTCASE( true, "\\", ".\\a\\", "\\a\\" ),
4804: MAKE_TESTCASE( true, "\\", "\\.\\", "\\" ),
4805: MAKE_TESTCASE( true, "\\", "\\.\\a", "\\a" ),
4806: MAKE_TESTCASE( true, "\\", "\\.\\a\\", "\\a\\" ),
4807:
4808: MAKE_TESTCASE( true, "a", "..", "" ),
4809: MAKE_TESTCASE( true, "a", "..\\", "" ),
4810: MAKE_TESTCASE( true, "a", "\\..", "" ),
4811: MAKE_TESTCASE( true, "a", "..\\x", "x" ),
4812: MAKE_TESTCASE( true, "a", "\\..\\x", "x" ),
4813:
4814: MAKE_TESTCASE( true, "a\\", "..", "" ),
4815: MAKE_TESTCASE( true, "a\\", "..\\", "" ),
4816: MAKE_TESTCASE( true, "a\\", "\\..", "" ),
4817: MAKE_TESTCASE( true, "a\\", "..\\x", "x" ),
4818: MAKE_TESTCASE( true, "a\\", "\\..\\x", "x" ),
4819:
4820: MAKE_TESTCASE( true, "a\\b\\", "..", "a" ),
4821: MAKE_TESTCASE( true, "a\\b\\", "..\\", "a\\" ),
4822: MAKE_TESTCASE( true, "a\\b\\", "\\..", "a" ),
4823: MAKE_TESTCASE( true, "a\\b\\", "..\\x", "a\\x" ),
4824: MAKE_TESTCASE( true, "a\\b\\", "\\..\\x", "a\\x" ),
4825:
4826: MAKE_TESTCASE( true, "a\\b", "..", "a" ),
4827: MAKE_TESTCASE( true, "a\\b", "..\\", "a\\" ),
4828: MAKE_TESTCASE( true, "a\\b", "\\..", "a" ),
4829: MAKE_TESTCASE( true, "a\\bbb", "..\\x", "a\\x" ),
4830: MAKE_TESTCASE( true, "a\\b", "..\\x", "a\\x" ),
4831: MAKE_TESTCASE( true, "a\\b", "\\..\\x", "a\\x" ),
4832: MAKE_TESTCASE( true, "a\\b\\", "..", "a" ),
4833: MAKE_TESTCASE( true, "a\\b\\", "..\\", "a\\" ),
4834: MAKE_TESTCASE( true, "a\\b\\", "\\..", "a" ),
4835: MAKE_TESTCASE( true, "a\\b\\", "..\\x", "a\\x" ),
4836: MAKE_TESTCASE( true, "a\\b\\", "\\..\\x", "a\\x" ),
4837:
4838: MAKE_TESTCASE( false, "", "..", null ),
4839: MAKE_TESTCASE( false, "a", "..\\..", null ),
4840: MAKE_TESTCASE( false, "a\\", "..\\..", null ),
4841: MAKE_TESTCASE( false, "a\\b", "..\\..\\..", null ),
4842: MAKE_TESTCASE( false, "a\\b\\", "..\\..\\..", null ),
4843: #undef MAKE_TESTCASE
4844: };
4845: {for( int i = 0; i < numof( testcase ); ++i )
4846: {
4847: char buffer[ MAX_PATH_BUF ];
4848: const bool b = MakeFullPath( buffer, numof( buffer ), testcase[ i ].dir, testcase[ i ].sub );
4849: ASSERT( (!b && !testcase[ i ].b) || (b && testcase[ i ].b && streql( buffer, testcase[ i ].result )) );
4850: }}
4851: }
4852:
4853: }//test_pathname
4854:
4855: //*********************************************************
4856: // test_time()
4857: //*********************************************************
4858: DEFINE_TESTPROC( test_time )
4859: {
4860: //---------------------------------------------------------
4861: // 定数 の テスト
4862: //---------------------------------------------------------
4863:
4864: //---------------------------------------------------------
4865: // ファイルスコープ関数 の テスト
4866: //---------------------------------------------------------
4867:
4868: //---------------------------------------------------------
4869: // 公開関数 の テスト
4870: //---------------------------------------------------------
4871:
4872: // IsValidDate(),
4873: {
4874: const struct
4875: {
4876: bool valid;
4877: int year;
4878: int month;
4879: int day;
4880: }
4881: testcase[] =
4882: {
4883: { false, 0, -1, 1 }, // -1 月
4884: { false, 0, 0, 0 }, // 0 月 0 日
4885: { false, 0, 0, 1 }, // 0 月
4886: { false, 0, 1, -1 }, // -1 日
4887: { false, 0, 1, 0 }, // 0 日
4888: { true, 0, 1, 1 }, //
4889: { true, 0, 1, 2 }, //
4890: { true, 0, 1, 30 }, //
4891: { true, 0, 1, 31 }, //
4892: { true, 0, 2, 1 }, //
4893: { true, 0, 2, 2 }, //
4894: { true, 0, 2, 28 }, //
4895: { true, 1, 2, 28 }, //
4896: { true, 0, 2, 29 }, //
4897: { false, 1, 2, 29 }, // 閏年でない 2 月 29 日
4898: { true, 0, 12, 31 }, //
4899: { false, 0, 12, 32 }, // 32 日
4900: { false, 0, 13, 1 }, // 13 月
4901: };
4902: {for( int i = 0; i < numof(testcase); ++i )
4903: {
4904: const bool valid = IsValidDate( testcase[ i ].year, testcase[ i ].month, testcase[ i ].day );
4905: VERIFY( ( valid && testcase[ i ].valid)
4906: || (!valid && !testcase[ i ].valid) );
4907: }}
4908: }
4909:
4910: // IsLeapYear()
4911: {
4912: const struct
4913: {
4914: int year;
4915: bool leap;
4916: }
4917: testcase[] =
4918: {
4919: { 0, true },
4920: { 1, false },
4921: { 2, false },
4922: { 3, false },
4923: { 4, true },
4924: { 5, false },
4925: { 100, false },
4926: { 200, false },
4927: { 300, false },
4928: { 400, true },
4929: { 500, false },
4930: { 504, true },
4931: { 2000, true },
4932: };
4933: {for( int i = 0; i < numof( testcase ); ++i )
4934: {
4935: const bool leap = IsLeapYear( testcase[ i ].year );
4936: VERIFY( ( leap && testcase[ i ].leap)
4937: || (!leap && !testcase[ i ].leap) );
4938: }}
4939: }
4940:
4941: // GetMonthDays()
4942: {for( int y = 1971; y < 2036; ++y )
4943: {
4944: {for( int m = 1; m <= 12; ++m )
4945: {
4946: const int d = GetMonthDays( y, m );
4947:
4948: {
4949: struct tm when;
4950: when.tm_year = y - 1900;
4951: when.tm_mon = m - 1;
4952: when.tm_mday = d;
4953: when.tm_hour = 0;
4954: when.tm_min = 0;
4955: when.tm_sec = 0;
4956: when.tm_isdst = -1;
4957: VERIFY( ((time_t)-1) != mktime( &when ) );
4958: VERIFY( m-1 == when.tm_mon );
4959: }
4960:
4961: {
4962: struct tm when;
4963: when.tm_year = y - 1900;
4964: when.tm_mon = m - 1;
4965: when.tm_mday = 1+d;
4966: when.tm_hour = 0;
4967: when.tm_min = 0;
4968: when.tm_sec = 0;
4969: when.tm_isdst = -1;
4970: VERIFY( ((time_t)-1) != mktime( &when ) );
4971: VERIFY( (m-1) != when.tm_mon );
4972: VERIFY( ((1+(m-1)) % 12) == when.tm_mon ); // 次の月に繰り上がり
4973: }
4974: }}
4975: }}
4976:
4977: // GetDayOfWeek()
4978: {
4979: //
4980: SYSTEMTIME st;
4981: GetLocalTime( &st );
4982: VERIFY( st.wDayOfWeek == GetDayOfWeek( st.wYear, st.wMonth, st.wDay ) );
4983:
4984: //
4985: {for( int y = 1971; y < 2038; ++y )
4986: {
4987: {for( int m = 1; m <= 12; ++m )
4988: {
4989: {for( int d = 1; d <= 28; ++d )
4990: {
4991: struct tm when;
4992: when.tm_year = y - 1900;
4993: when.tm_mon = m - 1;
4994: when.tm_mday = d;
4995: when.tm_hour = 0;
4996: when.tm_min = 0;
4997: when.tm_sec = 0;
4998: when.tm_isdst = -1;
4999: VERIFY( ((time_t)-1) != mktime( &when ) );
5000: VERIFY( when.tm_wday == GetDayOfWeek( y, m, d ) );
5001: }}
5002: }}
5003: }}
5004: }
5005:
5006: }//test_time
5007:
5008: //*********************************************************
5009: // test_str()
5010: //*********************************************************
5011: DEFINE_TESTPROC( test_str )
5012: {
5013: //---------------------------------------------------------
5014: // 定数 の テスト
5015: //---------------------------------------------------------
5016:
5017: //---------------------------------------------------------
5018: // ファイルスコープ関数 の テスト
5019: //---------------------------------------------------------
5020:
5021: // SET_STRMAP_BIT(), GET_STRMAP_BIT(),
5022: {
5023: BYTE map[ STRMAP_SIZE ];
5024: memzero( map, sizeof( map ) );
5025: {for( int i = 0; i < CHAR_BIT * STRMAP_SIZE; ++i )
5026: {
5027: VERIFY( 0 == GET_STRMAP_BIT( map, i ) );
5028: SET_STRMAP_BIT( map, i );
5029: VERIFY( 0 != GET_STRMAP_BIT( map, i ) );
5030: }}
5031: }
5032:
5033:
5034: //---------------------------------------------------------
5035: // 公開関数 の テスト
5036: //---------------------------------------------------------
5037: // strcode()
5038: // strnext()
5039: // strchop()
5040: // strcopy(), strncopy()
5041: // strlower(), strupper()
5042: // strmatch()
5043: // strrep()
5044: // strrevj()
5045: // strshift()
5046: // strsub
5047:
5048: // strdup(), strndup()
5049: {
5050: const struct
5051: {
5052: size_t len;
5053: const char *string;
5054: size_t count;
5055: }
5056: testcase[] =
5057: {
5058: #define MAKE_TESTCASE( len, string, count ) { len, string, count }
5059: MAKE_TESTCASE( 0, "", 0 ),
5060: MAKE_TESTCASE( 0, "", 1 ),
5061: MAKE_TESTCASE( 0, "-", 0 ),
5062: MAKE_TESTCASE( 1, "-", 1 ),
5063: MAKE_TESTCASE( 1, "-", 2 ),
5064: MAKE_TESTCASE( 0, "abc", 0 ),
5065: MAKE_TESTCASE( 1, "abc", 1 ),
5066: MAKE_TESTCASE( 2, "abc", 2 ),
5067: MAKE_TESTCASE( 3, "abc", 3 ),
5068: MAKE_TESTCASE( 3, "abc", 5 ),
5069: #undef MAKE_TESTCASE
5070: };
5071: {for( int i = 0; i < numof( testcase ); ++i )
5072: {
5073: // strdup()
5074: {
5075: char *string = strdup( testcase[ i ].string );
5076: VERIFY( streql( string, testcase[ i ].string ) );
5077: free( string );
5078: }
5079:
5080: // strndup()
5081: {
5082: char *string = strndup( testcase[ i ].string, testcase[ i ].count );
5083: VERIFY( strneql( string, testcase[ i ].string, testcase[ i ].count ) );
5084: VERIFY( testcase[ i ].len == strlen( string ) );
5085: free( string );
5086: }
5087: }}
5088: }
5089:
5090: // strmove()
5091: {
5092: const struct testcase_tag
5093: {
5094: int n;
5095: int m;
5096: const char *buf;
5097: const char *str;
5098: }
5099: testcase[] =
5100: {
5101: { 0, 0, "", "" },
5102: { 0, 0, "ABCDEFG", "ABCDEFG" },
5103: { 1, 0, "ABCDEFG", "AABCDEFG" },
5104: { 0, 1, "ABCDEFG", "BCDEFG" },
5105: { 7, 0, "ABCDEFG", "ABCDEFGABCDEFG" },
5106: { 0, 7, "ABCDEFG", "" },
5107: };
5108:
5109: {for( int t = 0; t < numof( testcase ); ++t )
5110: {
5111: // strmove()
5112: {
5113: char buf[ 1024 ];
5114: strcopy( buf, numof(buf), testcase[ t ].buf );
5115: VERIFY( '\0' == *strmove( buf + testcase[ t ].n, buf + testcase[ t ].m ) );
5116: VERIFY( streql( buf, testcase[ t ].str ) );
5117: }
5118:
5119: }}
5120: }
5121:
5122: // strputs()
5123: {
5124: const struct
5125: {
5126: const char *buffer;
5127: size_t bufsize;
5128: size_t offset;
5129: const char *string;
5130: size_t count;
5131: const char *result;
5132: }
5133: testcase[] =
5134: {
5135: #define MAKE_TESTCASE( buffer, bufsize, offset, string, count, result ) { buffer, bufsize, offset, string, count, result }
5136: MAKE_TESTCASE( "--", 3, 0, "s", 1, "s" ),
5137: MAKE_TESTCASE( "--", 3, 1, "s", 1, "-s" ),
5138: MAKE_TESTCASE( "--", 3, 2, "s", 0, "--" ),
5139: MAKE_TESTCASE( "--", 3, 3, "s", 0, "--" ),
5140: MAKE_TESTCASE( "--", 3, 0, "string", 2, "st" ),
5141: MAKE_TESTCASE( "--", 3, 1, "string", 1, "-s" ),
5142: MAKE_TESTCASE( "--", 3, 2, "string", 0, "--" ),
5143: MAKE_TESTCASE( "--", 3, 3, "string", 0, "--" ),
5144: MAKE_TESTCASE( "--", 2, 0, "string", 1, "s" ),
5145: MAKE_TESTCASE( "--", 2, 1, "string", 0, "-" ),
5146: MAKE_TESTCASE( "--", 2, 2, "string", 0, "--" ),
5147: MAKE_TESTCASE( "--", 1, 0, "string", 0, "" ),
5148: MAKE_TESTCASE( "--", 1, 1, "string", 0, "--" ),
5149: MAKE_TESTCASE( "--", 0, 0, "string", 0, "--" ),
5150: #undef MAKE_TESTCASE
5151: };
5152: {for( int i = 0; i < numof( testcase ); ++i )
5153: {
5154: // strputs()
5155: {
5156: char buffer[ 1024 ];
5157: strcopy( buffer, numof(buffer), testcase[i].buffer );
5158: VERIFY( streql( buffer, testcase[i].buffer ) );
5159: VERIFY( strlen(testcase[i].string) == strputs( null, 0, testcase[i].offset, testcase[i].string ) );
5160: VERIFY( testcase[i].count == strputs( buffer, testcase[i].bufsize, testcase[i].offset, testcase[i].string ) );
5161: VERIFY( streql( buffer, testcase[i].result ) );
5162: }
5163: }}
5164: }
5165:
5166: // jmschr(), jmsrchr(), strchri(), strrchri()
5167: {
5168: const struct testcase_tag
5169: {
5170: int j; // jmschr
5171: int rj; // jmsrchr
5172: int i; // strchri
5173: int ri; // strrchri
5174: int c;
5175: const char *str;
5176: }
5177: testcase[] =
5178: {
5179: #define _( str ) MAKEDBC( (str)[0], (str)[1] )
5180: #define MAKE_TESTCASE( j, rj, i, ri, c, str ) { j, rj, i, ri, c, str }
5181: MAKE_TESTCASE( -1, -1, -1, -1, 'A', "\0aAb" ),
5182: MAKE_TESTCASE( 0, 0, 0, 0, '\0', "\0aAb" ),
5183: MAKE_TESTCASE( 0, 0, 0, 1, 'a', "aA\0aAb" ),
5184: MAKE_TESTCASE( 1, 1, 0, 1, 'a', "Aa\0aAb" ),
5185: MAKE_TESTCASE( 1, 1, 0, 1, 'A', "aA\0aAb" ),
5186: MAKE_TESTCASE( 0, 0, 0, 1, 'A', "Aa\0aAb" ),
5187: MAKE_TESTCASE( 0, 0, 0, 2, 'a', "axA\0aAb" ),
5188: MAKE_TESTCASE( 2, 2, 0, 2, 'a', "Axa\0aAb" ),
5189: MAKE_TESTCASE( 2, 2, 0, 2, 'A', "axA\0aAb" ),
5190: MAKE_TESTCASE( 0, 0, 0, 2, 'A', "Axa\0aAb" ),
5191: MAKE_TESTCASE( 1, 1, 1, 2, 'a', "xaA\0aAb" ),
5192: MAKE_TESTCASE( 2, 2, 1, 2, 'a', "xAa\0aAb" ),
5193: MAKE_TESTCASE( 2, 2, 1, 2, 'A', "xaA\0aAb" ),
5194: MAKE_TESTCASE( 1, 1, 1, 2, 'A', "xAa\0aAb" ),
5195: MAKE_TESTCASE( 1, 1, 0, 1, 'a', "Aax\0aAb" ),
5196: MAKE_TESTCASE( 0, 0, 0, 1, 'a', "aAx\0aAb" ),
5197: MAKE_TESTCASE( 0, 0, 0, 1, 'A', "Aax\0aAb" ),
5198: MAKE_TESTCASE( 1, 1, 0, 1, 'A', "aAx\0aAb" ),
5199: MAKE_TESTCASE( 0, 2, 0, 2, 'A', "AAA\0aAb" ),
5200: MAKE_TESTCASE( -1, -1, 0, 2, 'A', "aaa\0aAb" ),
5201: MAKE_TESTCASE( 3, 3, 3, 3, '\0', "aAx\0aAb" ),
5202: MAKE_TESTCASE( -1, -1, -1, -1, 'b', "aAx\0aAb" ),
5203: MAKE_TESTCASE( -1, -1, -1, -1, '\\', "ソ" ),
5204: MAKE_TESTCASE( 0, 8, 0, 8, _("A"), "ABabABab" ),
5205: MAKE_TESTCASE( 4, 12, 4, 12, _("a"), "ABabABab" ),
5206: #undef MAKE_TESTCASE
5207: #undef _
5208: };
5209:
5210: {for( int t = 0; t < numof( testcase ); ++t )
5211: {
5212: ASSERT( testcase[ t ].i <= testcase[ t ].ri );
5213: ASSERT( testcase[ t ].j <= testcase[ t ].rj );
5214:
5215: // jmschr
5216: {
5217: const char *j = jmschr( testcase[ t ].str, testcase[ t ].c );
5218: VERIFY( ((-1 == testcase[ t ].j) && (null == j))
5219: || (j == testcase[ t ].str + testcase[ t ].j) );
5220: VERIFY( strtail( testcase[ t ].str ) == jmschr( testcase[ t ].str, '\0' ) );
5221: }
5222:
5223: // jmsrchr
5224: {
5225: const char *rj = jmsrchr( testcase[ t ].str, testcase[ t ].c );
5226: VERIFY( ((-1 == testcase[ t ].rj) && (null == rj))
5227: || (rj == testcase[ t ].str + testcase[ t ].rj) );
5228: VERIFY( strtail( testcase[ t ].str ) == jmsrchr( testcase[ t ].str, '\0' ) );
5229: }
5230:
5231:
5232: // strchri
5233: {
5234: const char *i = strchri( testcase[ t ].str, testcase[ t ].c );
5235: VERIFY( ((-1 == testcase[ t ].i) && (null == i))
5236: || (i == testcase[ t ].str + testcase[ t ].i) );
5237: VERIFY( strtail( testcase[ t ].str ) == strchri( testcase[ t ].str, '\0' ) );
5238: }
5239:
5240: // strrchri
5241: {
5242: const char *ri = strrchri( testcase[ t ].str, testcase[ t ].c );
5243: VERIFY( ((-1 == testcase[ t ].ri) && (null == ri))
5244: || (ri == testcase[ t ].str + testcase[ t ].ri) );
5245: VERIFY( strtail( testcase[ t ].str ) == strrchri( testcase[ t ].str, '\0' ) );
5246: }
5247: }}
5248: }
5249:
5250: // strnchr(), strnchri(), strnrchr(), strnrchri()
5251: {
5252: const struct testcase_tag
5253: {
5254: int n; // strnchr
5255: int ni; // strnchri
5256: int nr; // strnrchr
5257: int nri; // strnrchri
5258: int c;
5259: const char *str;
5260: int cnt;
5261: }
5262: testcase[] =
5263: {
5264: #define MAKE_TESTCASE( n, ni, nr, nri, c, str, cnt ) { n, ni, nr, nri, c, str, cnt }
5265: MAKE_TESTCASE( -1, -1, -1, -1, 'A', "\0aAb", 0 ),
5266: MAKE_TESTCASE( -1, -1, -1, -1, '\0', "\0aAb", 0 ),
5267: MAKE_TESTCASE( 0, 0, 0, 0, '\0', "\0aAb", 1 ),
5268: MAKE_TESTCASE( 0, 0, 0, 1, 'a', "aA\0aAb", 2 ),
5269: MAKE_TESTCASE( 1, 0, 1, 1, 'a', "Aa\0aAb", 2 ),
5270: MAKE_TESTCASE( 1, 0, 1, 1, 'A', "aA\0aAb", 2 ),
5271: MAKE_TESTCASE( 0, 0, 0, 1, 'A', "Aa\0aAb", 2 ),
5272: MAKE_TESTCASE( 0, 0, 0, 2, 'a', "axA\0aAb", 3 ),
5273: MAKE_TESTCASE( 2, 0, 2, 2, 'a', "Axa\0aAb", 3 ),
5274: MAKE_TESTCASE( 2, 0, 2, 2, 'A', "axA\0aAb", 3 ),
5275: MAKE_TESTCASE( 0, 0, 0, 2, 'A', "Axa\0aAb", 3 ),
5276: MAKE_TESTCASE( 1, 1, 1, 2, 'a', "xaA\0aAb", 3 ),
5277: MAKE_TESTCASE( 2, 1, 2, 2, 'a', "xAa\0aAb", 3 ),
5278: MAKE_TESTCASE( 2, 1, 2, 2, 'A', "xaA\0aAb", 3 ),
5279: MAKE_TESTCASE( 1, 1, 1, 2, 'A', "xAa\0aAb", 3 ),
5280: MAKE_TESTCASE( 1, 0, 1, 1, 'a', "Aax\0aAb", 3 ),
5281: MAKE_TESTCASE( 0, 0, 0, 1, 'a', "aAx\0aAb", 3 ),
5282: MAKE_TESTCASE( 0, 0, 0, 1, 'A', "Aax\0aAb", 3 ),
5283: MAKE_TESTCASE( 1, 0, 1, 1, 'A', "aAx\0aAb", 3 ),
5284: MAKE_TESTCASE( -1, -1, -1, -1, '\0', "aAx\0aAb", 3 ),
5285: MAKE_TESTCASE( 3, 3, 3, 3, '\0', "aAx\0aAb", 4 ),
5286: MAKE_TESTCASE( -1, -1, -1, -1, 'b', "aAx\0aAb", 3 ),
5287: MAKE_TESTCASE( -1, -1, -1, -1, 'b', "aAx\0aAb", 9 ),
5288: MAKE_TESTCASE( -1, -1, -1, -1, '\\', "ソ", 9 ),
5289: MAKE_TESTCASE( -1, -1, -1, -1, '\\', "ソソソ\\", 6 ),
5290: MAKE_TESTCASE( 6, 6, 6, 6, '\\', "ソソソ\\", 7 ),
5291: #undef MAKE_TESTCASE
5292: };
5293:
5294: {for( int t = 0; t < numof( testcase ); ++t )
5295: {
5296: ASSERT( testcase[ t ].n < testcase[ t ].cnt );
5297: ASSERT( testcase[ t ].ni < testcase[ t ].cnt );
5298: ASSERT( testcase[ t ].nr < testcase[ t ].cnt );
5299: ASSERT( testcase[ t ].nri < testcase[ t ].cnt );
5300: ASSERT( testcase[ t ].n <= testcase[ t ].nr );
5301: ASSERT( testcase[ t ].ni <= testcase[ t ].nri );
5302:
5303: // strnchr
5304: {
5305: const char *n = strnchr( testcase[ t ].str, testcase[ t ].c, testcase[ t ].cnt );
5306: VERIFY( ((-1 == testcase[ t ].n) && (null == n))
5307: || (n == testcase[ t ].str + testcase[ t ].n) );
5308: }
5309:
5310: // strnchri
5311: {
5312: const char *ni = strnchri( testcase[ t ].str, testcase[ t ].c, testcase[ t ].cnt );
5313: VERIFY( ((-1 == testcase[ t ].ni) && (null == ni))
5314: || (ni == testcase[ t ].str + testcase[ t ].ni) );
5315: }
5316:
5317: // strnrchr
5318: {
5319: const char *nr = strnrchr( testcase[ t ].str, testcase[ t ].c, testcase[ t ].cnt );
5320: VERIFY( ((-1 == testcase[ t ].nr) && (null == nr))
5321: || (nr == testcase[ t ].str + testcase[ t ].nr) );
5322: }
5323:
5324: // strnrchri
5325: {
5326: const char *nri = strnrchri( testcase[ t ].str, testcase[ t ].c, testcase[ t ].cnt );
5327: VERIFY( ((-1 == testcase[ t ].nri) && (null == nri))
5328: || (nri == testcase[ t ].str + testcase[ t ].nri) );
5329: }
5330:
5331: // str... <=> strn...
5332: {
5333: const size_t length = strlen( testcase[ t ].str );
5334: VERIFY( jmschr( testcase[ t ].str, testcase[ t ].c )
5335: == strnchr( testcase[ t ].str, testcase[ t ].c, 1 + length ) );
5336: VERIFY( strchri( testcase[ t ].str, testcase[ t ].c )
5337: == strnchri( testcase[ t ].str, testcase[ t ].c, 1 + length ) );
5338: VERIFY( jmsrchr( testcase[ t ].str, testcase[ t ].c )
5339: == strnrchr( testcase[ t ].str, testcase[ t ].c, 1 + length ) );
5340: VERIFY( strrchri( testcase[ t ].str, testcase[ t ].c )
5341: == strnrchri( testcase[ t ].str, testcase[ t ].c, 1 + length ) );
5342: }
5343: }}
5344: }
5345:
5346: // strhstr(), strhstri(),
5347: {
5348: const struct
5349: {
5350: bool h;
5351: bool hi;
5352: const char *str1;
5353: const char *str2;
5354: }
5355: testcase[] =
5356: {
5357: #define MAKE_TESTCASE( h, hi, str1, str2 ) { h, hi, str1, str2 }
5358: MAKE_TESTCASE( true, true, "", "" ), //
5359: MAKE_TESTCASE( true, true, "x", "" ), //
5360: MAKE_TESTCASE( true, true, "x-", "" ), //
5361: MAKE_TESTCASE( false, false, "", "x" ), //
5362: MAKE_TESTCASE( false, false, "-", "x" ), //
5363: MAKE_TESTCASE( true, true, "x", "x" ), //
5364: MAKE_TESTCASE( false, false, "-x", "x" ), //
5365: MAKE_TESTCASE( false, true, "x", "X" ), //
5366: MAKE_TESTCASE( false, true, "X", "x" ), //
5367: MAKE_TESTCASE( true, true, "X", "X" ), //
5368: MAKE_TESTCASE( false, false, "ab", "ac" ), //
5369: MAKE_TESTCASE( true, true, "ab", "ab" ), //
5370: MAKE_TESTCASE( false, true, "AB", "ab" ), //
5371: MAKE_TESTCASE( false, true, "ab", "AB" ), //
5372: MAKE_TESTCASE( true, true, "AB", "AB" ), //
5373: MAKE_TESTCASE( false, false, "-AB", "AB" ), //
5374: MAKE_TESTCASE( true, true, "x-", "x" ), //
5375: MAKE_TESTCASE( false, true, "x-", "X" ), //
5376: MAKE_TESTCASE( false, true, "X-", "x" ), //
5377: MAKE_TESTCASE( true, true, "X-", "X" ), //
5378: MAKE_TESTCASE( true, true, "ab-", "ab" ), //
5379: MAKE_TESTCASE( false, true, "AB-", "ab" ), //
5380: MAKE_TESTCASE( false, true, "ab-", "AB" ), //
5381: MAKE_TESTCASE( true, true, "AB-", "AB" ), //
5382: MAKE_TESTCASE( false, false, "x", "x-" ), //
5383: MAKE_TESTCASE( false, false, "ab", "ab-" ), //
5384: #undef MAKE_TESTCASE
5385: };
5386: {for( int i = 0; i < numof( testcase ); ++i )
5387: {
5388: // strhstr
5389: {
5390: const bool h = strhstr( testcase[ i ].str1, testcase[ i ].str2 );
5391: VERIFY( ( h && testcase[ i ].h )
5392: || ( !h && !testcase[ i ].h ) );
5393: }
5394:
5395: // strhstri
5396: {
5397: const bool hi = strhstri( testcase[ i ].str1, testcase[ i ].str2 );
5398: VERIFY( ( hi && testcase[ i ].hi )
5399: || ( !hi && !testcase[ i ].hi ) );
5400: }
5401: }}
5402: }
5403:
5404: // strnrstr(), strnrstri(), strnstr(), strnstri(),
5405: {
5406: const struct testcase_tag
5407: {
5408: int n; // strnstr
5409: int ni; // strnstri
5410: int nr; // strnrstr
5411: int nri; // strnrstri
5412: const char *str;
5413: const char *ptn;
5414: int cnt;
5415: }
5416: testcase[] =
5417: {
5418: #define MAKE_TESTCASE( n, ni, nr, nri, str, ptn, cnt ) { n, ni, nr, nri, str, ptn, cnt }
5419: MAKE_TESTCASE( -1, -1, -1, -1, "\0aaAA", "", 0 ),
5420: MAKE_TESTCASE( 0, 0, 0, 0, "\0aaAA", "", 1 ),
5421: MAKE_TESTCASE( -1, -1, -1, -1, "\0aaAA", "a", 1 ),
5422: MAKE_TESTCASE( -1, -1, -1, -1, "a\0aaAA", "", 0 ),
5423: MAKE_TESTCASE( 0, 0, 0, 0, "a\0aaAA", "", 1 ),
5424: MAKE_TESTCASE( 0, 0, 1, 1, "a\0aaAA", "", 2 ),
5425: MAKE_TESTCASE( 0, 0, 2, 2, "aaa\0aaAA", "", 3 ),
5426: MAKE_TESTCASE( 0, 0, 3, 3, "aaa\0aaAA", "", 4 ),
5427: MAKE_TESTCASE( -1, -1, -1, -1, "a\0aaAA", "a", 0 ),
5428: MAKE_TESTCASE( 0, 0, 0, 0, "a\0aaAA", "a", 1 ),
5429: MAKE_TESTCASE( 0, 0, 3, 3, "aaaaa\0aaAA", "aa", 5 ),
5430: MAKE_TESTCASE( 0, 0, 2, 2, "aaaaa\0aaAA", "aa", 4 ),
5431: MAKE_TESTCASE( 0, 0, 1, 1, "aaaaa\0aaAA", "aa", 3 ),
5432: MAKE_TESTCASE( 0, 0, 0, 0, "aaaaa\0aaAA", "aa", 2 ),
5433: MAKE_TESTCASE( -1, -1, -1, -1, "aaaaa\0aaAA", "aa", 1 ),
5434: MAKE_TESTCASE( -1, 0, -1, 3, "aaaaa\0aaAA", "aA", 5 ),
5435: MAKE_TESTCASE( -1, 0, -1, 2, "aaaaa\0aaAA", "aA", 4 ),
5436: MAKE_TESTCASE( -1, -1, -1, -1, "aaaaa\0aaAA", "aA", 1 ),
5437: MAKE_TESTCASE( -1, 0, -1, 3, "AAAAA\0aaAA", "aA", 5 ),
5438: MAKE_TESTCASE( -1, 0, -1, 2, "AAAAA\0aaAA", "aA", 4 ),
5439: MAKE_TESTCASE( -1, -1, -1, -1, "AAAAA\0aaAA", "aA", 1 ),
5440: MAKE_TESTCASE( -1, 0, -1, 3, "aAaAa\0aaAA", "aa", 5 ),
5441: MAKE_TESTCASE( -1, 0, -1, 2, "aAaAa\0aaAA", "aa", 4 ),
5442: MAKE_TESTCASE( -1, -1, -1, -1, "aAaAa\0aaAA", "aa", 1 ),
5443: MAKE_TESTCASE( -1, 0, -1, 3, "aAaAa\0aaAA", "AA", 5 ),
5444: MAKE_TESTCASE( -1, 0, -1, 2, "aAaAa\0aaAA", "AA", 4 ),
5445: MAKE_TESTCASE( -1, -1, -1, -1, "aAaAa\0aaAA", "AA", 1 ),
5446: MAKE_TESTCASE( 1, 1, 2, 2, "baaab\0aaAA", "aa", 5 ),
5447: MAKE_TESTCASE( 1, 1, 2, 2, "baaab\0aaAA", "aa", 4 ),
5448: MAKE_TESTCASE( -1, -1, -1, -1, "baaab\0aaAA", "aa", 2 ),
5449: MAKE_TESTCASE( -1, -1, -1, -1, "baaab\0aaAA", "ax", 5 ),
5450: MAKE_TESTCASE( -1, -1, -1, -1, "baaab\0aaAA", "ax", 9 ),
5451: MAKE_TESTCASE( -1, -1, -1, -1, "ソ", "\\", 9 ),
5452: MAKE_TESTCASE( -1, -1, -1, -1, "ソソソ\\", "\\", 6 ),
5453: MAKE_TESTCASE( 6, 6, 6, 6, "ソソソ\\", "\\", 7 ),
5454: #undef MAKE_TESTCASE
5455: };
5456:
5457: {for( int t = 0; t < numof( testcase ); ++t )
5458: {
5459: ASSERT( testcase[ t ].n < testcase[ t ].cnt );
5460: ASSERT( testcase[ t ].ni < testcase[ t ].cnt );
5461: ASSERT( testcase[ t ].nr < testcase[ t ].cnt );
5462: ASSERT( testcase[ t ].nri < testcase[ t ].cnt );
5463: ASSERT( testcase[ t ].n <= testcase[ t ].nr );
5464: ASSERT( testcase[ t ].ni <= testcase[ t ].nri );
5465:
5466: // strnstr
5467: {
5468: const char *n = strnstr( testcase[ t ].str, testcase[ t ].ptn, testcase[ t ].cnt );
5469: VERIFY( ((-1 == testcase[ t ].n) && (null == n))
5470: || ( n == testcase[ t ].str + testcase[ t ].n ) );
5471: }
5472:
5473: // strnstri
5474: {
5475: const char *ni = strnstri( testcase[ t ].str, testcase[ t ].ptn, testcase[ t ].cnt );
5476: VERIFY( ((-1 == testcase[ t ].ni) && (null == ni))
5477: || ( ni == testcase[ t ].str + testcase[ t ].ni ) );
5478: }
5479:
5480: // strnrstr
5481: {
5482: const char *nr = strnrstr( testcase[ t ].str, testcase[ t ].ptn, testcase[ t ].cnt );
5483: VERIFY( ((-1 == testcase[ t ].nr) && (null == nr))
5484: || ( nr == testcase[ t ].str + testcase[ t ].nr ) );
5485: }
5486:
5487: // strnrstri
5488: {
5489: const char *nri = strnrstri( testcase[ t ].str, testcase[ t ].ptn, testcase[ t ].cnt );
5490: VERIFY( ((-1 == testcase[ t ].nri) && (null == nri))
5491: || ( nri == testcase[ t ].str + testcase[ t ].nri ) );
5492: }
5493:
5494: // str... <=> strn...
5495: {
5496: const size_t length = strlen( testcase[ t ].str );
5497: VERIFY( jmsstr( testcase[ t ].str, testcase[ t ].ptn )
5498: == strnstr( testcase[ t ].str, testcase[ t ].ptn, 1 + length ) );
5499: VERIFY( strstri( testcase[ t ].str, testcase[ t ].ptn )
5500: == strnstri( testcase[ t ].str, testcase[ t ].ptn, 1 + length ) );
5501: VERIFY( strrstr( testcase[ t ].str, testcase[ t ].ptn )
5502: == strnrstr( testcase[ t ].str, testcase[ t ].ptn, 1 + length ) );
5503: VERIFY( strrstri( testcase[ t ].str, testcase[ t ].ptn )
5504: == strnrstri( testcase[ t ].str, testcase[ t ].ptn, 1 + length ) );
5505: }
5506: }}
5507: }
5508:
5509: // strrstr(), strrstri(), strstri(),
5510: {
5511: const struct testcase_tag
5512: {
5513: int i; // strstri
5514: int r; // strrstr
5515: int ri; // strrstri
5516: const char *str;
5517: const char *ptn;
5518: }
5519: testcase[] =
5520: {
5521: #define MAKE_TESTCASE( i, r, ri, str, ptn ) { i, r, ri, str, ptn }
5522: MAKE_TESTCASE( 0, 0, 0, "\0aaAA", "" ),
5523: MAKE_TESTCASE( -1, -1, -1, "\0aaAA", "a" ),
5524: MAKE_TESTCASE( 0, 1, 1, "a\0aaAA", "" ),
5525: MAKE_TESTCASE( 0, 3, 3, "aaa\0aaAA", "" ),
5526: MAKE_TESTCASE( 0, 0, 0, "a\0aaAA", "a" ),
5527: MAKE_TESTCASE( 0, 3, 3, "aaaaa\0aaAA", "aa" ),
5528: MAKE_TESTCASE( 0, -1, 3, "aaaaa\0aaAA", "aA" ),
5529: MAKE_TESTCASE( 0, -1, 3, "AAAAA\0aaAA", "aA" ),
5530: MAKE_TESTCASE( 0, -1, 3, "aAaAa\0aaAA", "aa" ),
5531: MAKE_TESTCASE( 0, -1, 3, "aAaAa\0aaAA", "AA" ),
5532: MAKE_TESTCASE( 1, 2, 2, "baaab\0aaAA", "aa" ),
5533: MAKE_TESTCASE( -1, -1, -1, "baaab\0aaAA", "ax" ),
5534: MAKE_TESTCASE( -1, -1, -1, "ソ", "\\" ),
5535: #undef MAKE_TESTCASE
5536: };
5537:
5538: {for( int t = 0; t < numof( testcase ); ++t )
5539: {
5540: ASSERT( testcase[ t ].i <= testcase[ t ].ri );
5541:
5542: // strstri
5543: {
5544: const char *i = strstri( testcase[ t ].str, testcase[ t ].ptn );
5545: VERIFY( ((-1 == testcase[ t ].i) && (null == i))
5546: || ( i == testcase[ t ].str + testcase[ t ].i ) );
5547: }
5548:
5549: // strrstr
5550: {
5551: const char *r = strrstr( testcase[ t ].str, testcase[ t ].ptn );
5552: VERIFY( ((-1 == testcase[ t ].r) && (null == r))
5553: || ( r == testcase[ t ].str + testcase[ t ].r ) );
5554: VERIFY( strtail( testcase[ t ].str ) == strrstr( testcase[ t ].str, "" ) );
5555: }
5556:
5557: // strrstri
5558: {
5559: const char *ri = strrstri( testcase[ t ].str, testcase[ t ].ptn );
5560: VERIFY( ((-1 == testcase[ t ].ri) && (null == ri))
5561: || ( ri == testcase[ t ].str + testcase[ t ].ri ) );
5562: VERIFY( strtail( testcase[ t ].str ) == strrstri( testcase[ t ].str, "" ) );
5563: }
5564: }}
5565: }
5566:
5567: // strtstr, strtstri
5568: {
5569: const struct
5570: {
5571: bool t;
5572: bool ti;
5573: const char *str1;
5574: const char *str2;
5575: }
5576: testcase[] =
5577: {
5578: #define MAKE_TESTCASE( t, ti, str1, str2 ) { t, ti, str1, str2 }
5579: MAKE_TESTCASE( true, true, "", "" ), //
5580: MAKE_TESTCASE( true, true, "x", "" ), //
5581: MAKE_TESTCASE( false, false, "", "x" ), //
5582: MAKE_TESTCASE( true, true, "x", "x" ), //
5583: MAKE_TESTCASE( false, true, "x", "X" ), //
5584: MAKE_TESTCASE( false, true, "X", "x" ), //
5585: MAKE_TESTCASE( true, true, "X", "X" ), //
5586: MAKE_TESTCASE( true, true, "abc", "abc" ), //
5587: MAKE_TESTCASE( false, true, "abc", "Abc" ), //
5588: MAKE_TESTCASE( false, true, "abc", "aBc" ), //
5589: MAKE_TESTCASE( false, true, "abc", "abC" ), //
5590: MAKE_TESTCASE( false, true, "Abc", "abc" ), //
5591: MAKE_TESTCASE( false, true, "aBc", "abc" ), //
5592: MAKE_TESTCASE( false, true, "abC", "abc" ), //
5593: MAKE_TESTCASE( true, true, "-abc", "abc" ), //
5594: MAKE_TESTCASE( false, false, "abc-", "abc" ), //
5595: MAKE_TESTCASE( false, false, "abc", "abc-" ), //
5596: MAKE_TESTCASE( false, false, "abc", "-abc" ), //
5597: MAKE_TESTCASE( false, false, "ソ", "\\" ), //
5598: #undef MAKE_TESTCASE
5599: };
5600: {for( int i = 0; i < numof( testcase ); ++i )
5601: {
5602: // strtstr
5603: {
5604: const bool t = !! strtstr( testcase[ i ].str1, testcase[ i ].str2 );
5605: VERIFY( ( t && testcase[ i ].t )
5606: || ( !t && !testcase[ i ].t ) );
5607: }
5608:
5609: // strtstri
5610: {
5611: const bool ti = !! strtstri( testcase[ i ].str1, testcase[ i ].str2 );
5612: VERIFY( ( ti && testcase[ i ].ti )
5613: || ( !ti && !testcase[ i ].ti ) );
5614: }
5615: }}
5616: }
5617:
5618: // strcount()
5619: {
5620: const struct
5621: {
5622: int count;
5623: const char *str;
5624: const char *ptn;
5625: }
5626: testcase[] =
5627: {
5628: #define MAKE_TESTCASE( count, str, ptn ) { count, str, ptn }
5629: MAKE_TESTCASE( 0, "", "" ),
5630: MAKE_TESTCASE( 0, "-", "" ),
5631: MAKE_TESTCASE( 0, "", "-" ),
5632: MAKE_TESTCASE( 1, "-", "-" ),
5633: MAKE_TESTCASE( 2, "--", "-" ),
5634: MAKE_TESTCASE( 3, "---", "-" ),
5635: MAKE_TESTCASE( 1, "---", "--" ),
5636: MAKE_TESTCASE( 2, "----", "--" ),
5637: MAKE_TESTCASE( 2, "-----", "--" ),
5638: MAKE_TESTCASE( 2, "-0-", "-" ),
5639: MAKE_TESTCASE( 1, "-0-", "0" ),
5640: MAKE_TESTCASE( 3, "-0-0-", "-" ),
5641: MAKE_TESTCASE( 0, "-0-0-", "--" ),
5642: MAKE_TESTCASE( 1, "-0-0-", "-0-" ),
5643: MAKE_TESTCASE( 2, "-0-0-0-", "-0-" ),
5644: MAKE_TESTCASE( 1, "---", "---" ),
5645: MAKE_TESTCASE( 0, "---", "-----" ),
5646: MAKE_TESTCASE( 0, "ソソソ", "\\" ),
5647: #undef MAKE_TESTCASE
5648: };
5649: {for( int i = 0; i < numof( testcase ); ++i )
5650: {
5651: const int count = strcount( testcase[ i ].str, testcase[ i ].ptn );
5652: VERIFY( count == testcase[ i ].count );
5653: }}
5654: }
5655:
5656: // strtail()
5657: {
5658: const struct
5659: {
5660: size_t tail;
5661: const char *string;
5662: }
5663: testcase[] =
5664: {
5665: #define MAKE_TESTCASE( tail, string ) { tail, string }
5666: MAKE_TESTCASE( 0, "" ),
5667: MAKE_TESTCASE( 1, "-" ),
5668: MAKE_TESTCASE( 3, "---" ),
5669: #undef MAKE_TESTCASE
5670: };
5671: {for( int i = 0; i < numof( testcase ); ++i )
5672: {
5673: const char *tail = strtail( testcase[ i ].string );
5674: VERIFY( tail == testcase[ i ].string + testcase[ i ].tail );
5675: VERIFY( '\0' == *tail );
5676: }}
5677: }
5678:
5679: // strntail()
5680: {
5681: const struct
5682: {
5683: size_t tail;
5684: const char *string;
5685: size_t count;
5686: }
5687: testcase[] =
5688: {
5689: #define MAKE_TESTCASE( tail, string, count ) { tail, string, count }
5690: MAKE_TESTCASE( 0, "", 0 ),
5691: MAKE_TESTCASE( 0, "", 1 ),
5692: MAKE_TESTCASE( 0, "-", 0 ),
5693: MAKE_TESTCASE( 1, "-", 1 ),
5694: MAKE_TESTCASE( 1, "-", 2 ),
5695: MAKE_TESTCASE( 0, "---", 0 ),
5696: MAKE_TESTCASE( 1, "---", 1 ),
5697: MAKE_TESTCASE( 2, "---", 2 ),
5698: MAKE_TESTCASE( 3, "---", 3 ),
5699: MAKE_TESTCASE( 3, "---", 5 ),
5700: MAKE_TESTCASE( 2, "−a", 2 ),
5701: MAKE_TESTCASE( 3, "−a", 3 ),
5702: MAKE_TESTCASE( 3, "−a", 4 ),
5703: #undef MAKE_TESTCASE
5704: };
5705: {for( int i = 0; i < numof( testcase ); ++i )
5706: {
5707: ASSERT( testcase[ i ].tail <= testcase[ i ].count );
5708:
5709: const char *tail = strntail( testcase[ i ].string, testcase[ i ].count );
5710: VERIFY( tail == testcase[ i ].string + testcase[ i ].tail );
5711: VERIFY( strtail( testcase[ i ].string ) == strntail( testcase[ i ].string, strlen( testcase[ i ].string ) ) );
5712: }}
5713: }
5714:
5715: // streql(), streqli(),
5716: {
5717: const struct
5718: {
5719: bool eql;
5720: bool eqli;
5721: const char *str1;
5722: const char *str2;
5723: }
5724: testcase[] =
5725: {
5726: #define MAKE_TESTCASE( eql, eqli, str1, str2 ) { eql, eqli, str1, str2 }
5727: MAKE_TESTCASE( true, true, "", "" ), //
5728: MAKE_TESTCASE( false, false, "a", "b" ), //
5729: MAKE_TESTCASE( true, true, "a", "a" ), //
5730: MAKE_TESTCASE( false, true, "a", "A" ), //
5731: MAKE_TESTCASE( false, true, "A", "a" ), //
5732: MAKE_TESTCASE( false, false, "ab", "a" ), //
5733: MAKE_TESTCASE( false, false, "a", "ab" ), //
5734: MAKE_TESTCASE( true, true, "ab", "ab" ), //
5735: MAKE_TESTCASE( false, true, "AB", "ab" ), //
5736: MAKE_TESTCASE( false, true, "ab", "AB" ), //
5737: MAKE_TESTCASE( true, true, "AB", "AB" ), //
5738: #undef MAKE_TESTCASE
5739: };
5740: {for( int i = 0; i < numof( testcase ); ++i )
5741: {
5742: // streql
5743: {
5744: const bool eql = streql( testcase[ i ].str1, testcase[ i ].str2 );
5745: VERIFY( ( eql && testcase[ i ].eql )
5746: || ( !eql && !testcase[ i ].eql ) );
5747: }
5748:
5749: // streqli
5750: {
5751: const bool eqli = streqli( testcase[ i ].str1, testcase[ i ].str2 );
5752: VERIFY( ( eqli && testcase[ i ].eqli )
5753: || ( !eqli && !testcase[ i ].eqli ) );
5754: }
5755: }}
5756: }
5757:
5758: // strneql(), strneqli(),
5759: {
5760: const struct
5761: {
5762: bool n;
5763: bool ni;
5764: const char *str1;
5765: const char *str2;
5766: size_t count;
5767: }
5768: testcase[] =
5769: {
5770: #define MAKE_TESTCASE( n, ni, str1, str2, count ) { n, ni, str1, str2, count }
5771: MAKE_TESTCASE( true, true, "", "", 0 ), //
5772: MAKE_TESTCASE( true, true, "", "", 1 ), //
5773: MAKE_TESTCASE( true, true, "", "", 2 ), //
5774: MAKE_TESTCASE( true, true, "a", "b", 0 ), //
5775: MAKE_TESTCASE( false, false, "a", "b", 1 ), //
5776: MAKE_TESTCASE( true, true, "a", "a", 1 ), //
5777: MAKE_TESTCASE( false, true, "a", "A", 1 ), //
5778: MAKE_TESTCASE( false, true, "A", "a", 1 ), //
5779: MAKE_TESTCASE( true, true, "A", "A", 1 ), //
5780: MAKE_TESTCASE( true, true, "a", "ab", 1 ), //
5781: MAKE_TESTCASE( true, true, "ab", "a", 1 ), //
5782: MAKE_TESTCASE( false, false, "a", "ab", 2 ), //
5783: MAKE_TESTCASE( false, false, "ab", "a", 2 ), //
5784: MAKE_TESTCASE( true, true, "ab", "ab", 5 ), //
5785: MAKE_TESTCASE( false, true, "AB", "ab", 5 ), //
5786: MAKE_TESTCASE( false, true, "ab", "AB", 5 ), //
5787: MAKE_TESTCASE( true, true, "AB", "AB", 5 ), //
5788: MAKE_TESTCASE( true, true, "−a", "−b", 2 ), //
5789: MAKE_TESTCASE( false, false, "−a", "−b", 3 ), //
5790: #undef MAKE_TESTCASE
5791: };
5792: {for( int i = 0; i < numof( testcase ); ++i )
5793: {
5794: // strneql
5795: {
5796: const bool n = strneql( testcase[ i ].str1, testcase[ i ].str2, testcase[ i ].count );
5797: VERIFY( ( n && testcase[ i ].n )
5798: || ( !n && !testcase[ i ].n ) );
5799: }
5800:
5801: // strneqli
5802: {
5803: const bool ni = strneqli( testcase[ i ].str1, testcase[ i ].str2, testcase[ i ].count );
5804: VERIFY( ( ni && testcase[ i ].ni )
5805: || ( !ni && !testcase[ i ].ni ) );
5806: }
5807: }}
5808: }
5809:
5810: // jmsspn, jmscspn, strncspn, strnspn,
5811: {
5812: const struct
5813: {
5814: size_t cspn;
5815: size_t spn;
5816: const char *target;
5817: const char *ctrl;
5818: size_t count;
5819: }
5820: testcase[] =
5821: {
5822: #define MAKE_TESTCASE( cspn, spn, target, ctrl, count ) { cspn, spn, target, ctrl, count }
5823: MAKE_TESTCASE( 0, 0, "", "", 0 ),
5824: MAKE_TESTCASE( 0, 0, "a", "", 0 ),
5825: MAKE_TESTCASE( 0, 0, "", "a", 0 ),
5826: MAKE_TESTCASE( 0, 0, "", "", 1 ),
5827: MAKE_TESTCASE( 1, 0, "a", "", 1 ),
5828: MAKE_TESTCASE( 0, 0, "", "a", 1 ),
5829: MAKE_TESTCASE( 0, 1, "a", "a", 1 ),
5830: MAKE_TESTCASE( 0, 1, "a", "ab", 1 ),
5831: MAKE_TESTCASE( 0, 1, "a", "abc", 1 ),
5832: MAKE_TESTCASE( 0, 1, "b", "abc", 1 ),
5833: MAKE_TESTCASE( 0, 1, "c", "abc", 1 ),
5834: MAKE_TESTCASE( 1, 0, "z", "a", 1 ),
5835: MAKE_TESTCASE( 1, 0, "z", "abc", 1 ),
5836: MAKE_TESTCASE( 0, 1, "ax", "abc", 2 ),
5837: MAKE_TESTCASE( 0, 1, "bx", "abc", 2 ),
5838: MAKE_TESTCASE( 0, 1, "cx", "abc", 2 ),
5839: MAKE_TESTCASE( 1, 0, "xa", "abc", 1 ),
5840: MAKE_TESTCASE( 1, 0, "xb", "abc", 1 ),
5841: MAKE_TESTCASE( 1, 0, "xc", "abc", 1 ),
5842: MAKE_TESTCASE( 1, 0, "xa", "abc", 2 ),
5843: MAKE_TESTCASE( 1, 0, "xb", "abc", 2 ),
5844: MAKE_TESTCASE( 1, 0, "xc", "abc", 2 ),
5845: MAKE_TESTCASE( 0, 1, "abc", "a", 3 ),
5846: MAKE_TESTCASE( 1, 0, "abc", "b", 3 ),
5847: MAKE_TESTCASE( 2, 0, "abc", "c", 3 ),
5848: MAKE_TESTCASE( 0, 3, "abc", "abc", 3 ),
5849: MAKE_TESTCASE( 0, 2, "abc", "abc", 2 ),
5850: MAKE_TESTCASE( 0, 1, "abc", "abc", 1 ),
5851: MAKE_TESTCASE( 0, 3, "abcde", "abc", 5 ),
5852: MAKE_TESTCASE( 0, 3, "xyz", "axyz", 3 ),
5853: MAKE_TESTCASE( 3, 0, "xyz", "a", 3 ),
5854: MAKE_TESTCASE( 3, 0, "xyz", "abc", 3 ),
5855: MAKE_TESTCASE( 2, 0, "xyz", "abc", 2 ),
5856: MAKE_TESTCASE( 1, 0, "xyz", "abc", 1 ),
5857: MAKE_TESTCASE( 0, 3, "xyz", "abcxyz", 3 ),
5858: MAKE_TESTCASE( 4, 0, "xyz+", "abc", 4 ),
5859: MAKE_TESTCASE( 4, 0, "xyz+", "abc", 9 ),
5860: MAKE_TESTCASE( 2, 0, "ソ", "\\", 9 ),
5861: MAKE_TESTCASE( 3, 0, "ソソ\\", "\\", 3 ),
5862: MAKE_TESTCASE( 4, 0, "ソソ\\", "\\", 4 ),
5863: MAKE_TESTCASE( 4, 0, "ソソ\\", "\\", 5 ),
5864: MAKE_TESTCASE( 4, 0, "ソソ\\", "\\", 6 ),
5865: #undef MAKE_TESTCASE
5866: };
5867: {for( int i = 0; i < numof( testcase ); ++i )
5868: {
5869: ASSERT( testcase[ i ].spn <= testcase[ i ].count );
5870: ASSERT( testcase[ i ].cspn <= testcase[ i ].count );
5871:
5872: const size_t length = strlen( testcase[ i ].target );
5873: {
5874: // strncspn()
5875: VERIFY( testcase[ i ].cspn == strncspn( testcase[ i ].target, testcase[ i ].ctrl, testcase[ i ].count ) );
5876: VERIFY( jmscspn( testcase[ i ].target, testcase[ i ].ctrl )
5877: == strncspn( testcase[ i ].target, testcase[ i ].ctrl, length ) );
5878:
5879: // strnspn()
5880: VERIFY( testcase[ i ].spn == strnspn( testcase[ i ].target, testcase[ i ].ctrl, testcase[ i ].count ) );
5881: VERIFY( jmsspn( testcase[ i ].target, testcase[ i ].ctrl )
5882: == strnspn( testcase[ i ].target, testcase[ i ].ctrl, length ) );
5883: }
5884: }}
5885: }
5886:
5887: // jmspbrk, strnpbrk
5888: {
5889: const struct
5890: {
5891: int pbrk;
5892: const char *target;
5893: const char *ctrl;
5894: size_t count;
5895: }
5896: testcase[] =
5897: {
5898: #define MAKE_TESTCASE( pbrk, target, ctrl, count ) { pbrk, target, ctrl, count }
5899: MAKE_TESTCASE( -1, "", "", 0 ),
5900: MAKE_TESTCASE( -1, "a", "", 0 ),
5901: MAKE_TESTCASE( -1, "", "a", 0 ),
5902: MAKE_TESTCASE( -1, "", "", 1 ),
5903: MAKE_TESTCASE( -1, "a", "", 1 ),
5904: MAKE_TESTCASE( -1, "", "a", 1 ),
5905: MAKE_TESTCASE( 0, "a", "a", 1 ),
5906: MAKE_TESTCASE( 0, "a", "ab", 1 ),
5907: MAKE_TESTCASE( 0, "a", "abc", 1 ),
5908: MAKE_TESTCASE( 0, "b", "abc", 1 ),
5909: MAKE_TESTCASE( 0, "c", "abc", 1 ),
5910: MAKE_TESTCASE( -1, "z", "a", 1 ),
5911: MAKE_TESTCASE( -1, "z", "abc", 1 ),
5912: MAKE_TESTCASE( 0, "ax", "abc", 2 ),
5913: MAKE_TESTCASE( 0, "bx", "abc", 2 ),
5914: MAKE_TESTCASE( 0, "cx", "abc", 2 ),
5915: MAKE_TESTCASE( -1, "xa", "abc", 1 ),
5916: MAKE_TESTCASE( -1, "xb", "abc", 1 ),
5917: MAKE_TESTCASE( -1, "xc", "abc", 1 ),
5918: MAKE_TESTCASE( 1, "xa", "abc", 2 ),
5919: MAKE_TESTCASE( 1, "xb", "abc", 2 ),
5920: MAKE_TESTCASE( 1, "xc", "abc", 2 ),
5921: MAKE_TESTCASE( 0, "abc", "a", 3 ),
5922: MAKE_TESTCASE( 1, "abc", "b", 3 ),
5923: MAKE_TESTCASE( 2, "abc", "c", 3 ),
5924: MAKE_TESTCASE( 0, "abc", "abc", 3 ),
5925: MAKE_TESTCASE( 0, "abc", "abc", 2 ),
5926: MAKE_TESTCASE( 0, "abc", "abc", 1 ),
5927: MAKE_TESTCASE( 0, "abcde", "abc", 5 ),
5928: MAKE_TESTCASE( 0, "xyz", "axyz", 3 ),
5929: MAKE_TESTCASE( -1, "xyz", "a", 3 ),
5930: MAKE_TESTCASE( -1, "xyz", "abc", 3 ),
5931: MAKE_TESTCASE( -1, "xyz", "abc", 2 ),
5932: MAKE_TESTCASE( -1, "xyz", "abc", 1 ),
5933: MAKE_TESTCASE( 0, "xyz", "abcxyz", 3 ),
5934: MAKE_TESTCASE( -1, "xyz+", "abc", 4 ),
5935: MAKE_TESTCASE( -1, "xyz+", "abc", 9 ),
5936: MAKE_TESTCASE( -1, "ソ", "\\", 9 ),
5937: MAKE_TESTCASE( -1, "ソソ\\", "\\", 4 ),
5938: MAKE_TESTCASE( 4, "ソソ\\", "\\", 5 ),
5939: MAKE_TESTCASE( 4, "ソソ\\", "\\", 6 ),
5940: #undef MAKE_TESTCASE
5941: };
5942: {for( int i = 0; i < numof( testcase ); ++i )
5943: {
5944: ASSERT( testcase[ i ].pbrk < static_cast<ptrdiff_t>( testcase[ i ].count ) );
5945:
5946: const char *pbrk = strnpbrk( testcase[ i ].target, testcase[ i ].ctrl, testcase[ i ].count );
5947: VERIFY( ((-1 == testcase[ i ].pbrk) && (null == pbrk))
5948: || (pbrk == testcase[ i ].target + testcase[ i ].pbrk) );
5949: VERIFY( jmspbrk( testcase[ i ].target, testcase[ i ].ctrl )
5950: == strnpbrk( testcase[ i ].target, testcase[ i ].ctrl, strlen( testcase[ i ].target ) ) );
5951: }}
5952: }
5953:
5954: // strskip(), strnskip()
5955: {
5956: const struct
5957: {
5958: int spn;
5959: const char *string;
5960: const char *skip;
5961: }
5962: testcase[] =
5963: {
5964: #define MAKE_TESTCASE( spn, string, skip ) { spn, string, skip }
5965: MAKE_TESTCASE( 0, "", "" ),
5966: MAKE_TESTCASE( 0, "a", "" ),
5967: MAKE_TESTCASE( 0, "", "a" ),
5968: MAKE_TESTCASE( 0, "", "" ),
5969: MAKE_TESTCASE( 1, "a", "a" ),
5970: MAKE_TESTCASE( 1, "a", "abc" ),
5971: MAKE_TESTCASE( 1, "b", "abc" ),
5972: MAKE_TESTCASE( 1, "c", "abc" ),
5973: MAKE_TESTCASE( 0, "z", "a" ),
5974: MAKE_TESTCASE( 0, "z", "abc" ),
5975: MAKE_TESTCASE( 1, "ax", "abc" ),
5976: MAKE_TESTCASE( 1, "bx", "abc" ),
5977: MAKE_TESTCASE( 1, "cx", "abc" ),
5978: MAKE_TESTCASE( 0, "xa", "abc" ),
5979: MAKE_TESTCASE( 0, "xb", "abc" ),
5980: MAKE_TESTCASE( 0, "xc", "abc" ),
5981: MAKE_TESTCASE( 1, "abc", "a" ),
5982: MAKE_TESTCASE( 0, "abc", "b" ),
5983: MAKE_TESTCASE( 0, "abc", "c" ),
5984: MAKE_TESTCASE( 3, "abc", "abc" ),
5985: #undef MAKE_TESTCASE
5986: };
5987: {for( int i = 0; i < numof( testcase ); ++i )
5988: {
5989: VERIFY( testcase[ i ].string + testcase[ i ].spn
5990: == strskip( testcase[ i ].string, testcase[ i ].skip ) );
5991: }}
5992: }
5993:
5994: // strnlen
5995: {
5996: const struct
5997: {
5998: size_t len;
5999: const char *string;
6000: size_t count;
6001: }
6002: testcase[] =
6003: {
6004: #define MAKE_TESTCASE( len, string, count ) { len, string, count }
6005: MAKE_TESTCASE( 0, "", 0 ),
6006: MAKE_TESTCASE( 0, "", 1 ),
6007: MAKE_TESTCASE( 0, "-", 0 ),
6008: MAKE_TESTCASE( 1, "-", 1 ),
6009: MAKE_TESTCASE( 1, "-", 2 ),
6010: MAKE_TESTCASE( 0, "--", 0 ),
6011: MAKE_TESTCASE( 1, "--", 1 ),
6012: MAKE_TESTCASE( 2, "--", 2 ),
6013: MAKE_TESTCASE( 2, "--", 3 ),
6014: MAKE_TESTCASE( 6, "−−−", 6 ),
6015: MAKE_TESTCASE( 2, "−−−", 2 ),
6016: #undef MAKE_TESTCASE
6017: };
6018: {for( int i = 0; i < numof( testcase ); ++i )
6019: {
6020: ASSERT( testcase[ i ].len <= testcase[ i ].count );
6021:
6022: //
6023: VERIFY( testcase[ i ].len == strnlen( testcase[ i ].string, testcase[ i ].count ) );
6024: VERIFY( strlen( testcase[ i ].string ) == strnlen( testcase[ i ].string, strlen( testcase[ i ].string ) ) );
6025: }}
6026: }
6027:
6028: }//test_str
6029:
6030: //*********************************************************
6031: // test_memmem()
6032: //*********************************************************
6033: DEFINE_TESTPROC( test_memmem )
6034: {
6035: //---------------------------------------------------------
6036: // 定数 の テスト
6037: //---------------------------------------------------------
6038:
6039: //---------------------------------------------------------
6040: // ファイルスコープ関数 の テスト
6041: //---------------------------------------------------------
6042:
6043: // SET_MEMMAP_BIT(), GET_MEMMAP_BIT(),
6044: {
6045: BYTE map[ MEMMAP_SIZE ];
6046: memzero( map, sizeof( map ) );
6047: {for( int i = 0; i < CHAR_BIT * MEMMAP_SIZE; ++i )
6048: {
6049: VERIFY( 0 == GET_MEMMAP_BIT( map, i ) );
6050: SET_MEMMAP_BIT( map, i );
6051: VERIFY( 0 != GET_MEMMAP_BIT( map, i ) );
6052: }}
6053: }
6054:
6055:
6056: //---------------------------------------------------------
6057: // 公開関数 の テスト
6058: //---------------------------------------------------------
6059:
6060: // memmem(),
6061: {
6062: const struct testcase_tag
6063: {
6064: int result; // memmem
6065: const char *str;
6066: int cnt;
6067: const char *ptn;
6068: int len;
6069: }
6070: testcase[] =
6071: {
6072: //
6073: { -1, "", 0, "", 0 },
6074: { -1, "", 0, "x", 1 },
6075: { 0, "x", 1, "", 0 },
6076: { 0, "a", 1, "a", 1 },
6077: { -1, "b", 1, "a", 1 },
6078: { 0, "abc", 3, "a", 1 },
6079: { 1, "abc", 3, "b", 1 },
6080: { 2, "abc", 3, "c", 1 },
6081: { 0, "abc", 3, "ab", 2 },
6082: { 1, "abc", 3, "bc", 2 },
6083: { -1, "abc", 3, "ac", 2 },
6084: { -1, "abc", 2, "c", 1 },
6085: { -1, "abc", 2, "bc", 2 },
6086: { 0, "abc", 3, "abc", 3 },
6087: };
6088:
6089: {for( int t = 0; t < numof( testcase ); ++t )
6090: {
6091: // memmem
6092: {
6093: const char *result = (char *)memmem( testcase[ t ].str, testcase[ t ].cnt, testcase[ t ].ptn, testcase[ t ].len );
6094: VERIFY( ((-1 == testcase[ t ].result) && (null == result))
6095: || ( result == testcase[ t ].str + testcase[ t ].result ) );
6096: }
6097: }}
6098: }
6099:
6100: // memcspn, memspn,
6101: {
6102: const struct
6103: {
6104: size_t cspn;
6105: size_t spn;
6106: const char *target;
6107: int length;
6108: const char *ctrl;
6109: int clen;
6110: }
6111: testcase[] =
6112: {
6113: { 0, 0, "", 0, "", 0 },
6114: { 1, 0, "a", 1, "", 0 },
6115: { 0, 0, "", 0, "a", 1 },
6116: { 0, 1, "a", 1, "a", 1 },
6117: { 0, 1, "a", 1, "ab", 1 },
6118: { 0, 1, "a", 1, "abc", 3 },
6119: { 0, 1, "b", 1, "abc", 3 },
6120: { 0, 1, "c", 1, "abc", 3 },
6121: { 1, 0, "z", 1, "a", 1 },
6122: { 1, 0, "z", 1, "abc", 3 },
6123: { 0, 1, "ax", 2, "abc", 3 },
6124: { 0, 1, "bx", 2, "abc", 3 },
6125: { 0, 1, "cx", 2, "abc", 3 },
6126: { 1, 0, "xa", 2, "abc", 3 },
6127: { 1, 0, "xb", 2, "abc", 3 },
6128: { 1, 0, "xc", 2, "abc", 3 },
6129: { 0, 1, "abc", 3, "a", 1 },
6130: { 1, 0, "abc", 3, "b", 1 },
6131: { 2, 0, "abc", 3, "c", 1 },
6132: { 0, 3, "abc", 3, "abc", 3 },
6133: { 0, 3, "abcde", 3, "abc", 3 },
6134: { 3, 0, "xyz", 3, "axyz", 1 },
6135: { 3, 0, "xyz", 3, "a", 1 },
6136: { 3, 0, "xyz", 3, "abc", 3 },
6137: { 3, 0, "xyz", 3, "abcxyz", 3 },
6138: { 3, 0, "xyz+", 3, "abc", 3 },
6139: };
6140: {for( int i = 0; i < numof( testcase ); ++i )
6141: {
6142: VERIFY( testcase[ i ].cspn == memcspn( testcase[ i ].target, testcase[ i ].length, testcase[ i ].ctrl, testcase[ i ].clen ) );
6143: VERIFY( testcase[ i ].spn == memspn( testcase[ i ].target, testcase[ i ].length, testcase[ i ].ctrl, testcase[ i ].clen ) );
6144: }}
6145: }
6146:
6147: // mempbrk
6148: {
6149: const struct
6150: {
6151: int pbrk;
6152: const char *target;
6153: int length;
6154: const char *ctrl;
6155: int clen;
6156: }
6157: testcase[] =
6158: {
6159: { -1, "", 0, "", 0 },
6160: { -1, "a", 1, "", 0 },
6161: { -1, "", 0, "a", 1 },
6162: { 0, "a", 1, "a", 1 },
6163: { 0, "a", 1, "ab", 1 },
6164: { 0, "a", 1, "abc", 3 },
6165: { 0, "b", 1, "abc", 3 },
6166: { 0, "c", 1, "abc", 3 },
6167: { -1, "z", 1, "a", 1 },
6168: { -1, "z", 1, "abc", 3 },
6169: { 0, "ax", 2, "abc", 3 },
6170: { 0, "bx", 2, "abc", 3 },
6171: { 0, "cx", 2, "abc", 3 },
6172: { 1, "xa", 2, "abc", 3 },
6173: { 1, "xb", 2, "abc", 3 },
6174: { 1, "xc", 2, "abc", 3 },
6175: { 0, "abc", 3, "a", 1 },
6176: { 1, "abc", 3, "b", 1 },
6177: { 2, "abc", 3, "c", 1 },
6178: { 0, "abc", 3, "abc", 3 },
6179: { 0, "abcde", 3, "abc", 3 },
6180: { -1, "xyz", 3, "axyz", 1 },
6181: { -1, "xyz", 3, "a", 1 },
6182: { -1, "xyz", 3, "abc", 3 },
6183: { -1, "xyz", 3, "abcxyz", 3 },
6184: { -1, "xyz+", 3, "abc", 3 },
6185: };
6186: {for( int i = 0; i < numof( testcase ); ++i )
6187: {
6188: const char *pbrk = (char *)mempbrk( testcase[ i ].target, testcase[ i ].length, testcase[ i ].ctrl, testcase[ i ].clen );
6189: VERIFY( ((-1 == testcase[ i ].pbrk) && (null == pbrk))
6190: || (pbrk == testcase[ i ].target + testcase[ i ].pbrk) );
6191: }}
6192: }
6193:
6194: }//test_memmem
6195:
6196: //*********************************************************
6197: // test_IsValidArgcArgv()
6198: //*********************************************************
6199: DEFINE_TESTPROC( test_IsValidArgcArgv )
6200: {
6201: //---------------------------------------------------------
6202: // 公開関数 の テスト
6203: //---------------------------------------------------------
6204:
6205: // IsValidArgcArgv()
6206: {
6207: //
6208: {
6209: char *argv[] = { "", null };
6210: VERIFY( IsValidArgcArgv( numof(argv)-1, argv ) );
6211: }
6212:
6213: // 要素数 0 は可
6214: {
6215: char *argv[] = { null }; //
6216: VERIFY( IsValidArgcArgv( numof(argv)-1, argv ) );
6217: }
6218:
6219: // null で終了しなくてはならない
6220: {
6221: char *argv[] = { "", "", "" };
6222: VERIFY( ! IsValidArgcArgv( numof(argv)-1, argv ) );
6223: }
6224:
6225: // 途中に null があることはない
6226: {
6227: char *argv[] = { "", null, null };
6228: VERIFY( ! IsValidArgcArgv( numof(argv)-1, argv ) );
6229: }
6230: }
6231:
6232:
6233: }//test_IsValidArgcArgv
6234:
6235: /*
6236:
6237: DECLARE_TESTPROC( p );
6238: CALLONCE_TESTPROC( p ); // [テスト]
6239:
6240: //*********************************************************
6241: // test_str()
6242: //*********************************************************
6243: DEFINE_TESTPROC( test_str )
6244: {
6245: //---------------------------------------------------------
6246: // 定数 の テスト
6247: //---------------------------------------------------------
6248:
6249: //---------------------------------------------------------
6250: // ファイルスコープ関数 の テスト
6251: //---------------------------------------------------------
6252:
6253: //---------------------------------------------------------
6254: // 公開関数 の テスト
6255: //---------------------------------------------------------
6256:
6257: }//test_str
6258: */
6259:
6260:
6261: #endif // #ifdef _DEBUG
6262:
6263:
6264: //** end **
参照:
水無瀬の部屋 > sample > tools > toolbase.cpp |
---|
このページは cpp2web が出力しました。
水無瀬 優 postmaster@katsura-kotonoha.sakura.ne.jp
http://katsura-kotonoha.sakura.ne.jp/prog/code/tools/toolbase_cpp.shtml