]> Creatis software - gdcm.git/blob - src/gdcmDirList.cxx
fix mistyping
[gdcm.git] / src / gdcmDirList.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmDirList.cxx,v $
5   Language:  C++
6   Date:      $Date: 2009/05/26 10:27:38 $
7   Version:   $Revision: 1.68 $
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/Gdcm/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 #include "gdcmDirList.h"
20 #include "gdcmUtil.h"
21 #include "gdcmDebug.h"
22
23 #include "gdcmDicomDirImage.h"
24
25 #include <iterator>
26 #include <assert.h>
27 #include <errno.h>
28 #include <sys/stat.h>  //stat function
29
30 #ifdef _MSC_VER
31    #include <windows.h>
32    #include <direct.h>
33 #else
34    #include <dirent.h>   
35    #include <sys/types.h>
36 #endif
37
38 namespace GDCM_NAME_SPACE
39 {
40 //-----------------------------------------------------------------------------
41 // Constructor / Destructor
42 /**
43  * \brief Constructor  
44  * @param  dirName root directory name
45  * @param  recursive whether we want to explore recursively or not 
46  */
47 DirList::DirList(std::string const &dirName, bool recursive, bool all)
48 {
49    DirName = dirName;
50    Explore(dirName, recursive, all);
51 }
52
53 /**
54  * \brief Constructor  
55  * @param  se DicomDirSerie we want to explore
56  */
57 DirList::DirList(DicomDirSerie *se)
58 {
59    Explore(se);
60 }
61 /**
62  * \brief  Destructor
63  */
64 DirList::~DirList()
65 {
66 }
67
68 //-----------------------------------------------------------------------------
69 // Public
70 /**
71  * \brief Tells us if file name corresponds to a Directory   
72  * @param  dirName file name to check
73  * @return true if the file IS a Directory
74  */
75 bool DirList::IsDirectory(std::string const &dirName)
76 {
77    struct stat fs;
78    // std::cout << "dirName[dirName.size()-1] [" << dirName[dirName.size()-1] << "]"
79    //           << std::endl;
80    //assert( dirName[dirName.size()-1] != GDCM_FILESEPARATOR );
81    if ( stat(dirName.c_str(), &fs) == 0 )
82    {
83 #if _WIN32
84       return ((fs.st_mode & _S_IFDIR) != 0);
85 #else
86       return S_ISDIR(fs.st_mode);
87 #endif
88    }
89    else
90    {
91       gdcmStaticWarningMacro("[" << dirName << "] not found or is not a Directory");
92       //gdcmStaticErrorMacro( strerror(errno) );
93       return false;
94    }
95 }
96
97 /**
98  * \brief   Get the first entry while visiting Filenames
99  * \return  The first  if found, otherwhise ""
100  */ 
101 std::string DirList::GetFirst()
102 {
103    ItDirList = Filenames.begin();
104    if (ItDirList != Filenames.end())
105       return *ItDirList;
106    return "";
107
108
109 /**
110  * \brief   Get the next entry while visiting Filenames
111  * \return  The next  if found, otherwhise ""
112  */ 
113 std::string DirList::GetNext()
114 {
115    gdcmAssertMacro (ItDirList != Filenames.end())
116    {
117       ++ItDirList;
118       if (ItDirList != Filenames.end())
119          return *ItDirList;      
120    }
121    return "";
122
123
124 //-----------------------------------------------------------------------------
125 // Protected
126
127 //-----------------------------------------------------------------------------
128 // Private
129
130 /**
131  * \brief   Explores a DicomDirSerie
132  *          return number of files found
133  * @param  se DicomDirSerie to explore
134  */
135 int DirList::Explore(DicomDirSerie *se)
136 {
137    int numberOfFiles = 0;
138
139    DicomDirImage *im = se->GetFirstImage();
140    while ( im ) 
141    { 
142       Filenames.push_back( im->GetEntryString(0x0004, 0x1500) );// File name (Referenced File ID)
143       numberOfFiles++;           
144       im = se->GetNextImage();   
145    }
146    return numberOfFiles;
147 }
148    
149 /**
150  * \brief   Explore a directory with possibility of recursion
151  *          return number of files read
152  * @param  dirpath   directory to explore
153  * @param  recursive whether we want recursion or not
154  * @param all whether we want all (i.e; File names + Directory names) default=false
155  */
156 int DirList::Explore(std::string const &dirpath, bool recursive, bool all)
157 {
158    int numberOfFiles = 0;
159    std::string fileName;
160    std::string dirName = Util::NormalizePath(dirpath);
161 #ifdef _MSC_VER
162    WIN32_FIND_DATA fileData;
163    //assert( dirName[dirName.size()-1] == '' );
164    HANDLE hFile = FindFirstFile((dirName+"*").c_str(), &fileData);
165
166    for(BOOL b = (hFile != INVALID_HANDLE_VALUE);
167        b;
168        b = FindNextFile(hFile, &fileData))
169    {
170       fileName = dirName + fileData.cFileName;
171       // avoid infinite loop! 
172       if ( GDCM_NAME_SPACE::Util::GetName(fileName) == "." || GDCM_NAME_SPACE::Util::GetName(fileName) == "..")
173          continue;
174
175       if (all)  // meaningfull only when recursive=false
176       {
177          Filenames.push_back( fileName );
178          numberOfFiles++;
179       }
180       else
181       {
182         if ( !( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )    //is it a regular file?
183         {
184            Filenames.push_back( fileName );
185            numberOfFiles++;
186
187         }
188         else if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) //directory?
189         {
190            if ( GDCM_NAME_SPACE::Util::GetName(fileName)[0] != '.' && recursive ) //we also skip hidden files
191            {
192               numberOfFiles += Explore( fileName, recursive);
193            }
194         }
195         else
196         {
197            gdcmErrorMacro( "Unexpected error" );
198            return -1;
199         }
200      }
201    }
202
203    DWORD dwError = GetLastError();
204    if (hFile != INVALID_HANDLE_VALUE) 
205       FindClose(hFile);
206    if (dwError != ERROR_NO_MORE_FILES) 
207    {
208       LPVOID lpMsgBuf;
209       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
210                     FORMAT_MESSAGE_FROM_SYSTEM|
211                     FORMAT_MESSAGE_IGNORE_INSERTS,
212                     NULL,GetLastError(),
213                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
214                     (LPTSTR) &lpMsgBuf,0,NULL);
215
216       gdcmErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
217                    <<" for the directory : "<<dirName);
218       return -1;
219    }
220
221 #else
222   // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
223   // work on debian for example
224
225    DIR* dir = opendir(dirName.c_str());
226    if (!dir)
227    {
228       return 0;
229    }
230
231    // According to POSIX, the dirent structure contains a field char d_name[]
232    // of unspecified size, with at most NAME_MAX characters preceeding the
233    // terminating null character. Use of other fields will harm the  porta-
234    // bility of your programs.
235
236    struct stat buf;
237    dirent *d;
238    for (d = readdir(dir); d; d = readdir(dir))
239    {
240       fileName = dirName + d->d_name;
241       //std::cout << d->d_name << std::endl;
242       // avoid infinite loop!  
243       if ( GDCM_NAME_SPACE::Util::GetName(d->d_name) == "." || GDCM_NAME_SPACE::Util::GetName(d->d_name) == "..")
244          continue;      
245       
246       if( stat(fileName.c_str(), &buf) != 0 )
247       {
248          gdcmErrorMacro( strerror(errno) );
249       }
250       
251       if (all)  // meaningfull only when recursive=false
252       {
253          Filenames.push_back( fileName );
254          numberOfFiles++;      
255       }
256       else
257       {
258         if ( S_ISREG(buf.st_mode) )    //is it a regular file?
259         {
260            Filenames.push_back( fileName );
261            numberOfFiles++;
262         }
263         else if ( S_ISDIR(buf.st_mode) ) //directory?
264         {
265            if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
266            {
267               numberOfFiles += Explore( fileName, recursive);
268            }
269         }
270         else
271         {
272            gdcmErrorMacro( "Unexpected error" );
273            return -1;
274         }
275      }
276    }
277    
278    if( closedir(dir) != 0 )
279    {
280       gdcmErrorMacro( strerror(errno) );
281    }
282 #endif
283
284   return numberOfFiles;
285 }
286
287 //-----------------------------------------------------------------------------
288 // Print
289 /**
290  * \brief   Print method
291  * @param os ostream to write to 
292  */
293 void DirList::Print(std::ostream &os, std::string const &)
294 {
295    std::copy(Filenames.begin(), Filenames.end(), 
296              std::ostream_iterator<std::string>(os, "\n"));
297 }
298
299 //-----------------------------------------------------------------------------
300 } // end namespace gdcm