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