]> Creatis software - gdcm.git/blob - src/gdcmDirList.cxx
avoid Doxygen Warnings
[gdcm.git] / src / gdcmDirList.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: gdcmDirList.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/09/17 12:21:56 $
7   Version:   $Revision: 1.63 $
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)
48 {
49    DirName = dirName;
50    Explore(dirName, recursive);
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       gdcmStaticErrorMacro( strerror(errno) );
92       return false;
93    }
94 }
95
96 /**
97  * \brief   Get the first entry while visiting Filenames
98  * \return  The first  if found, otherwhise ""
99  */ 
100 std::string DirList::GetFirst()
101 {
102    ItDirList = Filenames.begin();
103    if (ItDirList != Filenames.end())
104       return *ItDirList;
105    return "";
106
107
108 /**
109  * \brief   Get the next entry while visiting Filenames
110  * \return  The next  if found, otherwhise ""
111  */ 
112 std::string DirList::GetNext()
113 {
114    gdcmAssertMacro (ItDirList != Filenames.end())
115    {
116       ++ItDirList;
117       if (ItDirList != Filenames.end())
118          return *ItDirList;      
119    }
120    return "";
121
122
123 //-----------------------------------------------------------------------------
124 // Protected
125
126 //-----------------------------------------------------------------------------
127 // Private
128
129 /**
130  * \brief   Explores a DicomDirSerie
131  *          return number of files found
132  * @param  se DicomDirSerie to explore
133  */
134 int DirList::Explore(DicomDirSerie *se)
135 {
136    int numberOfFiles = 0;
137
138    DicomDirImage *im = se->GetFirstImage();
139    while ( im ) 
140    { 
141       Filenames.push_back( im->GetEntryString(0x0004, 0x1500) );// File name (Referenced File ID)
142       numberOfFiles++;           
143       im = se->GetNextImage();   
144    }
145    return numberOfFiles;
146 }   
147    
148 /**
149  * \brief   Explore a directory with possibility of recursion
150  *          return number of files read
151  * @param  dirpath   directory to explore
152  * @param  recursive whether we want recursion or not
153  */
154 int DirList::Explore(std::string const &dirpath, bool recursive)
155 {
156    int numberOfFiles = 0;
157    std::string fileName;
158    std::string dirName = Util::NormalizePath(dirpath);
159 #ifdef _MSC_VER
160    WIN32_FIND_DATA fileData;
161    //assert( dirName[dirName.size()-1] == '' );
162    HANDLE hFile = FindFirstFile((dirName+"*").c_str(), &fileData);
163
164    for(BOOL b = (hFile != INVALID_HANDLE_VALUE); b;
165        b = FindNextFile(hFile, &fileData))
166    {
167       fileName = fileData.cFileName;
168       if ( fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
169       {
170          // Need to check for . and .. to avoid infinite loop
171          if ( fileName != "." && fileName != ".." && recursive )
172          {
173             numberOfFiles += Explore(dirName+fileName,recursive);
174          }
175       }
176       else
177       {
178          Filenames.push_back(dirName+fileName);
179          numberOfFiles++;
180       }
181    }
182    DWORD dwError = GetLastError();
183    if (hFile != INVALID_HANDLE_VALUE) 
184       FindClose(hFile);
185    if (dwError != ERROR_NO_MORE_FILES) 
186    {
187       LPVOID lpMsgBuf;
188       FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
189                     FORMAT_MESSAGE_FROM_SYSTEM|
190                     FORMAT_MESSAGE_IGNORE_INSERTS,
191                     NULL,GetLastError(),
192                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
193                     (LPTSTR) &lpMsgBuf,0,NULL);
194
195       gdcmErrorMacro("FindNextFile error. Error is " << (char *)lpMsgBuf
196                    <<" for the directory : "<<dirName);
197       return -1;
198    }
199
200 #else
201   // Real POSIX implementation: scandir is a BSD extension only, and doesn't 
202   // work on debian for example
203
204    DIR* dir = opendir(dirName.c_str());
205    if (!dir)
206    {
207       return 0;
208    }
209
210    // According to POSIX, the dirent structure contains a field char d_name[]
211    // of unspecified size, with at most NAME_MAX characters preceeding the
212    // terminating null character. Use of other fields will harm the  porta-
213    // bility of your programs.
214
215    struct stat buf;
216    dirent *d;
217    for (d = readdir(dir); d; d = readdir(dir))
218    {
219       fileName = dirName + d->d_name;
220       if( stat(fileName.c_str(), &buf) != 0 )
221       {
222          gdcmErrorMacro( strerror(errno) );
223       }
224       if ( S_ISREG(buf.st_mode) )    //is it a regular file?
225       {
226          Filenames.push_back( fileName );
227          numberOfFiles++;
228       }
229       else if ( S_ISDIR(buf.st_mode) ) //directory?
230       {
231          if ( d->d_name[0] != '.' && recursive ) //we also skip hidden files
232          {
233             numberOfFiles += Explore( fileName, recursive);
234          }
235       }
236       else
237       {
238          gdcmErrorMacro( "Unexpected error" );
239          return -1;
240       }
241    }
242    if( closedir(dir) != 0 )
243    {
244       gdcmErrorMacro( strerror(errno) );
245    }
246 #endif
247
248   return numberOfFiles;
249 }
250
251 //-----------------------------------------------------------------------------
252 // Print
253 /**
254  * \brief   Print method
255  * @param os ostream to write to 
256  */
257 void DirList::Print(std::ostream &os, std::string const &)
258 {
259    std::copy(Filenames.begin(), Filenames.end(), 
260              std::ostream_iterator<std::string>(os, "\n"));
261 }
262
263 //-----------------------------------------------------------------------------
264 } // end namespace gdcm