]> 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                         if ((bbGetInputType()==1) || (bbGetInputType()==2))
145                         {
146                         std::string temp = dirName+fileName;
147                         Filenames.push_back(temp);       
148                         numberOfFiles++;
149                         } // Type All_directories
150                 }// fileName && !recursive
151       } else  {
152 //      std::string temp = "\"" +dirName+fileName + "\"";
153         std::string temp = dirName+fileName;
154
155 /*
156         std::string::size_type spacePosition = temp.find_first_of(' ');
157                 if (spacePosition != std::string::npos) 
158                 {
159                         std::cout << "=========================================== File name : [" <<temp << 
160               "] contains space(s); Discarted !" << std::endl;
161                 temp.insert(spacePosition, "\\");
162                         continue;  /// \TODO : fix the trouble (vtk?)
163                 } // if !npos
164 */
165
166
167                 if (bbGetInputType()==0)
168                 {
169                         Filenames.push_back(temp);       
170                         numberOfFiles++;
171                 } // Type files
172
173       } // if !directory
174         } // for
175         DWORD dwError = GetLastError();
176         if (hFile != INVALID_HANDLE_VALUE) 
177         {
178                 FindClose(hFile);
179         }// hFile
180         if (dwError != ERROR_NO_MORE_FILES) 
181         {
182       LPVOID lpMsgBuf;
183       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
184                     FORMAT_MESSAGE_FROM_SYSTEM|
185                     FORMAT_MESSAGE_IGNORE_INSERTS,
186                     NULL,GetLastError(),
187                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
188                     (LPTSTR) &lpMsgBuf,0,NULL);
189
190       //gdcmErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
191       //             <<" for the directory : "<<dirName);
192       return -1;
193         } // dwError
194
195 #else
196   // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
197   // work on debian for example
198
199         DIR* dir = opendir( dirName.c_str() );
200         if (!dir)
201         {
202                 return 0;
203         }
204
205    // According to POSIX, the dirent structure contains a field char d_name[]
206    // of unspecified size, with at most NAME_MAX characters preceeding the
207    // terminating null character. Use of other fields will harm the  porta-
208    // bility of your programs.
209
210         struct stat     buf;
211         dirent                  *d;
212         for (d = readdir(dir); d; d = readdir(dir))
213         {
214         fileName = dirName + d->d_name;
215         std::string temp = fileName;
216         if( stat(fileName.c_str(), &buf) != 0 )
217         {
218                  //gdcmErrorMacro( strerror(errno) );
219         } // stat
220         if ( S_ISREG(buf.st_mode) )    //is it a regular file?
221         {
222                 if ( d->d_name[0]!='.')
223                 {
224
225 /*
226                         std::string::size_type  spacePosition = temp.find_first_of(' ');
227                 if (spacePosition != std::string::npos)
228                         {
229                                         std::cout << "=========================================== File name : [" <<temp << 
230                                 "] contains space(s); Discarted !" << std::endl;
231                         temp.insert(spacePosition, "\\");
232                                         continue;   /// \TODO : fix the trouble (vtk?)
233                 } // if spacePosition
234 */
235
236                                 if (bbGetInputType()==0)
237                                 {
238                         Filenames.push_back(temp);       
239                                 numberOfFiles++;
240                                 } // Type files
241                 } // d_name
242         } else if ( S_ISDIR(buf.st_mode) ) {  //directory?
243                 if ( (d->d_name[0]!='.') && recursive ) //we also skip hidden files
244                 {
245                                 if (bbGetInputType()==1)
246                                 {
247                         Filenames.push_back(fileName);   
248                                 numberOfFiles++;
249                                 } // Type All_directories
250
251                                 tmpNumberOfFiles        = Explore( fileName, recursive);
252                                 if ((bbGetInputType()==2)&&tmpNumberOfFiles==0)
253                                 {
254                                         Filenames.push_back(fileName);   
255                                 numberOfFiles++;
256                                 } // Type Lsast_directories
257                         numberOfFiles           = numberOfFiles+tmpNumberOfFiles;
258                 }// d_name && recursive
259                 if ( (d->d_name[0]!='.') && !recursive ) { //we also skip hidden files
260                                 if ((bbGetInputType()==1) || (bbGetInputType()==2))
261                                 {
262                         Filenames.push_back(fileName);   
263                                 numberOfFiles++;
264                                 } // Type All_directories
265                         
266                         }// d_name && !recursive
267
268                 } else {
269                 //gdcmErrorMacro( "Unexpected error" );
270                 return -1;
271         } // Regular FILE
272    }
273    if( closedir(dir) != 0 )
274    {
275       //gdcmErrorMacro( strerror(errno) );
276    }// closedir
277 #endif
278
279
280         return numberOfFiles;
281 }
282
283
284 //------------------------------------------------------------------------------
285 void FilesFromDirectory::CleanFilenames( std::string basePath )
286 {
287         std::string tmpString;
288         int i,ii,sizeFilenames = Filenames.size();
289         int j,sizeFileEnd = bbGetInputFileEnd().size();
290
291         int okEraseElement;
292         
293 //Selecting just the files in the FileEnd List
294         if (bbGetInputFileEnd().size()!=0)
295         {
296                 for (i=sizeFilenames-1; i>=0; i--)
297                 {
298                         okEraseElement=0;
299                         for (j=0; j<sizeFileEnd; j++)
300                         {
301                                 std::string tmp=Filenames[i].substr( (Filenames[i].length()) - (bbGetInputFileEnd()[j]).length() ) ;
302                                 if (bbGetInputFileEnd()[j].compare( tmp )==0 )
303                                 {
304                                         okEraseElement++;
305                                 } // if FileEnd
306                         } // for j                                      
307
308                         if (okEraseElement==0) 
309                         { 
310                                 Filenames.erase( Filenames.begin()+i );
311                         }
312                 } // for i      
313         } // if FileEnd !=0
314
315         sizeFilenames = Filenames.size();
316
317 // Cleanning paths with spaces  
318         for (i=0; i<sizeFilenames; i++)
319         {
320                 tmpString=Filenames[i];
321
322                 std::string::size_type  spacePosition = tmpString.find_first_of(' ');
323                 if (spacePosition != std::string::npos)
324                 {
325                         std::cout << "=========================================== File name : [" <<tmpString << 
326                 "] contains space(s); Discarted !" << std::endl;
327                         tmpString.insert(spacePosition, "\\");
328                         Filenames[i]=tmpString;
329 //                      continue;   /// \TODO : fix the trouble (vtk?)
330                 } // if spacePosition
331         }
332
333
334 // Alphabetical order   
335         for (i=0; i<sizeFilenames; i++)
336         {
337         for (ii=i; ii<sizeFilenames; ii++)
338                 {
339                         if (Filenames[i]>Filenames[ii]) 
340                 {
341                         tmpString=Filenames[i];
342                         Filenames[i]=Filenames[ii];
343                         Filenames[ii]=tmpString;
344                 } // if 
345         } // for ii
346         } // for i
347
348 // Creating SimpleFilenames
349         unsigned int lenghtBasePath = basePath.length();
350         for (i=0; i<sizeFilenames; i++)
351         {
352                 SimpleFilenames.push_back( Filenames[i].substr( lenghtBasePath ) );
353         } // for i
354
355 }
356
357
358
359
360 /*
361
362 int FilesFromDirectory::Explore(std::string const &dirpath, bool recursive)
363 {
364    Filenames.clear();
365    int numberOfFiles = 0;
366    std::string fileName;
367    std::string dirName = NormalizePath(dirpath);
368 #ifdef _MSC_VER
369    WIN32_FIND_DATA fileData;
370    //assert( dirName[dirName.size()-1] == '' );
371    HANDLE hFile = FindFirstFile((dirName+"*").c_str(), &fileData);
372
373    for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
374        b = FindNextFile(hFile, &fileData))
375    {
376       fileName = fileData.cFileName;
377       if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
378       {
379          // Need to check for . and .. to avoid infinite loop
380          if ( fileName != "." && fileName != ".." && recursive )
381          {
382             numberOfFiles += Explore(dirName+fileName, recursive);
383          }
384       }
385       else
386       {
387 //         std::string temp = "\"" +dirName+fileName + "\"";
388          std::string temp = dirName+fileName;
389          std::string::size_type spacePosition = temp.find_first_of(' ');
390                  if (spacePosition != std::string::npos) 
391          {
392    std::cout << "=========================================== File name : [" <<temp << 
393               "] contains space(s); Discarted !" << std::endl;
394             temp.insert(spacePosition, "\\");
395    continue;  /// \TODO : fix the trouble (vtk?)
396          }      
397          Filenames.push_back(temp);
398          numberOfFiles++;
399       }
400    }
401    DWORD dwError = GetLastError();
402    if (hFile != INVALID_HANDLE_VALUE) 
403       FindClose(hFile);
404    if (dwError != ERROR_NO_MORE_FILES) 
405    {
406       LPVOID lpMsgBuf;
407       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
408                     FORMAT_MESSAGE_FROM_SYSTEM|
409                     FORMAT_MESSAGE_IGNORE_INSERTS,
410                     NULL,GetLastError(),
411                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
412                     (LPTSTR) &lpMsgBuf,0,NULL);
413
414       //gdcmErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
415       //             <<" for the directory : "<<dirName);
416       return -1;
417    }
418
419 #else
420   // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
421   // work on debian for example
422
423    DIR* dir = opendir(dirName.c_str());
424    if (!dir)
425    {
426       return 0;
427    }
428
429    // According to POSIX, the dirent structure contains a field char d_name[]
430    // of unspecified size, with at most NAME_MAX characters preceeding the
431    // terminating null character. Use of other fields will harm the  porta-
432    // bility of your programs.
433
434    struct stat buf;
435    dirent *d;
436    for (d = readdir(dir); d; d = readdir(dir))
437    {
438       fileName = dirName + d->d_name;
439       std::string temp = fileName;
440       if( stat(fileName.c_str(), &buf) != 0 )
441       {
442          //gdcmErrorMacro( strerror(errno) );
443       }
444       if ( S_ISREG(buf.st_mode) )    //is it a regular file?
445       {
446          if ( d->d_name[0]!='.')
447          {
448          
449              std::string::size_type  spacePosition = temp.find_first_of(' ');
450              if (spacePosition != std::string::npos)
451              {
452    std::cout << "=========================================== File name : [" <<temp << 
453               "] contains space(s); Discarted !" << std::endl;
454                  temp.insert(spacePosition, "\\");
455    continue;   /// \TODO : fix the trouble (vtk?)
456              }
457              Filenames.push_back(temp);  
458              numberOfFiles++;
459          }
460       }
461       else if ( S_ISDIR(buf.st_mode) ) //directory?
462       {
463          if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
464          {
465             numberOfFiles += Explore( fileName, recursive);
466          }
467       }
468       else
469       {
470          //gdcmErrorMacro( "Unexpected error" );
471          return -1;
472       }
473    }
474    if( closedir(dir) != 0 )
475    {
476       //gdcmErrorMacro( strerror(errno) );
477    }
478 #endif
479
480   std::string tmpString;
481   int i,ii,sizeFilenames = Filenames.size();
482   for (i=0; i<sizeFilenames; i++)
483   {
484     for (ii=i; ii<sizeFilenames; ii++)
485     {
486         if (Filenames[i]>Filenames[ii]) 
487         {
488           tmpString=Filenames[i];
489           Filenames[i]=Filenames[ii];
490           Filenames[ii]=tmpString;
491         } // if 
492     } // for ii
493   } // for i
494
495   return numberOfFiles;
496 }
497 */
498
499 }
500 // EO namespace bbstd
501
502