ARRAYU3.C

[目次 | 関数 | マクロ]

目次

関数一覧

マクロ一覧


   1|/**************************************************************************
   2|*  1. <<< 配列使用管理・メモリ領域 (ArrayU3) >>> 
   3|***************************************************************************/
   4|
   5|#include "mixer_precomp.h"
   6|// #pragma hdrstop ("mixer_precomp")
   7|
   8|#ifdef  USES_MXP_AUTOINC
   9|#include  <ArrayU3.ah>  /* Auto include header, Look at mixer-... folder */
  10|#endif
  11|
  12|#define  i_check  /* 配列番号チェッカー */
  13|
  14|
  15| 
  16|/**************************************************************************
  17|*  2. <<< [ArrayU3_init] 初期化する >>> 
  18|*【引数】
  19|*  ・ArrayU3* m;   「配列使用管理」のアドレス
  20|*  ・char*  p;        「管理配列」の先頭アドレス
  21|*  ・int  elem_size;  配列に含まれる1つの要素(データ)のサイズ
  22|*  ・int  nElem;      配列要素数
  23|*【補足】
  24|*  p に指定する管理配列のサイズは次のように指定します。
  25|*  例:
  26|*  #define  elem_size  256
  27|*  #define  nElem      100
  28|*  char*  mem[ ArrayU3_getMemSize( elem_size, nElem ) ];
  29|*  ArrayU3_init( m, mem, elem_size, nElem );
  30|***************************************************************************/
  31|void  ArrayU3_init( ArrayU3* m, char* p, int elem_size, int nElem )
  32|{
  33|  int   i;
  34|
  35|  m->p = p;
  36|  m->size = elem_size + sizeof(int)*2;
  37|  m->iUseTop = -1;
  38|  m->iNoUseTop = 0;
  39|  m->iNoUseLast = nElem - 1;
  40|  m->nNoUseButValid = 0;
  41|
  42|  for ( i=0; i < nElem; i++ ) {
  43|    ((ArrayU3_Elem*) p )->iPrev = i-1;
  44|    ((ArrayU3_Elem*) p )->iNext = i+1;
  45|    p += m->size;
  46|  }
  47|  ArrayU3_getInElem( m, nElem-1 )->iNext = -1;
  48|}
  49|
  50|
  51| 
  52|/**************************************************************************
  53|*  3. <<< [ArrayU3_alloc_imp] 配列要素を確保する >>> 
  54|*【引数】
  55|*  ・ArrayU3* m;   「配列使用管理」のアドレス
  56|*  ・void*  返り値;   確保した配列要素の先頭アドレス
  57|***************************************************************************/
  58|void*  ArrayU3_alloc_imp( ArrayU3* m )
  59|{
  60|  int  i;
  61|
  62|  i = ArrayU3_getNoUseTop( m );
  63|  if ( i == -1 )  error();
  64|
  65|  ArrayU3_use( m, i );
  66|
  67|  return  ArrayU3_getElem( m, i, void* );
  68|}
  69|
  70|
  71| 
  72|/**************************************************************************
  73|*  4. <<< [ArrayU3_free] 配列要素を解放する >>> 
  74|*【引数】
  75|*  ・ArrayU3* m;   「配列使用管理」のアドレス
  76|*  ・void*    elem;   解放する配列要素の先頭アドレス
  77|***************************************************************************/
  78|void  ArrayU3_free( ArrayU3* m, void* elem )
  79|{
  80|  int  i;
  81|
  82|  i = ArrayU3_getI( m, (char*)elem );
  83|  ArrayU3_disuse( m, i );
  84|}
  85|
  86|
  87| 
  88|/**************************************************************************
  89|*  5. <<< [ArrayU3_use] 「管理配列要素」を使用状態にする >>> 
  90|*【引数】
  91|*  ・ArrayU3* m;    「配列使用管理」のアドレス
  92|*  ・int  i;          使用状態にする「管理配列要素」の番号
  93|*【機能】
  94|*・「配列使用管理」m の「管理配列要素」(番号 i )を使用状態にします。
  95|***************************************************************************/
  96|void  ArrayU3_use( ArrayU3* m, int i )
  97|{
  98|  /* 使用状態にする「管理配列要素」p を取得する */
  99|  ArrayU3_Elem*  p = ArrayU3_getInElem( m, i );
 100|
 101|  ASSERT( i >= 0 && i < ArrayU3_getNElem( m ) );
 102|
 103|  /* p が使用状態なら、そのまま関数を抜ける */
 104|  if ( ArrayU3_isUse( m, i ) )  return;
 105|
 106|  /* p を未使用状態のリストから外す */
 107|  {
 108|    /* p がリストの先頭なら、*/
 109|    /* p の次の「管理配列要素」を未使用状態のリストの先頭にする */
 110|    if ( p->iPrev == -1 )  m->iNoUseTop = p->iNext;
 111|
 112|    /* p の両隣の「管理配列要素」をつなぐ */
 113|    else
 114|      ArrayU3_getInElem( m, p->iPrev ) -> iNext = p->iNext;
 115|
 116|    if ( p->iNext >= 0 )
 117|      ArrayU3_getInElem( m, p->iNext ) -> iPrev = p->iPrev;
 118|
 119|    /* p の前の「管理配列要素」を未使用状態のリストの末尾にする */
 120|    else
 121|      m->iNoUseLast = p->iPrev;
 122|
 123|    /* 未使用状態の「管理配列要素」の数を減らす */
 124|    m->nNoUseButValid --;
 125|  }
 126|
 127|  /* p を使用状態のリストに入れる */
 128|  if ( m->iUseTop != -1 )
 129|    ArrayU3_getInElem( m, m->iUseTop ) -> iPrev = i;
 130|  p->iNext = m->iUseTop;
 131|  p->iPrev = -1;
 132|  m->iUseTop = i;
 133|}
 134|
 135|
 136| 
 137|/**************************************************************************
 138|*  6. <<< [ArrayU3_useTop] 最も古い「管理配列要素」を使用状態にする >>> 
 139|*【機能】
 140|*・最も古い未使用状態の「管理配列要素」を使用状態にします。
 141|*【引数】
 142|*  ・ArrayU3* m;    「配列使用管理」のアドレス
 143|*【補足】
 144|*・使用条件:未使用要素があること。m->iNoUseTop != -1 ならあります。
 145|*・ArrayU3_use 関数より高速です。
 146|*・使用状態にする「管理配列要素」は、関数を呼んだ後で知る方法が無いので、
 147|*  この関数を呼ぶ前に ArrayU3_getTop 関数で取得すること。
 148|***************************************************************************/
 149|void  ArrayU3_useTop( ArrayU3* m )
 150|{
 151|  /* 使用状態にする「管理配列要素」p(番号 i)を取得する */
 152|  int  i = m->iNoUseTop;
 153|  ArrayU3_Elem*  p = ArrayU3_getInElem( m, i );
 154|
 155|  /* p を未使用状態のリストから外す */
 156|  m->iNoUseTop = p->iNext;
 157|  if ( p->iNext >= 0 )
 158|    ArrayU3_getInElem( m, p->iNext ) -> iPrev = -1;
 159|  else
 160|    m->iNoUseLast = -1;
 161|
 162|  /* p を使用状態のリストに入れる */
 163|  if ( m->iUseTop != -1 )
 164|    ArrayU3_getInElem( m, m->iUseTop ) -> iPrev = i;
 165|  p->iNext = m->iUseTop;
 166|  p->iPrev = -1;
 167|  m->iUseTop = i;
 168|}
 169|
 170|
 171| 
 172|/**************************************************************************
 173|*  7. <<< [ArrayU3_disuse]「管理配列要素」を未使用状態にする >>> 
 174|*【引数】
 175|*  ・ArrayU3* m;    「配列使用管理」のアドレス
 176|*  ・int  i;          未使用状態にする「管理配列要素」の番号
 177|***************************************************************************/
 178|void  ArrayU3_disuse( ArrayU3* m, int i )
 179|{
 180|  /* 未使用状態にする「管理配列要素」p を取得する */
 181|  ArrayU3_Elem*  p = ArrayU3_getInElem( m, i );
 182|
 183|  ASSERT( i >= 0 && i < ArrayU3_getNElem( m ) );
 184|
 185|  /* p が未使用状態のなら、そのまま関数を抜ける */
 186|  if ( ! ArrayU3_isUse( m, i ) )  return;
 187|
 188|  /* p を使用状態のリストから外す */
 189|  {
 190|    /* p がリストの先頭なら、*/
 191|    /* p の次の「管理配列要素」を使用状態のリストの先頭にする */
 192|    if ( p->iPrev == -1 )  m->iUseTop = p->iNext;
 193|
 194|    /* p の両隣の「管理配列要素」をつなぐ */
 195|    else
 196|      ArrayU3_getInElem( m, p->iPrev ) -> iNext = p->iNext;
 197|
 198|    if ( p->iNext >= 0 )
 199|      ArrayU3_getInElem( m, p->iNext ) -> iPrev = p->iPrev;
 200|  }
 201|
 202|  /* p を未使用状態のリストの末尾に入れる */
 203|  if ( m->iNoUseLast == -1 )
 204|    m->iNoUseTop = i;
 205|  else
 206|    ArrayU3_getInElem( m, m->iNoUseLast ) -> iNext = i;
 207|  p->iPrev = m->iNoUseLast;
 208|  p->iNext = -1;
 209|  m->iNoUseLast = i;
 210|  m->nNoUseButValid ++;
 211|}
 212|
 213|
 214| 
 215|/**************************************************************************
 216|*  8. <<< [ArrayU3_getPElem]「配列要素」のアドレスを返す >>> 
 217|*【補足】
 218|*・ユーザは、このアドレスの配列要素にアクセスします。
 219|***************************************************************************/
 220|char*  ArrayU3_getPElem( ArrayU3* m, int i )
 221|{
 222|  ASSERT( i >= 0 && i < ArrayU3_getNElem( m ) );
 223|
 224|  /*「管理配列要素」に含まれる「配列要素」のアドレスを返す */
 225|  return  (char*)ArrayU3_getInElem(m, i) + 2*sizeof(int);
 226|}
 227|
 228|
 229| 
 230|/**************************************************************************
 231|*  9. <<< [ArrayU3_getNext] リストの次の「管理配列要素」の番号を返す >>> 
 232|*【機能】
 233|*・使用状態(または未使用状態)のリストの次の「管理配列要素」の番号を返します。
 234|*【引数】
 235|*  ・ArrayU3* m;  「配列使用管理」のアドレス
 236|*  ・int  i;        基準となる「管理配列要素」の番号
 237|*  ・int  返り値;   次の「管理配列要素」の番号
 238|*【補足】
 239|*・次の「管理配列要素」の番号が無い場合は -1 を返します。
 240|***************************************************************************/
 241|int   ArrayU3_getNext( ArrayU3* m, int i )
 242|{
 243|  return  ArrayU3_getInElem( m, i ) -> iNext;
 244|}
 245|
 246|
 247| 
 248|/**************************************************************************
 249|*  10. <<< [ArrayU3_getPrev] リストの前の「管理配列要素」の番号を返す >>> 
 250|*【機能】
 251|*・使用状態(または未使用状態)のリストの前の「管理配列要素」の番号を返します。
 252|*【引数】
 253|*  ・ArrayU3* m;  「配列使用管理」のアドレス
 254|*  ・int  i;        基準となる「管理配列要素」の番号
 255|*  ・int  返り値;   前の「管理配列要素」の番号
 256|*【補足】
 257|*・前の「管理配列要素」の番号が無い場合は -1 を返します。
 258|***************************************************************************/
 259|int   ArrayU3_getPrev( ArrayU3* m, int i )
 260|{
 261|  ASSERT( i >= 0 && i < ArrayU3_getNElem( m ) );
 262|
 263|  return  ArrayU3_getInElem( m, i ) -> iPrev;
 264|}
 265|
 266|
 267| 
 268|/**************************************************************************
 269|*  11. <<< [ArrayU3_getI]「配列要素」のアドレスから「配列要素」番号を返す >>> 
 270|***************************************************************************/
 271|int   ArrayU3_getI( ArrayU3* m, char* elem )
 272|{
 273|  char*  InElem = (char*)elem - 2*sizeof(int);  /*「管理配列要素」のアド */
 274|
 275|  return  (InElem - m->p) / m->size;
 276|}
 277|
 278|
 279| 
 280|/**************************************************************************
 281|*  12. <<< [ArrayU3_isUse]「管理配列要素」が使用状態かどうかを返す >>> 
 282|*【引数】
 283|*  ・ArrayU3* m;  「配列使用管理」のアドレス
 284|*  ・int  i;        使用状態を確認する「管理配列要素」の番号
 285|*  ・bool  返り値;  1=使用状態, 0=未使用状態
 286|*【補足】
 287|*・リストの先頭までたどっていくので、比較的処理が遅くなります。
 288|***************************************************************************/
 289|bool  ArrayU3_isUse( ArrayU3* m, int i )
 290|{
 291|  /* 使用状態を確認する「管理配列要素」p を取得する */
 292|  ArrayU3_Elem*  p = ArrayU3_getInElem( m, i );
 293|
 294|  ASSERT( i >= 0 && i < ArrayU3_getNElem( m ) );
 295|
 296|  /* p を使用状態(または未使用状態)のリストの先頭に移動する */
 297|  while ( p->iPrev != -1 ) {
 298|    p = ArrayU3_getInElem( m, p->iPrev );
 299|  }
 300|
 301|  /* p が使用状態のリストの先頭かどうかを返す */
 302|  return  p == ArrayU3_getInElem( m, m->iUseTop );
 303|}
 304|
 305|
 306| 
 307|/**************************************************************************
 308|*  13. <<< [ArrayU3_getNElem] 配列要素数を返す >>> 
 309|***************************************************************************/
 310|int  ArrayU3_getNElem( ArrayU3* m )
 311|{
 312|  int  i;
 313|
 314|  /* n を 0 に初期化する */
 315|  int  n = 0;
 316|
 317|  /* 未使用状態の「管理配列要素」の数を n に加算する */
 318|  i = ArrayU3_getNoUseTop( m );
 319|  while ( i != -1 ) {
 320|    n++;
 321|    i = ArrayU3_getNext( m, i );
 322|  }
 323|
 324|  /* 使用状態の「管理配列要素」の数を n に加算する */
 325|  i = ArrayU3_getUseTop( m );
 326|  while ( i != -1 ) {
 327|    n++;
 328|    i = ArrayU3_getNext( m, i );
 329|  }
 330|
 331|  return  n;
 332|}
 333|
 334|
 335| 
 336|/**************************************************************************
 337|*  14. <<< [ArrayU3_watch] ウォッチ(デバッグ用)>>> 
 338|***************************************************************************/
 339|#ifdef USES_WATCH
 340|void  ArrayU3_watch( ArrayU3* m )
 341|{
 342|  int  i;
 343|  int  nElem = ArrayU3_getNElem( m );
 344|
 345|  for ( i = 0; i < nElem; i++ ) {
 346|
 347|    /* 要素番号と使用状態をウォッチ */
 348|    watch( i, ArrayU3_isUse( m, i ) );
 349|
 350|    /* 配列要素の先頭の4バイトと、そのアドレスをウォッチ */
 351|    watch( ArrayU3_getElem( m, i, int ),
 352|           (int)ArrayU3_getPElem( m, i ) );
 353|  }
 354|}
 355|#endif  /* USES_WATCH */
 356|
 357|
 358| 
 359|/**************************************************************************
 360|*  15. <<< [ArrayU3_print] 表示(デバッグ用)>>> 
 361|*【機能】
 362|*・使用状態と未使用状態のリスト構造をたどり、
 363|*  各要素のアドレスを表示します。
 364|***************************************************************************/
 365|#ifdef   FOR_DOS16
 366|void  ArrayU3_print( ArrayU3* m )
 367|{
 368|  int  i;
 369|
 370|  /* 使用状態の「配列要素」のアドレスを先頭から列挙表示する */
 371|  printf( "status=USE ... " );
 372|  i = m->iUseTop;
 373|  while ( i != -1 ) {
 374|    printf( "%p, ", ArrayU3_getPElem( m, i ) );
 375|    i = ArrayU3_getNext( m, i );
 376|  }
 377|  printf( "\n" );
 378|
 379|  /* 未使用状態の「配列要素」のアドレスを先頭から列挙表示する */
 380|  printf( "status=NOUSE ... " );
 381|  i = m->iNoUseTop;
 382|  while ( i != -1 ) {
 383|    printf( "%p, ", ArrayU3_getPElem( m, i ) );
 384|    i = ArrayU3_getNext( m, i );
 385|  }
 386|  printf( "\n" );
 387|}
 388|#endif  /* FOR_DOS16 */
 389|
 390|
 391| 
 392|/**************************************************************************
 393|*  16. <<< [ArrayU3_print2] 表示(デバッグ用)>>> 
 394|*【引数】
 395|*  ・int  n;  要素数、-1 にすると自動的に計算
 396|*【機能】
 397|*・iUseTop, iNoUseTop, iNoUseLast の値を表示します。
 398|*・配列番号 0 から n-1 の要素のアドレスと、前後の番号を表示します。
 399|*【補足】
 400|*・n を -1 にすると、ArrayU3_getNElem 関数の返り値を n に設定しますが、
 401|*  その関数が異常なら、1つの要素も表示できないことがあります。
 402|***************************************************************************/
 403|#ifdef   FOR_DOS16
 404|void  ArrayU3_print2( ArrayU3* m, int n )
 405|{
 406|  int  i;
 407|
 408|  /* iUseTop, iNoUseTop, iNoUseLast の値を表示する */
 409|  printf( "iUseTop = %d, iNoUseTop = %d, iNoUseLast = %d\n",
 410|          m->iUseTop, m->iNoUseTop, m->iNoUseLast );
 411|
 412|  /* もし n == -1 なら要素数 n を計算する */
 413|  if ( n == -1 )
 414|    n = ArrayU3_getNElem( m );
 415|
 416|  /* すべての要素のアドレスと、前後の番号を表示する */
 417|  for ( i = 0; i < n; i++ ) {
 418|    ArrayU3_Elem*  inElem;
 419|
 420|    printf( "  [%d]", i );
 421|    printf( "%p  ", ArrayU3_getPElem( m, i ) );
 422|
 423|    inElem = ArrayU3_getInElem( m, i );
 424|    printf( "prev=%d  ", inElem->iPrev );
 425|    printf( "next=%d \n", inElem->iNext );
 426|  }
 427|  printf( "\n" );
 428|}
 429|#endif  /* FOR_DOS16 */
 430|
 431|
 432| 
 433|