]> Creatis software - bbtk.git/blob - packages/std/src/bbstdFilesFromDirectory.cxx
#3385 BBTK Bug New Normal - box FilesFromDirectory CreateImage InvertCrop ComboBox...
[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         if (bbGetInputIn()!="")
53         {
54                 DirName         = bbGetInputIn();
55                 /*int nbFiles = */ Explore(DirName, bbGetInputRecursive(), bbGetInputRecursiveLevel() );
56                 CleanFilenames( DirName );
57         } // if In
58         bbSetOutputOut(Filenames);   
59         bbSetOutputOutSimple(SimpleFilenames);   
60 }
61
62 void FilesFromDirectory::bbUserSetDefaultValues()
63 {
64     bbSetInputIn(".");
65     bbSetInputRecursive(false);  
66     bbSetInputType(0);  
67     bbSetInputRecursiveLevel(999);  
68 }
69
70 void FilesFromDirectory::bbUserInitializeProcessing() 
71
72 }
73
74 void FilesFromDirectory::bbUserFinalizeProcessing() 
75 {
76 }
77   
78 /**
79  * \brief   Add a SEPARATOR to the end of the name if necessary
80  * @param   pathname file/directory name to normalize 
81  */
82 std::string FilesFromDirectory::NormalizePath(std::string const &pathname)
83 {
84 #ifdef _WIN32
85    const char FILESEPARATOR = '\\';
86 #else
87    const char FILESEPARATOR = '/';
88 #endif
89
90    std::string name = pathname;
91    int size = name.size();
92
93    if (!((name[size-1]=='/')||(name[size-1]=='\\')))
94    {
95       name += FILESEPARATOR;
96    }
97    return name;
98
99
100 /**
101  * \brief   Explores a directory with possibility of recursion
102  *          return number of files read
103  * @param  dirpath   directory to explore
104  * @param  recursive whether we want recursion or not
105  */
106
107
108
109 int FilesFromDirectory::Explore(std::string const &dirpath, bool recursive, int recursiveLevel)
110 {
111         int             numberOfFiles           = 0;
112
113 if (recursiveLevel>=0){
114
115         std::string dirName                     = NormalizePath(dirpath);
116         int             tmpNumberOfFiles;
117         std::string fileName;
118 #ifdef _MSC_VER
119         WIN32_FIND_DATA fileData;
120         //assert( dirName[dirName.size()-1] == '' );
121         HANDLE hFile = FindFirstFile((dirName+"*").c_str(), &fileData);
122
123         for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
124        b = FindNextFile(hFile, &fileData))
125         {
126       fileName = fileData.cFileName;
127       if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
128       {
129          // Need to check for . and .. to avoid infinite loop
130          if ( fileName != "." && fileName != ".." && recursive )
131          {
132                         if (bbGetInputType()==1)
133                         {
134                         std::string temp = dirName+fileName;
135                         Filenames.push_back(temp);       
136                         numberOfFiles++;
137                         } // Type ALL_directories
138
139                         tmpNumberOfFiles        =       Explore(dirName+fileName, recursive,recursiveLevel-1);
140                         if ((bbGetInputType()==2)&&tmpNumberOfFiles==0)
141                         {
142                         std::string temp = dirName+fileName;
143                         Filenames.push_back(temp);       
144                         numberOfFiles++;
145                         } // Type Lsast_directories
146                         
147                         numberOfFiles           =       numberOfFiles + tmpNumberOfFiles;
148          } // if recursive
149          if ( fileName != "." && fileName != ".." && !recursive )
150                  {
151                         if ((bbGetInputType()==1) || (bbGetInputType()==2))
152                         {
153                         std::string temp = dirName+fileName;
154                         Filenames.push_back(temp);       
155                         numberOfFiles++;
156                         } // Type All_directories
157                 }// fileName && !recursive
158       } else  {
159 //      std::string temp = "\"" +dirName+fileName + "\"";
160         std::string temp = dirName+fileName;
161
162 /*
163         std::string::size_type spacePosition = temp.find_first_of(' ');
164                 if (spacePosition != std::string::npos) 
165                 {
166                         std::cout << "=========================================== File name : [" <<temp << 
167               "] contains space(s); Discarted !" << std::endl;
168                 temp.insert(spacePosition, "\\");
169                         continue;  /// \TODO : fix the trouble (vtk?)
170                 } // if !npos
171 */
172
173
174                 if (bbGetInputType()==0)
175                 {
176                         Filenames.push_back(temp);       
177                         numberOfFiles++;
178                 } // Type files
179
180       } // if !directory
181         } // for
182         DWORD dwError = GetLastError();
183         if (hFile != INVALID_HANDLE_VALUE) 
184         {
185                 FindClose(hFile);
186         }// hFile
187         if (dwError != ERROR_NO_MORE_FILES) 
188         {
189       LPVOID lpMsgBuf;
190       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
191                     FORMAT_MESSAGE_FROM_SYSTEM|
192                     FORMAT_MESSAGE_IGNORE_INSERTS,
193                     NULL,GetLastError(),
194                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
195                     (LPTSTR) &lpMsgBuf,0,NULL);
196
197       //gdcmErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
198       //             <<" for the directory : "<<dirName);
199       return -1;
200         } // dwError
201
202 #else
203   // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
204   // work on debian for example
205
206         DIR* dir = opendir( dirName.c_str() );
207         if (!dir)
208         {
209                 return 0;
210         }
211
212    // According to POSIX, the dirent structure contains a field char d_name[]
213    // of unspecified size, with at most NAME_MAX characters preceeding the
214    // terminating null character. Use of other fields will harm the  porta-
215    // bility of your programs.
216
217         struct stat     buf;
218         dirent                  *d;
219         for (d = readdir(dir); d; d = readdir(dir))
220         {
221         fileName = dirName + d->d_name;
222         std::string temp = fileName;
223         if( stat(fileName.c_str(), &buf) != 0 )
224         {
225                  //gdcmErrorMacro( strerror(errno) );
226         } // stat
227         if ( S_ISREG(buf.st_mode) )    //is it a regular file?
228         {
229                 if ( d->d_name[0]!='.')
230                 {
231
232 /*
233                         std::string::size_type  spacePosition = temp.find_first_of(' ');
234                 if (spacePosition != std::string::npos)
235                         {
236                                         std::cout << "=========================================== File name : [" <<temp << 
237                                 "] contains space(s); Discarted !" << std::endl;
238                         temp.insert(spacePosition, "\\");
239                                         continue;   /// \TODO : fix the trouble (vtk?)
240                 } // if spacePosition
241 */
242
243                                 if (bbGetInputType()==0)
244                                 {
245                         Filenames.push_back(temp);       
246                                 numberOfFiles++;
247                                 } // Type files
248                 } // d_name
249         } else if ( S_ISDIR(buf.st_mode) ) {  //directory?
250                 if ( (d->d_name[0]!='.') && recursive ) //we also skip hidden files
251                 {
252                                 if (bbGetInputType()==1)
253                                 {
254                         Filenames.push_back(fileName);   
255                                 numberOfFiles++;
256                                 } // Type All_directories
257
258                                 tmpNumberOfFiles        = Explore( fileName, recursive, recursiveLevel-1);
259                                 if ((bbGetInputType()==2)&&tmpNumberOfFiles==0)
260                                 {
261                                         Filenames.push_back(fileName);   
262                                 numberOfFiles++;
263                                 } // Type Lsast_directories
264                         numberOfFiles           = numberOfFiles+tmpNumberOfFiles;
265                 }// d_name && recursive
266                 if ( (d->d_name[0]!='.') && !recursive ) { //we also skip hidden files
267                                 if ((bbGetInputType()==1) || (bbGetInputType()==2))
268                                 {
269                         Filenames.push_back(fileName);   
270                                 numberOfFiles++;
271                                 } // Type All_directories
272                         
273                         }// d_name && !recursive
274
275                 } else {
276                 //gdcmErrorMacro( "Unexpected error" );
277                 return -1;
278         } // Regular FILE
279    }
280    if( closedir(dir) != 0 )
281    {
282       //gdcmErrorMacro( strerror(errno) );
283    }// closedir
284 #endif
285
286 } // if recursiveLevel 
287
288         return numberOfFiles;
289 }
290
291
292 //------------------------------------------------------------------------------
293 void FilesFromDirectory::CleanFilenames( std::string basePath )
294 {
295         std::string tmpString;
296         int i,ii,sizeFilenames  = Filenames.size();
297         int j,sizeFileEnd               = bbGetInputFileEnd().size();
298         int okEraseElement;
299         int posStr;
300 //Selecting just the files in the FileEnd List
301         if (bbGetInputFileEnd().size()!=0)
302         {
303                 for (i=sizeFilenames-1; i>=0; i--)
304                 {
305                         okEraseElement = 0;
306                         for (j=0; j<sizeFileEnd; j++)
307                         {
308                                 posStr=(Filenames[i].length()) - (bbGetInputFileEnd()[j]).length();
309                                 if (posStr>=0)
310                                 {
311                                         std::string tmp=Filenames[i].substr( posStr ) ;
312                                         if (bbGetInputFileEnd()[j].compare( tmp )==0 )
313                                         {
314                                                 okEraseElement++;
315                                         } // if FileEnd
316                                 }// if posStr
317                         } // for j                                      
318
319                         if (okEraseElement==0) 
320                         { 
321                                 Filenames.erase( Filenames.begin()+i );
322                         }
323                 } // for i      
324         } // if FileEnd !=0
325         sizeFilenames = Filenames.size();
326 // Cleanning paths with spaces  
327         for (i=0; i<sizeFilenames; i++)
328         {
329                 tmpString=Filenames[i];
330                 std::string::size_type  spacePosition = tmpString.find_first_of(' ');
331                 if (spacePosition != std::string::npos)
332                 {
333                         std::cout << "=========================================== File name : [" <<tmpString << 
334                 "] contains space(s); Discarted !" << std::endl;
335                         tmpString.insert(spacePosition, "\\");
336                         Filenames[i]=tmpString;
337 //                      continue;   /// \TODO : fix the trouble (vtk?)
338                 } // if spacePosition
339         }
340
341 // Alphabetical order   
342         for (i=0; i<sizeFilenames; i++)
343         {
344         for (ii=i; ii<sizeFilenames; ii++)
345                 {
346                         if (Filenames[i]>Filenames[ii]) 
347                 {
348                         tmpString=Filenames[i];
349                         Filenames[i]=Filenames[ii];
350                         Filenames[ii]=tmpString;
351                 } // if 
352         } // for ii
353         } // for i
354 // Creating SimpleFilenames
355         unsigned int lenghtBasePath = basePath.length();
356         for (i=0; i<sizeFilenames; i++)
357         {
358                 SimpleFilenames.push_back( Filenames[i].substr( lenghtBasePath ) );
359         } // for i
360 }
361
362
363
364
365 /*
366
367 int FilesFromDirectory::Explore(std::string const &dirpath, bool recursive)
368 {
369    Filenames.clear();
370    int numberOfFiles = 0;
371    std::string fileName;
372    std::string dirName = NormalizePath(dirpath);
373 #ifdef _MSC_VER
374    WIN32_FIND_DATA fileData;
375    //assert( dirName[dirName.size()-1] == '' );
376    HANDLE hFile = FindFirstFile((dirName+"*").c_str(), &fileData);
377
378    for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
379        b = FindNextFile(hFile, &fileData))
380    {
381       fileName = fileData.cFileName;
382       if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
383       {
384          // Need to check for . and .. to avoid infinite loop
385          if ( fileName != "." && fileName != ".." && recursive )
386          {
387             numberOfFiles += Explore(dirName+fileName, recursive);
388          }
389       }
390       else
391       {
392 //         std::string temp = "\"" +dirName+fileName + "\"";
393          std::string temp = dirName+fileName;
394          std::string::size_type spacePosition = temp.find_first_of(' ');
395                  if (spacePosition != std::string::npos) 
396          {
397    std::cout << "=========================================== File name : [" <<temp << 
398               "] contains space(s); Discarted !" << std::endl;
399             temp.insert(spacePosition, "\\");
400    continue;  /// \TODO : fix the trouble (vtk?)
401          }      
402          Filenames.push_back(temp);
403          numberOfFiles++;
404       }
405    }
406    DWORD dwError = GetLastError();
407    if (hFile != INVALID_HANDLE_VALUE) 
408       FindClose(hFile);
409    if (dwError != ERROR_NO_MORE_FILES) 
410    {
411       LPVOID lpMsgBuf;
412       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
413                     FORMAT_MESSAGE_FROM_SYSTEM|
414                     FORMAT_MESSAGE_IGNORE_INSERTS,
415                     NULL,GetLastError(),
416                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
417                     (LPTSTR) &lpMsgBuf,0,NULL);
418
419       //gdcmErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
420       //             <<" for the directory : "<<dirName);
421       return -1;
422    }
423
424 #else
425   // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
426   // work on debian for example
427
428    DIR* dir = opendir(dirName.c_str());
429    if (!dir)
430    {
431       return 0;
432    }
433
434    // According to POSIX, the dirent structure contains a field char d_name[]
435    // of unspecified size, with at most NAME_MAX characters preceeding the
436    // terminating null character. Use of other fields will harm the  porta-
437    // bility of your programs.
438
439    struct stat buf;
440    dirent *d;
441    for (d = readdir(dir); d; d = readdir(dir))
442    {
443       fileName = dirName + d->d_name;
444       std::string temp = fileName;
445       if( stat(fileName.c_str(), &buf) != 0 )
446       {
447          //gdcmErrorMacro( strerror(errno) );
448       }
449       if ( S_ISREG(buf.st_mode) )    //is it a regular file?
450       {
451          if ( d->d_name[0]!='.')
452          {
453          
454              std::string::size_type  spacePosition = temp.find_first_of(' ');
455              if (spacePosition != std::string::npos)
456              {
457    std::cout << "=========================================== File name : [" <<temp << 
458               "] contains space(s); Discarted !" << std::endl;
459                  temp.insert(spacePosition, "\\");
460    continue;   /// \TODO : fix the trouble (vtk?)
461              }
462              Filenames.push_back(temp);  
463              numberOfFiles++;
464          }
465       }
466       else if ( S_ISDIR(buf.st_mode) ) //directory?
467       {
468          if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
469          {
470             numberOfFiles += Explore( fileName, recursive);
471          }
472       }
473       else
474       {
475          //gdcmErrorMacro( "Unexpected error" );
476          return -1;
477       }
478    }
479    if( closedir(dir) != 0 )
480    {
481       //gdcmErrorMacro( strerror(errno) );
482    }
483 #endif
484
485   std::string tmpString;
486   int i,ii,sizeFilenames = Filenames.size();
487   for (i=0; i<sizeFilenames; i++)
488   {
489     for (ii=i; ii<sizeFilenames; ii++)
490     {
491         if (Filenames[i]>Filenames[ii]) 
492         {
493           tmpString=Filenames[i];
494           Filenames[i]=Filenames[ii];
495           Filenames[ii]=tmpString;
496         } // if 
497     } // for ii
498   } // for i
499
500   return numberOfFiles;
501 }
502 */
503
504 }
505 // EO namespace bbstd
506
507