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