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