]> Creatis software - crea.git/blob - src/creaFilesFromDirectory.cxx
Class to return names of the files within a directory (recursive exploration or
[crea.git] / src / creaFilesFromDirectory.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   crea
4   Module:    $RCSfile: creaFilesFromDirectory.cxx,v $
5   Language:  C++
6   Date:      $Date: 2008/11/25 13:15:57 $
7   Version:   $Revision: 1.1 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/crea/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18
19
20 /**
21  *  \file 
22  *  \brief  class Exception:generic class for throwing any exception (header) 
23  *
24  *    Long description:
25  */
26 #ifdef _MSC_VER
27    #include <windows.h>
28    #include <direct.h>
29 #else
30    #include <dirent.h>   
31    #include <sys/types.h>
32 #endif
33
34 #include <sys/stat.h>  //stat function
35
36  #include "creaFilesFromDirectory.h"
37
38 namespace crea
39
40
41 /**
42  * \brief   Add a SEPARATOR to the end of the name if necessary
43  * @param   pathname file/directory name to normalize 
44  */
45 std::string DirList::NormalizePath(std::string const &pathname)
46 {
47
48
49 #ifdef _WIN32
50    const char FILESEPARATOR = '\\;
51 #else
52    const char FILESEPARATOR = '/';
53 #endif
54
55    std::string name = pathname;
56    int size = name.size();
57
58 //   if ( name[size-1] != SEPARATOR_X && name[size-1] != SEPARATOR_WIN )
59    if ( name[size-1] != FILESEPARATOR )
60    {
61       name += FILESEPARATOR;
62    }
63    return name;
64 }  
65 /**
66  * \brief   Explore a directory with possibility of recursion
67  *          return number of files read
68  * @param  dirpath   directory to explore
69  * @param  recursive whether we want recursion or not
70  */
71 int DirList::Explore(std::string const &dirpath, bool recursive)
72 {
73    int numberOfFiles = 0;
74    std::string fileName;
75    std::string dirName = NormalizePath(dirpath);
76 #ifdef _MSC_VER
77    WIN32_FIND_DATA fileData;
78    //assert( dirName[dirName.size()-1] == '' );
79    HANDLE hFile = FindFirstFile((dirName+"*").c_str(), &fileData);
80
81    for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
82        b = FindNextFile(hFile, &fileData))
83    {
84       fileName = fileData.cFileName;
85       if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
86       {
87          // Need to check for . and .. to avoid infinite loop
88          if ( fileName != "." && fileName != ".." && recursive )
89          {
90             numberOfFiles += Explore(dirName+fileName,recursive);
91          }
92       }
93       else
94       {
95          Filenames.push_back(dirName+fileName);
96          numberOfFiles++;
97       }
98    }
99    DWORD dwError = GetLastError();
100    if (hFile != INVALID_HANDLE_VALUE) 
101       FindClose(hFile);
102    if (dwError != ERROR_NO_MORE_FILES) 
103    {
104       LPVOID lpMsgBuf;
105       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
106                     FORMAT_MESSAGE_FROM_SYSTEM|
107                     FORMAT_MESSAGE_IGNORE_INSERTS,
108                     NULL,GetLastError(),
109                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
110                     (LPTSTR) &lpMsgBuf,0,NULL);
111
112       gdcmErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
113                    <<" for the directory : "<<dirName);
114       return -1;
115    }
116
117 #else
118   // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
119   // work on debian for example
120
121    DIR* dir = opendir(dirName.c_str());
122    if (!dir)
123    {
124       return 0;
125    }
126
127    // According to POSIX, the dirent structure contains a field char d_name[]
128    // of unspecified size, with at most NAME_MAX characters preceeding the
129    // terminating null character. Use of other fields will harm the  porta-
130    // bility of your programs.
131
132    struct stat buf;
133    dirent *d;
134    for (d = readdir(dir); d; d = readdir(dir))
135    {
136       fileName = dirName + d->d_name;
137       if( stat(fileName.c_str(), &buf) != 0 )
138       {
139          //gdcmErrorMacro( strerror(errno) );
140       }
141       if ( S_ISREG(buf.st_mode) )    //is it a regular file?
142       {
143          Filenames.push_back( fileName );
144          numberOfFiles++;
145       }
146       else if ( S_ISDIR(buf.st_mode) ) //directory?
147       {
148          if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
149          {
150             numberOfFiles += Explore( fileName, recursive);
151          }
152       }
153       else
154       {
155          //gdcmErrorMacro( "Unexpected error" );
156          return -1;
157       }
158    }
159    if( closedir(dir) != 0 )
160    {
161       //gdcmErrorMacro( strerror(errno) );
162    }
163 #endif
164
165   return numberOfFiles;
166 }
167
168 }