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|