]>
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; | |
b494c48b | 118 | for ( bool cont = GetFirst(&dirname, wxEmptyString, wxDIR_DIRS | (flags & wxDIR_HIDDEN) ); |
350777b6 | 119 | cont; |
51485b76 | 120 | cont = cont && GetNext(&dirname) ) |
35332784 | 121 | { |
350777b6 | 122 | const wxString fulldirname = prefix + dirname; |
35332784 | 123 | |
350777b6 | 124 | switch ( sink.OnDir(fulldirname) ) |
35332784 | 125 | { |
350777b6 | 126 | default: |
9a83f860 | 127 | wxFAIL_MSG(wxT("unexpected OnDir() return value") ); |
350777b6 VZ |
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: | |
9a83f860 | 155 | wxFAIL_MSG(wxT("unexpected OnOpenError() return value") ); |
350777b6 VZ |
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 | ; | |
35332784 | 186 | } |
35332784 VZ |
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, | |
9a83f860 | 204 | wxT("unexpected OnFile() return value") ); |
35332784 VZ |
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 | { | |
df5168c4 | 226 | m_files.push_back(filename); |
35332784 VZ |
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; | |
fc7a2a60 | 237 | |
c0c133e1 | 238 | wxDECLARE_NO_COPY_CLASS(wxDirTraverserSimple); |
35332784 VZ |
239 | }; |
240 | ||
241 | /* static */ | |
242 | size_t wxDir::GetAllFiles(const wxString& dirname, | |
243 | wxArrayString *files, | |
244 | const wxString& filespec, | |
245 | int flags) | |
246 | { | |
9a83f860 | 247 | wxCHECK_MSG( files, (size_t)-1, wxT("NULL pointer in wxDir::GetAllFiles") ); |
35332784 VZ |
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 | } | |
d1af8e2d VZ |
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 | ||
c0c133e1 | 290 | wxDECLARE_NO_COPY_CLASS(wxDirTraverserFindFirst); |
d1af8e2d VZ |
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 | } | |
23b8a262 JS |
309 | |
310 | ||
311 | // ---------------------------------------------------------------------------- | |
312 | // wxDir::GetTotalSize() | |
313 | // ---------------------------------------------------------------------------- | |
314 | ||
bd08f2f7 VZ |
315 | #if wxUSE_LONGLONG |
316 | ||
23b8a262 JS |
317 | class wxDirTraverserSumSize : public wxDirTraverser |
318 | { | |
319 | public: | |
a8df8389 | 320 | wxDirTraverserSumSize() { } |
23b8a262 JS |
321 | |
322 | virtual wxDirTraverseResult OnFile(const wxString& filename) | |
323 | { | |
23b8a262 JS |
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 | |
191d6608 VZ |
327 | wxULongLong sz = wxFileName::GetSize(filename); |
328 | ||
23b8a262 JS |
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; } | |
191d6608 | 351 | const wxArrayString& GetSkippedFiles() const |
23b8a262 JS |
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; | |
852febd8 | 371 | if (dir.Traverse(traverser) == (size_t)-1 ) |
23b8a262 JS |
372 | return wxInvalidSize; |
373 | ||
374 | if (filesSkipped) | |
191d6608 | 375 | *filesSkipped = traverser.GetSkippedFiles(); |
23b8a262 JS |
376 | |
377 | return traverser.GetTotalSize(); | |
378 | } | |
379 | ||
f422aafe VZ |
380 | #endif // wxUSE_LONGLONG |
381 | ||
d38315df FM |
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 | } | |
ce00f59b | 403 |