nestfind.c

C:\home\SVGCats_src\src\nestfind.c

[目次 | 関数]

目次

関数一覧


   1|/**************************************************************************
   2|*  1. <<< サブ・フォルダファイル列挙 (NestFind) >>> 
   3|*【役割】
   4|*・カレントフォルダからネストしてファイル名を列挙します。
   5|*【補足】
   6|*・フォルダをネストしないで列挙する場合、FileFind クラスを用います。
   7|*・ファイルが存在しているフォルダ名を参照することは出来ますが、
   8|*  列挙される要素としてカウントされません。
   9|*【例】
  10|*  static NestFind  find;
  11|*
  12|*  NestFind_init( &find, "c:\\bc4\\" );
  13|*  while ( NestFind_next( &find ) ) {
  14|*    printf( "%s\n", NestFind_getPath( &find ) );
  15|*  }
  16|***************************************************************************/
  17|
  18|#ifdef  USES_MXP_AUTOINC
  19| #include  "nestfind.ah"  /* Auto include header, Look at mixer-... folder */
  20|#else
  21| #include  "all.h"
  22|#endif
  23|#include  <string.h>
  24|#include  <stdlib.h>
  25|#include  <stdio.h>
  26|
  27|#ifdef __UNIX__
  28|#include  "filefind.h"
  29|#endif
  30|#ifdef __BORLAND__
  31|#include  "dir.h"
  32|#include  "dos.h"
  33|#endif
  34|#ifdef _MSC_VER
  35|#include  "io.h"
  36|#include  "dos.h"
  37|#endif
  38|
  39|
  40|#ifndef K_AND_R
  41|static void  NestFind_getFNames( NestFind* m );
  42|#else
  43|static void  NestFind_getFNames( m );
  44|  NestFind* m;
  45|#endif
  46|
  47|static int   NestFind_bFirst = true;
  48|
  49|
  50| 
  51|/**************************************************************************
  52|*  2. <<< [NestFind_init] 初期化する >>> 
  53|*【引数】
  54|*  ・char*  absPath;      列挙する基底のディレクトリ・パス
  55|*  ・bool  bFinishedDir;  探索が済んだディレクトリも列挙するかどうか
  56|*【補足】
  57|*・"*.txt" のようにマスクをかけることはできません。
  58|*・初期化しても、NestFind_next するまで、ファイル名を参照することはできません。
  59|***************************************************************************/
  60|#ifndef K_AND_R
  61|void  NestFind_init( NestFind* m, const char* absPath,
  62|  bool bFinishedDir )
  63|#else
  64|void  NestFind_init( m, absPath, bFinishedDir )
  65|  NestFind* m; char* absPath;  bool bFinishedDir;
  66|#endif
  67|{
  68|  int  i;
  69|  static char* fnameX[NestFind_bufM];
  70|  static char  fname[NestFind_bufM][NestFind_nameSize+1];
  71|  static bool  isdir[NestFind_bufM];
  72|  static long  sizeX[NestFind_bufM];
  73|
  74|  #ifndef NDEBUG
  75|    if ( NestFind_bFirst )  NestFind_bFirst = false;
  76|    else  error();
  77|  #endif
  78|
  79|  m->fname = fnameX;
  80|  for ( i = 0; i < NestFind_bufM; i++ )
  81|    m->fname[i] = fname[i];
  82|  m->isdir = isdir;
  83|  m->size = sizeX;
  84|  m->bFinishedDir = bFinishedDir;
  85|
  86|  m->I[0] = -1;  /* 0 でないのは 次の NestFind_next() で有効になるように */
  87|  m->maxI[0] = -1; /* 1つも無いので -1 */
  88|  m->nest = 0;
  89|  strcpy( m->absPath, absPath );
  90|  StrX_setLast( m->absPath, '\\' );
  91|  strcpy( m->workPath, m->absPath );
  92|  NestFind_getFNames( m );
  93|}
  94|
  95| 
  96|/**************************************************************************
  97|*  3. <<< [NestFind_finish] 後始末する >>> 
  98|***************************************************************************/
  99|void  NestFind_finish( NestFind* m )
 100|{
 101|  NestFind_bFirst = true;
 102|}
 103|
 104|
 105| 
 106|/**************************************************************************
 107|*  4. <<< [NestFind_next] 次のファイルを参照する >>> 
 108|*【引数】
 109|*  ・返り値 : 次の候補があるか
 110|*【補足】
 111|*・最初、または次のファイルを参照するようにします。つまり、この関数を
 112|*  呼び出すたびに、NestFind_getFName 関数、NestFind_getPath 関数、
 113|*  NestFind_getAbsPath 関数によって参照されるファイル名が変わります。
 114|***************************************************************************/
 115|#ifndef K_AND_R
 116|bool  NestFind_next( NestFind* m )
 117|#else
 118|bool  NestFind_next( m )
 119|  NestFind* m;
 120|#endif
 121|{
 122|  bool  loop;
 123|
 124|  /* インデックスを次の候補に移動 */
 125|  m->I[m->nest]++;
 126|
 127|  do {
 128|    loop = false;
 129|
 130|    /* あるディレクトリのファイルをすべて走査したら、親ディレクトリへ戻る */
 131|    if ( m->I[m->nest] > m->maxI[m->nest] ) {
 132|      m->nest--;
 133|      if ( m->nest < 0 )
 134|        return  false;
 135|      if ( m->bFinishedDir )
 136|        return  true;
 137|      m->I[m->nest]++;
 138|
 139|      loop = true;
 140|    }
 141|
 142|    /* ディレクトリなら、ファイル名の列挙を読み込む */
 143|    else if ( m->isdir[m->I[m->nest]] ) {
 144|
 145|      /* path を列挙するディレクトリの絶対パス名にする */
 146|      NestFind_getAbsPath( m );
 147|      strcat( m->workPath, StrX_DirMark_str );
 148|
 149|      /* ネストする */
 150|      m->nest++;
 151|      if ( m->nest >= NestFind_nestM ) {
 152|        m->nest--;
 153|        error2_1( NestFind_Err_OverNest, "NestFind: over Nest (%s)\n",
 154|          NestFind_getAbsPath( m ) );
 155|      }
 156|      m->maxI[m->nest] = m->maxI[m->nest-1];
 157|      m->I[m->nest] = m->maxI[m->nest-1] + 1;
 158|
 159|      /* ファイル一覧を取得する */
 160|      NestFind_getFNames( m );
 161|
 162|      loop = true;
 163|    }
 164|  } while ( loop );
 165|
 166|  return  true;
 167|}
 168|
 169|
 170| 
 171|/**************************************************************************
 172|*  5. <<< [NestFind_getFName] ファイル名を参照する >>> 
 173|*【補足】
 174|*・フォルダの場所(絶対パス)を含まない、単独のファイル名を参照します。
 175|*・c:\folder\sub\filename.txt の filename.txt が参照されます。
 176|*・m->absPath == "c:\folder\" の場合、
 177|*  NestFind_getFName 関数では "filename.txt"、
 178|*  NestFind_getPath 関数では "sub\filename.txt"、
 179|*  NestFind_getAbsPath 関数では "c:\folder\sub\filename.txt" が参照されます。
 180|*・参照しているファイル名は、変更しないでください。
 181|***************************************************************************/
 182|#ifndef K_AND_R
 183|char*  NestFind_getFName( NestFind* m )
 184|#else
 185|char*  NestFind_getFName( m )
 186|  NestFind* m;
 187|#endif
 188|{
 189|  return  m->fname[ m->I[m->nest] ];
 190|}
 191|
 192|
 193| 
 194|/**************************************************************************
 195|*  6. <<< [NestFind_getPath] 相対パスを参照する >>> 
 196|*【補足】
 197|*・NestFind_init 関数の absPath 引数に指定したパスからの相対パスを参照します。
 198|*・参照している相対パスは、NestFind_getPath() か NestFind_getAbsPath()
 199|*  のどれかが再び呼び出されると変更されます。
 200|***************************************************************************/
 201|#ifndef K_AND_R
 202|char*  NestFind_getPath( NestFind* m )
 203|#else
 204|char*  NestFind_getPath( m )
 205|  NestFind* m;
 206|#endif
 207|{
 208|  int  i;
 209|
 210|  strcpy( m->workPath, "" );
 211|  for ( i = 0; i <= m->nest; i++ ) {
 212|    strcat( m->workPath, m->fname[ m->I[i] ] );
 213|    strcat( m->workPath, StrX_DirMark_str );
 214|  }
 215|  StrX_bs( m->workPath );
 216|
 217|  return  m->workPath;
 218|}
 219|
 220|
 221| 
 222|/**************************************************************************
 223|*  7. <<< [NestFind_getAbsPath] 絶対パスを参照する >>> 
 224|*【補足】
 225|*・参照している相対パスは、NestFind_getPath() か NestFind_getAbsPath()
 226|*  のどれかが再び呼び出されると変更されます。
 227|***************************************************************************/
 228|#ifndef K_AND_R
 229|char*  NestFind_getAbsPath( NestFind* m )
 230|#else
 231|char*  NestFind_getAbsPath( m )
 232|  NestFind* m;
 233|#endif
 234|{
 235|  char  s[_MAX_PATH];
 236|
 237|  strcpy( s, NestFind_getPath( m ) );
 238|  strcpy( m->workPath, m->absPath );
 239|  strcat( m->workPath, s );
 240|
 241|  return  m->workPath;
 242|}
 243|
 244|
 245| 
 246|/**************************************************************************
 247|*  8. <<< [NestFind_getNumer] 走査した候補の割合の分子を返す >>> 
 248|*【補足】
 249|*・計算の仕方は、子の要素数をそれぞれ乗算して、自分のいる位置を乗算した和
 250|*【例】
 251|*・要素  11122222334444 : Level(1)が3つ、(2)が5つ、(3)が2つ、(4)が4つの意
 252|*  位置   ^    ^ ^   ^
 253|*  分子 : (5*2*4)*1 + (2*4)*3 + (4)*0 = 64
 254|*  分母 : 3*5*2*4=120
 255|***************************************************************************/
 256|int  NestFind_getNumer( NestFind* m )
 257|{
 258|  int  ret;   /* 分子 */
 259|  int  n, i;  /* ネスト・レベル */
 260|  int  k;     /* 乗数 */
 261|
 262|  ret = 0;
 263|  for ( n = 0; n <= m->nest; n++ ) {
 264|
 265|    /* 乗数 k を取得する */
 266|    k = 1;
 267|    for ( i = m->nest; i > n; i-- ) {
 268|      k *= m->maxI[i] - m->maxI[i-1];
 269|    }
 270|
 271|    /* 乗数 k に、現在の位置を乗算する */
 272|    if ( n == 0 )
 273|      ret += k * (m->I[n]);
 274|    else
 275|      ret += k * (m->I[n] - m->maxI[n-1] - 1);
 276|  }
 277|
 278|  return  ret;
 279|}
 280|
 281|
 282| 
 283|/**************************************************************************
 284|*  9. <<< [NestFind_getDenomi] 走査した候補の割合の分母を返す >>> 
 285|*【補足】
 286|*・計算の仕方は、NestFind_getNumer を参照
 287|***************************************************************************/
 288|int  NestFind_getDenomi( NestFind* m )
 289|{
 290|  int  ret;  /* 分母 */
 291|  int  i;
 292|
 293|  ret = m->maxI[0]+1;
 294|  for ( i = 1; i <= m->nest; i++ )
 295|      ret *= m->maxI[i] - m->maxI[i-1];
 296|
 297|  return  ret;
 298|}
 299|
 300|
 301| 
 302|/**************************************************************************
 303|*  10. <<< [NestFind_getIsDir] ディレクトリかどうかを確認する >>> 
 304|***************************************************************************/
 305|#ifndef K_AND_R
 306|bool  NestFind_getIsDir( NestFind* m )
 307|#else
 308|bool  NestFind_getIsDir( m )
 309|  NestFind* m;
 310|#endif
 311|{
 312|  return  m->isdir[ m->I[m->nest] ];
 313|}
 314|
 315|
 316| 
 317|/**************************************************************************
 318|*  11. <<< [NestFind_getSize] ファイルサイズを返す >>> 
 319|***************************************************************************/
 320|#ifdef NestFind_UseAttr
 321|long  NestFind_getSize( NestFind* m )
 322|{
 323|  return  m->size[ m->I[m->nest] ];
 324|}
 325|#endif
 326| 
 327|/*-------------------------------------------------------------------------*/
 328|/* 12. <<< ◆内部用 ------------------------------------------------------ >>> */ 
 329|/*-------------------------------------------------------------------------*/
 330|
 331| 
 332|/**************************************************************************
 333|*  13. <<< [NestFind_getFNames] ファイル名の列挙をバッファ fname に入れる >>> 
 334|*【補足】
 335|*・path に列挙するパス名を入れること、末尾に ...\ が必要
 336|***************************************************************************/
 337|#ifndef K_AND_R
 338|static void  NestFind_getFNames( NestFind* m )
 339|#else
 340|static void  NestFind_getFNames( m )
 341|  NestFind* m;
 342|#endif
 343|
 344|{
 345|  int  done;
 346|  char*  filename;
 347|  bool   isdir;
 348|  #ifdef  NestFind_UseAttr
 349|    long  size;
 350|  #endif
 351|
 352|  #ifdef __UNIX__
 353|    static FileFind  find;
 354|  #endif
 355|  #ifdef __BORLAND__
 356|    struct ffblk ffblk;
 357|  #endif
 358|  #ifdef _MSC_VER
 359|    struct _finddata_t  find;
 360|    long   handle;
 361|  #endif
 362|
 363|  /* findfirst を初期化して、最初のファイル名を得る */
 364|  #ifdef __UNIX__
 365|    strcat( m->workPath, "*" );
 366|    FileFind_Init( &find, m->workPath );
 367|    done = ! FileFind_Find( &find );
 368|    filename = find.FileName;
 369|  #endif
 370|  #ifdef __BORLAND__
 371|    strcat( m->workPath, "*.*" );
 372|    done = findfirst( m->workPath, &ffblk, FA_RDONLY | FA_DIREC | FA_ARCH );
 373|    filename = ffblk.ff_name;
 374|  #endif
 375|  #ifdef _MSC_VER
 376|    strcat( m->workPath, "*.*" );
 377|    handle = _findfirst( m->workPath, &find );
 378|    done = ( handle == -1 );
 379|    filename = find.name;
 380|  #endif
 381|
 382|  while (!done)
 383|  {
 384|    /* カレント、または親ディレクトリなら、次の候補にする */
 385|    while ( strcmp( filename, "." ) == 0 ||
 386|            strcmp( filename, ".." ) == 0 ) {
 387|
 388|      #ifdef __UNIX__
 389|        done = ! FileFind_Find( &find );
 390|        filename = find.FileName;
 391|      #endif
 392|      #ifdef __BORLAND__
 393|        done = findnext(&ffblk);
 394|        filename = ffblk.ff_name;
 395|      #endif
 396|      #ifdef _MSC_VER
 397|        done = ( _findnext(handle, &find) == -1 );
 398|        filename = find.name;
 399|      #endif
 400|
 401|      if ( done ) {
 402|        goto exit_while;
 403|      }
 404|    }
 405|
 406|    /* ファイルの属性を取得する */
 407|    #ifdef __UNIX__
 408|      isdir = find.IsDir;
 409|    #endif
 410|    #ifdef __BORLAND__
 411|      isdir = ( ( ffblk.ff_attrib & FA_DIREC ) != 0 );
 412|    #endif
 413|    #ifdef _MSC_VER
 414|      isdir = ( ( find.attrib & _A_SUBDIR ) != 0 );
 415|    #endif
 416|
 417|    #ifdef  NestFind_UseAttr
 418|      #ifdef __UNIX__
 419|        #error
 420|      #endif
 421|      #ifdef __BORLAND__
 422|        #error
 423|      #endif
 424|      #ifdef _MSC_VER
 425|        size = (long)find.size;
 426|      #endif
 427|    #endif
 428|
 429|    /* ファイル名と属性を格納する */
 430|    m->maxI[m->nest]++;
 431|    if ( m->maxI[m->nest] >= NestFind_bufM ) {
 432|      error2_1( NestFind_Err_OverBuf, "NestFind: over Buf (%s)\n",
 433|        NestFind_getAbsPath( m ) );
 434|    }
 435|    strcpy( m->fname[ m->maxI[m->nest] ], filename );
 436|    m->isdir[ m->maxI[m->nest] ] = isdir;
 437|    #ifdef  NestFind_UseAttr
 438|      m->size[ m->maxI[m->nest] ] = size;
 439|    #endif
 440|
 441|    /* 次の候補にする */
 442|    #ifdef __UNIX__
 443|      done = ! FileFind_Find( &find );
 444|      filename = find.FileName;
 445|    #endif
 446|    #ifdef __BORLAND__
 447|      done = findnext(&ffblk);
 448|      filename = ffblk.ff_name;
 449|    #endif
 450|    #ifdef _MSC_VER
 451|      done = ( _findnext(handle, &find) == -1 );
 452|      filename = find.name;
 453|    #endif
 454|  }
 455| exit_while:;
 456|
 457|  #ifdef __UNIX__
 458|    FileFind_Finish( &find );
 459|  #endif
 460|  #ifdef _MSC_VER
 461|    _findclose( handle );
 462|  #endif
 463|}
 464| 
 465|