Add missing wx/scopeguard.h include to fix the build.
[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 // Licence: 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 // ============================================================================
39 // implementation
40 // ============================================================================
41
42 // ----------------------------------------------------------------------------
43 // wxDirTraverser
44 // ----------------------------------------------------------------------------
45
46 wxDirTraverseResult
47 wxDirTraverser::OnOpenError(const wxString& WXUNUSED(dirname))
48 {
49 return wxDIR_IGNORE;
50 }
51
52 // ----------------------------------------------------------------------------
53 // wxDir::HasFiles() and HasSubDirs()
54 // ----------------------------------------------------------------------------
55
56 // dumb generic implementation
57
58 bool wxDir::HasFiles(const wxString& spec) const
59 {
60 wxString s;
61 return GetFirst(&s, spec, wxDIR_FILES | wxDIR_HIDDEN);
62 }
63
64 // we have a (much) faster version for Unix
65 #if (defined(__CYGWIN__) && defined(__WINDOWS__)) || !defined(__UNIX_LIKE__) || defined(__EMX__) || defined(__WINE__)
66
67 bool wxDir::HasSubDirs(const wxString& spec) const
68 {
69 wxString s;
70 return GetFirst(&s, spec, wxDIR_DIRS | wxDIR_HIDDEN);
71 }
72
73 #endif // !Unix
74
75 // ----------------------------------------------------------------------------
76 // wxDir::GetNameWithSep()
77 // ----------------------------------------------------------------------------
78
79 wxString wxDir::GetNameWithSep() const
80 {
81 // Note that for historical reasons (i.e. because GetName() was there
82 // first) we implement this one in terms of GetName() even though it might
83 // actually make more sense to reverse this logic.
84
85 wxString name = GetName();
86 if ( !name.empty() )
87 {
88 // Notice that even though GetName() isn't supposed to return the
89 // separator, it can still be present for the root directory name.
90 if ( name.Last() != wxFILE_SEP_PATH )
91 name += wxFILE_SEP_PATH;
92 }
93
94 return name;
95 }
96
97 // ----------------------------------------------------------------------------
98 // wxDir::Traverse()
99 // ----------------------------------------------------------------------------
100
101 size_t wxDir::Traverse(wxDirTraverser& sink,
102 const wxString& filespec,
103 int flags) const
104 {
105 wxCHECK_MSG( IsOpened(), (size_t)-1,
106 wxT("dir must be opened before traversing it") );
107
108 // the total number of files found
109 size_t nFiles = 0;
110
111 // the name of this dir with path delimiter at the end
112 const wxString prefix = GetNameWithSep();
113
114 // first, recurse into subdirs
115 if ( flags & wxDIR_DIRS )
116 {
117 wxString dirname;
118 for ( bool cont = GetFirst(&dirname, wxEmptyString, wxDIR_DIRS | (flags & wxDIR_HIDDEN) );
119 cont;
120 cont = cont && GetNext(&dirname) )
121 {
122 const wxString fulldirname = prefix + dirname;
123
124 switch ( sink.OnDir(fulldirname) )
125 {
126 default:
127 wxFAIL_MSG(wxT("unexpected OnDir() return value") );
128 // fall through
129
130 case wxDIR_STOP:
131 cont = false;
132 break;
133
134 case wxDIR_CONTINUE:
135 {
136 wxDir subdir;
137
138 // don't give the error messages for the directories
139 // which we can't open: there can be all sorts of good
140 // reason for this (e.g. insufficient privileges) and
141 // this shouldn't be treated as an error -- instead
142 // let the user code decide what to do
143 bool ok;
144 do
145 {
146 wxLogNull noLog;
147 ok = subdir.Open(fulldirname);
148 if ( !ok )
149 {
150 // ask the user code what to do
151 bool tryagain;
152 switch ( sink.OnOpenError(fulldirname) )
153 {
154 default:
155 wxFAIL_MSG(wxT("unexpected OnOpenError() return value") );
156 // fall through
157
158 case wxDIR_STOP:
159 cont = false;
160 // fall through
161
162 case wxDIR_IGNORE:
163 tryagain = false;
164 break;
165
166 case wxDIR_CONTINUE:
167 tryagain = true;
168 }
169
170 if ( !tryagain )
171 break;
172 }
173 }
174 while ( !ok );
175
176 if ( ok )
177 {
178 nFiles += subdir.Traverse(sink, filespec, flags);
179 }
180 }
181 break;
182
183 case wxDIR_IGNORE:
184 // nothing to do
185 ;
186 }
187 }
188 }
189
190 // now enum our own files
191 if ( flags & wxDIR_FILES )
192 {
193 flags &= ~wxDIR_DIRS;
194
195 wxString filename;
196 bool cont = GetFirst(&filename, filespec, flags);
197 while ( cont )
198 {
199 wxDirTraverseResult res = sink.OnFile(prefix + filename);
200 if ( res == wxDIR_STOP )
201 break;
202
203 wxASSERT_MSG( res == wxDIR_CONTINUE,
204 wxT("unexpected OnFile() return value") );
205
206 nFiles++;
207
208 cont = GetNext(&filename);
209 }
210 }
211
212 return nFiles;
213 }
214
215 // ----------------------------------------------------------------------------
216 // wxDir::GetAllFiles()
217 // ----------------------------------------------------------------------------
218
219 class wxDirTraverserSimple : public wxDirTraverser
220 {
221 public:
222 wxDirTraverserSimple(wxArrayString& files) : m_files(files) { }
223
224 virtual wxDirTraverseResult OnFile(const wxString& filename)
225 {
226 m_files.push_back(filename);
227 return wxDIR_CONTINUE;
228 }
229
230 virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname))
231 {
232 return wxDIR_CONTINUE;
233 }
234
235 private:
236 wxArrayString& m_files;
237
238 wxDECLARE_NO_COPY_CLASS(wxDirTraverserSimple);
239 };
240
241 /* static */
242 size_t wxDir::GetAllFiles(const wxString& dirname,
243 wxArrayString *files,
244 const wxString& filespec,
245 int flags)
246 {
247 wxCHECK_MSG( files, (size_t)-1, wxT("NULL pointer in wxDir::GetAllFiles") );
248
249 size_t nFiles = 0;
250
251 wxDir dir(dirname);
252 if ( dir.IsOpened() )
253 {
254 wxDirTraverserSimple traverser(*files);
255
256 nFiles += dir.Traverse(traverser, filespec, flags);
257 }
258
259 return nFiles;
260 }
261
262 // ----------------------------------------------------------------------------
263 // wxDir::FindFirst()
264 // ----------------------------------------------------------------------------
265
266 class wxDirTraverserFindFirst : public wxDirTraverser
267 {
268 public:
269 wxDirTraverserFindFirst() { }
270
271 virtual wxDirTraverseResult OnFile(const wxString& filename)
272 {
273 m_file = filename;
274 return wxDIR_STOP;
275 }
276
277 virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname))
278 {
279 return wxDIR_CONTINUE;
280 }
281
282 const wxString& GetFile() const
283 {
284 return m_file;
285 }
286
287 private:
288 wxString m_file;
289
290 wxDECLARE_NO_COPY_CLASS(wxDirTraverserFindFirst);
291 };
292
293 /* static */
294 wxString wxDir::FindFirst(const wxString& dirname,
295 const wxString& filespec,
296 int flags)
297 {
298 wxDir dir(dirname);
299 if ( dir.IsOpened() )
300 {
301 wxDirTraverserFindFirst traverser;
302
303 dir.Traverse(traverser, filespec, flags | wxDIR_FILES);
304 return traverser.GetFile();
305 }
306
307 return wxEmptyString;
308 }
309
310
311 // ----------------------------------------------------------------------------
312 // wxDir::GetTotalSize()
313 // ----------------------------------------------------------------------------
314
315 #if wxUSE_LONGLONG
316
317 class wxDirTraverserSumSize : public wxDirTraverser
318 {
319 public:
320 wxDirTraverserSumSize() { }
321
322 virtual wxDirTraverseResult OnFile(const wxString& filename)
323 {
324 // wxFileName::GetSize won't use this class again as
325 // we're passing it a file and not a directory;
326 // thus we are sure to avoid an endless loop
327 wxULongLong sz = wxFileName::GetSize(filename);
328
329 if (sz == wxInvalidSize)
330 {
331 // if the GetSize() failed (this can happen because e.g. a
332 // file is locked by another process), we can proceed but
333 // we need to at least warn the user that the resulting
334 // final size could be not reliable (if e.g. the locked
335 // file is very big).
336 m_skippedFiles.Add(filename);
337 return wxDIR_CONTINUE;
338 }
339
340 m_sz += sz;
341 return wxDIR_CONTINUE;
342 }
343
344 virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname))
345 {
346 return wxDIR_CONTINUE;
347 }
348
349 wxULongLong GetTotalSize() const
350 { return m_sz; }
351 const wxArrayString& GetSkippedFiles() const
352 { return m_skippedFiles; }
353
354 protected:
355 wxULongLong m_sz;
356 wxArrayString m_skippedFiles;
357 };
358
359 wxULongLong wxDir::GetTotalSize(const wxString &dirname, wxArrayString *filesSkipped)
360 {
361 if (!wxDirExists(dirname))
362 return wxInvalidSize;
363
364 // to get the size of this directory and its contents we need
365 // to recursively walk it...
366 wxDir dir(dirname);
367 if ( !dir.IsOpened() )
368 return wxInvalidSize;
369
370 wxDirTraverserSumSize traverser;
371 if (dir.Traverse(traverser) == (size_t)-1 )
372 return wxInvalidSize;
373
374 if (filesSkipped)
375 *filesSkipped = traverser.GetSkippedFiles();
376
377 return traverser.GetTotalSize();
378 }
379
380 #endif // wxUSE_LONGLONG
381
382 // ----------------------------------------------------------------------------
383 // wxDir helpers
384 // ----------------------------------------------------------------------------
385
386 /* static */
387 bool wxDir::Exists(const wxString& dir)
388 {
389 return wxFileName::DirExists(dir);
390 }
391
392 /* static */
393 bool wxDir::Make(const wxString &dir, int perm, int flags)
394 {
395 return wxFileName::Mkdir(dir, perm, flags);
396 }
397
398 /* static */
399 bool wxDir::Remove(const wxString &dir, int flags)
400 {
401 return wxFileName::Rmdir(dir, flags);
402 }
403