]> Creatis software - bbtk.git/blob - packages/std/src/bbstdFilesFromDirectory.cxx
#2816 BBTK Bug New Normal - std FilesFromDirectory box not clean the list for the...
[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    DirName = bbGetInputIn();
51    bool rec = bbGetInputRecursive();
52    /*int nbFiles = */ Explore(DirName, rec);
53    bbSetOutputOut(Filenames);   
54    
55 //  for (int i=0; i<Filenames.size(); i++)
56 //     std::cout << "Filenames [" << i << "] = [" << Filenames[i] << "]" << std::endl;  
57 }
58
59 void FilesFromDirectory::bbUserSetDefaultValues()
60 {
61     bbSetInputIn(".");
62     bbSetInputRecursive(false);  
63 }
64
65 void FilesFromDirectory::bbUserInitializeProcessing() 
66
67 }
68
69 void FilesFromDirectory::bbUserFinalizeProcessing() 
70 {
71 }
72   
73 /**
74  * \brief   Add a SEPARATOR to the end of the name if necessary
75  * @param   pathname file/directory name to normalize 
76  */
77 std::string FilesFromDirectory::NormalizePath(std::string const &pathname)
78 {
79 #ifdef _WIN32
80    const char FILESEPARATOR = '\\';
81 #else
82    const char FILESEPARATOR = '/';
83 #endif
84
85    std::string name = pathname;
86    int size = name.size();
87
88    if ( name[size-1] != FILESEPARATOR )
89    {
90       name += FILESEPARATOR;
91    }
92    return name;
93
94
95 /**
96  * \brief   Explores a directory with possibility of recursion
97  *          return number of files read
98  * @param  dirpath   directory to explore
99  * @param  recursive whether we want recursion or not
100  */
101 int FilesFromDirectory::Explore(std::string const &dirpath, bool recursive)
102 {
103    Filenames.clear();
104    int numberOfFiles = 0;
105    std::string fileName;
106    std::string dirName = NormalizePath(dirpath);
107 #ifdef _MSC_VER
108    WIN32_FIND_DATA fileData;
109    //assert( dirName[dirName.size()-1] == '' );
110    HANDLE hFile = FindFirstFile((dirName+"*").c_str(), &fileData);
111
112    for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
113        b = FindNextFile(hFile, &fileData))
114    {
115       fileName = fileData.cFileName;
116       if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
117       {
118          // Need to check for . and .. to avoid infinite loop
119          if ( fileName != "." && fileName != ".." && recursive )
120          {
121             numberOfFiles += Explore(dirName+fileName, recursive);
122          }
123       }
124       else
125       {
126 //         std::string temp = "\"" +dirName+fileName + "\"";
127          std::string temp = dirName+fileName;
128          std::string::size_type spacePosition = temp.find_first_of(' ');
129                  if (spacePosition != std::string::npos) 
130          {
131    std::cout << "=========================================== File name : [" <<temp << 
132               "] contains space(s); Discarted !" << std::endl;
133             temp.insert(spacePosition, "\\");
134    continue;  /// \TODO : fix the trouble (vtk?)
135          }      
136          Filenames.push_back(temp);
137          numberOfFiles++;
138       }
139    }
140    DWORD dwError = GetLastError();
141    if (hFile != INVALID_HANDLE_VALUE) 
142       FindClose(hFile);
143    if (dwError != ERROR_NO_MORE_FILES) 
144    {
145       LPVOID lpMsgBuf;
146       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
147                     FORMAT_MESSAGE_FROM_SYSTEM|
148                     FORMAT_MESSAGE_IGNORE_INSERTS,
149                     NULL,GetLastError(),
150                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
151                     (LPTSTR) &lpMsgBuf,0,NULL);
152
153       //gdcmErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
154       //             <<" for the directory : "<<dirName);
155       return -1;
156    }
157
158 #else
159   // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
160   // work on debian for example
161
162    DIR* dir = opendir(dirName.c_str());
163    if (!dir)
164    {
165       return 0;
166    }
167
168    // According to POSIX, the dirent structure contains a field char d_name[]
169    // of unspecified size, with at most NAME_MAX characters preceeding the
170    // terminating null character. Use of other fields will harm the  porta-
171    // bility of your programs.
172
173    struct stat buf;
174    dirent *d;
175    for (d = readdir(dir); d; d = readdir(dir))
176    {
177       fileName = dirName + d->d_name;
178       std::string temp = fileName;
179       if( stat(fileName.c_str(), &buf) != 0 )
180       {
181          //gdcmErrorMacro( strerror(errno) );
182       }
183       if ( S_ISREG(buf.st_mode) )    //is it a regular file?
184       {
185          if ( d->d_name[0]!='.')
186          {
187          
188              std::string::size_type /* long int */ spacePosition = temp.find_first_of(' ');
189              if (spacePosition != std::string::npos)
190              {
191    std::cout << "=========================================== File name : [" <<temp << 
192               "] contains space(s); Discarted !" << std::endl;
193                  temp.insert(spacePosition, "\\");
194    continue;   /// \TODO : fix the trouble (vtk?)
195              }
196              Filenames.push_back(temp);  
197              numberOfFiles++;
198          }
199       }
200       else if ( S_ISDIR(buf.st_mode) ) //directory?
201       {
202          if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
203          {
204             numberOfFiles += Explore( fileName, recursive);
205          }
206       }
207       else
208       {
209          //gdcmErrorMacro( "Unexpected error" );
210          return -1;
211       }
212    }
213    if( closedir(dir) != 0 )
214    {
215       //gdcmErrorMacro( strerror(errno) );
216    }
217 #endif
218
219   std::string tmpString;
220   int i,ii,sizeFilenames = Filenames.size();
221   for (i=0; i<sizeFilenames; i++)
222   {
223     for (ii=i; ii<sizeFilenames; ii++)
224     {
225         if (Filenames[i]>Filenames[ii]) 
226         {
227           tmpString=Filenames[i];
228           Filenames[i]=Filenames[ii];
229           Filenames[ii]=tmpString;
230         } // if 
231     } // for ii
232   } // for i
233
234   return numberOfFiles;
235 }
236
237
238 }
239 // EO namespace bbstd
240
241