]>
Commit | Line | Data |
---|---|---|
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 | // ============================================================================ | |
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::Traverse() | |
77 | // ---------------------------------------------------------------------------- | |
78 | ||
79 | size_t wxDir::Traverse(wxDirTraverser& sink, | |
80 | const wxString& filespec, | |
81 | int flags) const | |
82 | { | |
83 | wxCHECK_MSG( IsOpened(), (size_t)-1, | |
84 | _T("dir must be opened before traversing it") ); | |
85 | ||
86 | // the total number of files found | |
87 | size_t nFiles = 0; | |
88 | ||
89 | // the name of this dir with path delimiter at the end | |
90 | wxString prefix = GetName(); | |
91 | prefix += wxFILE_SEP_PATH; | |
92 | ||
93 | // first, recurse into subdirs | |
94 | if ( flags & wxDIR_DIRS ) | |
95 | { | |
96 | wxString dirname; | |
97 | for ( bool cont = GetFirst(&dirname, wxEmptyString, wxDIR_DIRS | (flags & wxDIR_HIDDEN) ); | |
98 | cont; | |
99 | cont = cont && GetNext(&dirname) ) | |
100 | { | |
101 | const wxString fulldirname = prefix + dirname; | |
102 | ||
103 | switch ( sink.OnDir(fulldirname) ) | |
104 | { | |
105 | default: | |
106 | wxFAIL_MSG(_T("unexpected OnDir() return value") ); | |
107 | // fall through | |
108 | ||
109 | case wxDIR_STOP: | |
110 | cont = false; | |
111 | break; | |
112 | ||
113 | case wxDIR_CONTINUE: | |
114 | { | |
115 | wxDir subdir; | |
116 | ||
117 | // don't give the error messages for the directories | |
118 | // which we can't open: there can be all sorts of good | |
119 | // reason for this (e.g. insufficient privileges) and | |
120 | // this shouldn't be treated as an error -- instead | |
121 | // let the user code decide what to do | |
122 | bool ok; | |
123 | do | |
124 | { | |
125 | wxLogNull noLog; | |
126 | ok = subdir.Open(fulldirname); | |
127 | if ( !ok ) | |
128 | { | |
129 | // ask the user code what to do | |
130 | bool tryagain; | |
131 | switch ( sink.OnOpenError(fulldirname) ) | |
132 | { | |
133 | default: | |
134 | wxFAIL_MSG(_T("unexpected OnOpenError() return value") ); | |
135 | // fall through | |
136 | ||
137 | case wxDIR_STOP: | |
138 | cont = false; | |
139 | // fall through | |
140 | ||
141 | case wxDIR_IGNORE: | |
142 | tryagain = false; | |
143 | break; | |
144 | ||
145 | case wxDIR_CONTINUE: | |
146 | tryagain = true; | |
147 | } | |
148 | ||
149 | if ( !tryagain ) | |
150 | break; | |
151 | } | |
152 | } | |
153 | while ( !ok ); | |
154 | ||
155 | if ( ok ) | |
156 | { | |
157 | nFiles += subdir.Traverse(sink, filespec, flags); | |
158 | } | |
159 | } | |
160 | break; | |
161 | ||
162 | case wxDIR_IGNORE: | |
163 | // nothing to do | |
164 | ; | |
165 | } | |
166 | } | |
167 | } | |
168 | ||
169 | // now enum our own files | |
170 | if ( flags & wxDIR_FILES ) | |
171 | { | |
172 | flags &= ~wxDIR_DIRS; | |
173 | ||
174 | wxString filename; | |
175 | bool cont = GetFirst(&filename, filespec, flags); | |
176 | while ( cont ) | |
177 | { | |
178 | wxDirTraverseResult res = sink.OnFile(prefix + filename); | |
179 | if ( res == wxDIR_STOP ) | |
180 | break; | |
181 | ||
182 | wxASSERT_MSG( res == wxDIR_CONTINUE, | |
183 | _T("unexpected OnFile() return value") ); | |
184 | ||
185 | nFiles++; | |
186 | ||
187 | cont = GetNext(&filename); | |
188 | } | |
189 | } | |
190 | ||
191 | return nFiles; | |
192 | } | |
193 | ||
194 | // ---------------------------------------------------------------------------- | |
195 | // wxDir::GetAllFiles() | |
196 | // ---------------------------------------------------------------------------- | |
197 | ||
198 | class wxDirTraverserSimple : public wxDirTraverser | |
199 | { | |
200 | public: | |
201 | wxDirTraverserSimple(wxArrayString& files) : m_files(files) { } | |
202 | ||
203 | virtual wxDirTraverseResult OnFile(const wxString& filename) | |
204 | { | |
205 | m_files.push_back(filename); | |
206 | return wxDIR_CONTINUE; | |
207 | } | |
208 | ||
209 | virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname)) | |
210 | { | |
211 | return wxDIR_CONTINUE; | |
212 | } | |
213 | ||
214 | private: | |
215 | wxArrayString& m_files; | |
216 | ||
217 | DECLARE_NO_COPY_CLASS(wxDirTraverserSimple) | |
218 | }; | |
219 | ||
220 | /* static */ | |
221 | size_t wxDir::GetAllFiles(const wxString& dirname, | |
222 | wxArrayString *files, | |
223 | const wxString& filespec, | |
224 | int flags) | |
225 | { | |
226 | wxCHECK_MSG( files, (size_t)-1, _T("NULL pointer in wxDir::GetAllFiles") ); | |
227 | ||
228 | size_t nFiles = 0; | |
229 | ||
230 | wxDir dir(dirname); | |
231 | if ( dir.IsOpened() ) | |
232 | { | |
233 | wxDirTraverserSimple traverser(*files); | |
234 | ||
235 | nFiles += dir.Traverse(traverser, filespec, flags); | |
236 | } | |
237 | ||
238 | return nFiles; | |
239 | } | |
240 | ||
241 | // ---------------------------------------------------------------------------- | |
242 | // wxDir::FindFirst() | |
243 | // ---------------------------------------------------------------------------- | |
244 | ||
245 | class wxDirTraverserFindFirst : public wxDirTraverser | |
246 | { | |
247 | public: | |
248 | wxDirTraverserFindFirst() { } | |
249 | ||
250 | virtual wxDirTraverseResult OnFile(const wxString& filename) | |
251 | { | |
252 | m_file = filename; | |
253 | return wxDIR_STOP; | |
254 | } | |
255 | ||
256 | virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname)) | |
257 | { | |
258 | return wxDIR_CONTINUE; | |
259 | } | |
260 | ||
261 | const wxString& GetFile() const | |
262 | { | |
263 | return m_file; | |
264 | } | |
265 | ||
266 | private: | |
267 | wxString m_file; | |
268 | ||
269 | DECLARE_NO_COPY_CLASS(wxDirTraverserFindFirst) | |
270 | }; | |
271 | ||
272 | /* static */ | |
273 | wxString wxDir::FindFirst(const wxString& dirname, | |
274 | const wxString& filespec, | |
275 | int flags) | |
276 | { | |
277 | wxDir dir(dirname); | |
278 | if ( dir.IsOpened() ) | |
279 | { | |
280 | wxDirTraverserFindFirst traverser; | |
281 | ||
282 | dir.Traverse(traverser, filespec, flags | wxDIR_FILES); | |
283 | return traverser.GetFile(); | |
284 | } | |
285 | ||
286 | return wxEmptyString; | |
287 | } | |
288 | ||
289 | ||
290 | // ---------------------------------------------------------------------------- | |
291 | // wxDir::GetTotalSize() | |
292 | // ---------------------------------------------------------------------------- | |
293 | ||
294 | #if wxUSE_LONGLONG | |
295 | ||
296 | class wxDirTraverserSumSize : public wxDirTraverser | |
297 | { | |
298 | public: | |
299 | wxDirTraverserSumSize() { } | |
300 | ||
301 | virtual wxDirTraverseResult OnFile(const wxString& filename) | |
302 | { | |
303 | wxULongLong sz = wxFileName::GetSize(filename); | |
304 | ||
305 | // wxFileName::GetSize won't use this class again as | |
306 | // we're passing it a file and not a directory; | |
307 | // thus we are sure to avoid an endless loop | |
308 | if (sz == wxInvalidSize) | |
309 | { | |
310 | // if the GetSize() failed (this can happen because e.g. a | |
311 | // file is locked by another process), we can proceed but | |
312 | // we need to at least warn the user that the resulting | |
313 | // final size could be not reliable (if e.g. the locked | |
314 | // file is very big). | |
315 | m_skippedFiles.Add(filename); | |
316 | return wxDIR_CONTINUE; | |
317 | } | |
318 | ||
319 | m_sz += sz; | |
320 | return wxDIR_CONTINUE; | |
321 | } | |
322 | ||
323 | virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname)) | |
324 | { | |
325 | return wxDIR_CONTINUE; | |
326 | } | |
327 | ||
328 | wxULongLong GetTotalSize() const | |
329 | { return m_sz; } | |
330 | wxArrayString &FilesSkipped() | |
331 | { return m_skippedFiles; } | |
332 | ||
333 | protected: | |
334 | wxULongLong m_sz; | |
335 | wxArrayString m_skippedFiles; | |
336 | }; | |
337 | ||
338 | wxULongLong wxDir::GetTotalSize(const wxString &dirname, wxArrayString *filesSkipped) | |
339 | { | |
340 | if (!wxDirExists(dirname)) | |
341 | return wxInvalidSize; | |
342 | ||
343 | // to get the size of this directory and its contents we need | |
344 | // to recursively walk it... | |
345 | wxDir dir(dirname); | |
346 | if ( !dir.IsOpened() ) | |
347 | return wxInvalidSize; | |
348 | ||
349 | wxDirTraverserSumSize traverser; | |
350 | if (dir.Traverse(traverser) == (size_t)-1 || | |
351 | traverser.GetTotalSize() == 0) | |
352 | return wxInvalidSize; | |
353 | ||
354 | if (filesSkipped) | |
355 | *filesSkipped = traverser.FilesSkipped(); | |
356 | ||
357 | return traverser.GetTotalSize(); | |
358 | } | |
359 | ||
360 | #endif // wxUSE_LONGLONG |