]> Creatis software - bbtk.git/blob - packages/std/src/bbstdFilesFromDirectory.cxx
Box to return file names from a directory (recursive expl or not)
[bbtk.git] / packages / std / src / bbstdFilesFromDirectory.cxx
1 #include "bbstdFilesFromDirectory.h"
2 #include "bbstdPackage.h"
3
4 #ifdef _MSC_VER
5    #include <windows.h>
6    #include <direct.h>
7 #else
8    #include <dirent.h>   
9    #include <sys/types.h>
10 #endif
11
12 #include <sys/stat.h>  //stat function
13
14 namespace bbstd
15 {
16
17 BBTK_ADD_BLACK_BOX_TO_PACKAGE(std,FilesFromDirectory)
18 BBTK_BLACK_BOX_IMPLEMENTATION(FilesFromDirectory,bbtk::AtomicBlackBox);
19
20 void FilesFromDirectory::Process()
21 {
22
23    DirName = bbGetInputIn();
24    bool rec = bbGetInputRecursive();
25    /*int nbFiles = */ Explore(DirName, rec);
26    bbSetOutputOut(Filenames);
27    
28   
29 }
30 void FilesFromDirectory::bbUserConstructor()
31 {
32
33     bbSetInputIn(".");
34     bbSetInputRecursive(false);
35   
36 }
37 void FilesFromDirectory::bbUserCopyConstructor(bbtk::BlackBox::Pointer)
38 {
39
40   
41 }
42 void FilesFromDirectory::bbUserDestructor()
43 {
44
45   
46 }
47
48 /**
49  * \brief   Add a SEPARATOR to the end of the name if necessary
50  * @param   pathname file/directory name to normalize 
51  */
52 std::string FilesFromDirectory::NormalizePath(std::string const &pathname)
53 {
54 #ifdef _WIN32
55    const char FILESEPARATOR = '\\;
56 #else
57    const char FILESEPARATOR = '/';
58 #endif
59
60    std::string name = pathname;
61    int size = name.size();
62
63    if ( name[size-1] != FILESEPARATOR )
64    {
65       name += FILESEPARATOR;
66    }
67    return name;
68
69
70 /**
71  * \brief   Explores a directory with possibility of recursion
72  *          return number of files read
73  * @param  dirpath   directory to explore
74  * @param  recursive whether we want recursion or not
75  */
76 int FilesFromDirectory::Explore(std::string const &dirpath, bool recursive)
77 {
78    int numberOfFiles = 0;
79    std::string fileName;
80    std::string dirName = NormalizePath(dirpath);
81 #ifdef _MSC_VER
82    WIN32_FIND_DATA fileData;
83    //assert( dirName[dirName.size()-1] == '' );
84    HANDLE hFile = FindFirstFile((dirName+"*").c_str(), &fileData);
85
86    for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
87        b = FindNextFile(hFile, &fileData))
88    {
89       fileName = fileData.cFileName;
90       if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
91       {
92          // Need to check for . and .. to avoid infinite loop
93          if ( fileName != "." && fileName != ".." && recursive )
94          {
95             numberOfFiles += Explore(dirName+fileName,recursive);
96          }
97       }
98       else
99       {
100          Filenames.push_back(dirName+fileName);
101          numberOfFiles++;
102       }
103    }
104    DWORD dwError = GetLastError();
105    if (hFile != INVALID_HANDLE_VALUE) 
106       FindClose(hFile);
107    if (dwError != ERROR_NO_MORE_FILES) 
108    {
109       LPVOID lpMsgBuf;
110       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
111                     FORMAT_MESSAGE_FROM_SYSTEM|
112                     FORMAT_MESSAGE_IGNORE_INSERTS,
113                     NULL,GetLastError(),
114                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
115                     (LPTSTR) &lpMsgBuf,0,NULL);
116
117       //gdcmErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
118       //             <<" for the directory : "<<dirName);
119       return -1;
120    }
121
122 #else
123   // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
124   // work on debian for example
125
126    DIR* dir = opendir(dirName.c_str());
127    if (!dir)
128    {
129       return 0;
130    }
131
132    // According to POSIX, the dirent structure contains a field char d_name[]
133    // of unspecified size, with at most NAME_MAX characters preceeding the
134    // terminating null character. Use of other fields will harm the  porta-
135    // bility of your programs.
136
137    struct stat buf;
138    dirent *d;
139    for (d = readdir(dir); d; d = readdir(dir))
140    {
141       fileName = dirName + d->d_name;
142       if( stat(fileName.c_str(), &buf) != 0 )
143       {
144          //gdcmErrorMacro( strerror(errno) );
145       }
146       if ( S_ISREG(buf.st_mode) )    //is it a regular file?
147       {
148          Filenames.push_back( fileName );
149          numberOfFiles++;
150       }
151       else if ( S_ISDIR(buf.st_mode) ) //directory?
152       {
153          if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
154          {
155             numberOfFiles += Explore( fileName, recursive);
156          }
157       }
158       else
159       {
160          //gdcmErrorMacro( "Unexpected error" );
161          return -1;
162       }
163    }
164    if( closedir(dir) != 0 )
165    {
166       //gdcmErrorMacro( strerror(errno) );
167    }
168 #endif
169
170   return numberOfFiles;
171 }
172
173
174 }
175 // EO namespace bbstd
176
177