]> Creatis software - bbtk.git/blob - packages/std/src/bbstdFilesFromDirectory.cxx
#3382 BBTK Feature New Normal - box Tab selection output
[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
299         int okEraseElement;
300         
301 //Selecting just the files in the FileEnd List
302         if (bbGetInputFileEnd().size()!=0)
303         {
304                 for (i=sizeFilenames-1; i>=0; i--)
305                 {
306                         okEraseElement=0;
307                         for (j=0; j<sizeFileEnd; j++)
308                         {
309                                 std::string tmp=Filenames[i].substr( (Filenames[i].length()) - (bbGetInputFileEnd()[j]).length() ) ;
310                                 if (bbGetInputFileEnd()[j].compare( tmp )==0 )
311                                 {
312                                         okEraseElement++;
313                                 } // if FileEnd
314                         } // for j                                      
315
316                         if (okEraseElement==0) 
317                         { 
318                                 Filenames.erase( Filenames.begin()+i );
319                         }
320                 } // for i      
321         } // if FileEnd !=0
322
323         sizeFilenames = Filenames.size();
324
325 // Cleanning paths with spaces  
326         for (i=0; i<sizeFilenames; i++)
327         {
328                 tmpString=Filenames[i];
329
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
342 // Alphabetical order   
343         for (i=0; i<sizeFilenames; i++)
344         {
345         for (ii=i; ii<sizeFilenames; ii++)
346                 {
347                         if (Filenames[i]>Filenames[ii]) 
348                 {
349                         tmpString=Filenames[i];
350                         Filenames[i]=Filenames[ii];
351                         Filenames[ii]=tmpString;
352                 } // if 
353         } // for ii
354         } // for i
355
356 // Creating SimpleFilenames
357         unsigned int lenghtBasePath = basePath.length();
358         for (i=0; i<sizeFilenames; i++)
359         {
360                 SimpleFilenames.push_back( Filenames[i].substr( lenghtBasePath ) );
361         } // for i
362
363 }
364
365
366
367
368 /*
369
370 int FilesFromDirectory::Explore(std::string const &dirpath, bool recursive)
371 {
372    Filenames.clear();
373    int numberOfFiles = 0;
374    std::string fileName;
375    std::string dirName = NormalizePath(dirpath);
376 #ifdef _MSC_VER
377    WIN32_FIND_DATA fileData;
378    //assert( dirName[dirName.size()-1] == '' );
379    HANDLE hFile = FindFirstFile((dirName+"*").c_str(), &fileData);
380
381    for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
382        b = FindNextFile(hFile, &fileData))
383    {
384       fileName = fileData.cFileName;
385       if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
386       {
387          // Need to check for . and .. to avoid infinite loop
388          if ( fileName != "." && fileName != ".." && recursive )
389          {
390             numberOfFiles += Explore(dirName+fileName, recursive);
391          }
392       }
393       else
394       {
395 //         std::string temp = "\"" +dirName+fileName + "\"";
396          std::string temp = dirName+fileName;
397          std::string::size_type spacePosition = temp.find_first_of(' ');
398                  if (spacePosition != std::string::npos) 
399          {
400    std::cout << "=========================================== File name : [" <<temp << 
401               "] contains space(s); Discarted !" << std::endl;
402             temp.insert(spacePosition, "\\");
403    continue;  /// \TODO : fix the trouble (vtk?)
404          }      
405          Filenames.push_back(temp);
406          numberOfFiles++;
407       }
408    }
409    DWORD dwError = GetLastError();
410    if (hFile != INVALID_HANDLE_VALUE) 
411       FindClose(hFile);
412    if (dwError != ERROR_NO_MORE_FILES) 
413    {
414       LPVOID lpMsgBuf;
415       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
416                     FORMAT_MESSAGE_FROM_SYSTEM|
417                     FORMAT_MESSAGE_IGNORE_INSERTS,
418                     NULL,GetLastError(),
419                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
420                     (LPTSTR) &lpMsgBuf,0,NULL);
421
422       //gdcmErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
423       //             <<" for the directory : "<<dirName);
424       return -1;
425    }
426
427 #else
428   // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
429   // work on debian for example
430
431    DIR* dir = opendir(dirName.c_str());
432    if (!dir)
433    {
434       return 0;
435    }
436
437    // According to POSIX, the dirent structure contains a field char d_name[]
438    // of unspecified size, with at most NAME_MAX characters preceeding the
439    // terminating null character. Use of other fields will harm the  porta-
440    // bility of your programs.
441
442    struct stat buf;
443    dirent *d;
444    for (d = readdir(dir); d; d = readdir(dir))
445    {
446       fileName = dirName + d->d_name;
447       std::string temp = fileName;
448       if( stat(fileName.c_str(), &buf) != 0 )
449       {
450          //gdcmErrorMacro( strerror(errno) );
451       }
452       if ( S_ISREG(buf.st_mode) )    //is it a regular file?
453       {
454          if ( d->d_name[0]!='.')
455          {
456          
457              std::string::size_type  spacePosition = temp.find_first_of(' ');
458              if (spacePosition != std::string::npos)
459              {
460    std::cout << "=========================================== File name : [" <<temp << 
461               "] contains space(s); Discarted !" << std::endl;
462                  temp.insert(spacePosition, "\\");
463    continue;   /// \TODO : fix the trouble (vtk?)
464              }
465              Filenames.push_back(temp);  
466              numberOfFiles++;
467          }
468       }
469       else if ( S_ISDIR(buf.st_mode) ) //directory?
470       {
471          if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
472          {
473             numberOfFiles += Explore( fileName, recursive);
474          }
475       }
476       else
477       {
478          //gdcmErrorMacro( "Unexpected error" );
479          return -1;
480       }
481    }
482    if( closedir(dir) != 0 )
483    {
484       //gdcmErrorMacro( strerror(errno) );
485    }
486 #endif
487
488   std::string tmpString;
489   int i,ii,sizeFilenames = Filenames.size();
490   for (i=0; i<sizeFilenames; i++)
491   {
492     for (ii=i; ii<sizeFilenames; ii++)
493     {
494         if (Filenames[i]>Filenames[ii]) 
495         {
496           tmpString=Filenames[i];
497           Filenames[i]=Filenames[ii];
498           Filenames[ii]=tmpString;
499         } // if 
500     } // for ii
501   } // for i
502
503   return numberOfFiles;
504 }
505 */
506
507 }
508 // EO namespace bbstd
509
510