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