]> Creatis software - bbtk.git/blob - packages/std/src/bbstdFilesFromDirectory.cxx
#3474 bug profile_creatools in Linux/Win32
[bbtk.git] / packages / std / src / bbstdFilesFromDirectory.cxx
1 /*
2  # ---------------------------------------------------------------------
3  #
4  # Copyright (c) CREATIS (Centre de Recherche en Acquisition et Traitement de l'Image
5  #                        pour la SantÈ)
6  # Authors : Eduardo Davila, Frederic Cervenansky, Claire Mouton
7  # Previous Authors : Laurent Guigues, Jean-Pierre Roux
8  # CreaTools website : www.creatis.insa-lyon.fr/site/fr/creatools_accueil
9  #
10  #  This software is governed by the CeCILL-B license under French law and
11  #  abiding by the rules of distribution of free software. You can  use,
12  #  modify and/ or redistribute the software under the terms of the CeCILL-B
13  #  license as circulated by CEA, CNRS and INRIA at the following URL
14  #  http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
15  #  or in the file LICENSE.txt.
16  #
17  #  As a counterpart to the access to the source code and  rights to copy,
18  #  modify and redistribute granted by the license, users are provided only
19  #  with a limited warranty  and the software's author,  the holder of the
20  #  economic rights,  and the successive licensors  have only  limited
21  #  liability.
22  #
23  #  The fact that you are presently reading this means that you have had
24  #  knowledge of the CeCILL-B license and that you accept its terms.
25  # ------------------------------------------------------------------------ */
26
27
28 #include "bbstdFilesFromDirectory.h"
29 #include "bbstdPackage.h"
30 #include <string>
31
32 #ifdef _MSC_VER
33    #include <windows.h>
34    #include <direct.h>
35 #else
36    #include <dirent.h>   
37    #include <sys/types.h>
38 #endif
39
40 #include <sys/stat.h>  //stat function
41
42 namespace bbstd
43 {
44
45 BBTK_ADD_BLACK_BOX_TO_PACKAGE(std,FilesFromDirectory)
46 BBTK_BLACK_BOX_IMPLEMENTATION(FilesFromDirectory,bbtk::AtomicBlackBox);
47
48 void FilesFromDirectory::Process()
49 {
50         Filenames.clear();
51         SimpleFilenames.clear();
52         
53         if (bbGetInputActive()==true)
54         {
55                 if (bbGetInputIn()!="")
56                 {
57                         DirName         = bbGetInputIn();
58                         /*int nbFiles = */ Explore(DirName, bbGetInputRecursive(), bbGetInputRecursiveLevel() );
59                         CleanFilenames( DirName );
60                 } // if In
61         } // Active
62         bbSetOutputOut(Filenames);   
63         bbSetOutputOutSimple(SimpleFilenames);   
64 }
65
66 void FilesFromDirectory::bbUserSetDefaultValues()
67 {
68     bbSetInputActive(true);
69     bbSetInputIn(".");
70     bbSetInputRecursive(false);  
71     bbSetInputType(0);  
72     bbSetInputRecursiveLevel(999);  
73 }
74
75 void FilesFromDirectory::bbUserInitializeProcessing() 
76
77 }
78
79 void FilesFromDirectory::bbUserFinalizeProcessing() 
80 {
81 }
82   
83 /**
84  * \brief   Add a SEPARATOR to the end of the name if necessary
85  * @param   pathname file/directory name to normalize 
86  */
87 std::string FilesFromDirectory::NormalizePath(std::string const &pathname)
88 {
89 #ifdef _WIN32
90    const char FILESEPARATOR = '\\';
91 #else
92    const char FILESEPARATOR = '/';
93 #endif
94
95    std::string name = pathname;
96    int size = name.size();
97
98    if (!((name[size-1]=='/')||(name[size-1]=='\\')))
99    {
100       name += FILESEPARATOR;
101    }
102    return name;
103
104
105 /**
106  * \brief   Explores a directory with possibility of recursion
107  *          return number of files read
108  * @param  dirpath   directory to explore
109  * @param  recursive whether we want recursion or not
110  */
111
112
113
114 int FilesFromDirectory::Explore(std::string const &dirpath, bool recursive, int recursiveLevel)
115 {
116         int             numberOfFiles           = 0;
117
118 if (recursiveLevel>=0){
119
120         std::string dirName                     = NormalizePath(dirpath);
121         int             tmpNumberOfFiles;
122         std::string fileName;
123 #ifdef _MSC_VER
124         WIN32_FIND_DATA fileData;
125         //assert( dirName[dirName.size()-1] == '' );
126         HANDLE hFile = FindFirstFile((dirName+"*").c_str(), &fileData);
127
128         for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
129        b = FindNextFile(hFile, &fileData))
130         {
131       fileName = fileData.cFileName;
132       if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
133       {
134          // Need to check for . and .. to avoid infinite loop
135          if ( fileName != "." && fileName != ".." && recursive )
136          {
137                         if (bbGetInputType()==1)
138                         {
139                         std::string temp = dirName+fileName;
140                         Filenames.push_back(temp);       
141                         numberOfFiles++;
142                         } // Type ALL_directories
143
144                         tmpNumberOfFiles        =       Explore(dirName+fileName, recursive,recursiveLevel-1);
145                         if ((bbGetInputType()==2)&&tmpNumberOfFiles==0)
146                         {
147                         std::string temp = dirName+fileName;
148                         Filenames.push_back(temp);       
149                         numberOfFiles++;
150                         } // Type Lsast_directories
151                         
152                         numberOfFiles           =       numberOfFiles + tmpNumberOfFiles;
153          } // if recursive
154          if ( fileName != "." && fileName != ".." && !recursive )
155                  {
156                         if ((bbGetInputType()==1) || (bbGetInputType()==2))
157                         {
158                         std::string temp = dirName+fileName;
159                         Filenames.push_back(temp);       
160                         numberOfFiles++;
161                         } // Type All_directories
162                 }// fileName && !recursive
163       } else  {
164 //      std::string temp = "\"" +dirName+fileName + "\"";
165         std::string temp = dirName+fileName;
166
167 /*
168         std::string::size_type spacePosition = temp.find_first_of(' ');
169                 if (spacePosition != std::string::npos) 
170                 {
171                         std::cout << "=========================================== File name : [" <<temp << 
172               "] contains space(s); Discarted !" << std::endl;
173                 temp.insert(spacePosition, "\\");
174                         continue;  /// \TODO : fix the trouble (vtk?)
175                 } // if !npos
176 */
177
178
179                 if (bbGetInputType()==0)
180                 {
181                         Filenames.push_back(temp);       
182                         numberOfFiles++;
183                 } // Type files
184
185       } // if !directory
186         } // for
187         DWORD dwError = GetLastError();
188         if (hFile != INVALID_HANDLE_VALUE) 
189         {
190                 FindClose(hFile);
191         }// hFile
192         if (dwError != ERROR_NO_MORE_FILES) 
193         {
194       LPVOID lpMsgBuf;
195       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
196                     FORMAT_MESSAGE_FROM_SYSTEM|
197                     FORMAT_MESSAGE_IGNORE_INSERTS,
198                     NULL,GetLastError(),
199                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
200                     (LPTSTR) &lpMsgBuf,0,NULL);
201
202       //gdcmErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
203       //             <<" for the directory : "<<dirName);
204       return -1;
205         } // dwError
206
207 #else
208   // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
209   // work on debian for example
210
211         DIR* dir = opendir( dirName.c_str() );
212         if (!dir)
213         {
214                 return 0;
215         }
216
217    // According to POSIX, the dirent structure contains a field char d_name[]
218    // of unspecified size, with at most NAME_MAX characters preceeding the
219    // terminating null character. Use of other fields will harm the  porta-
220    // bility of your programs.
221
222         struct stat     buf;
223         dirent                  *d;
224         for (d = readdir(dir); d; d = readdir(dir))
225         {
226         fileName = dirName + d->d_name;
227         std::string temp = fileName;
228         if( stat(fileName.c_str(), &buf) != 0 )
229         {
230                  //gdcmErrorMacro( strerror(errno) );
231         } // stat
232         if ( S_ISREG(buf.st_mode) )    //is it a regular file?
233         {
234                 if ( d->d_name[0]!='.')
235                 {
236
237 /*
238                         std::string::size_type  spacePosition = temp.find_first_of(' ');
239                 if (spacePosition != std::string::npos)
240                         {
241                                         std::cout << "=========================================== File name : [" <<temp << 
242                                 "] contains space(s); Discarted !" << std::endl;
243                         temp.insert(spacePosition, "\\");
244                                         continue;   /// \TODO : fix the trouble (vtk?)
245                 } // if spacePosition
246 */
247
248                                 if (bbGetInputType()==0)
249                                 {
250                         Filenames.push_back(temp);       
251                                 numberOfFiles++;
252                                 } // Type files
253                 } // d_name
254         } else if ( S_ISDIR(buf.st_mode) ) {  //directory?
255                 if ( (d->d_name[0]!='.') && recursive ) //we also skip hidden files
256                 {
257                                 if (bbGetInputType()==1)
258                                 {
259                         Filenames.push_back(fileName);   
260                                 numberOfFiles++;
261                                 } // Type All_directories
262
263                                 tmpNumberOfFiles        = Explore( fileName, recursive, recursiveLevel-1);
264                                 if ((bbGetInputType()==2)&&tmpNumberOfFiles==0)
265                                 {
266                                         Filenames.push_back(fileName);   
267                                 numberOfFiles++;
268                                 } // Type Lsast_directories
269                         numberOfFiles           = numberOfFiles+tmpNumberOfFiles;
270                 }// d_name && recursive
271                 if ( (d->d_name[0]!='.') && !recursive ) { //we also skip hidden files
272                                 if ((bbGetInputType()==1) || (bbGetInputType()==2))
273                                 {
274                         Filenames.push_back(fileName);   
275                                 numberOfFiles++;
276                                 } // Type All_directories
277                         
278                         }// d_name && !recursive
279
280                 } else {
281                 //gdcmErrorMacro( "Unexpected error" );
282                 return -1;
283         } // Regular FILE
284    }
285    if( closedir(dir) != 0 )
286    {
287       //gdcmErrorMacro( strerror(errno) );
288    }// closedir
289 #endif
290
291 } // if recursiveLevel 
292
293         return numberOfFiles;
294 }
295
296
297 //------------------------------------------------------------------------------
298 void FilesFromDirectory::CleanFilenames( std::string basePath )
299 {
300         std::string tmpString;
301         int i,ii,sizeFilenames  = Filenames.size();
302         int j,sizeFileEnd               = bbGetInputFileEnd().size();
303         int okEraseElement;
304         int posStr;
305 //Selecting just the files in the FileEnd List
306         if (bbGetInputFileEnd().size()!=0)
307         {
308                 for (i=sizeFilenames-1; i>=0; i--)
309                 {
310                         okEraseElement = 0;
311                         for (j=0; j<sizeFileEnd; j++)
312                         {
313                                 posStr=(Filenames[i].length()) - (bbGetInputFileEnd()[j]).length();
314                                 if (posStr>=0)
315                                 {
316                                         std::string tmp=Filenames[i].substr( posStr ) ;
317                                         if (bbGetInputFileEnd()[j].compare( tmp )==0 )
318                                         {
319                                                 okEraseElement++;
320                                         } // if FileEnd
321                                 }// if posStr
322                         } // for j                                      
323
324                         if (okEraseElement==0) 
325                         { 
326                                 Filenames.erase( Filenames.begin()+i );
327                         }
328                 } // for i      
329         } // if FileEnd !=0
330         sizeFilenames = Filenames.size();
331 // Cleanning paths with spaces  
332         for (i=0; i<sizeFilenames; i++)
333         {
334                 tmpString=Filenames[i];
335                 std::string::size_type  spacePosition = tmpString.find_first_of(' ');
336                 if (spacePosition != std::string::npos)
337                 {
338                         std::cout << "=========================================== File name : [" <<tmpString << 
339                 "] contains space(s); Discarted !" << std::endl;
340                         tmpString.insert(spacePosition, "\\");
341                         Filenames[i]=tmpString;
342 //                      continue;   /// \TODO : fix the trouble (vtk?)
343                 } // if spacePosition
344         }
345
346 // Alphabetical order   
347         for (i=0; i<sizeFilenames; i++)
348         {
349         for (ii=i; ii<sizeFilenames; ii++)
350                 {
351                         if (Filenames[i]>Filenames[ii]) 
352                 {
353                         tmpString=Filenames[i];
354                         Filenames[i]=Filenames[ii];
355                         Filenames[ii]=tmpString;
356                 } // if 
357         } // for ii
358         } // for i
359 // Creating SimpleFilenames
360         unsigned int lenghtBasePath = basePath.length();
361         for (i=0; i<sizeFilenames; i++)
362         {
363                 SimpleFilenames.push_back( Filenames[i].substr( lenghtBasePath ) );
364         } // for i
365 }
366
367
368
369
370 /*
371
372 int FilesFromDirectory::Explore(std::string const &dirpath, bool recursive)
373 {
374    Filenames.clear();
375    int numberOfFiles = 0;
376    std::string fileName;
377    std::string dirName = NormalizePath(dirpath);
378 #ifdef _MSC_VER
379    WIN32_FIND_DATA fileData;
380    //assert( dirName[dirName.size()-1] == '' );
381    HANDLE hFile = FindFirstFile((dirName+"*").c_str(), &fileData);
382
383    for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
384        b = FindNextFile(hFile, &fileData))
385    {
386       fileName = fileData.cFileName;
387       if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
388       {
389          // Need to check for . and .. to avoid infinite loop
390          if ( fileName != "." && fileName != ".." && recursive )
391          {
392             numberOfFiles += Explore(dirName+fileName, recursive);
393          }
394       }
395       else
396       {
397 //         std::string temp = "\"" +dirName+fileName + "\"";
398          std::string temp = dirName+fileName;
399          std::string::size_type spacePosition = temp.find_first_of(' ');
400                  if (spacePosition != std::string::npos) 
401          {
402    std::cout << "=========================================== File name : [" <<temp << 
403               "] contains space(s); Discarted !" << std::endl;
404             temp.insert(spacePosition, "\\");
405    continue;  /// \TODO : fix the trouble (vtk?)
406          }      
407          Filenames.push_back(temp);
408          numberOfFiles++;
409       }
410    }
411    DWORD dwError = GetLastError();
412    if (hFile != INVALID_HANDLE_VALUE) 
413       FindClose(hFile);
414    if (dwError != ERROR_NO_MORE_FILES) 
415    {
416       LPVOID lpMsgBuf;
417       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
418                     FORMAT_MESSAGE_FROM_SYSTEM|
419                     FORMAT_MESSAGE_IGNORE_INSERTS,
420                     NULL,GetLastError(),
421                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
422                     (LPTSTR) &lpMsgBuf,0,NULL);
423
424       //gdcmErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
425       //             <<" for the directory : "<<dirName);
426       return -1;
427    }
428
429 #else
430   // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
431   // work on debian for example
432
433    DIR* dir = opendir(dirName.c_str());
434    if (!dir)
435    {
436       return 0;
437    }
438
439    // According to POSIX, the dirent structure contains a field char d_name[]
440    // of unspecified size, with at most NAME_MAX characters preceeding the
441    // terminating null character. Use of other fields will harm the  porta-
442    // bility of your programs.
443
444    struct stat buf;
445    dirent *d;
446    for (d = readdir(dir); d; d = readdir(dir))
447    {
448       fileName = dirName + d->d_name;
449       std::string temp = fileName;
450       if( stat(fileName.c_str(), &buf) != 0 )
451       {
452          //gdcmErrorMacro( strerror(errno) );
453       }
454       if ( S_ISREG(buf.st_mode) )    //is it a regular file?
455       {
456          if ( d->d_name[0]!='.')
457          {
458          
459              std::string::size_type  spacePosition = temp.find_first_of(' ');
460              if (spacePosition != std::string::npos)
461              {
462    std::cout << "=========================================== File name : [" <<temp << 
463               "] contains space(s); Discarted !" << std::endl;
464                  temp.insert(spacePosition, "\\");
465    continue;   /// \TODO : fix the trouble (vtk?)
466              }
467              Filenames.push_back(temp);  
468              numberOfFiles++;
469          }
470       }
471       else if ( S_ISDIR(buf.st_mode) ) //directory?
472       {
473          if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
474          {
475             numberOfFiles += Explore( fileName, recursive);
476          }
477       }
478       else
479       {
480          //gdcmErrorMacro( "Unexpected error" );
481          return -1;
482       }
483    }
484    if( closedir(dir) != 0 )
485    {
486       //gdcmErrorMacro( strerror(errno) );
487    }
488 #endif
489
490   std::string tmpString;
491   int i,ii,sizeFilenames = Filenames.size();
492   for (i=0; i<sizeFilenames; i++)
493   {
494     for (ii=i; ii<sizeFilenames; ii++)
495     {
496         if (Filenames[i]>Filenames[ii]) 
497         {
498           tmpString=Filenames[i];
499           Filenames[i]=Filenames[ii];
500           Filenames[ii]=tmpString;
501         } // if 
502     } // for ii
503   } // for i
504
505   return numberOfFiles;
506 }
507 */
508
509 }
510 // EO namespace bbstd
511
512