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