OSX regrouping
[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 // 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(__WXMAC__) && !wxOSX_USE_IPHONE) || 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