arrx.c

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|