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|