]> Creatis software - crea.git/blob - src/creaFilesFromDirectory.cxx
06c5e6f024895bb148c9b694845cae3eee698cb8
[crea.git] / src / creaFilesFromDirectory.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   crea
4   Module:    $RCSfile: creaFilesFromDirectory.cxx,v $
5   Language:  C++
6   Date:      $Date: 2008/12/03 14:53:42 $
7   Version:   $Revision: 1.2 $
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  #include "creaMessageManager.h"
38
39 namespace crea
40
41
42 /**
43  * \brief   Add a SEPARATOR to the end of the name if necessary
44  * @param   pathname file/directory name to normalize 
45  */
46 std::string DirList::NormalizePath(std::string const &pathname)
47 {
48
49
50 #ifdef _WIN32
51    const char FILESEPARATOR = '\\';
52 #else
53    const char FILESEPARATOR = '/';
54 #endif
55
56    std::string name = pathname;
57    int size = name.size();
58
59 //   if ( name[size-1] != SEPARATOR_X && name[size-1] != SEPARATOR_WIN )
60    if ( name[size-1] != FILESEPARATOR )
61    {
62       name += FILESEPARATOR;
63    }
64    return name;
65 }  
66 /**
67  * \brief   Explore a directory with possibility of recursion
68  *          return number of files read
69  * @param  dirpath   directory to explore
70  * @param  recursive whether we want recursion or not
71  */
72 int DirList::Explore(std::string const &dirpath, bool recursive)
73 {
74    int numberOfFiles = 0;
75    std::string fileName;
76    std::string dirName = NormalizePath(dirpath);
77 #ifdef _MSC_VER
78    WIN32_FIND_DATA fileData;
79    //assert( dirName[dirName.size()-1] == '' );
80    HANDLE hFile = FindFirstFile((dirName+"*").c_str(), &fileData);
81
82    for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
83        b = FindNextFile(hFile, &fileData))
84    {
85       fileName = fileData.cFileName;
86       if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
87       {
88          // Need to check for . and .. to avoid infinite loop
89          if ( fileName != "." && fileName != ".." && recursive )
90          {
91             numberOfFiles += Explore(dirName+fileName,recursive);
92          }
93       }
94       else
95       {
96          Filenames.push_back(dirName+fileName);
97          numberOfFiles++;
98       }
99    }
100    DWORD dwError = GetLastError();
101    if (hFile != INVALID_HANDLE_VALUE) 
102       FindClose(hFile);
103    if (dwError != ERROR_NO_MORE_FILES) 
104    {
105       LPVOID lpMsgBuf;
106       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
107                     FORMAT_MESSAGE_FROM_SYSTEM|
108                     FORMAT_MESSAGE_IGNORE_INSERTS,
109                     NULL,GetLastError(),
110                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
111                     (LPTSTR) &lpMsgBuf,0,NULL);
112
113       creaError("FindNextFile error. Error is " << (char *)lpMsgBuf
114                    <<" for the directory : "<<dirName);
115       return -1;
116    }
117
118 #else
119   // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
120   // work on debian for example
121
122    DIR* dir = opendir(dirName.c_str());
123    if (!dir)
124    {
125       return 0;
126    }
127
128    // According to POSIX, the dirent structure contains a field char d_name[]
129    // of unspecified size, with at most NAME_MAX characters preceeding the
130    // terminating null character. Use of other fields will harm the  porta-
131    // bility of your programs.
132
133    struct stat buf;
134    dirent *d;
135    for (d = readdir(dir); d; d = readdir(dir))
136    {
137       fileName = dirName + d->d_name;
138       if( stat(fileName.c_str(), &buf) != 0 )
139       {
140          //gdcmErrorMacro( strerror(errno) );
141       }
142       if ( S_ISREG(buf.st_mode) )    //is it a regular file?
143       {
144          Filenames.push_back( fileName );
145          numberOfFiles++;
146       }
147       else if ( S_ISDIR(buf.st_mode) ) //directory?
148       {
149          if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
150          {
151             numberOfFiles += Explore( fileName, recursive);
152          }
153       }
154       else
155       {
156          //gdcmErrorMacro( "Unexpected error" );
157          return -1;
158       }
159    }
160    if( closedir(dir) != 0 )
161    {
162       //gdcmErrorMacro( strerror(errno) );
163    }
164 #endif
165
166   return numberOfFiles;
167 }
168
169 }