[PR]

水無瀬の部屋 > Programming > sample > tools > toolbase.cpp
最終更新日: 2007/10/22

   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 **

参照:


Google
ご意見・ご感想をお聞かせ下さい。匿名で送信できます。

 * 返信が必要な場合には postmaster@katsura-kotonoha.sakura.ne.jp へ直接メールしてください。

水無瀬の部屋 > sample > tools > toolbase.cpp

このページは cpp2web が出力しました。
水無瀬 優 postmaster@katsura-kotonoha.sakura.ne.jp
http://katsura-kotonoha.sakura.ne.jp/prog/code/tools/toolbase_cpp.shtml
『新妻LOVELY×CATION』を応援しています!