Compile fixes
[wxWidgets.git] / src / common / dircmn.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/dircmn.cpp
3 // Purpose: wxDir methods common to all implementations
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 19.05.01
7 // RCS-ID: $Id$
8 // Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #ifndef WX_PRECOMP
28 #include "wx/string.h"
29 #include "wx/log.h"
30 #include "wx/intl.h"
31 #include "wx/filefn.h"
32 #include "wx/arrstr.h"
33 #endif //WX_PRECOMP
34
35 #include "wx/dir.h"
36 #include "wx/filename.h"
37
38 // error code of wxFileName::GetSize()
39 extern wxULongLong wxInvalidSize;
40
41 // ============================================================================
42 // implementation
43 // ============================================================================
44
45 // ----------------------------------------------------------------------------
46 // wxDirTraverser
47 // ----------------------------------------------------------------------------
48
49 wxDirTraverseResult
50 wxDirTraverser::OnOpenError(const wxString& WXUNUSED(dirname))
51 {
52 return wxDIR_IGNORE;
53 }
54
55 // ----------------------------------------------------------------------------
56 // wxDir::HasFiles() and HasSubDirs()
57 // ----------------------------------------------------------------------------
58
59 // dumb generic implementation
60
61 bool wxDir::HasFiles(const wxString& spec)
62 {
63 wxString s;
64 return GetFirst(&s, spec, wxDIR_FILES | wxDIR_HIDDEN);
65 }
66
67 // we have a (much) faster version for Unix
68 #if (defined(__CYGWIN__) && defined(__WINDOWS__)) || !defined(__UNIX_LIKE__) || defined(__WXMAC__) || defined(__EMX__) || defined(__WINE__)
69
70 bool wxDir::HasSubDirs(const wxString& spec)
71 {
72 wxString s;
73 return GetFirst(&s, spec, wxDIR_DIRS | wxDIR_HIDDEN);
74 }
75
76 #endif // !Unix
77
78 // ----------------------------------------------------------------------------
79 // wxDir::Traverse()
80 // ----------------------------------------------------------------------------
81
82 size_t wxDir::Traverse(wxDirTraverser& sink,
83 const wxString& filespec,
84 int flags) const
85 {
86 wxCHECK_MSG( IsOpened(), (size_t)-1,
87 _T("dir must be opened before traversing it") );
88
89 // the total number of files found
90 size_t nFiles = 0;
91
92 // the name of this dir with path delimiter at the end
93 wxString prefix = GetName();
94 prefix += wxFILE_SEP_PATH;
95
96 // first, recurse into subdirs
97 if ( flags & wxDIR_DIRS )
98 {
99 wxString dirname;
100 for ( bool cont = GetFirst(&dirname, wxEmptyString, wxDIR_DIRS | (flags & wxDIR_HIDDEN) );
101 cont;
102 cont = cont && GetNext(&dirname) )
103 {
104 const wxString fulldirname = prefix + dirname;
105
106 switch ( sink.OnDir(fulldirname) )
107 {
108 default:
109 wxFAIL_MSG(_T("unexpected OnDir() return value") );
110 // fall through
111
112 case wxDIR_STOP:
113 cont = false;
114 break;
115
116 case wxDIR_CONTINUE:
117 {
118 wxDir subdir;
119
120 // don't give the error messages for the directories
121 // which we can't open: there can be all sorts of good
122 // reason for this (e.g. insufficient privileges) and
123 // this shouldn't be treated as an error -- instead
124 // let the user code decide what to do
125 bool ok;
126 do
127 {
128 wxLogNull noLog;
129 ok = subdir.Open(fulldirname);
130 if ( !ok )
131 {
132 // ask the user code what to do
133 bool tryagain;
134 switch ( sink.OnOpenError(fulldirname) )
135 {
136 default:
137 wxFAIL_MSG(_T("unexpected OnOpenError() return value") );
138 // fall through
139
140 case wxDIR_STOP:
141 cont = false;
142 // fall through
143
144 case wxDIR_IGNORE:
145 tryagain = false;
146 break;
147
148 case wxDIR_CONTINUE:
149 tryagain = true;
150 }
151
152 if ( !tryagain )
153 break;
154 }
155 }
156 while ( !ok );
157
158 if ( ok )
159 {
160 nFiles += subdir.Traverse(sink, filespec, flags);
161 }
162 }
163 break;
164
165 case wxDIR_IGNORE:
166 // nothing to do
167 ;
168 }
169 }
170 }
171
172 // now enum our own files
173 if ( flags & wxDIR_FILES )
174 {
175 flags &= ~wxDIR_DIRS;
176
177 wxString filename;
178 bool cont = GetFirst(&filename, filespec, flags);
179 while ( cont )
180 {
181 wxDirTraverseResult res = sink.OnFile(prefix + filename);
182 if ( res == wxDIR_STOP )
183 break;
184
185 wxASSERT_MSG( res == wxDIR_CONTINUE,
186 _T("unexpected OnFile() return value") );
187
188 nFiles++;
189
190 cont = GetNext(&filename);
191 }
192 }
193
194 return nFiles;
195 }
196
197 // ----------------------------------------------------------------------------
198 // wxDir::GetAllFiles()
199 // ----------------------------------------------------------------------------
200
201 class wxDirTraverserSimple : public wxDirTraverser
202 {
203 public:
204 wxDirTraverserSimple(wxArrayString& files) : m_files(files) { }
205
206 virtual wxDirTraverseResult OnFile(const wxString& filename)
207 {
208 m_files.push_back(filename);
209 return wxDIR_CONTINUE;
210 }
211
212 virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname))
213 {
214 return wxDIR_CONTINUE;
215 }
216
217 private:
218 wxArrayString& m_files;
219
220 DECLARE_NO_COPY_CLASS(wxDirTraverserSimple)
221 };
222
223 /* static */
224 size_t wxDir::GetAllFiles(const wxString& dirname,
225 wxArrayString *files,
226 const wxString& filespec,
227 int flags)
228 {
229 wxCHECK_MSG( files, (size_t)-1, _T("NULL pointer in wxDir::GetAllFiles") );
230
231 size_t nFiles = 0;
232
233 wxDir dir(dirname);
234 if ( dir.IsOpened() )
235 {
236 wxDirTraverserSimple traverser(*files);
237
238 nFiles += dir.Traverse(traverser, filespec, flags);
239 }
240
241 return nFiles;
242 }
243
244 // ----------------------------------------------------------------------------
245 // wxDir::FindFirst()
246 // ----------------------------------------------------------------------------
247
248 class wxDirTraverserFindFirst : public wxDirTraverser
249 {
250 public:
251 wxDirTraverserFindFirst() { }
252
253 virtual wxDirTraverseResult OnFile(const wxString& filename)
254 {
255 m_file = filename;
256 return wxDIR_STOP;
257 }
258
259 virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname))
260 {
261 return wxDIR_CONTINUE;
262 }
263
264 const wxString& GetFile() const
265 {
266 return m_file;
267 }
268
269 private:
270 wxString m_file;
271
272 DECLARE_NO_COPY_CLASS(wxDirTraverserFindFirst)
273 };
274
275 /* static */
276 wxString wxDir::FindFirst(const wxString& dirname,
277 const wxString& filespec,
278 int flags)
279 {
280 wxDir dir(dirname);
281 if ( dir.IsOpened() )
282 {
283 wxDirTraverserFindFirst traverser;
284
285 dir.Traverse(traverser, filespec, flags | wxDIR_FILES);
286 return traverser.GetFile();
287 }
288
289 return wxEmptyString;
290 }
291
292
293 // ----------------------------------------------------------------------------
294 // wxDir::GetTotalSize()
295 // ----------------------------------------------------------------------------
296
297 class wxDirTraverserSumSize : public wxDirTraverser
298 {
299 public:
300 wxDirTraverserSumSize() { }
301
302 virtual wxDirTraverseResult OnFile(const wxString& filename)
303 {
304 wxULongLong sz = wxFileName::GetSize(filename);
305
306 // wxFileName::GetSize won't use this class again as
307 // we're passing it a file and not a directory;
308 // thus we are sure to avoid an endless loop
309 if (sz == wxInvalidSize)
310 {
311 // if the GetSize() failed (this can happen because e.g. a
312 // file is locked by another process), we can proceed but
313 // we need to at least warn the user that the resulting
314 // final size could be not reliable (if e.g. the locked
315 // file is very big).
316 m_skippedFiles.Add(filename);
317 return wxDIR_CONTINUE;
318 }
319
320 m_sz += sz;
321 return wxDIR_CONTINUE;
322 }
323
324 virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname))
325 {
326 return wxDIR_CONTINUE;
327 }
328
329 wxULongLong GetTotalSize() const
330 { return m_sz; }
331 wxArrayString &FilesSkipped()
332 { return m_skippedFiles; }
333
334 protected:
335 wxULongLong m_sz;
336 wxArrayString m_skippedFiles;
337 };
338
339 wxULongLong wxDir::GetTotalSize(const wxString &dirname, wxArrayString *filesSkipped)
340 {
341 if (!wxDirExists(dirname))
342 return wxInvalidSize;
343
344 // to get the size of this directory and its contents we need
345 // to recursively walk it...
346 wxDir dir(dirname);
347 if ( !dir.IsOpened() )
348 return wxInvalidSize;
349
350 wxDirTraverserSumSize traverser;
351 if (dir.Traverse(traverser) == (size_t)-1 ||
352 traverser.GetTotalSize() == 0)
353 return wxInvalidSize;
354
355 if (filesSkipped)
356 *filesSkipped = traverser.FilesSkipped();
357
358 return traverser.GetTotalSize();
359 }
360