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