C:\home\SVGCats_src\src\arrx.c
1|/**************************************************************** 2|* 1. <<< 固定要素数配列 (ArrX) >>> 3|*・ArrX は任意の型の配列を統一的に用いるようにします。 4|*・要素数を配列と別の変数にしないので、配列自体を1つの識別子だけで 5|* 参照することができます。 6|* char arr[50]; ... char* pArr; 7|* int arr_n; int* pArr_n; 8|* ArrX arr; ... ArrX* pArr; 9|* 10|* 2. <<< 配列内の全要素を走査する >>> 11|*・配列内の全要素を走査するには、次のようにします。 12|* ArrX* arr; // 配列 13|* type* pElem; // 要素へのポインタ 14|* type* pElem_last; // 最終要素の次のアドレス 15|* 16|* pElem_last = arr->last; 17|* for ( pElem = arr->first; pElem < pElem_last; pElem++ ) { 18|* *pElem; // 要素へのアクセス、ポインタ参照 '*' に注意 19|* pElem->member; 20|* } 21|*****************************************************************/ 22|#include "mixer_precomp.h" /* Auto precompiled header, Look at mixer-... folder */ 23|// #pragma hdrstop ("mixer_precomp") 24| 25|#define STDLIBS_INCLUDE_STDIO_H 26|#define STDLIBS_INCLUDE_STRING_H 27|#define STDLIBS_INCLUDE_STDARG_H 28| 29|#if defined(USES_MXP_AUTOINC) 30| #include "arrx.ah" /* Auto include header, Look at mixer-... folder */ 31|#endif 32| 33|#include <stdlib.h> 34| 35|#if defined(FOR_GHS) || defined(FOR_CA) || defined(FOR_WINCE) 36| #define ARRX_NO_STRICMP 37|#endif 38| 39|/*-------------------------------------------------------------------------*/ 40|/* ◆3. <<<< (ArrX_C) C言語配列 >>>> */ 41|/*-------------------------------------------------------------------------*/ 42| 43| 44| 45|/*********************************************************************** 46| 3-1. <<< [ArrX_C_shaffle] 配列の内容をランダムにシャッフルする >>> 47|【引数】 48| ・void* arr_adr; 配列の先頭アドレス 49| ・int elem_size; 配列の要素のサイズ(バイト) 50| ・int nElem; 配列の要素数 51| ・int seed; 乱数の種(時刻など, -1= seed を使わない, 1=再初期化) 52|************************************************************************/ 53|void ArrX_C_shaffle( void* arr_adr, int elem_size, int nElem, int seed ) 54|{ 55| int i, j, x; 56| char elem; 57| char* p1; 58| char* p2; 59| 60| if ( seed != -1 ) srand( seed ); 61| 62| for ( i = 0; i < nElem; i++ ) { 63| j = nElem * rand() / (RAND_MAX+1); 64| 65| p1 = (char*)arr_adr + elem_size * i; 66| p2 = (char*)arr_adr + elem_size * j; 67| for ( x = 0; x < elem_size; x++ ) { 68| elem = p1[x]; p1[x] = p2[x]; p2[x] = elem; 69| } 70| } 71|} 72| 73| 74|/*-------------------------------------------------------------------------*/ 75|/* ◆4. <<<< 最小固定要素配列 (ArrX) >>>> */ 76|/*-------------------------------------------------------------------------*/ 77| 78|#ifdef USES_SYM 79|SYM_STRUCT_START( ArrX ) 80|SYM_STRUCT_LOOP_FUNC( ArrX, ArrX_doLoopFunc ) 81|SYM_STRUCT_MEMB( ArrX, void*, first ) 82|SYM_STRUCT_MEMB( ArrX, void*, last ) 83|SYM_STRUCT_END( ArrX ) 84|#endif 85| 86| 87|/**************************************************************** 88| 4-1. <<< [ArrX_init] 初期化する(type1) >>> 89|【引数】 90| ・int arr_sizeof; 全要素のデータのサイズ (byte) 91|【補足】 92|・次のように指定することで、確保したメモリ領域 arr のサイズに 93| 関わらず、任意の要素数 n の type 型配列とすることができます。 94| ArrX_init( &arrx, arr, sizeof(type)* n ); 95|*****************************************************************/ 96|void ArrX_init( ArrX* m, void* first, int arr_sizeof ) 97|{ 98| ERRORS_INITCHK( m, 0 ); 99| 100| m->first = first; 101| m->last = (char*)first + arr_sizeof; 102| 103| ASSERT( ArrX_chk( m ) ); 104|} 105| 106| 107| 108|/**************************************************************** 109| 4-2. <<< [ArrX_init2] 初期化する(type2) >>> 110|【引数】 111| ・void* first; 配列の先頭アドレス 112| ・void* over; 配列の末尾の次の要素のアドレス 113|【補足】 114|・over には、たとえば、struct* p; に配列の末尾の要素のアドレスが 115| 格納されている場合、p+1( (char*)p + sizeof(struct))を指定します。 116|*****************************************************************/ 117|void ArrX_init2( ArrX* m, void* first, void* over ) 118|{ 119| ERRORS_INITCHK( m, 0 ); 120| 121| m->first = first; 122| m->last = over; 123| 124| ASSERT( ArrX_chk( m ) ); 125|} 126| 127| 128|/**************************************************************** 129| 4-3. <<< [ArrX_initByStr] 文字列を ArrX 型にする >>> 130|*****************************************************************/ 131|void ArrX_initByStr( ArrX* m, char* str ) 132|{ 133| ERRORS_INITCHK( m, 0 ); 134| 135| m->first = str; 136| m->last = str + strlen( str ); 137| 138| ASSERT( ArrX_chk( m ) ); 139|} 140| 141| 142| 143|/*********************************************************************** 144| 4-4. <<< [ArrX_initPtrArr_imp] ポインタ配列を作る >>> 145|【補足】 146|・ArrX_initPtrArr の実装部です。 147|************************************************************************/ 148|void ArrX_initPtrArr_imp( ArrX* m, ArrX_Buf* buf, ArrX* arr, 149| int elem_size ) 150|{ 151| char* pElem; /* arr の要素 */ 152| char* pElem_over; 153| void** p_first; 154| void** p; 155| int nElem; 156| 157| ERRORS_INITCHK( m, 0 ); 158| ASSERT( ArrX_Buf_chk( buf ) && ArrX_chk( arr ) ); 159| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_size == 0 ); 160| 161| /* ポインタ配列のメモリ領域を確保する */ 162| nElem = ((char*)arr->last - (char*)arr->first) / elem_size; 163| p_first = ArrX_Buf_allocs( buf, void*, nElem ); 164| p = p_first; 165| 166| /* アドレスをポインタ配列に格納する */ 167| pElem_over = (char*)arr->last; 168| for ( pElem = (char*)arr->first; pElem < pElem_over; pElem += elem_size ) { 169| *p = pElem; p++; 170| } 171| 172| /* ポインタ配列を初期化する */ 173| ArrX_init2( m, (void*)p_first, (void*)p ); 174| 175| ASSERT( ArrX_chk( m ) ); 176|} 177| 178| 179| 180|/**************************************************************** 181| 4-5. <<< [ArrX_castFrom_ArrX_Buf_imp] ArrX 型にキャストする >>> 182|*****************************************************************/ 183|ArrX* ArrX_castFrom_ArrX_Buf_imp( ArrX* arr, ArrX_Buf* buf ) 184|{ 185| ArrX_init2( arr, buf->first, buf->last ); 186| return arr; 187|} 188| 189| 190|/**************************************************************** 191| 4-6. <<< [ArrX_chk] 正規チェック >>> 192|*****************************************************************/ 193|int ArrX_chk( ArrX* m ) 194|{ 195| ERRORS_INITCHK_FOR_SUB( m, 1 ); 196| return m->first <= m->last; 197|} 198| 199| 200|/**************************************************************** 201| 4-7. <<< [ArrX_getN_imp] 要素数を返す >>> 202|・ArrX_getN の実装部です。(デバッグ用) 203|*****************************************************************/ 204|int ArrX_getN_imp( ArrX* m, int size ) 205|{ 206| ERRORS_INITCHK( m, 1 ); 207| ASSERT( ArrX_chk( m ) ); 208| ASSERT( ( (char*)m->last - (char*)m->first ) % size == 0 ); 209| 210| return ( (char*)m->last - (char*)m->first ) / size; 211|} 212| 213| 214|/**************************************************************** 215| 4-8. <<< [ArrX_get_imp] 配列番号から要素を返す >>> 216|【引数】 217| ・ArrX* m; 配列 218| ・int i; 配列番号 219| ・int size; 配列要素のサイズ 220|【補足】 221|・リリース時は、マクロ版 ArrX_get を呼び出します。 222|*****************************************************************/ 223|void* ArrX_get_imp( ArrX* m, int i, int size ) 224|{ 225| void* p = (char*)m->first + i * size; 226| 227| ASSERT( p < m->last ); 228| ASSERT( ( (char*)m->last - (char*)m->first ) % size == 0 ); 229| 230| return p; 231|} 232| 233| 234| 235|/**************************************************************** 236| 4-9. <<< [ArrX_Able_getNext_imp] ArrX_Able_getNext の実装部 >>> 237|*****************************************************************/ 238|#ifdef USES_OFFSET 239|void* ArrX_Able_getNext_imp( ArrX_Able* m, void* base, 240| int elem_size, Offset inherit ) 241|{ 242| char* p = (char*)base; 243| 244| ASSERT( ( (char*)m->arr.last - (char*)m->arr.first ) % elem_size == 0 ); 245| 246| p += elem_size; 247| while ( p < (char*)m->arr.last ) { 248| if ( Offset_ref( inherit, p, ArrX_AbleElem ) ) 249| return (void*)p; 250| p += elem_size; 251| } 252| return NULL; 253|} 254|#endif 255| 256|/**************************************************************** 257| 4-10. <<< [ArrX_setStrs] 複数の文字列を配列に入れる >>> 258|【機能】 259|・配列のすべての文字列要素を入れます。 260|【補足】 261|・引数 ... に指定する文字列は、配列の用素数だけ指定します。 262| それより多くても少なくてもいけません。 263| ArrX_init( &aa, buf, sizeof(char*)*3 ); のように、 264| 用素数を調整してください。 265|*****************************************************************/ 266|#ifdef STDLIBS_INCLUDE_STDARG_H 267|void ArrX_setStrs( ArrX* m, ... ) 268|{ 269| va_list va; 270| char** p; 271| 272| va_start( va, m ); 273| 274| for ( p = (char**)m->first; p < (char**)m->last; p++ ) 275| *p = va_arg( va, char* ); 276| 277| va_end( va ); 278|} 279|#endif 280| 281| 282| 283|/*********************************************************************** 284| 4-11. <<< [ArrX_memrot_imp] 配列の要素をローテーションする >>> 285|【引数】 286| ・void* ball; 配列の要素へのアドレス 287| ・void* target; 要素の移動先のアドレス 288| ・void* work; ワーク領域(配列の要素の型の変数へのアドレス) 289| ・int ball_size; 要素のメモリサイズ 290|【補足】 291|・ArrX_memrot の実装部です。 292|************************************************************************/ 293|void ArrX_memrot_imp( void* ball, void* target, void* work, int ball_size ) 294|{ 295| memcpy( work, ball, ball_size ); 296| if ( ball > target ) { 297| memmove( (char*)target + ball_size, target, 298| (char*)ball - (char*)target ); 299| } 300| else { 301| memmove( ball, (char*)ball + ball_size, 302| (char*)target - (char*)ball ); 303| } 304| memcpy( target, work, ball_size ); 305|} 306| 307| 308|/*********************************************************************** 309| 4-12. <<< [ArrX_print] 配列の要素をデバッグ表示する >>> 310|【引数】 311| ・ArrX* m; 配列 312| ・char* types; 型リスト 313|【補足】 314|・型リストは、配列要素の型を次の文字で指定した文字列です。 315| ・'i' ... 整数型(int) 316| ・'s' ... 文字列型(char*) 317| ・'p' ... アドレス型(void*) 318| 整数と文字列が1つずつ入った構造体の場合は、"is" と指定します。 319|************************************************************************/ 320|#ifdef USES_ERRORS 321|#ifndef ERRORS_CUT_DEBUG_TOOL 322|void ArrX_print( ArrX* m, char* types ) 323|{ 324| char* t = types; 325| int* p; 326| int i = 0; 327| 328| for ( ArrX_forEach( m, &p, int ) ) { 329| switch ( *t ) { 330| case 'i': 331| Errors_printf( " [%d] = %d (0x%X) '%c'", i, *p, *p, *p ); 332| break; 333| case 's': 334| Errors_printf( " [%d] = (%p) \"%s\"", i, *p, *p ); 335| break; 336| case 'p': 337| Errors_printf( " [%d] = (%p)", i, *p ); 338| break; 339| default: 340| error(); 341| } 342| t++; if ( *t == '\0' ) t = types; 343| i++; 344| } 345|} 346|#endif 347|#endif 348| 349|/************************************************************************** 350| 4-13. <<< [ArrX_search_i_imp] int 型のキーを用いて線形検索する >>> 351|・この関数は、ArrX_search_i マクロの実装部です。 352|***************************************************************************/ 353|#ifdef USES_OFFSET 354|void* ArrX_search_i_imp( ArrX* m, Offset_Key* key, int val, 355| int elem_sizeof ) 356|{ 357| ASSERT( ArrX_chk( m ) && Offset_Key_chk( key ) ); 358| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_sizeof == 0 ); 359| 360| return ArrX_Imp_linearSearch( m->first, m->last, (int)elem_sizeof, 361| &val, key->offset, 0, sizeof(int) ); 362|} 363|#endif /* USES_OFFSET */ 364| 365| 366| 367|/************************************************************************** 368| 4-14. <<< [ArrX_search_d_imp] double 型のキーを用いて線形検索する >>> 369|・この関数は、ArrX_search_d マクロの実装部です。 370|***************************************************************************/ 371|#ifdef USES_OFFSET 372|void* ArrX_search_d_imp( ArrX* m, Offset_Key* key, double val, 373| int elem_sizeof ) 374|{ 375| ASSERT( ArrX_chk( m ) && Offset_Key_chk( key ) ); 376| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_sizeof == 0 ); 377| 378| return ArrX_Imp_linearSearch( m->first, m->last, (int)elem_sizeof, 379| &val, key->offset, 0, sizeof(double) ); 380|} 381|#endif /* USES_OFFSET */ 382| 383| 384| 385|/************************************************************************** 386| 4-15. <<< [ArrX_search_s_imp] 文字列型のキーを用いて線形検索する >>> 387|・この関数は、ArrX_search_s マクロの実装部です。 388|***************************************************************************/ 389|#ifdef USES_OFFSET 390|void* ArrX_search_s_imp( ArrX* m, Offset_Key* key, const char* val, 391| int elem_sizeof ) 392|{ 393| ASSERT( ArrX_chk( m ) && Offset_Key_chk( key ) ); 394| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_sizeof == 0 ); 395| 396| if ( key->type == Offset_CString ) 397| return ArrX_Imp_linearSearch( m->first, m->last, (int)elem_sizeof, 398| val, key->offset, 0, -1 ); 399| else if ( key->type == Offset_CStringP || key->type == Offset_StrV ) { 400| return ArrX_Imp_linearSearch( m->first, m->last, (int)elem_sizeof, 401| val, key->offset, 1, -1 ); 402| } 403| #ifndef ARRX_NO_STRICMP 404| else if ( key->type == Offset_CStringPI ) { 405| return ArrX_Imp_linearSearchF( m->first, m->last, (int)elem_sizeof, 406| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpIStr ); 407| } 408| #endif 409| else { 410| ASSERT( key->type == Offset_CStringPW ); 411| #ifdef USES_STRX 412| return ArrX_Imp_linearSearchF( m->first, m->last, (int)elem_sizeof, 413| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpMatchMask ); 414| #else 415| Errors_notSupport(); 416| return NULL; /* dummy */ 417| #endif 418| } 419|} 420|#endif /* USES_OFFSET */ 421| 422| 423| 424|/************************************************************************** 425| 4-16. <<< [ArrX_search_ps_imp] 文字列型のキーを用いて線形検索する >>> 426|・この関数は、ArrX_search_ps マクロの実装部です。 427|***************************************************************************/ 428|#ifdef USES_OFFSET 429|void* ArrX_search_ps_imp( ArrX* m, Offset_Key* key, const char* val ) 430|{ 431| ASSERT( ArrX_chk( m ) && Offset_Key_chk( key ) ); 432| 433| if ( key->type == Offset_CString ) 434| return ArrX_Imp_linearSearchP( (void**)m->first, (void**)m->last, 435| val, key->offset, 0, -1 ); 436| else if ( key->type == Offset_CStringP ) { 437| return ArrX_Imp_linearSearchP( (void**)m->first, (void**)m->last, 438| val, key->offset, 1, -1 ); 439| } 440| #ifndef ARRX_NO_STRICMP 441| else if ( key->type == Offset_CStringPI ) { 442| return ArrX_Imp_linearSearchPF( (void**)m->first, (void**)m->last, 443| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpIStr ); 444| } 445| #endif 446| else { 447| ASSERT( key->type == Offset_CStringPW ); 448| #ifdef USES_STRX 449| return ArrX_Imp_linearSearchPF( (void**)m->first, (void**)m->last, 450| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpMatchMask ); 451| #else 452| Errors_notSupport(); 453| return NULL; /* dummy */ 454| #endif 455| } 456|} 457|#endif /* USES_OFFSET */ 458| 459| 460|/************************************************************************** 461| 4-17. <<< [ArrX_doLoopFunc] SYM_STRUCT_LOOP_FUNC に指定する関数 >>> 462|***************************************************************************/ 463|#ifdef USES_SYM 464|bool ArrX_doLoopFunc( Sym_Ref* container, Sym_Ref* elem ) 465|{ 466| ArrX* m; 467| 468| if ( container->type == Sym_StructType ) m = (ArrX*)container->adr; 469| else m = *(ArrX**)container->adr; 470| 471| if ( elem->adr == NULL ) elem->adr = m->first; 472| else { 473| if ( elem->type == Sym_StructTypeP ) 474| elem->adr = (void*)( (char*)elem->adr + sizeof(void*) ); 475| else 476| elem->adr = (void*)( (char*)elem->adr + (int)container->elem_param ); 477| } 478| 479| return elem->adr < m->last; 480|} 481|#endif 482| 483| 484|/*-------------------------------------------------------------------------*/ 485|/* ◆5. <<<< バッファ (ArrX_Buf) >>>> */ 486|/*-------------------------------------------------------------------------*/ 487| 488|#ifdef USES_SYM 489|SYM_STRUCT_START( ArrX_Buf ) 490|SYM_STRUCT_LOOP_FUNC( ArrX_Buf, ArrX_Buf_doLoopFunc ) 491|SYM_STRUCT_MEMB( ArrX_Buf, void*, first ) 492|SYM_STRUCT_MEMB( ArrX_Buf, void*, last ) 493|SYM_STRUCT_END( ArrX_Buf ) 494|#endif 495| 496|/*********************************************************************** 497| 5-1. <<< ツリー構造におけるコンテナ >>> 498| 499|【メモ】(作成中) 500| 501| <IMG src="arrx4.gif"> 502| 503| ツリーにノードを追加する関数とツリーからノードを削除する関数のうち、 504| インターフェイスとして必要な最低限の関数がどれか分析することで 505| より単純で効率のよいコンテナの種類を使うことが出来ます。 506| 507| 入力データにおいて、同じ親のノードが一個所に集まっている 508| (親ノードが所有する子ノードが十分揃っている)(シーケンシャル) 509| かどうかを分析することでも、より単純で効率のよいコンテナの種類を 510| 使うことが出来ます。 511| 512| コンテナは、シーケンシャル・タイプとランダム・タイプがあります。 513| シーケンシャル・タイプは、ArrX と ArrX_Buf の組み合わせ、 514| ランダム・レングス・タイプは ArrX2 コンポーネント(予定)が 515| あります。 516| 517| ツリーのリンク(関連)は、子配列タイプと、子ポインタ・タイプと、 518| 親ポインタ・タイプがあります。 519| ・子配列タイプは、子ノードをメモリ的に連続させる必要があるので、 520| 分配方法に工夫が必要になります。(静的データは除く) 521| シーケンシャル・タイプとランダム・レングス・タイプ 522| ・子ポインタ・タイプは、子ノードをリスト構造でつなげます。 523| ランダム・タイプ(例:ArrayU3)があります。 524| リスト構造でなく、使用/未使用または ID の配列でも構いません。 525| ・親ポインタ・タイプは、親ノードへのポインタを持ちます。 526| ただし、対応づけが逆なので後で検索が必要になります。 527| 528| ノードを削除する関数を決めることで、メモリ管理の配置位置が 529| 決まります。削除するノードのうち、最も子の方のノードには、 530| シーケンシャル・タイプをメンバに持たせます。そして、 531| その親のノードには、ランダム・タイプをメンバに持たせて、 532| 子ノードを削除できるようにします。 533| 534| ノードを削除ではなく再初期化する(再利用する領域を明示的に指定する) 535| 関数を決めた場合、親のノードには、シーケンシャル・タイプを 536| メンバに持たせることが出来ます。ただし、再初期化しても 537| メモリサイズを変更することはできません。変更する場合は、 538| 更に親のノードを削除するか再初期化して、 539| メモリサイズの設定を初めからやり直してください。 540| 541| シーケンシャルでなくても、子ポインタ・タイプや 542| 親ポインタ・タイプの場合、 543| シーケンシャル・タイプをメンバに持たせることが出来ます。 544| 545| 十分性が有れば、更に親の十分性も検討することが出来ます。 546| ランダム・レングス・タイプを使った場合、それより親のノードは 547| 必ずランダム・レングス・タイプにしなければなりません。 548| 549| ノードを追加する関数は、必要に応じて親ノードへの参照や 550| メモリ管理を引数に指定するようにします。 551| ノードを追加する関数の内部では、そのノードより子の方のノード 552| を追加する場合、追加するノードより親の方にあるメモリ管理から 553| 領域を確保します。 554| 555| 対多関連をシーケンシャルにすれば階層ごとにバッファを用意すればよい 556| シーケンシャルは抽象クラスでもよい(クラスIDが必要だが) 557|************************************************************************/ 558| 559| 560| 561|/**************************************************************** 562| 5-2. <<< [ArrX_Buf_init] 初期化する >>> 563|【補足】 564|・初期化するとバッファは空になります。 565|*****************************************************************/ 566|void ArrX_Buf_init( ArrX_Buf* m, void* mem, int mem_sizeof ) 567|{ 568| ERRORS_INITCHK( m, 0 ); 569| 570| m->first = mem; 571| m->last = mem; 572| m->bufLast = (char*)mem + mem_sizeof; 573| 574| ASSERT( ArrX_Buf_chk( m ) ); 575|} 576| 577| 578| 579|/**************************************************************** 580| 5-3. <<< [ArrX_Buf_inits] 複数のバッファを初期化する >>> 581|【引数】 582| ・void* mem; メモリ領域(サイズは ArrX_Buf_getMemSize より) 583| ・int* ms; 最大要素数が格納されている配列 584| ・int n; 初期化するバッファの数 585| ・... バッファ1、要素サイズ1、バッファ2、要素サイズ2... 586| ・void* 返り値; 使用しなかったメモリ領域の先頭アドレス 587|【補足】 588|・mem を各バッファに割り振ります。 589|・... には、初期化するバッファと要素サイズを複数並べます。 590| バッファは ArrX_Buf* 型、要素サイズは int 型です。 591|・初期化するとバッファは空になります。 592|【例】 593| next = ArrX_Buf_inits( mem, ms, 3, 594| &m->polys, sizeof(Pdo_Poly), 595| &m->materials, sizeof(Pdo_Material), 596| &m->points, sizeof(Pdo_Point) ); 597|*****************************************************************/ 598|#ifdef STDLIBS_INCLUDE_STDARG_H 599|void* ArrX_Buf_inits( void* mem, int* ms, int n, ... ) 600|{ 601| int i; 602| va_list va; 603| ArrX_Buf* buf; 604| int size; 605| 606| va_start( va, n ); 607| 608| for ( i = 0; i < n; i++ ) { 609| buf = va_arg( va, ArrX_Buf* ); 610| size = *ms * va_arg( va, int ); 611| ArrX_Buf_init( buf, mem, size ); 612| mem = (void*)( (char*)mem + size ); 613| ms ++; 614| } 615| 616| va_end( va ); 617| 618| return mem; 619|} 620|#endif 621| 622| 623|/**************************************************************** 624| 5-4. <<< [ArrX_Buf_getMemSize] 必要なメモリサイズを返す >>> 625|【引数】 626| ・int* ms; 最大要素数が格納されている配列 627| ・int n; 初期化するバッファの数 628| ・... 要素サイズ1、要素サイズ2... 629| ・int 返り値; 必要なメモリサイズ 630|【補足】 631|・ArrX_Buf_inits の引数に指定するメモリ領域に必要なメモリサイズを 632| 計算します。 633|【例】 634| size = ArrX_Buf_getMemSize( ms, 3, 635| sizeof(Pdo_Poly), sizeof(Pdo_Material), sizeof(Pdo_Point) ); 636|*****************************************************************/ 637|#ifdef STDLIBS_INCLUDE_STDARG_H 638|int ArrX_Buf_getMemSize( int* ms, int n, ... ) 639|{ 640| int i; 641| int ret = 0; 642| va_list va; 643| 644| va_start( va, n ); 645| 646| for ( i = 0; i < n ; i++ ) { 647| ret += va_arg( va, int ) * (*ms); 648| ms++; 649| } 650| 651| va_end( va ); 652| 653| return ret; 654|} 655|#endif 656| 657| 658|/**************************************************************** 659| 5-5. <<< [ArrX_Buf_chk] 正規チェック >>> 660|*****************************************************************/ 661|int ArrX_Buf_chk( ArrX_Buf* m ) 662|{ 663| ERRORS_INITCHK_FOR_SUB( m, 1 ); 664| return m->first <= m->last && 665| m->first <= m->bufLast && 666| m->last <= m->bufLast; 667|} 668| 669| 670|/**************************************************************** 671| 5-6. <<< [ArrX_Buf_get_imp] 配列番号から要素を返す >>> 672|【引数】 673| ・ArrX* m; 配列 674| ・int i; 配列番号 675| ・int size; 配列要素のサイズ 676|【補足】 677|・リリース時は、マクロ版 ArrX_Buf_get を呼び出します。 678|*****************************************************************/ 679|void* ArrX_Buf_get_imp( ArrX_Buf* m, int i, int size ) 680|{ 681| void* p = (char*)m->first + i * size; 682| 683| ASSERT( p < m->last ); 684| ASSERT( ( (char*)m->last - (char*)m->first ) % size == 0 ); 685| 686| return p; 687|} 688| 689| 690| 691|/************************************************************************** 692| 5-7. <<< [ArrX_Buf_alloc_imp] 指定サイズのバッファをアロケートする >>> 693|【引数】 694| ・int alloc_sizeof; 要素のサイズ 695| ・void* 返り値; 確保した領域の先頭アドレス 696|【補足】 697|・alloc_sizeof のサイズのメモリ領域を確保(アロケート)して、 698| その先頭アドレスを返します。 699|・アロケートしたら、メモリ領域( m->first から m->bufLast まで) 700| を超えてしまう場合(メモリ不足の場合)、error 関数を呼び出します。 701|・この関数は、ArrX_Buf_alloc マクロの実装部です。 702|***************************************************************************/ 703|void* ArrX_Buf_alloc_imp( ArrX_Buf* m, int alloc_sizeof ) 704|{ 705| void* ret = m->last; 706| void* nextLast = (char*)m->last + alloc_sizeof; 707| 708| ASSERT( ArrX_Buf_chk( m ) ); 709| if ( nextLast > m->bufLast ) { 710| #if !defined(NDEBUG) && !defined(ERRORS_CUT_DEBUG_TOOL) 711| ArrX_Buf_printElem( m, char, "" ); 712| #endif 713| error2_0( ArrX_Err_Full, "バッファが満杯です" ); 714| } 715| 716| /* メモリ領域を確保する */ 717| m->last = nextLast; 718| 719| ASSERT( ArrX_Buf_chk( m ) ); 720| 721| return ret; 722|} 723| 724| 725| 726|/************************************************************************** 727| 5-8. <<< [ArrX_Buf_allocs_imp] 指定サイズのバッファを複数アロケートする >>> 728|【引数】 729| ・int alloc_sizeof; 要素1つのサイズ 730| ・int nElem; 要素の数 731| ・void* 返り値; 確保した領域の先頭アドレス 732|【補足】 733|・alloc_sizeof * nElem のサイズのメモリ領域を確保(アロケート)して、 734| その先頭アドレスを返します。 735|・アロケートしたら、メモリ領域( m->first から m->bufLast まで) 736| を超えてしまう場合(メモリ不足の場合)、error 関数を呼び出します。 737|・この関数は、ArrX_Buf_allocs マクロの実装部です。 738|***************************************************************************/ 739|void* ArrX_Buf_allocs_imp( ArrX_Buf* m, int alloc_sizeof, int nElem ) 740|{ 741| void* ret = m->last; 742| void* nextLast = (char*)m->last + alloc_sizeof * nElem; 743| 744| ASSERT( ArrX_Buf_chk( m ) ); 745| if ( nextLast > m->bufLast ) 746| error2_0( ArrX_Err_Full, "バッファが満杯です" ); 747| 748| /* メモリ領域を確保する */ 749| m->last = nextLast; 750| 751| ASSERT( ArrX_Buf_chk( m ) ); 752| 753| return ret; 754|} 755| 756| 757| 758|/**************************************************************** 759| 5-9. <<< [ArrX_Buf_addCopy] バッファに追加する >>> 760|【引数】 761| ・ArrX* plus; 追加するデータまたは配列へのポインタ 762|【補足】 763|・plus は、単一のデータでも配列でも構いません。 764|・単一のデータの場合、plus->first = ptr,plus->last = ptr+1 と 765| して引数に渡します。 766|*****************************************************************/ 767|void ArrX_Buf_addCopy( ArrX_Buf* m, ArrX* plus ) 768|{ 769| int plus_size = (char*)plus->last - (char*)plus->first; 770| 771| ASSERT( ArrX_Buf_chk( m ) && ArrX_chk( plus ) ); 772| if ( m->last >= m->bufLast ) { 773| char s1[20], s2[20]; 774| strncpy( s1, (char*)m->first, sizeof(s1)-1 ); s1[19] = '\0'; 775| strncpy( s2, (char*)m->last-19, sizeof(s2)-1 ); s2[19] = '\0'; 776| Errors_printf_release( "バッファが満杯です\n%s 〜 %s", s1, s2 ); 777| error2_0( ArrX_Err_Full, "バッファが満杯です" ); 778| } 779| 780| /* バッファに余裕がある場合、*/ 781| if ( (char*)m->last + plus_size <= (char*)m->bufLast ) { 782| memcpy( m->last, plus->first, plus_size ); 783| m->last = (void*)((char*)m->last + plus_size); 784| } 785| 786| /* バッファに一部しか入らない場合、*/ 787| else { 788| memcpy( m->last, plus->first, 789| (char*)m->bufLast - (char*)m->last ); 790| m->last = m->bufLast; 791| } 792| 793| ASSERT( ArrX_Buf_chk( m ) ); 794|} 795| 796| 797| 798|/**************************************************************** 799| 5-10. <<< [ArrX_Buf_addChr] バッファに1バイト追加する >>> 800|【引数】 801| ・unsigned char c; 追加するデータ 802|*****************************************************************/ 803|void ArrX_Buf_addChr( ArrX_Buf* m, unsigned char c ) 804|{ 805| ASSERT( ArrX_Buf_chk( m ) ); 806| 807| /* バッファが満杯の場合、バッファの最後に追加する */ 808| if ( m->last == m->bufLast ) 809| m->last = (void*)((unsigned char*)m->last - 1); 810| 811| /* バッファに余裕がある場合、*/ 812| *(unsigned char*)m->last = c; 813| m->last = (void*)((unsigned char*)m->last + 1); 814| 815| ASSERT( ArrX_Buf_chk( m ) ); 816|} 817| 818| 819| 820|/**************************************************************** 821| 5-11. <<< [ArrX_Buf_addStr] バッファに文字列を追加する >>> 822|【引数】 823| ・char* s; 追加するデータ 824|【補足】 825|・strcat と同じような機能です。 826|・バッファの内容の最後には、'\0' が付いています。ただし、一度も 827| 本関数を呼ばなかったときは、付いていないので、一度、空文字を 828| 追加しておいてください。 829|*****************************************************************/ 830|void ArrX_Buf_addStr( ArrX_Buf* m, const char* s ) 831|{ 832| int left = (char*)m->bufLast - (char*)m->last; 833| int s_len = strlen( s ); 834| 835| if ( s_len < left ) { 836| strcpy( (char*)m->last, s ); 837| m->last = (char*)m->last + s_len; 838| } 839| else { 840| *( (char*)m->bufLast - 1 ) = '\0'; 841| strncpy( (char*)m->last, s, left - 1 ); 842| m->last = m->bufLast; 843| } 844|} 845| 846| 847|/**************************************************************** 848| 5-12. <<< [ArrX_Buf_addMem] バッファにデータを追加する >>> 849|【引数】 850| ・char* s; 追加するデータの先頭アドレス 851| ・char* s_size; 追加するデータのサイズ 852|【補足】 853|・strcat と同じような機能ですが、最後(*s_over)に '\0' は付きません。 854|・容量が足りないときは、入れられる分だけ入れます。 855|*****************************************************************/ 856|void ArrX_Buf_addMem( ArrX_Buf* m, const void* s, 857| int s_size ) 858|{ 859| int left = (char*)m->bufLast - (char*)m->last; 860| 861| if ( s_size <= left ) { 862| memcpy( m->last, s, s_size ); 863| m->last = (char*)m->last + s_size; 864| } 865| else { 866| memcpy( m->last, s, left ); 867| m->last = m->bufLast; 868| } 869|} 870| 871| 872|/********************************************************************* 873| 5-13. <<< [ArrX_Buf_addEndOfC] バッファに文字列の終端文字を追加する >>> 874|【補足】 875|・バッファが満杯の場合、バッファの最後の1バイトに入っていたデータの 876| 代わりに終端文字 '\0' を入れます。 877|**********************************************************************/ 878|void ArrX_Buf_addEndOfC( ArrX_Buf* m ) 879|{ 880| ASSERT( ArrX_Buf_chk( m ) ); 881| 882| /* バッファが満杯の場合、*/ 883| if ( m->last == m->bufLast ) { 884| *((unsigned char*)m->last - 1) = '\0'; 885| } 886| 887| /* バッファに余裕がある場合、*/ 888| else { 889| *(unsigned char*)m->last = '\0'; 890| m->last = (void*)((unsigned char*)m->last + 1); 891| } 892| 893| ASSERT( ArrX_Buf_chk( m ) ); 894|} 895| 896| 897| 898|/************************************************************************** 899| 5-14. <<< [ArrX_Buf_getLast_f_imp] ArrX_Buf_getLast_f の実装部 >>> 900|***************************************************************************/ 901|void* ArrX_Buf_getLast_f_imp( ArrX_Buf* m, int size ) 902|{ 903| ASSERT( m->first != m->last ); /* 要素数が0では使用できません */ 904| 905| return (char*)(m->last) - size; 906|} 907| 908|/************************************************************************** 909| 5-15. <<< [ArrX_Buf_free_imp] 指定サイズのバッファを解放する >>> 910|【引数】 911| ・void* p; 解放する領域の先頭アドレス 912| ・int free_sizeof; 要素のサイズ 913|【補足】 914|・新しい領域(末尾)から順番に解放すれば、素早く解放することも出来ます。 915|・領域の途中を開放したときは、その部分より後の領域を手前に詰めます。 916|・この関数は、ArrX_Buf_free マクロの実装部です。 917|***************************************************************************/ 918|void ArrX_Buf_free_imp( ArrX_Buf* m, void* p, int free_sizeof ) 919|{ 920| void* nextLast = (char*)m->last - free_sizeof; 921| 922| ASSERT( ArrX_Buf_chk( m ) ); 923| 924| /* メモリの途中を開放する */ 925| if ( nextLast != p ) { 926| ASSERT( (char*)p >= (char*)m->first && (char*)p < (char*)m->last ); 927| memcpy( p, (char*)p + free_sizeof, (char*)m->last - ((char*)p + free_sizeof) ); 928| } 929| 930| /* メモリ領域の末尾を解放する */ 931| m->last = nextLast; 932| 933| ASSERT( ArrX_Buf_chk( m ) ); 934|} 935| 936| 937| 938|/************************************************************************** 939| 5-16. <<< [ArrX_Buf_search_i_imp] int 型のキーを用いて線形検索する >>> 940|・この関数は、ArrX_Buf_search_i マクロの実装部です。 941|***************************************************************************/ 942|#ifdef USES_OFFSET 943|void* ArrX_Buf_search_i_imp( ArrX_Buf* m, Offset_Key* key, int val, 944| int elem_sizeof ) 945|{ 946| ASSERT( ArrX_Buf_chk( m ) && Offset_Key_chk( key ) ); 947| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_sizeof == 0 ); 948| 949| return ArrX_Imp_linearSearch( m->first, m->last, (int)elem_sizeof, 950| &val, key->offset, 0, sizeof(int) ); 951|} 952|#endif /* USES_OFFSET */ 953| 954| 955| 956|/************************************************************************** 957| 5-17. <<< [ArrX_Buf_search_d_imp] double 型のキーを用いて線形検索する >>> 958|・この関数は、ArrX_Buf_search_d マクロの実装部です。 959|***************************************************************************/ 960|#ifdef USES_OFFSET 961|void* ArrX_Buf_search_d_imp( ArrX_Buf* m, Offset_Key* key, double val, 962| int elem_sizeof ) 963|{ 964| ASSERT( ArrX_Buf_chk( m ) && Offset_Key_chk( key ) ); 965| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_sizeof == 0 ); 966| 967| return ArrX_Imp_linearSearch( m->first, m->last, (int)elem_sizeof, 968| &val, key->offset, 0, sizeof(double) ); 969|} 970|#endif /* USES_OFFSET */ 971| 972| 973| 974|/************************************************************************** 975| 5-18. <<< [ArrX_Buf_search_s_imp] 文字列型のキーを用いて線形検索する >>> 976|・この関数は、ArrX_Buf_search_s マクロの実装部です。 977|***************************************************************************/ 978|#ifdef USES_OFFSET 979|void* ArrX_Buf_search_s_imp( ArrX_Buf* m, Offset_Key* key, const char* val, 980| int elem_sizeof ) 981|{ 982| ASSERT( ArrX_Buf_chk( m ) && Offset_Key_chk( key ) ); 983| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_sizeof == 0 ); 984| 985| if ( key->type == Offset_CString ) 986| return ArrX_Imp_linearSearch( m->first, m->last, (int)elem_sizeof, 987| val, key->offset, 0, -1 ); 988| else if ( key->type == Offset_CStringP || key->type == Offset_StrV ) { 989| return ArrX_Imp_linearSearch( m->first, m->last, (int)elem_sizeof, 990| val, key->offset, 1, -1 ); 991| } 992| #ifndef ARRX_NO_STRICMP 993| else if ( key->type == Offset_CStringPI ) { 994| return ArrX_Imp_linearSearchF( m->first, m->last, (int)elem_sizeof, 995| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpIStr ); 996| } 997| #endif 998| else { 999| ASSERT( key->type == Offset_CStringPW ); 1000| #ifdef USES_STRX 1001| return ArrX_Imp_linearSearchF( m->first, m->last, (int)elem_sizeof, 1002| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpMatchMask ); 1003| #else 1004| Errors_notSupport(); 1005| return NULL; /* dummy */ 1006| #endif 1007| } 1008|} 1009|#endif /* USES_OFFSET */ 1010| 1011| 1012| 1013|/************************************************************************** 1014| 5-19. <<< [ArrX_Buf_search_ps_imp] 文字列型のキーを用いて線形検索する >>> 1015|・この関数は、ArrX_Buf_search_ps マクロの実装部です。 1016|***************************************************************************/ 1017|#ifdef USES_OFFSET 1018|void* ArrX_Buf_search_ps_imp( ArrX_Buf* m, Offset_Key* key, const char* val ) 1019|{ 1020| ASSERT( ArrX_Buf_chk( m ) && Offset_Key_chk( key ) ); 1021| 1022| if ( key->type == Offset_CString ) 1023| return ArrX_Imp_linearSearchP( (void**)m->first, (void**)m->last, 1024| val, key->offset, 0, -1 ); 1025| else if ( key->type == Offset_CStringP ) { 1026| return ArrX_Imp_linearSearchP( (void**)m->first, (void**)m->last, 1027| val, key->offset, 1, -1 ); 1028| } 1029| #ifndef ARRX_NO_STRICMP 1030| else if ( key->type == Offset_CStringPI ) { 1031| return ArrX_Imp_linearSearchPF( (void**)m->first, (void**)m->last, 1032| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpIStr ); 1033| } 1034| #endif 1035| else { 1036| ASSERT( key->type == Offset_CStringPW ); 1037| #ifdef USES_STRX 1038| return ArrX_Imp_linearSearchPF( (void**)m->first, (void**)m->last, 1039| val, key->offset, NULL, (ArrX_CmpF)ArrX_Imp_cmpMatchMask ); 1040| #else 1041| Errors_notSupport(); 1042| return NULL; /* dummy */ 1043| #endif 1044| } 1045|} 1046|#endif /* USES_OFFSET */ 1047| 1048| 1049|/************************************************************************** 1050| 5-20. <<< [ArrX_Buf_print_imp] 内部状態を表示する >>> 1051|***************************************************************************/ 1052|#ifndef ERRORS_CUT_DEBUG_TOOL 1053|void ArrX_Buf_print_imp( ArrX_Buf* m, const char* title ) 1054|{ 1055| ERRORS_INITCHK( m, 1 ); 1056| 1057| Errors_printf( "%sArrX_Buf(%p) : first = %p, last = %p, bufLast = %p", title, 1058| m, m->first, m->last, m->bufLast ); 1059|} 1060|#endif 1061| 1062| 1063|/************************************************************************** 1064| 5-21. <<< [ArrX_Buf_printElem_imp] 内部状態を表示する >>> 1065|***************************************************************************/ 1066|#ifndef ERRORS_CUT_DEBUG_TOOL 1067|void ArrX_Buf_printElem_imp( ArrX_Buf* m, int elem_sizeof, const char* title ) 1068|{ 1069| int size = (char*)m->last - (char*)m->first; 1070| int bufSize = (char*)m->bufLast - (char*)m->first; 1071| 1072| ERRORS_INITCHK( m, 1 ); 1073| ASSERT( ( (char*)m->last - (char*)m->first ) % elem_sizeof == 0 ); 1074| 1075| Errors_printf( "%sArrX_Buf(%p) : first = %p, last = %p, bufLast = %p", title, 1076| m, m->first, m->last, m->bufLast ); 1077| if ( elem_sizeof == 1 ) { 1078| Errors_printf( "%ssize = %d/%d", title, size, bufSize ); 1079| } 1080| else { 1081| Errors_printf( "%ssize = %d/%d count = %d/%d", title, 1082| size, bufSize, size/elem_sizeof, bufSize/elem_sizeof ); 1083| } 1084|} 1085|#endif 1086| 1087| 1088|/************************************************************************** 1089| 5-22. <<< [ArrX_Buf_print2] 配列の要素をデバッグ表示する >>> 1090|【補足】 1091|・詳細は、ArrX_print 関数を参照してください。 1092|***************************************************************************/ 1093|#ifdef USES_ERRORS 1094|#ifndef ERRORS_CUT_DEBUG_TOOL 1095|void ArrX_Buf_print2( ArrX_Buf* m, char* types ) 1096|{ 1097| ArrX arr; 1098| 1099| ArrX_castFrom_ArrX_Buf( &arr, m ); 1100| ArrX_print( &arr, types ); 1101|} 1102|#endif 1103|#endif 1104| 1105|/************************************************************************** 1106| 5-23. <<< [ArrX_Buf_doLoopFunc] SYM_STRUCT_LOOP_FUNC に指定する関数 >>> 1107|***************************************************************************/ 1108|#ifdef USES_SYM 1109|bool ArrX_Buf_doLoopFunc( Sym_Ref* container, Sym_Ref* elem ) 1110|{ 1111| ArrX_Buf* m; 1112| 1113| if ( container->type == Sym_StructType ) m = (ArrX_Buf*)container->adr; 1114| else m = *(ArrX_Buf**)container->adr; 1115| 1116| if ( elem->adr == NULL ) elem->adr = m->first; 1117| else { 1118| if ( elem->type == Sym_StructTypeP ) 1119| elem->adr = (void*)( (char*)elem->adr + sizeof(void*) ); 1120| else 1121| elem->adr = (void*)( (char*)elem->adr + (int)container->elem_param ); 1122| } 1123| 1124| return elem->adr < m->last; 1125|} 1126|#endif 1127| 1128| 1129|/*-------------------------------------------------------------------------*/ 1130|/* ◆6. <<<< (ArrX_Able) 有効フラグ付き配列 >>>> */ 1131|/*-------------------------------------------------------------------------*/ 1132| 1133| 1134| 1135|/**************************************************************** 1136| 6-1. <<< [ArrX_Able_init_imp] 初期化する(すべての要素を無効にする) >>> 1137|【引数】 1138| ・int arr_size; 全要素のデータのサイズ (byte) 1139|【補足】 1140|・ArrX_Able_init の実装部です。(本関数は内部用です) 1141|*****************************************************************/ 1142|#ifdef USES_OFFSET 1143|void ArrX_Able_init_imp( ArrX_Able* m, void* arr_adr, int arr_size, 1144| int elem_size, Offset ofsFlag ) 1145|{ 1146| char* p; 1147| ERRORS_INITCHK( m, 0 ); 1148| ASSERT( arr_size % elem_size == 0 ); 1149| 1150| ArrX_init( &m->arr, arr_adr, arr_size ); 1151| 1152| for ( p = (char*)m->arr.first; p < (char*)m->arr.last; 1153| p += elem_size ) { 1154| 1155| Offset_ref( ofsFlag, p, bool ) = false; 1156| } 1157|} 1158|#endif 1159| 1160|/*********************************************************************** 1161| 6-2. <<< [ArrX_Able_getN_imp] 有効な要素数を返す >>> 1162|【補足】 1163|・ArrX_Able_getN の実装部です。(本関数は内部用です) 1164|************************************************************************/ 1165|#ifdef USES_OFFSET 1166|int ArrX_Able_getN_imp( ArrX_Able* m, int elem_size, Offset ofsFlag ) 1167|{ 1168| char* p; 1169| int n = 0; 1170| ERRORS_INITCHK( m, 1 ); 1171| 1172| for ( p = (char*)m->arr.first; p < (char*)m->arr.last; 1173| p += elem_size ) { 1174| 1175| if ( Offset_ref( ofsFlag, p, bool ) ) 1176| n++; 1177| } 1178| 1179| return n; 1180|} 1181|#endif 1182| 1183| 1184|/*********************************************************************** 1185| 6-3. <<< [ArrX_Able_getFirst_imp] 最初の有効な要素を返す >>> 1186|************************************************************************/ 1187|#ifdef USES_OFFSET 1188|void* ArrX_Able_getFirst_imp( ArrX_Able* m, int elem_size, Offset ofsFlag ) 1189|{ 1190| char* p; 1191| ERRORS_INITCHK( m, 1 ); 1192| 1193| for ( p = (char*)m->arr.first; p < (char*)m->arr.last; 1194| p += elem_size ) { 1195| 1196| if ( Offset_ref( ofsFlag, p, bool ) ) 1197| return (void*)p; 1198| } 1199| return NULL; 1200|} 1201|#endif 1202| 1203| 1204|/*********************************************************************** 1205| 6-4. <<< [ArrX_Able_getFirstDis_imp] 最初の無効な要素を返す >>> 1206|************************************************************************/ 1207|#ifdef USES_OFFSET 1208|void* ArrX_Able_getFirstDis_imp( ArrX_Able* m, int elem_size, Offset ofsFlag ) 1209|{ 1210| char* p; 1211| ERRORS_INITCHK( m, 1 ); 1212| 1213| for ( p = (char*)m->arr.first; p < (char*)m->arr.last; 1214| p += elem_size ) { 1215| 1216| if ( ! Offset_ref( ofsFlag, p, bool ) ) 1217| return (void*)p; 1218| } 1219| error2_0( ArrX_Err_Full, "ArrX_Able が満杯です" ); 1220| return NULL; /* dummy */ 1221|} 1222|#endif 1223| 1224| 1225|/*********************************************************************** 1226| 6-5. <<< [ArrX_Able_forEach_imp] ArrX_Able_forEach用カウントアップ >>> 1227|【引数】 1228| ・void* pp; カウントアップするポインタのアドレス 1229| ・int size; 配列要素サイズ 1230| ・Offset offset; 配列要素の ArrX_Able_flag メンバ変数へのオフセット 1231| ・void* over; カウント・オーバーする配列要素のアドレス 1232|【補足】 1233|・内部用です。 1234|************************************************************************/ 1235|#ifdef USES_OFFSET 1236|void ArrX_Able_forEach_imp( void* pp, int size, Offset offset, void* over ) 1237|{ 1238| char** p = (char**)pp; 1239| 1240| while ( ! Offset_ref( offset, *p, bool ) && *p < (char*)over ) { 1241| *p += size; 1242| } 1243|} 1244|#endif 1245| 1246| 1247| 1248|/*********************************************************************** 1249| 6-6. <<< [ArrX_Able_forEachDisabled_imp] ArrX_Able_forEachDisabled用カウントアップ >>> 1250|【引数】 1251| ・void* pp; カウントアップするポインタのアドレス 1252| ・int size; 配列要素サイズ 1253| ・Offset offset; 配列要素の ArrX_Able_flag メンバ変数へのオフセット 1254| ・void* over; カウント・オーバーする配列要素のアドレス 1255|【補足】 1256|・内部用です。 1257|************************************************************************/ 1258|#ifdef USES_OFFSET 1259|void ArrX_Able_forEachDisabled_imp( void* pp, int size, Offset offset, void* over ) 1260|{ 1261| char** p = (char**)pp; 1262| 1263| while ( Offset_ref( offset, *p, bool ) && *p < (char*)over ) { 1264| *p += size; 1265| } 1266|} 1267|#endif 1268| 1269| 1270| 1271|/************************************************************************** 1272| 6-7. <<< [ArrX_Able_search_s_imp] 文字列型のキーを用いて線形検索する >>> 1273|***************************************************************************/ 1274|#ifdef USES_OFFSET 1275|void* ArrX_Able_search_s_imp( ArrX_Able* m, Offset_Key* key, const char* val, 1276| int elem_sizeof, Offset elem_ofs ) 1277|{ 1278| void* ret; 1279| ERRORS_INITCHK( m, 1 ); 1280| ASSERT( Offset_Key_chk( key ) ); 1281| 1282| for (;;) { 1283| ret = ArrX_search_s_imp( &m->arr, key, val, elem_sizeof ); 1284| 1285| /* 有効な要素を返す */ 1286| if ( ret == NULL ) return NULL; 1287| if ( Offset_ref( elem_ofs, ret, ArrX_AbleElem ) ) return ret; 1288| 1289| ret = (char*)ret + elem_sizeof; 1290| } 1291|} 1292|#endif 1293| 1294| 1295|/*-------------------------------------------------------------------------*/ 1296|/* ◆7. <<<< ソート・バッファ (ArrX_Sort) >>>> */ 1297|/*-------------------------------------------------------------------------*/ 1298| 1299| 1300| 1301|#ifdef USES_OFFSET 1302| 1303|/************************************************************************** 1304| 7-1. <<< [ArrX_Sort_init] 初期化する >>> 1305|【引数】 1306| ・void** mem; ソート・バッファ(ソート用ワーク領域) 1307| ・int mem_sizeof; mem のメモリサイズ 1308| ・Offset_Key* key; ソート・キー 1309|【補足】 1310|・mem には、void* 型の配列の先頭アドレスを渡します。要素数は、ソートする 1311| 要素の数と等しいかそれ以上にします。 1312|・初期化すると、ソート・バッファは空になります。 1313|***************************************************************************/ 1314|#ifdef USES_OFFSET 1315|void ArrX_Sort_init( ArrX_Sort* m, void** mem, int mem_sizeof, 1316| Offset_Key* key ) 1317|{ 1318| ERRORS_INITCHK( m, 0 ); 1319| 1320| ASSERT( Offset_Key_chk( key ) ); 1321| 1322| m->first = mem; 1323| m->last = mem; 1324| m->bufLast = (void**)((char*)mem + mem_sizeof); 1325| m->key = key; 1326| 1327| ASSERT( ArrX_Sort_chk( m ) ); 1328|} 1329|#endif 1330| 1331| 1332|/************************************************************************** 1333| 7-2. <<< [ArrX_Sort_chk] 正規チェック >>> 1334|【補足】 1335|・ツリー自体の正規チェックはしていません。 1336|***************************************************************************/ 1337|#ifdef USES_OFFSET 1338|int ArrX_Sort_chk( ArrX_Sort* m ) 1339|{ 1340| ERRORS_INITCHK_FOR_SUB( m, 1 ); 1341| 1342| return m->first <= m->last && 1343| m->first < m->bufLast && 1344| m->last <= m->bufLast && 1345| Offset_Key_chk( m->key ); 1346|} 1347|#endif 1348| 1349| 1350|/************************************************************************** 1351| 7-3. <<< [ArrX_Sort_print] デバッグ表示 >>> 1352|【補足】 1353|・プライオリティ・キューの要素については、データの先頭アドレスとキーの値のみ 1354| 表示します。 1355|***************************************************************************/ 1356|#ifndef ERRORS_CUT_DEBUG_TOOL 1357|#ifdef USES_OFFSET 1358|void ArrX_Sort_print( ArrX_Sort* m, const char* title ) 1359|{ 1360| int width = 1; 1361| int x = 1, y = 1; 1362| void** p; 1363| 1364| Errors_printf( "%sArrX_Sort(%p) nElem=%d, mElem=%d, buf=(%p..%p)", 1365| title, m, m->last - m->first, m->bufLast - m->first, 1366| m->first, m->bufLast ); 1367| Offset_Key_print( m->key, title ); 1368| 1369| Errors_printf( "%s(1)", title ); 1370| for ( p = m->first; p < m->last; p++ ) { 1371| Offset_Key_printData( m->key, *p, title ); 1372| 1373| /* ツリーの次の段になったら1行空ける */ 1374| x++; 1375| if ( x > width && p < m->last - 1 ) { 1376| x = 1; y++; width *= 2; 1377| Errors_printf( "%s(%d)", title, y ); 1378| } 1379| } 1380|} 1381|#endif 1382|#endif 1383| 1384| 1385| 1386|/************************************************************************** 1387| 7-4. <<< [ArrX_Sort_pushPQ] プライオリティ・キューとしてバッファに追加する >>> 1388|【引数】 1389| ・void* plus; 追加するデータへのポインタ 1390|【補足】 1391|・プライオリティ・キューは、配列にすべての要素をプッシュすると、ソートされ 1392| た順番にポップされていきます。 1393|・配列にはデータへのポインタのみ格納されるので、データの有効期限に注意して 1394| ください。 1395|・オーダーは log(N) N:要素数 と高速です。 1396| 1397|【内部補足】 1398|・配列を、親ノード番号が、(i-1)/2、子ノード番号が、i*2+1、i*2+2 になるような 1399| ツリー構造とみなしています。 1400| <IMG src="arrx1.gif"> 1401| 1402|・プッシュすると、すべてのノードのキー値を子ノードのキー値より優先順位が高い 1403| (昇順の場合は値が小さい方、降順の場合は値が大きい方)という部分的なソート 1404| 状態になります。ポップすると最も優先順位の高いものが取り出されます。 1405| つまり、すべての要素をプッシュ(ArrX_Sort_pushPQ)した後、ポップ( 1406| ArrX_Sort_popPQ)していくと、ソートされたデータを最初から取り出すことが 1407| 出来るということです。 1408|【参考】 1409|・C++ STL のプライオリティキューによるハフマンツリーの実装 1410| - Mark R.Nelson - DDJ Japan May.1996 p30 1411|***************************************************************************/ 1412|#ifdef USES_OFFSET 1413|void ArrX_Sort_pushPQ( ArrX_Sort* m, void* plus ) 1414|{ 1415| int i, iParent; /* 処理中の配列番号と、その親ノード(ルート方向) */ 1416| void **p, **pParent; /* 処理中の要素のアドレスと、その親ノード */ 1417| void* sp; 1418| 1419| ASSERT( ArrX_Sort_chk( m ) ); 1420| 1421| /* 配列が満杯なら、追加しない */ 1422| if ( m->last == m->bufLast ) { 1423| #ifdef _CHECKER 1424| error(); 1425| #endif 1426| return; 1427| } 1428| 1429| /* 要素を配列の最後に追加 */ 1430| *m->last = plus; 1431| m->last ++; 1432| 1433| /*「正規化」すべてのノードを、子ノードより優先順位を高くする */ 1434| i = m->last - m->first - 1; 1435| p = m->last - 1; 1436| while ( i > 0 ) { 1437| iParent = (i-1) / 2; 1438| pParent = m->first + iParent; 1439| 1440| /* あるノードを親ノードより優先順位を低くする */ 1441| if ( Offset_Key_cmp( m->key, *p, *pParent ) > 0 ) { 1442| 1443| /* 親ノードと入れ替える */ 1444| sp = *p; *p = *pParent; *pParent = sp; 1445| i = iParent; p = pParent; 1446| } 1447| else { 1448| /* 正規化された */ 1449| break; 1450| } 1451| } 1452| 1453| ASSERT( ArrX_Sort_chk( m ) ); 1454|} 1455|#endif 1456| 1457| 1458|/************************************************************************** 1459| 7-5. <<< [ArrX_Sort_popPQ] プライオリティ・キューとしてバッファから取り出す >>> 1460|【引数】 1461| ・void* 返り値; 最も優先順位の高い要素のアドレス 1462|【補足】 1463|・返り値として返されたポインタは、配列から取り除かれます。 1464|・キューが空の場合は、エラーになるので、ArrX_Sort_isEmpty 関数で調べて 1465| からこの関数を呼び出してください。 1466|***************************************************************************/ 1467|#ifdef USES_OFFSET 1468|void* ArrX_Sort_popPQ( ArrX_Sort* m ) 1469|{ 1470| int i, iChild; /* 処理中の配列番号と、その子ノードの配列番号の小さい方 */ 1471| void **p, **pChild; /* 要素番号 i の要素のアドレスと、同 iChild */ 1472| int iLast; /* 最後の配列番号 */ 1473| void* ret; 1474| void* sp; 1475| 1476| ASSERT( ArrX_Sort_chk( m ) ); 1477| 1478| /* 空の場合 NULL を返す */ 1479| ASSERT( m->first != m->last ); 1480| 1481| /* 優先順位のいちばん高いノードを ret に格納し、配列から取り除く */ 1482| ret = *m->first; 1483| m->last --; 1484| *m->first = *m->last; 1485| iLast = m->last - m->first - 1; 1486| 1487| /*「正規化」すべてのノードを、子ノードより優先順位を高くする */ 1488| i = 0; iChild = 1; 1489| p = m->first; pChild = p + 1; 1490| while ( iChild < iLast ) { 1491| 1492| /* 2つの子ノードのうち優先順位の高いものを iChild にする */ 1493| if ( Offset_Key_cmp( m->key, *(pChild + 1), *pChild ) > 0 ) { 1494| iChild++; pChild++; 1495| } 1496| 1497| /* あるノードを子ノードより優先順位を高くする */ 1498| if ( Offset_Key_cmp( m->key, *p, *pChild ) < 0 ) { 1499| 1500| /* 子ノードと入れ替える */ 1501| sp = *p; *p = *pChild; *pChild = sp; 1502| i = iChild; p = pChild; 1503| iChild = i * 2 + 1; pChild = m->first + iChild; 1504| } 1505| else { 1506| /* 正規化された */ 1507| ASSERT( ArrX_Sort_chk( m ) ); 1508| return ret; 1509| } 1510| } 1511| if ( iChild == iLast ) { /* 子ノードが片方しか無い場合 */ 1512| if ( Offset_Key_cmp( m->key, *p, *pChild ) < 0 ) { 1513| /* 子ノードと入れ替える */ 1514| sp = *p; *p = *pChild; *pChild = sp; 1515| } 1516| } 1517| ASSERT( ArrX_Sort_chk( m ) ); 1518| return ret; 1519|} 1520|#endif 1521| 1522|#endif /* USES_OFFSET */ 1523| 1524|/*-------------------------------------------------------------------------*/ 1525|/* ◆8. <<<< ハッシュテーブルを用いた辞書 (ArrX_Dic) >>>> */ 1526|/*-------------------------------------------------------------------------*/ 1527| 1528|#if defined(USES_OFFSET) && defined(USES_STRX) 1529| 1530|/************************************************************************** 1531| 8-1. <<< [ArrX_Dic_init] 初期化する >>> 1532|【引数】 1533| ・int width; ハッシュテーブルの幅 1534| ・ArrX_Buf* subDics; ArrX_Buf 型の配列の先頭アドレス 1535| ・int subDics_sizeof; subDics のメモリサイズ 1536| ・Offset_Key* key; キー、(ワードの位置) 1537| ・void* elems; 配列(辞書要素)の先頭アドレス 1538| ・int elems_sizeof; 配列(辞書要素)のメモリサイズ 1539|***************************************************************************/ 1540|void ArrX_Dic_init( ArrX_Dic* m, 1541| int width, ArrX_Buf* subDics, int subDics_sizeof, 1542| Offset_Key* key, void* elems, int elems_sizeof ) 1543|{ 1544| int i; 1545| void* pElem; 1546| int elem_sizeof = elems_sizeof / width; 1547| 1548| ASSERT( subDics_sizeof / sizeof(ArrX_Buf) == (unsigned int)width ); 1549| ASSERT( elems_sizeof >= width ); 1550| 1551| /* subDics を初期化する */ 1552| m->subDics = subDics; 1553| pElem = elems; 1554| for ( i = 0; i < width; i++ ) { 1555| ArrX_Buf_init( &m->subDics[i], pElem, elem_sizeof ); 1556| pElem = (char*)pElem + elem_sizeof; 1557| } 1558| 1559| /* その他の属性を初期化する */ 1560| m->width = width; 1561| m->key = key; 1562|} 1563| 1564| 1565|/************************************************************************** 1566| 8-2. <<< [ArrX_Dic_search_imp] 検索する >>> 1567|【引数】 1568| ・char* word; ワード 1569| ・int elem_sizeof; 検索する要素のサイズ 1570| ・void* 返り値; 検索された領域のアドレス、または NULL 1571|【補足】 1572|・指定したワードが辞書に登録されていない場合、NULL を返します。 1573|・この関数は、ArrX_Dic_search マクロの実装部です。 1574|***************************************************************************/ 1575|void* ArrX_Dic_search_imp( ArrX_Dic* m, const char* word, 1576| int elem_sizeof ) 1577|{ 1578| int hash = StrX_getHash( word, m->width ); 1579| 1580| return ArrX_Buf_search_s_imp( &m->subDics[hash], m->key, word, 1581| elem_sizeof ); 1582|} 1583| 1584| 1585|/************************************************************************** 1586| 8-3. <<< [ArrX_Dic_alloc_imp] 指定したワードの項目を確保する >>> 1587|【引数】 1588| ・char* word; ワード 1589| ・int elem_sizeof; 確保する要素のサイズ 1590| ・void* 返り値; 確保した領域のアドレス、または NULL 1591|【補足】 1592|・指定したワードがすでに辞書に登録されている場合、NULL を返します。 1593|・この関数は、ArrX_Dic_alloc マクロの実装部です。 1594|***************************************************************************/ 1595|void* ArrX_Dic_alloc_imp( ArrX_Dic* m, const char* word, 1596| int alloc_sizeof ) 1597|{ 1598| int hash = StrX_getHash( word, m->width ); 1599| 1600| if ( ArrX_Buf_search_s_imp( &m->subDics[hash], m->key, word, 1601| alloc_sizeof ) == NULL ) { 1602| return ArrX_Buf_alloc_imp( &m->subDics[hash], alloc_sizeof ); 1603| } 1604| else 1605| return NULL; /* すでに登録されている */ 1606|} 1607| 1608| 1609|/*********************************************************************** 1610| 8-4. <<< [ArrX_Dic_allocFromFile] ファイルから登録する >>> 1611|【引数】 1612| ・ArrX_Dic* m; 辞書 1613| ・char* path; 登録する文字列が書かれたファイル 1614| ・StrX_Mem* mem; 文字列記憶領域 1615|【補足】 1616|・文字列型(char*型)の配列をハッシュテーブルに登録します。 1617|・ファイルのフォーマットは、文字列をスペース系文字(' ','\t','\n')で 1618| 区切るものです。(fscanf と同様) 1619|・テーブルの要素は、構造体ではなく char* 型の固定です。 1620| ですから、キーワードが存在するかどうかの判定しか用途がありません。 1621|・word_size - 1 文字より大きい文字列は、それ以降を切り捨てて登録します。 1622|************************************************************************/ 1623|#if defined(USES_FILEX) 1624|#ifndef FOR_WINCE 1625|void ArrX_Dic_allocFromFile( ArrX_Dic* m, 1626| const char* path, StrX_Mem* mem ) 1627|{ 1628| enum { word_size = 256 }; 1629| char word[256]; 1630| FILE* file; 1631| char** data; 1632| 1633| file = FileX_open( path, "rt" ); 1634| 1635| for (;;) { 1636| fscanf( file, "%s", word ); 1637| if ( feof( file ) ) break; 1638| data = ArrX_Dic_alloc( m, word, char* ); 1639| if ( data != NULL ) { 1640| *data = StrX_Mem_alloc( mem ); 1641| strcpy( *data, word ); 1642| } 1643| } 1644| fclose( file ); 1645|} 1646|#endif 1647|#endif 1648| 1649| 1650| 1651|/*********************************************************************** 1652| 8-5. <<< [ArrX_Dic_print] デバッグ表示する >>> 1653|【引数】 1654| ・int elem_size; 辞書要素のメモリサイズ 1655| ・print; 辞書要素のデバッグ表示をする関数 1656|【補足】 1657|・print は、第1引数が要素へのポインタ、第2引数が title です。 1658|************************************************************************/ 1659|#ifndef ERRORS_CUT_DEBUG_TOOL 1660|void ArrX_Dic_print( ArrX_Dic* m, const char* title, int elem_size, 1661| void (*elem_print)(void*,const char*) ) 1662|{ 1663| ArrX_Buf* buf; 1664| ArrX_Buf* buf_over; 1665| void* pElem; 1666| 1667| Errors_printf( "%sArrX_Dic[%p] width=%d", title, m, m->width ); 1668| Offset_Key_print( m->key, title ); 1669| 1670| /* 配列要素をデバッグ表示する */ 1671| for ( buf = m->subDics, buf_over = m->subDics + m->width; 1672| buf < buf_over; buf++ ) { 1673| Errors_printf( "%s [%d] = %d", title, buf - m->subDics, 1674| ArrX_Buf_getN_imp( buf, elem_size ) ); 1675| } 1676| 1677| /* 配列要素をデバッグ表示する */ 1678| for ( buf = m->subDics, buf_over = m->subDics + m->width; 1679| buf < buf_over; buf++ ) { 1680| Errors_printf( "%s[%d] = %d ------------------------------", 1681| title, buf - m->subDics, 1682| ArrX_Buf_getN_imp( buf, elem_size ) ); 1683| for ( ArrX_Buf_forEach_imp( buf, &pElem, elem_size ) ) { 1684| (*elem_print)( pElem, title ); 1685| } 1686| } 1687|} 1688|#endif 1689| 1690|#endif /* USES_OFFSET */ 1691| 1692|/*-------------------------------------------------------------------------*/ 1693|/* ◆9. <<<< ハッシュテーブルを用いた辞書の走査子 (ArrX_DicIter) >>>> */ 1694|/*-------------------------------------------------------------------------*/ 1695| 1696| 1697| 1698|/************************************************************************** 1699| 9-1. <<< [ArrX_DicIter_init_imp] 走査子を初期化する >>> 1700|【補足】 1701|・この関数は、ArrX_DicIter_init マクロの実装です。 1702|***************************************************************************/ 1703|#ifdef USES_STRX 1704|void ArrX_DicIter_init_imp( ArrX_DicIter* m, ArrX_Dic* dic, int size ) 1705|{ 1706| m->dic = dic; 1707| m->curBuf = dic->subDics; 1708| m->curData = (void*)((char*)m->curBuf->first - size); 1709| m->iBuf = 0; 1710| m->size = size; 1711|} 1712| 1713|#endif /* USES_STRX */ 1714| 1715| 1716| 1717|/************************************************************************** 1718| 9-2. <<< [ArrX_DicIter_next_imp] 走査子を次の辞書要素に移動する >>> 1719|【引数】 1720| ・int size; 辞書要素のサイズ 1721| ・int 返り値; 0=正常、1=次の辞書要素は無い 1722|***************************************************************************/ 1723|#ifdef USES_STRX 1724|int ArrX_DicIter_next( ArrX_DicIter* m ) 1725|{ 1726| /* 現在のバッファ curBuf に次の辞書要素が有れば、それを指す */ 1727| m->curData = (void*)((char*)m->curData + m->size); 1728| if ( m->curData < m->curBuf->last ) { 1729| return 0; 1730| } 1731| 1732| /* 次の辞書要素が無ければ、辞書要素を持っている次のバッファを指す */ 1733| else { 1734| do { 1735| m->curBuf ++; 1736| m->iBuf ++; 1737| if ( m->iBuf == m->dic->width ) return 1; 1738| } while ( m->curBuf->first == m->curBuf->last ); 1739| m->curData = m->curBuf->first; 1740| return 0; 1741| } 1742|} 1743| 1744|#endif /* USES_STRX */ 1745| 1746| 1747| 1748|/*---------------------------------------------------------------------*/ 1749|/* ◆10. <<<< はしごポインタ (ArrX_ArrsPtrI) >>>> */ 1750|/*---------------------------------------------------------------------*/ 1751| 1752|/*********************************************************************** 1753| 10-1. <<< [ArrX_ArrsPtrI_init] 初期化する >>> 1754|【引数】 1755| ・int* arr[]; それぞれの配列のアドレスの配列 1756| ・int arr_n[]; それぞれの配列の要素数の配列 1757| ・int nArr; arr の要素数 1758| ・int iArr; ポインタの初期値(1)(arr の配列番号) 1759| ・int p; ポインタの初期値(2)(arr[iArr] の先頭を0としたアドレス) 1760|************************************************************************/ 1761|void ArrX_ArrsPtrI_init( ArrX_ArrsPtrI* m, int* arr[], int arr_n[], int nArr, 1762| int iArr, int p ) 1763|{ 1764| m->arr = arr; m->arr_n = arr_n; m->nArr = nArr; 1765| ArrX_ArrsPtrI_set( m, iArr, p ); 1766|} 1767| 1768| 1769| 1770|/*********************************************************************** 1771| 10-2. <<< [ArrX_ArrsPtrI_set] ポインタの値を設定する(ランダム指定)>>> 1772|【引数】 1773| ・int iArr; 配列の番号(要素番号ではない) 1774| ・int p; 配列番号(iArr の先頭を基準とする) 1775|************************************************************************/ 1776|void ArrX_ArrsPtrI_set( ArrX_ArrsPtrI* m, int iArr, int p ) 1777|{ 1778| m->p = m->arr[iArr]; 1779| m->iArr = iArr; 1780| m->pOver = m->arr[iArr] + m->arr_n[iArr]; 1781| 1782| ArrX_ArrsPtrI_plus( m, p ); 1783|} 1784| 1785| 1786| 1787|/*********************************************************************** 1788| 10-3. <<< [ArrX_ArrsPtrI_plus] ポインタの演算をする >>> 1789|【引数】 1790| ・int p; 配列番号の増分(正の数のみ) 1791|************************************************************************/ 1792|void ArrX_ArrsPtrI_plus( ArrX_ArrsPtrI* m, unsigned int plus ) 1793|{ 1794| m->p += plus; 1795| 1796| while ( m->p >= m->pOver ) { 1797| m->iArr ++; 1798| m->p = m->arr[m->iArr] + ( m->p - m->pOver ); 1799| m->pOver = m->arr[m->iArr] + m->arr_n[m->iArr]; 1800| } 1801|} 1802| 1803| 1804| 1805|/*-------------------------------------------------------------------------*/ 1806|/* ◆11. <<<< 実装 (ArrX_Imp) >>>> */ 1807|/*-------------------------------------------------------------------------*/ 1808| 1809| 1810| 1811|/************************************************************************** 1812| 11-1. <<< [ArrX_Imp_linearSearch] 線形検索する(1) >>> 1813|【引数】 1814| ・void* start; 配列の先頭アドレス 1815| ・void* last; 配列の末尾の次のアドレス 1816| ・int elem_size; 要素のサイズ 1817| ・void* key; キーのアドレス 1818| ・int key_offset; 要素中のキーのオフセット 1819| ・int key_type; キーのタイプ(補足を参照) 1820| ・int key_size; キーのサイズ(補足を参照) 1821| ・int 返り値; 見つかった要素のアドレス、または NULL=見つからない 1822|【補足】 1823|・key_type は、0=バイナリ か 1=ポインタのどちらかを指定します。 1824|・key_size を -1 にすると、'\0'付き文字列として比較します。 1825|・1つ見つかった後で、もう1つ見つけようとする場合、start に前に見つかった 1826| 要素の次の要素のアドレスを指定します。例:(type*)p + 1 1827|***************************************************************************/ 1828|void* ArrX_Imp_linearSearch( void* start, void* last, int elem_size, 1829| const void* key, int key_offset, int key_type, int key_size ) 1830|{ 1831| int flag; /* 比較結果, memcmp 関数と同じ返り値 */ 1832| void* elem_key; /* 要素中のキーのアドレス */ 1833| 1834| if ( key_type == 0 ) { 1835| if ( key_size >= 0 ) { 1836| while ( start < last ) { 1837| elem_key = ((char*)start + key_offset); 1838| flag = memcmp( elem_key, key, key_size ); 1839| if ( flag == 0 ) return start; 1840| start = (char*)start + elem_size; 1841| } 1842| } 1843| else { 1844| while ( start < last ) { 1845| elem_key = ((char*)start + key_offset); 1846| flag = strcmp( (char*)elem_key, (char*)key ); 1847| if ( flag == 0 ) return start; 1848| start = (char*)start + elem_size; 1849| } 1850| } 1851| } 1852| else { 1853| if ( key_size >= 0 ) { 1854| while ( start < last ) { 1855| elem_key = *((void**)((char*)start + key_offset)); 1856| flag = memcmp( elem_key, key, key_size ); 1857| if ( flag == 0 ) return start; 1858| start = (char*)start + elem_size; 1859| } 1860| } 1861| else { 1862| while ( start < last ) { 1863| elem_key = *((void**)((char*)start + key_offset)); 1864| flag = strcmp( (char*)elem_key, (char*)key ); 1865| if ( flag == 0 ) return start; 1866| start = (char*)start + elem_size; 1867| } 1868| } 1869| } 1870| 1871| return NULL; 1872|} 1873| 1874| 1875| 1876|/************************************************************************** 1877| 11-2. <<< [ArrX_Imp_linearSearchF] 線形検索する(2) >>> 1878|【引数】 1879| ・void* start; 配列の先頭アドレス 1880| ・void* last; 配列の末尾の次のアドレス 1881| ・int elem_size; 要素のサイズ 1882| ・void* key; キーのアドレス 1883| ・int key_offset; 要素中のキーのオフセット 1884| ・void* param; 判定関数に渡す任意のパラメータのアドレス 1885| ・ArrX_CmpF func; 判定関数のアドレス 1886| ・int 返り値; 見つかった要素のアドレス、または NULL=見つからない 1887|【補足】 1888|・1つ見つかった後で、もう1つ見つけようとする場合、start に前に見つかった 1889| 要素の次の要素のアドレスを指定します。例:(type*)p + 1 1890|***************************************************************************/ 1891|void* ArrX_Imp_linearSearchF( void* start, void* last, int elem_size, 1892| const void* key, int key_offset, void* param, ArrX_CmpF func ) 1893|{ 1894| int flag; /* 比較結果, memcmp 関数と同じ返り値 */ 1895| void* elem_key; /* 要素中のキーのアドレス */ 1896| 1897| while ( start < last ) { 1898| elem_key = ((char*)start + key_offset); 1899| flag = (*func)( elem_key, (void*)key, param ); 1900| if ( flag == 0 ) return start; 1901| start = (char*)start + elem_size; 1902| } 1903| return NULL; 1904|} 1905| 1906| 1907| 1908|/************************************************************************** 1909| 11-3. <<< [ArrX_Imp_linearSearchP] ポインタ配列を線形検索する(1) >>> 1910|【引数】 1911| ・void** start; ポインタ配列の先頭アドレス 1912| ・void** last; ポインタ配列の末尾の次のアドレス 1913| ・void* key; キーのアドレス 1914| ・int key_offset; 要素中のキーのオフセット 1915| ・int key_type; キーのタイプ(補足を参照) 1916| ・int key_size; キーのサイズ(補足を参照) 1917| ・int 返り値; 見つかった要素のアドレス、または NULL=見つからない 1918|【補足】 1919|・key_type は、0=バイナリ か 1=ポインタのどちらかを指定します。 1920|・key_size を -1 にすると、'\0'付き文字列として比較します。 1921|・1つ見つかった後で、もう1つ見つけようとする場合、start に前に見つかった 1922| 要素の次の要素のアドレスを指定します。例:(type*)p + 1 1923|***************************************************************************/ 1924|void* ArrX_Imp_linearSearchP( void** start, void** last, 1925| const void* key, int key_offset, int key_type, int key_size ) 1926|{ 1927| int flag; /* 比較結果, memcmp 関数と同じ返り値 */ 1928| void* elem_key; /* 要素中のキーのアドレス */ 1929| 1930| if ( key_type == 0 ) { 1931| if ( key_size >= 0 ) { 1932| while ( start < last ) { 1933| elem_key = ((char*)*start + key_offset); 1934| flag = memcmp( elem_key, key, key_size ); 1935| if ( flag == 0 ) return start; 1936| start ++; 1937| } 1938| } 1939| else { 1940| while ( start < last ) { 1941| elem_key = ((char*)*start + key_offset); 1942| flag = strcmp( (char*)elem_key, (char*)key ); 1943| if ( flag == 0 ) return start; 1944| start ++; 1945| } 1946| } 1947| } 1948| else { 1949| if ( key_size >= 0 ) { 1950| while ( start < last ) { 1951| elem_key = *((void**)((char*)*start + key_offset)); 1952| flag = memcmp( elem_key, key, key_size ); 1953| if ( flag == 0 ) return start; 1954| start ++; 1955| } 1956| } 1957| else { 1958| while ( start < last ) { 1959| elem_key = *((void**)((char*)*start + key_offset)); 1960| flag = strcmp( (char*)elem_key, (char*)key ); 1961| if ( flag == 0 ) return start; 1962| start ++; 1963| } 1964| } 1965| } 1966| 1967| return NULL; 1968|} 1969| 1970| 1971| 1972|/************************************************************************** 1973| 11-4. <<< [ArrX_Imp_linearSearchPF] ポインタ配列を線形検索する(2) >>> 1974|【引数】 1975| ・void** start; ポインタ配列の先頭アドレス 1976| ・void** last; ポインタ配列の末尾の次のアドレス 1977| ・void* key; キーのアドレス 1978| ・int key_offset; 要素中のキーのオフセット 1979| ・void* param; 判定関数に渡す任意のパラメータのアドレス 1980| ・ArrX_CmpF func; 判定関数のアドレス 1981| ・int 返り値; 見つかった要素のアドレス、または NULL=見つからない 1982|【補足】 1983|・1つ見つかった後で、もう1つ見つけようとする場合、start に前に見つかった 1984| 要素の次の要素のアドレスを指定します。例:(type*)p + 1 1985|***************************************************************************/ 1986|void* ArrX_Imp_linearSearchPF( void** start, void** last, 1987| const void* key, int key_offset, void* param, ArrX_CmpF func ) 1988|{ 1989| int flag; /* 比較結果, memcmp 関数と同じ返り値 */ 1990| void* elem_key; /* 要素中のキーのアドレス */ 1991| 1992| while ( start < last ) { 1993| elem_key = ((char*)*start + key_offset); 1994| flag = (*func)( elem_key, (void*)key, param ); 1995| if ( flag == 0 ) return start; 1996| start ++; 1997| } 1998| return NULL; 1999|} 2000| 2001| 2002| 2003|/************************************************************************** 2004| 11-5. <<< [ArrX_Imp_cmpMatchMask] ワイルドカードによる文字列比較 >>> 2005|【補足】 2006|・StrX_cmpWild 関数を ArrX_Imp_linearSearchF 関数で用いるための 2007| ラッパーです。 2008|***************************************************************************/ 2009|#ifdef USES_STRX 2010|int ArrX_Imp_cmpMatchMask( char** a, char* b, void* dummy ) 2011|{ 2012| return StrX_cmpWild( *a, b ); 2013|} 2014|#endif /* USES_STRX */ 2015| 2016|/************************************************************************** 2017| 11-6. <<< [ArrX_Imp_cmpIStr] 大文字小文字を区別しない文字列比較 >>> 2018|【補足】 2019|・stricmp 関数を ArrX_Imp_linearSearchF 関数で用いるための 2020|s ラッパーです。 2021|***************************************************************************/ 2022|#ifndef ARRX_NO_STRICMP 2023|int ArrX_Imp_cmpIStr( char** a, char* b, void* dummy ) 2024|{ 2025| return stricmp( *a, b ); 2026|} 2027|#endif 2028| 2029|