OSDN Git Service

Version 3.00
[vbslib/main.git] / samples / feq / src / feq.c
1 /***********************************************************************\r
2   <<< \81iWin32\83R\83\93\83\\81[\83\8b\82Å\93®\82­\81j\82Ì\83v\83\8d\83O\83\89\83\80 >>> \r
3 ************************************************************************/\r
4 \r
5 #define  _WIN32_WINNT 0x0400\r
6 #include  <windows.h>\r
7 #include  <stdio.h>\r
8 #include  <stdarg.h>\r
9 #include  <string.h>\r
10 #include  <io.h>\r
11 #include  <locale.h>\r
12 \r
13 \r
14 void  help(void);\r
15 \r
16 #define  error()  my_error_imp( __FILE__, __LINE__, -1, "" )\r
17 #define  ASSERT( x )  ( (x) ? 0 : my_error_imp( __FILE__, __LINE__, -2, #x ) )\r
18 #define  error2_0( id, fmt )    my_error_imp( __FILE__, __LINE__, id, fmt )\r
19 #define  error2_1( id, fmt, a )   my_error_imp( __FILE__, __LINE__, id, fmt, a )\r
20 #define  error2_2( id, fmt, a,b )   my_error_imp( __FILE__, __LINE__, id, fmt, a,b )\r
21 #define  error2_3( id, fmt, a,b,c )   my_error_imp( __FILE__, __LINE__, id, fmt, a,b,c )\r
22 #define  error2_4( id, fmt, a,b,c,d )   my_error_imp( __FILE__, __LINE__, id, fmt, a,b,c,d )\r
23 #define  error2_5( id, fmt, a,b,c,d,e )   my_error_imp( __FILE__, __LINE__, id, fmt, a,b,c,d,e )\r
24 void  my_error_imp( char* file, int line, int id, const char* fmt, ... )\r
25   { if ( fmt[0]!='\0' )  { va_list va;  va_start( va, fmt );  vprintf( fmt, va );  va_end( va ); }\r
26     printf( "ERROR %d in (%d) %s\n", id, line, file );\r
27     exit(4); }\r
28 \r
29 \r
30 typedef  int  (*FileX_NestFindF)( void* obj, const wchar_t* abs_path,\r
31    const wchar_t* step_path, const wchar_t* fname );\r
32 void FileX_callByNestFind( const char* path, void* obj, FileX_NestFindF callback );\r
33 int  FileX_isDir( const char* path );\r
34 int  FileX_isDiff( const char* path1, const char* path2 );\r
35 int  FileX_isDiffW( const wchar_t* path1, const wchar_t* path2 );\r
36 \r
37 \r
38  \r
39 /***********************************************************************\r
40   <<< \83\89\83C\83u\83\89\83\8a >>> \r
41 ************************************************************************/\r
42 void  FileX_callByNestFind( const char* path, void* obj, FileX_NestFindF callback );\r
43 void  FileX_callByNestFindW( const wchar_t* path, void* obj, FileX_NestFindF callback );\r
44 \r
45 \r
46 void   StrX_W_cpy( wchar_t* dst, const wchar_t* src, int dst_size );\r
47 #define  StrX_Err_BufOver  21\r
48 void   StrX_W_printf( wchar_t* s, size_t s_size, const wchar_t* fmt, ... );\r
49 void   StrX_W_printf_v( wchar_t* s, size_t s_size, const wchar_t* fmt, va_list va );\r
50 wchar_t*  StrX_W_cpyFolder( wchar_t* folder, const wchar_t* path, int folder_size );\r
51 wchar_t*  StrX_W_cutFName( wchar_t* path );\r
52 int  FileX_isExist( const char* path );\r
53 \r
54 \r
55  \r
56 /***********************************************************************\r
57   <<< [CmpFolder] \94ä\8ar\82·\82é\83t\83H\83\8b\83_\81i\95Ð\95û\81j >>> \r
58 ************************************************************************/\r
59 typedef struct {\r
60   wchar_t*   base;\r
61   wchar_t**  path;    /* \83t\83@\83C\83\8b\83p\83X\82Ì\94z\97ñ\81i\91\8a\91Î\81j*/\r
62   int        nFile;\r
63   char*      stat;    /* path \82É\91Î\89\9e\82·\82é\83f\81[\83^\81i\94z\97ñ\81j */\r
64   int        stat2;   /* \82à\82¤\95Ð\95û\82Ì\83t\83H\83\8b\83_\82É\8aÖ\82·\82é\83f\81[\83^ */\r
65   wchar_t**  folder;  /* \83t\83H\83\8b\83_\83p\83X\82Ì\94z\97ñ\81i\92Z\82¢\8f\87\81j\81A"." \82Í\93ü\82ê\82È\82¢ */\r
66   int        nFolder;\r
67 } CmpFolder;\r
68 \r
69 \r
70 void  CmpFolder_init( CmpFolder* m, const wchar_t* path );\r
71 void  CmpFolder_finish( CmpFolder* m );\r
72 \r
73 void  CmpFolder_scan( CmpFolder* m );\r
74 void  CmpFolder_resetStat( CmpFolder* m );\r
75 char* CmpFolder_refStat( CmpFolder* m, const wchar_t* step_path );\r
76 \r
77 \r
78  \r
79 /***********************************************************************\r
80   <<< \81\9f[main] \83t\83@\83C\83\8b\82Ü\82½\82Í\83t\83H\83\8b\83_\82ð\94ä\8ar\82µ\82Ü\82· >>> \r
81 \81y\88ø\90\94\81z\r
82   \81Eargv[1];     \83t\83@\83C\83\8b\82Ü\82½\82Í\83t\83H\83\8b\83_\82Ì\83p\83X\r
83   \81Eargv[2];     \83t\83@\83C\83\8b\82Ü\82½\82Í\83t\83H\83\8b\83_\82Ì\83p\83X\r
84   \81Eerrorlevel;  0=\93¯\82¶ 1=\88á\82¤\r
85 ************************************************************************/\r
86 int  chkSameFileByFo2( void* obj, const wchar_t* abs_path,  const wchar_t* step_path, const wchar_t* fname );\r
87 \r
88 \r
89 \r
90 int  main( int argc, char* argv[] )\r
91 {\r
92   int  ret;\r
93 \r
94   setlocale(LC_ALL, "Japanese");\r
95 \r
96   if ( argc != 3 )  { help();  return 1; }\r
97 \r
98   if ( FileX_isDir( argv[1] ) && FileX_isDir( argv[2] ) ) {\r
99     CmpFolder  fo1;\r
100     int  r, i;\r
101     wchar_t  path[4096];\r
102     wchar_t  path2[4096];\r
103     wchar_t  base2[4096];\r
104 \r
105     /* \83t\83@\83C\83\8b\82Ì\97L\96³\82ð\83`\83F\83b\83N\82µ\82Ü\82· */\r
106     r = MultiByteToWideChar( CP_OEMCP, MB_PRECOMPOSED, argv[1], -1,\r
107                             path, sizeof(path) / 2 );\r
108     if ( r == 0 )  error();\r
109     CmpFolder_init( &fo1, path );\r
110     CmpFolder_scan( &fo1 );\r
111     CmpFolder_resetStat( &fo1 );\r
112     fo1.stat2 = 0;\r
113     FileX_callByNestFind( argv[2], &fo1, chkSameFileByFo2 );\r
114     for ( i = 0; i < fo1.nFile; i++ ) {\r
115       if ( fo1.stat[i] != 1 )  break;\r
116     }\r
117     if ( i == fo1.nFile && fo1.stat2 == 0 ) {\r
118 \r
119       r = MultiByteToWideChar( CP_OEMCP, MB_PRECOMPOSED, argv[2], -1,\r
120                                base2, sizeof(base2) / 2 );\r
121       if ( r == 0 )  error();\r
122 \r
123       /* \83t\83@\83C\83\8b\82Ì\93à\97e\82ð\83`\83F\83b\83N\82µ\82Ü\82· */\r
124       for ( i = 0; i < fo1.nFile; i++ ) {\r
125         StrX_W_printf( path,  sizeof(path),  L"%s\\%s", fo1.base, fo1.path[i] );\r
126         StrX_W_printf( path2, sizeof(path2), L"%s\\%s", base2, fo1.path[i] );\r
127 \r
128         if ( FileX_isDiffW( path, path2 ) != 0 )  break;\r
129       }\r
130       ret = ( i == fo1.nFile ) ? 0 : 1;\r
131     }\r
132     else\r
133       ret = 1;\r
134   }\r
135   else if ( FileX_isExist( argv[1] ) && FileX_isExist( argv[2] ) )\r
136     ret = ( FileX_isDiff( argv[1], argv[2] ) == 0 ? 0 : 1 );\r
137   else {\r
138     if ( ! FileX_isExist( argv[1] ) )  printf( "Not found %s\n", argv[1] );\r
139     if ( ! FileX_isExist( argv[2] ) )  printf( "Not found %s\n", argv[2] );\r
140     ret = 2;\r
141   }\r
142 \r
143   if ( ret == 0 )  printf( "same.\n" );\r
144   else if ( ret == 1 )  printf( "different.\n" );\r
145 \r
146   return  ret;\r
147 }\r
148 \r
149 \r
150 int  chkSameFileByFo2( void* obj, const wchar_t* abs_path,  const wchar_t* step_path, const wchar_t* fname )\r
151 {\r
152   CmpFolder*  fo1 = (CmpFolder*) obj;\r
153   char*   p;\r
154 \r
155   p = CmpFolder_refStat( fo1, step_path );\r
156   if ( p != NULL )  *p = 1;\r
157   else  fo1->stat2 = 1;\r
158 \r
159   return  0;\r
160 }\r
161 \r
162 \r
163 \r
164  \r
165 /***********************************************************************\r
166   <<< [help] >>> \r
167 ************************************************************************/\r
168 void  help()\r
169 {\r
170   printf( "feq (path1) (path2)\n" );\r
171   printf( "  compare binary files or folders (sub folders)\n" );\r
172 }\r
173 \r
174 \r
175  \r
176 /*-------------------------------------------------------------------------*/\r
177 /* \81\9f<<<< \83\89\83C\83u\83\89\83\8a >>>> */ \r
178 /*-------------------------------------------------------------------------*/\r
179 \r
180 \r
181  \r
182 /***********************************************************************\r
183   <<< [FileX_callByNestFind] \83T\83u\83t\83H\83\8b\83_\82à\8aÜ\82ß\82Ä\8ae\83t\83@\83C\83\8b\82Ì\83p\83X\82ð\93n\82· >>> \r
184 \81y\88ø\90\94\81z\r
185   \81Echar*  path;                \83t\83@\83C\83\8b\82ð\97ñ\8b\93\82·\82é\83t\83H\83\8b\83_\82Ì\83p\83X\r
186   \81Evoid*  obj;                 \83R\81[\83\8b\83o\83b\83N\8aÖ\90\94\82Ì\91æ1\88ø\90\94\82É\93n\82·\92l\r
187   \81EFileX_NestFindF  callback;  \83R\81[\83\8b\83o\83b\83N\8aÖ\90\94\81i\83t\83@\83C\83\8b\82Ì\83p\83X\82ð\88ø\90\94\82É\8e\9d\82Â\81j\r
188 ************************************************************************/\r
189 typedef struct {\r
190   void*            obj;\r
191   FileX_NestFindF  callback;\r
192   wchar_t*         step_path;\r
193   wchar_t*         fname;\r
194   wchar_t          abs_path[4096];\r
195 } FileX_CallByNestFindData;\r
196 \r
197 void  FileX_callByNestFind_sub( FileX_CallByNestFindData* m );\r
198 \r
199 \r
200 void  FileX_callByNestFind( const char* path, void* obj, FileX_NestFindF callback )\r
201 {\r
202   FileX_CallByNestFindData  data;\r
203 \r
204   {\r
205     int  r;\r
206     wchar_t*   p;\r
207 \r
208     r = MultiByteToWideChar( CP_OEMCP, MB_PRECOMPOSED, path, -1,\r
209                            data.abs_path, sizeof(data.abs_path) / 2 );\r
210     if ( r == 0 )  error();\r
211 \r
212 \r
213     /* abs_path \82Ì\8dÅ\8cã\82É \ \82ª\96³\82¢\82È\82ç\92Ç\89Á\82·\82é */\r
214     p = wcschr( data.abs_path, L'\0' );\r
215     p--;\r
216     if ( *p != L'\\' ) {\r
217       p++;\r
218       if ( p >= data.abs_path + (sizeof(data.abs_path) / 2) - 1 )  error();\r
219       *p = L'\\';\r
220     }\r
221 \r
222 \r
223     /* data \82ð\8f\89\8aú\89»\82·\82é */\r
224     data.obj = obj;\r
225     data.callback = callback;\r
226     data.step_path = p + 1;\r
227     data.fname = p + 1;\r
228   }\r
229 \r
230   /* \8dÄ\8bN\8cÄ\82Ñ\8fo\82µ\8aÖ\90\94\82Ö */\r
231   FileX_callByNestFind_sub( &data );\r
232 }\r
233 \r
234 \r
235 void  FileX_callByNestFindW( const wchar_t* path, void* obj, FileX_NestFindF callback )\r
236 {\r
237   FileX_CallByNestFindData  data;\r
238 \r
239   {\r
240     wchar_t*   p;\r
241 \r
242     StrX_W_cpy( data.abs_path, path, sizeof(data.abs_path) );\r
243 \r
244 \r
245     /* abs_path \82Ì\8dÅ\8cã\82É \ \82ª\96³\82¢\82È\82ç\92Ç\89Á\82·\82é */\r
246     p = wcschr( data.abs_path, L'\0' );\r
247     p--;\r
248     if ( *p != L'\\' ) {\r
249       p++;\r
250       if ( p >= data.abs_path + (sizeof(data.abs_path) / 2) - 1 )  error();\r
251       *p = L'\\';\r
252     }\r
253 \r
254 \r
255     /* data \82ð\8f\89\8aú\89»\82·\82é */\r
256     data.obj = obj;\r
257     data.callback = callback;\r
258     data.step_path = p + 1;\r
259     data.fname = p + 1;\r
260   }\r
261 \r
262   /* \8dÄ\8bN\8cÄ\82Ñ\8fo\82µ\8aÖ\90\94\82Ö */\r
263   FileX_callByNestFind_sub( &data );\r
264 }\r
265 \r
266 \r
267 void  FileX_callByNestFind_sub( FileX_CallByNestFindData* m )\r
268 {\r
269   HANDLE  find;\r
270   WIN32_FIND_DATAW  data;\r
271   wchar_t*  p;\r
272   int  done;\r
273 \r
274 \r
275   /* * \82ð\92Ç\89Á */\r
276   p = m->fname;\r
277   if ( p >= m->abs_path + (sizeof(m->abs_path) / 2) - 2 )  error();\r
278   *p = L'*';  *(p+1) = L'\0';\r
279 \r
280 \r
281   /* \83t\83@\83C\83\8b\82©\83t\83H\83\8b\83_\82ð\97ñ\8b\93\82µ\82Ü\82· */\r
282   find = FindFirstFileExW( m->abs_path, FindExInfoStandard, &data,\r
283     FindExSearchNameMatch, NULL, 0 );\r
284   done = ( find == INVALID_HANDLE_VALUE );\r
285 \r
286   while (!done)\r
287   {\r
288     if ( wcscmp( data.cFileName, L"." ) == 0 ||\r
289          wcscmp( data.cFileName, L".." ) == 0 ) {\r
290       done = ! FindNextFileW( find, &data );\r
291       continue;\r
292     }\r
293 \r
294     StrX_W_cpy( m->fname, data.cFileName,\r
295       sizeof(m->abs_path) - ( (char*)m->fname - (char*)m->abs_path ) );\r
296 \r
297     if ( data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {\r
298       p = wcschr( m->fname, L'\0' );\r
299       if ( p >= m->abs_path + (sizeof(m->abs_path) / 2) - 2 )  error();\r
300       *p = L'\\';  *(p+1) = L'\0';\r
301       {  wchar_t*  w = m->fname;   m->fname = p + 1;   p = w; }\r
302 \r
303       FileX_callByNestFind_sub( m );  /* \8dÄ\8bN\8cÄ\82Ñ\8fo\82µ */\r
304 \r
305       m->fname = p;\r
306     }\r
307     else {\r
308       m->callback( m->obj, m->abs_path, m->step_path, m->fname );\r
309     }\r
310 \r
311     done = ! FindNextFileW( find, &data );\r
312   }\r
313   FindClose( find );\r
314 }\r
315 \r
316 \r
317 \r
318  \r
319 /************************************************************************\r
320   <<< [FileX_isExist] \83t\83@\83C\83\8b\89»\83t\83H\83\8b\83_\82Ì\91\8dÝ\82ð\8am\82©\82ß\82é >>> \r
321 *************************************************************************/\r
322 int  FileX_isExist( const char* path )\r
323 {\r
324   return  ( GetFileAttributes( path ) != -1 );\r
325 }\r
326 \r
327 \r
328  \r
329 /************************************************************************\r
330   <<< [FileX_isDir] \83t\83H\83\8b\83_\82Ì\91\8dÝ\82ð\8am\82©\82ß\82é >>> \r
331 \81y\88ø\90\94\81z\r
332   \81Econst char* fname;  \83t\83H\83\8b\83_\82Ö\82Ì\83p\83X\96¼\r
333   \81Ebool \95Ô\82è\92l;        \83t\83H\83\8b\83_\82Ì\91\8dÝ\r
334 \81y\95â\91«\81z\r
335 \81E\91\8a\91Î\83p\83X\82É\82æ\82Á\82Ä\8ew\92è\82·\82é\8fê\8d\87\81A\8c»\8dÝ\8eÀ\8ds\92\86\82Ì\83t\83H\83\8b\83_\82©\82ç\82Ì\91\8a\91Î\83p\83X\82É\r
336   \82È\82è\82Ü\82·\81B\r
337 \81E\8ew\92è\82µ\82½\83p\83X\82ª\83t\83@\83C\83\8b\82É\88ê\92v\82·\82é\8fê\8d\87\81Afalse \82ð\95Ô\82µ\82Ü\82·\81B\r
338 *************************************************************************/\r
339 int  FileX_isDir( const char* path )\r
340 {\r
341   DWORD  a;\r
342 \r
343   a = GetFileAttributes( path );\r
344   if ( a == -1 )  return  0;\r
345   return  ( a & FILE_ATTRIBUTE_DIRECTORY ) != 0;\r
346 }\r
347 \r
348 \r
349  \r
350 /*************************************************************************\r
351   <<< [FileX_isDiff] \82Q\82Â\82Ì\83t\83@\83C\83\8b\82Ì\93à\97e\82ª\93¯\88ê\82©\82Ç\82¤\82©\92²\82×\82é >>> \r
352 \81y\88ø\90\94\81z\r
353   \81Echar*  path1, path2;  \94ä\8ar\82·\82é\83t\83@\83C\83\8b\82Ì\83p\83X\r
354   \81Eint  \95Ô\82è\92l;   0=\93¯\88ê\81A 1=\88Ù\82È\82é\81A-1=fname1 \82ª\8aJ\82¯\82È\82¢\81A\r
355                   -2=fname2 \82ª\8aJ\82¯\82È\82¢\81A-3=fname1,fname2 \82Æ\82à\8aJ\82¯\82È\82¢\r
356 \81y\95â\91«\81z\r
357 \81E\97¼\95û\82Ì\83t\83@\83C\83\8b\82ª\91\8dÝ\82µ\82Ä\81A\93à\97e\82ª\93¯\88ê\82©\82Ç\82¤\82©\82ð\94»\92è\82·\82é\82È\82ç\82Î\81A\r
358   \95Ô\82è\92l\82Í bool \92l\81i\82O\82©\82O\88È\8aO\82©\81j\82Æ\82µ\82Ä\94»\92è\82·\82é\82±\82Æ\82ª\82Å\82«\82Ü\82·\81B\r
359 **************************************************************************/\r
360 int  FileX_isDiff_imp( FILE* file1, FILE* file2 );\r
361 \r
362 int  FileX_isDiff( const char* path1, const char* path2 )\r
363 {\r
364   return  FileX_isDiff_imp( fopen( path1, "rb" ), fopen( path2, "rb" ) );\r
365 }\r
366 \r
367 \r
368 int  FileX_isDiffW( const wchar_t* path1, const wchar_t* path2 )\r
369 {\r
370   return  FileX_isDiff_imp( _wfopen( path1, L"rb" ), _wfopen( path2, L"rb" ) );\r
371 }\r
372 \r
373 \r
374 int  FileX_isDiff_imp( FILE* file1, FILE* file2 )\r
375 {\r
376   int  ret;\r
377   int  size1, size2;\r
378   char  buf1[256], buf2[256];\r
379 \r
380   if ( file1 == NULL ) {\r
381     if ( file2 == NULL )  { ret = -3;  goto ret; }\r
382     else {\r
383       fclose( file2 );\r
384       { ret = -1;  goto ret; }\r
385     }\r
386   }\r
387   if ( file2 == NULL ) {\r
388     fclose( file1 );\r
389     { ret = -2;  goto ret; }\r
390   }\r
391 \r
392   ret = 1;\r
393   for (;;) {\r
394     size1 = fread( buf1, 1, 256, file1 );\r
395     size2 = fread( buf2, 1, 256, file2 );\r
396 \r
397     if ( size1 != size2 )  break;\r
398     if ( memcmp( buf1, buf2, size1 ) != 0 )  break;\r
399 \r
400     if ( size1 != 256 )  { ret = 0; break; }\r
401   }\r
402 \r
403   fclose( file1 );\r
404   fclose( file2 );\r
405 \r
406 ret:\r
407   return  ret;\r
408 }\r
409 \r
410 \r
411  \r
412 /***********************************************************************\r
413   <<< [StrX_W_printf] \83\8f\83C\83h\95\8e\9a\97ñ\82É\8fo\97Í\82·\82é printf >>> \r
414 ************************************************************************/\r
415 void   StrX_W_printf( wchar_t* s, size_t s_size, const wchar_t* fmt, ... )\r
416 {\r
417   va_list  va;\r
418 \r
419   va_start( va, fmt );\r
420   StrX_W_printf_v( s, s_size, fmt, va );\r
421   va_end( va );\r
422 }\r
423 \r
424 \r
425 \r
426  \r
427 /***********************************************************************\r
428   <<< [StrX_W_printf_v] \95\8e\9a\97ñ\82É\8fo\97Í\82·\82é printf >>> \r
429 ************************************************************************/\r
430 void   StrX_W_printf_v( wchar_t* s, size_t s_size, const wchar_t* fmt, va_list va )\r
431 {\r
432   s_size = s_size / 2;\r
433   s[s_size - 1] = '\0';\r
434 \r
435   _vsnwprintf( s, s_size, fmt, va );\r
436 \r
437   if ( s[s_size - 1] != '\0' ) {\r
438     s[s_size - 1] = L'\0';\r
439     error2_0( StrX_Err_BufOver, "" );\r
440   }\r
441 }\r
442 \r
443 \r
444  \r
445 /***********************************************************************\r
446   <<< [StrX_W_cpyFolder] \83p\83X\92\86\82Ì\83t\83@\83C\83\8b\96¼\88È\8aO\82ð\83R\83s\81[\82·\82é >>> \r
447 \81y\88ø\90\94\81z\r
448   \81Ewchar_t*  folder;    \83t\83H\83\8b\83_\83p\83X\82ð\8ai\94[\82·\82é\83A\83h\83\8c\83X\r
449   \81Ewchar_t*  path;      \83R\83s\81[\8c³\82Ì\83p\83X\r
450   \81Eint  folder_size;    folder \82Ì\83\81\83\82\83\8a\83T\83C\83Y\r
451   \81Ewchar_t*  \95Ô\82è\92l;    folder \82Æ\93¯\82\r
452 \81y\95â\91«\81z\r
453 \81Efolder \82Æ path \82ª\93¯\82\83A\83h\83\8c\83X\82Å\82à\8d\\82¢\82Ü\82¹\82ñ\81B\r
454 ************************************************************************/\r
455 wchar_t*  StrX_W_cpyFolder( wchar_t* folder, const wchar_t* path, int folder_size )\r
456 {\r
457   if ( folder != path )  StrX_W_cpy( folder, path, folder_size );\r
458   StrX_W_cutFName( folder );\r
459   return  folder;\r
460 }\r
461 \r
462 \r
463  \r
464 /***********************************************************************\r
465   <<< [StrX_W_cutFName] \83p\83X\92\86\82Ì\83t\83@\83C\83\8b\96¼\82ð\8dí\8f\9c\82·\82é >>> \r
466 \81y\88ø\90\94\81z\r
467   \81Echar* \95Ô\82è\92l;   path \82Æ\93¯\82\r
468 \81y\95â\91«\81z\r
469 \81E\83t\83H\83\8b\83_\82Ì\8bæ\90Ø\82è\8bL\8d\86\82Í '\' \82Å\82à '/' \82Å\82à\8d\\82¢\82Ü\82¹\82ñ\r
470 \81y\97á\81z\r
471 \81Epath="b:\dir\fname.txt" \82È\82ç "b:\dir"\r
472 \81Epath="b:\dir\subdir\" \82È\82ç "b:\dir"\r
473 \81Epath="step\" \82È\82ç ""\r
474 \81Epath="step" \82È\82ç ""\r
475 ************************************************************************/\r
476 wchar_t*  StrX_W_cutFName( wchar_t* path )\r
477 {\r
478   wchar_t*  p;\r
479   wchar_t*  p_last;\r
480 \r
481   /* \90â\91Î\83p\83X\82È\82ç\83\8b\81[\83g\82Ì\88Ê\92u\82ð\92T\82· */\r
482   p = path;\r
483   while ( *p != L':' && *p != L'/' && *p != L'\\' && *p != L'\0' )  p++;\r
484   if ( *p == L':' ) {\r
485     while ( *p != L'/' && *p != L'\\' ) {\r
486       if ( *p == L'\0' )  return  path;\r
487       p++;\r
488     }\r
489   }\r
490   else\r
491     p = NULL;\r
492 \r
493 \r
494   /* \96\96\94ö\82Ì\83f\83B\83\8c\83N\83g\83\8a\8bæ\90Ø\82è\8bL\8d\86\82ð\8eæ\82è\8f\9c\82­ */\r
495   p_last = wcsrchr( path, L'\0' ) - 1;\r
496   if ( *p_last == L'\\' || *p_last == L'/' ) {\r
497     *p_last = '\0';  p_last --;\r
498   }\r
499 \r
500   /* \83t\83@\83C\83\8b\96¼\82Ì\91O\82Ì\83f\83B\83\8c\83N\83g\83\8a\8bæ\90Ø\82è\8bL\8d\86\82ð\92T\82· */\r
501   while ( *p_last != L'/' && *p_last != L'\\' && p_last > path )  p_last --;\r
502 \r
503 \r
504   /* \83\8b\81[\83g\82Å\82È\82¢\8cÀ\82è\81A\82¢\82¿\82Î\82ñ\8cã\82ë\82Ì\83f\83B\83\8c\83N\83g\83\8a\8bæ\90Ø\82è\8bL\8d\86\82ð '\0'\82É\82·\82é */\r
505   if ( p == NULL || p < p_last ) {\r
506     *p_last = L'\0';\r
507   }\r
508 \r
509   return  path;\r
510 }\r
511 \r
512 \r
513 \r
514  \r
515 /***********************************************************************\r
516   <<< [StrX_W_cpy] \83\8f\83C\83h\95\8e\9a\97ñ\82ð\83R\83s\81[\82·\82é >>> \r
517 \81y\88ø\90\94\81z\r
518   \81Ewchar_t* dst;       \83R\83s\81[\90æ\r
519   \81Ewchar_t* src;       \83R\83s\81[\8c³\r
520   \81Eint      dst_size;  dst \82Ì\83\81\83\82\83\8a\83T\83C\83Y\81i\83o\83C\83g\81j\r
521 \81y\95â\91«\81z\r
522 \81Edst \82Ì\97e\97Ê\82ð\92´\82¦\82é\82Æ\81AStrX_Err_BufOver \83G\83\89\81[\82É\82È\82è\82Ü\82·\81B\r
523 ************************************************************************/\r
524 void  StrX_W_cpy( wchar_t* dst, const wchar_t* src, int dst_size )\r
525 {\r
526   int  src_len = wcslen( src ) * 2;\r
527 \r
528   if ( src_len >= dst_size - 1 ) {  /* \97á src="a" \81¨ src_len = 2, dst_size = 3 \82Å\83G\83\89\81[ */\r
529     if ( dst_size > 0 ) {\r
530       memcpy( dst, src, (dst_size - 2) & ~1 );\r
531       *(wchar_t*)( (char*) dst + dst_size - 2 ) = L'\0';\r
532     }\r
533     error2_1( StrX_Err_BufOver, "BufOver:%p", dst );\r
534   }\r
535   else\r
536     wcscpy( dst, src );\r
537 }\r
538 \r
539 \r
540 \r
541  \r
542 /*-------------------------------------------------------------------------*/\r
543 /* \81\9f<<<< (CmpFolder) \94ä\8ar\82·\82é\83t\83H\83\8b\83_\81i\95Ð\95û\81j >>>> */ \r
544 /*-------------------------------------------------------------------------*/\r
545 \r
546 \r
547  \r
548 /***********************************************************************\r
549   <<< [CmpFolder_init] >>> \r
550 ************************************************************************/\r
551 void  CmpFolder_init( CmpFolder* m, const wchar_t* path )\r
552 {\r
553   if ( _waccess( path, 0 ) != 0 )  error();\r
554 \r
555   m->base = malloc( ( wcslen( path ) + 1 ) * 2 );\r
556   wcscpy( m->base, path );\r
557   m->path = NULL;\r
558   m->nFile = 0;\r
559   m->stat = NULL;\r
560   m->folder = NULL;\r
561   m->nFolder = 0;\r
562 }\r
563 \r
564 \r
565 \r
566  \r
567 /***********************************************************************\r
568   <<< [CmpFolder_finish] >>> \r
569 ************************************************************************/\r
570 void  CmpFolder_finish( CmpFolder* m )\r
571 {\r
572   int  i;\r
573 \r
574   free( m->base );\r
575   if ( m->stat != NULL )  free( m->stat );\r
576 \r
577   for ( i = 0; i < m->nFile; i++ )\r
578     free( m->path[i] );\r
579 \r
580   for ( i = 0; i < m->nFolder; i++ )\r
581     free( m->folder[i] );\r
582 }\r
583 \r
584 \r
585 \r
586  \r
587 /***********************************************************************\r
588   <<< [CmpFolder_scan] >>> \r
589 \81y\95â\91«\81z\r
590 \81E\83J\83\8c\83\93\83g\83t\83H\83\8b\83_\82Ì m->name \83T\83u\83t\83H\83\8b\83_\82ð\83X\83L\83\83\83\93\82µ\82Ü\82·\81B\r
591 ************************************************************************/\r
592 int  CmpFolder_scan_sub( void* obj, const wchar_t* abs_path, const wchar_t* step_path, const wchar_t* fname );\r
593 \r
594 \r
595 void  CmpFolder_scan( CmpFolder* m )\r
596 {\r
597   int  i;\r
598 \r
599   for ( i = 0; i < m->nFile; i++ )\r
600     free( m->path[i] );\r
601 \r
602   for ( i = 0; i < m->nFolder; i++ )\r
603     free( m->folder[i] );\r
604 \r
605   m->nFile = 0;\r
606   m->nFolder = 0;\r
607   FileX_callByNestFindW( m->base, m, CmpFolder_scan_sub );\r
608 }\r
609 \r
610 \r
611 \r
612 int  CmpFolder_scan_sub( void* obj, const wchar_t* abs_path, const wchar_t* step_path, const wchar_t* fname )\r
613 {\r
614   CmpFolder*  m = (CmpFolder*) obj;\r
615   wchar_t**  p;\r
616 \r
617 \r
618   /* \83t\83@\83C\83\8b\83p\83X\82ð\93o\98^\82·\82é */\r
619   m->nFile ++;\r
620   m->path = (wchar_t**) realloc( m->path, m->nFile * sizeof(wchar_t*) );\r
621 \r
622   p = &m->path[ m->nFile - 1 ];\r
623   *p = malloc( ( wcslen( step_path ) + 1 ) * 2 );\r
624   wcscpy( *p, step_path );\r
625 \r
626 \r
627   /* \83t\83H\83\8b\83_\83p\83X\82ð\93o\98^\82·\82é */\r
628   {\r
629     int  i;\r
630     wchar_t  path[4096];\r
631 \r
632     StrX_W_cpyFolder( path, step_path, sizeof(path) );\r
633     for ( i = 0; i < m->nFolder; i++ )\r
634       if ( wcscmp( path, m->folder[i] ) == 0 )  break;\r
635 \r
636     if ( i == m->nFolder && path[0] != L'\0' ) {\r
637       m->nFolder ++;\r
638       m->folder = (wchar_t**) realloc( m->folder, m->nFolder * sizeof(wchar_t*) );\r
639 \r
640       p = &m->folder[ m->nFolder - 1 ];\r
641       *p = malloc( ( wcslen( path ) + 1 ) * 2 );\r
642       wcscpy( *p, path );\r
643 \r
644       for ( p;  p > m->folder;  p-- ) {\r
645         if ( wcslen( *p ) >= wcslen( *(p - 1) ) )  break;\r
646         { wchar_t*  w = *p;  *p = *(p - 1);  *(p - 1) = w; }\r
647       }\r
648     }\r
649   }\r
650 \r
651   return  0;\r
652 }\r
653 \r
654 \r
655 \r
656  \r
657 /***********************************************************************\r
658   <<< [CmpFolder_resetStat] m->stat \94z\97ñ\82ð\8am\95Û\82µ 0 \82Å\8f\89\8aú\89»\82µ\82Ü\82· >>> \r
659 ************************************************************************/\r
660 void  CmpFolder_resetStat( CmpFolder* m )\r
661 {\r
662   m->stat = realloc( m->stat, m->nFile * sizeof(*m->stat) );\r
663 \r
664   memset( m->stat, 0, m->nFile * sizeof(*m->stat) );\r
665 }\r
666 \r
667  \r
668 /***********************************************************************\r
669   <<< [CmpFolder_refStat] \83t\83@\83C\83\8b\82É\91Î\89\9e\82µ\82½ m->stat \82ð\8eQ\8fÆ\82µ\82Ü\82· >>> \r
670 \81y\88ø\90\94\81z\r
671   \81Ewchat_t*  step_path;  \83t\83@\83C\83\8b\83p\83X\81i\83x\81[\83X\82©\82ç\82Ì\91\8a\91Î\81j\r
672   \81Echar*  \95Ô\82è\92l;        step_path \82É\91Î\89\9e\82µ\82½\94C\88Ó\82Ì1\83o\83C\83g\97Ì\88æ(stat\93à)\82Ì\83A\83h\83\8c\83X\r
673 ************************************************************************/\r
674 char*  CmpFolder_refStat( CmpFolder* m, const wchar_t* step_path )\r
675 {\r
676   int  i;\r
677 \r
678   if ( m->stat == NULL )  error();\r
679 \r
680   for ( i = 0; i < m->nFile;  i++ ) {\r
681     if ( wcscmp( m->path[i], step_path ) == 0 )  break;\r
682   }\r
683   if ( i == m->nFile )  return  NULL;\r
684   else                  return  m->stat + i;\r
685 }\r
686 \r
687 \r
688 \r
689  \r