c5b32d982046dd333adc74d19b943d88cf6a5316
[occt.git] / src / OSD / OSD_FileIterator.cxx
1 // Copyright (c) 1998-1999 Matra Datavision
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #ifndef _WIN32
16
17
18 #include <OSD_File.hxx>
19 #include <OSD_FileIterator.hxx>
20 #include <OSD_OSDError.hxx>
21 #include <OSD_Path.hxx>
22 #include <OSD_WhoAmI.hxx>
23 #include <TCollection_AsciiString.hxx>
24
25 #include <dirent.h>
26 #include <stdio.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 # define NAMLEN(dirent) strlen((dirent)->d_name)
30 # ifdef VMS
31 extern char *vmsify PARAMS ((char *name, int type));
32 # endif
33
34 /* In GNU systems, <dirent.h> defines this macro for us.  */
35 #ifdef _D_NAMLEN
36 # undef NAMLEN
37 # define NAMLEN(d) _D_NAMLEN(d)
38 #endif
39
40 #if (defined (POSIX) || defined (VMS) || defined (WINDOWS32)) && !defined (__GNU_LIBRARY__)
41 /* Posix does not require that the d_ino field be present, and some
42    systems do not provide it. */
43 # define REAL_DIR_ENTRY(dp) 1
44 # define FAKE_DIR_ENTRY(dp)
45 #else
46 # define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
47 # define FAKE_DIR_ENTRY(dp) (dp->d_ino = 1)
48 #endif /* POSIX */
49
50 //const OSD_WhoAmI Iam = OSD_WFileIterator;
51
52
53 OSD_FileIterator::OSD_FileIterator() {
54  myDescr = NULL ;
55 }
56
57 OSD_FileIterator::OSD_FileIterator(const OSD_Path& where,
58                                    const TCollection_AsciiString& Mask){
59  myDescr = NULL ;
60  Initialize(where, Mask) ;
61 }
62
63 // For Windows NT compatibility
64 void OSD_FileIterator :: Destroy () {}
65
66 void OSD_FileIterator::Initialize(const OSD_Path& where,
67                                    const TCollection_AsciiString& Mask){
68  myFlag = Standard_False;
69  where.SystemName(myPlace);
70  if (myPlace.Length()==0) myPlace = ".";
71  myMask = Mask;
72  if (myDescr) {
73    closedir((DIR *)myDescr) ;
74    myDescr = NULL ;
75  }
76  myInit = 1 ;
77 }
78
79 // Is there another file entry ?
80
81 Standard_Boolean OSD_FileIterator::More(){
82  if (myInit) {
83    myInit = 0 ;
84    myDescr = (Standard_Address) opendir(myPlace.ToCString()); 
85    if (myDescr) {            // LD : Si repertoire inaccessible retourner False
86      myFlag = Standard_True;
87      myInit = 0 ;
88      Next();          // Now find first entry
89    }
90  }
91  return (myFlag);
92 }
93
94 // Private :  See if file name matches with a mask (like "*.c")
95
96 static int strcmp_joker(const char *Mask,const char *Name)
97 {
98   const char *p, *s ;
99
100   for(p = Mask,s = Name ; *p && *p != '*' ; p++,s++)
101     if (*p != *s) return 0 ;
102
103   if (!*p) return !(*s) ;
104   while (*p == '*') p++ ;
105   if (!*p) return 1 ;
106   for (;*s; s++)
107     if (strcmp_joker(p,s)) return 1 ;
108   return 0 ;
109 }
110
111 #if 0
112     // LD : ancienne version.
113
114 #define TRUE  1
115 #define FALSE 0
116 #define NO_MASK '*'
117
118 static int strcmp_joker(char *fileMask,char *fileName)
119 {
120     char *sauve_fileMask,*sauve_fileName;
121     int compare_result;
122     int beginning = 1;   // 0 if first character is a joker, otherwise 1
123
124     while (*fileName) {        // Test end of AsciiString
125
126      if (*fileMask == NO_MASK) {
127       beginning = 0;
128
129       while(*fileMask == NO_MASK) fileMask++;
130
131       if (*fileMask) {
132        while(*fileName && 
133              *fileName != *fileMask) 
134         fileName++;
135
136        sauve_fileMask = fileMask;  // Save strings
137        sauve_fileName = fileName;
138       }
139       else return(0);   // fileMask ends with a joker
140
141      }
142      else { // Compare two characters
143       compare_result = *fileMask++ - *fileName++;
144
145       if (compare_result != 0) 
146        if (beginning) 
147         return (compare_result); /* 1ere chaine pas de joker au debut */
148        else {  // Look ahead for same string
149         fileMask = sauve_fileMask;
150         fileName = ++sauve_fileName;
151         while(*fileName && 
152               *fileName != *fileMask)
153          fileName++;
154         sauve_fileName = fileName;
155        }
156
157     }    
158
159    }    
160
161    while(*fileMask == NO_MASK) fileMask++;
162    return(*fileMask - *fileName);
163 }
164 #endif
165
166 // Find next file entry in current directory
167
168 void OSD_FileIterator::Next(){
169 int again = 1;
170 struct stat stat_buf;
171 char full_name[255];
172
173  myFlag = 0;   // Initialize to nothing found
174
175  do {
176     myEntry = readdir((DIR *)myDescr);
177    
178     if (!myEntry){   // No file found
179      myEntry = NULL;              // Keep pointer clean
180      myFlag = Standard_False;   // No more files/directory
181      closedir((DIR *)myDescr) ;       // so close directory
182      myDescr = NULL;
183      again = 0;
184     }
185     else {
186      if (!strcmp(((struct dirent *)myEntry)->d_name,".")) continue;
187      if (!strcmp(((struct dirent *)myEntry)->d_name,"..")) continue;
188
189      // Is it a file ?
190
191      sprintf(full_name,"%s/%s",myPlace.ToCString(),
192              ((struct dirent *)myEntry)->d_name);                // LD debug
193 #ifdef OCCT_DEBUG
194      cout << "Place : " << myPlace << endl;
195      cout << "FName : " << full_name << endl;
196 #endif
197      stat(full_name, &stat_buf);
198      if (S_ISREG(stat_buf.st_mode))   // LD : Ensure me it's a regular file
199       if (strcmp_joker(myMask.ToCString(), ((struct dirent *)myEntry)->d_name)){
200                                                          // Does it follow mask ?
201        myFlag = Standard_True;
202        again = 0;
203       }
204     }
205
206  } while (again);
207
208 }
209
210 // Get Name of selected file
211
212 OSD_File OSD_FileIterator::Values(){
213 OSD_Path thisvalue;
214 TCollection_AsciiString Name;
215 TCollection_AsciiString Ext;
216 Standard_Integer position;
217
218  if (myEntry) Name = ((struct dirent *)myEntry)->d_name ;
219
220  position = Name.Search(".");
221
222  if (position != -1){
223   Ext = Name;
224   Ext.Remove(1,position-1);
225   Name.Remove( position,Ext.Length());
226  }
227
228  thisvalue.SetValues("", "", "", "", "", Name,Ext); 
229  TheIterator.SetPath (thisvalue);
230
231  return (TheIterator);
232 }
233
234
235 void OSD_FileIterator::Reset(){
236  myError.Reset();
237 }
238
239 Standard_Boolean OSD_FileIterator::Failed()const{
240  return( myError.Failed());
241 }
242
243 void OSD_FileIterator::Perror() {
244  myError.Perror();
245 }
246
247
248 Standard_Integer OSD_FileIterator::Error()const{
249  return( myError.Error());
250 }
251
252 #else
253
254 //------------------------------------------------------------------------
255 //-------------------  Windows NT sources for OSD_FileIterator -----------
256 //------------------------------------------------------------------------
257
258 #define STRICT
259 #include <windows.h>
260
261
262 #include <OSD_File.hxx>
263 #include <OSD_FileIterator.hxx>
264 #include <OSD_OSDError.hxx>
265 #include <OSD_Path.hxx>
266 #include <TCollection_AsciiString.hxx>
267 #include <TCollection_ExtendedString.hxx>
268
269 #define _FD (  ( PWIN32_FIND_DATAW )myData  )
270
271 void _osd_wnt_set_error ( OSD_Error&, OSD_WhoAmI, ... );
272
273 OSD_FileIterator :: OSD_FileIterator (
274                      const OSD_Path&                where,
275                      const TCollection_AsciiString& Mask
276                     ) {
277
278  myFlag   = Standard_False;
279  myHandle = INVALID_HANDLE_VALUE;
280
281  where.SystemName ( myPlace );
282
283  if (  myPlace.Length () == 0  ) myPlace = ".";
284
285  myMask = Mask;
286  myData = NULL;
287
288 }  // end constructor
289
290 void OSD_FileIterator :: Destroy () {
291
292  if ( myData != NULL ) HeapFree (  GetProcessHeap (), 0, myData  );
293
294  if (  myHandle != INVALID_HANDLE_VALUE  )
295
296   FindClose (  ( HANDLE )myHandle  );
297
298 }  // end  OSD_DirectoryIterator :: Destroy
299
300 Standard_Boolean OSD_FileIterator :: More () {
301
302  if (  myHandle == INVALID_HANDLE_VALUE  ) {
303  
304   TCollection_AsciiString wc = myPlace + "/" + myMask;
305
306   myData = HeapAlloc (
307             GetProcessHeap (), HEAP_GENERATE_EXCEPTIONS, sizeof ( WIN32_FIND_DATAW )
308            );
309
310   // make wchar_t string from UTF-8
311   TCollection_ExtendedString wcW(wc);
312   myHandle = FindFirstFileW ((const wchar_t*)wcW.ToExtString(), (PWIN32_FIND_DATAW)myData);
313
314   if (  myHandle == INVALID_HANDLE_VALUE  )
315   
316    _osd_wnt_set_error ( myError, OSD_WDirectoryIterator );
317   
318   else {
319   
320    myFlag      = Standard_True;
321    myFirstCall = Standard_True;
322
323    Next ();
324
325   }  // end else
326   
327  } else if ( !myFlag ) {
328  
329   FindClose (  ( HANDLE )myHandle  );
330   myHandle = INVALID_HANDLE_VALUE;
331  
332  }  // end if
333
334  return myFlag;
335
336 }  // end OSD_FileIterator :: More
337
338 void OSD_FileIterator :: Next () {
339
340  if (  myFirstCall && ( _FD -> dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )  ||
341        !myFirstCall
342  ) {
343  
344   do {
345   
346    if (   !FindNextFileW (  ( HANDLE )myHandle, _FD  )   ) {
347    
348     myFlag = Standard_False;
349
350     break;
351    
352    }  // end if
353   
354   } while (  ( _FD -> dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )  );
355  
356  }  // end if
357  
358  myFirstCall = Standard_False;
359
360 }  // end OSD_FileIterator :: Next
361
362 OSD_File OSD_FileIterator :: Values () {
363
364  // make UTF-8 string
365  TCollection_AsciiString aFileName
366    (TCollection_ExtendedString( (Standard_ExtString) _FD -> cFileName) );
367  TheIterator.SetPath (   OSD_Path ( aFileName  )   );
368
369  return TheIterator;
370
371 }  // end OSD_FileIterator :: Values
372
373 Standard_Boolean OSD_FileIterator :: Failed () const {
374
375  return myError.Failed ();
376
377 }  // end OSD_FileIterator :: Failed
378
379 void OSD_FileIterator :: Reset () {
380
381  myError.Reset ();
382
383 }  // end OSD_FileIterator :: Reset
384
385 void OSD_FileIterator :: Perror () {
386
387  myError.Perror ();
388
389 }  // end OSD_FileIterator :: Perror
390
391 Standard_Integer OSD_FileIterator :: Error () const {
392
393  return myError.Error ();
394
395 }  // end  OSD_FileIterator :: Error
396
397 // For compatibility with UNIX version
398 OSD_FileIterator::OSD_FileIterator() {}
399
400 void OSD_FileIterator::Initialize(
401                        const OSD_Path&,
402                        const TCollection_AsciiString&){}
403  
404 #endif