]> git.saurik.com Git - wxWidgets.git/blame - src/common/dircmn.cpp
Pass length including the null-terminator to cWC2MB
[wxWidgets.git] / src / common / dircmn.cpp
CommitLineData
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>
65571936 9// License: 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
46wxDirTraverseResult
47wxDirTraverser::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
58bool wxDir::HasFiles(const wxString& spec)
59{
60 wxString s;
61 return GetFirst(&s, spec, wxDIR_FILES | wxDIR_HIDDEN);
62}
63
64// we have a (much) faster version for Unix
c0e7c9a9 65#if (defined(__CYGWIN__) && defined(__WINDOWS__)) || !defined(__UNIX_LIKE__) || defined(__WXMAC__) || defined(__EMX__) || defined(__WINE__)
1357a7dd
VZ
66
67bool wxDir::HasSubDirs(const wxString& spec)
68{
69 wxString s;
70 return GetFirst(&s, spec, wxDIR_DIRS | wxDIR_HIDDEN);
71}
72
73#endif // !Unix
74
75// ----------------------------------------------------------------------------
35332784
VZ
76// wxDir::Traverse()
77// ----------------------------------------------------------------------------
78
79size_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;
b494c48b 97 for ( bool cont = GetFirst(&dirname, wxEmptyString, wxDIR_DIRS | (flags & wxDIR_HIDDEN) );
350777b6 98 cont;
51485b76 99 cont = cont && GetNext(&dirname) )
35332784 100 {
350777b6 101 const wxString fulldirname = prefix + dirname;
35332784 102
350777b6 103 switch ( sink.OnDir(fulldirname) )
35332784 104 {
350777b6
VZ
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 ;
35332784 165 }
35332784
VZ
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
198class wxDirTraverserSimple : public wxDirTraverser
199{
200public:
201 wxDirTraverserSimple(wxArrayString& files) : m_files(files) { }
202
203 virtual wxDirTraverseResult OnFile(const wxString& filename)
204 {
df5168c4 205 m_files.push_back(filename);
35332784
VZ
206 return wxDIR_CONTINUE;
207 }
208
209 virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname))
210 {
211 return wxDIR_CONTINUE;
212 }
213
214private:
215 wxArrayString& m_files;
fc7a2a60
VZ
216
217 DECLARE_NO_COPY_CLASS(wxDirTraverserSimple)
35332784
VZ
218};
219
220/* static */
221size_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}
d1af8e2d
VZ
240
241// ----------------------------------------------------------------------------
242// wxDir::FindFirst()
243// ----------------------------------------------------------------------------
244
245class wxDirTraverserFindFirst : public wxDirTraverser
246{
247public:
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
266private:
267 wxString m_file;
268
269 DECLARE_NO_COPY_CLASS(wxDirTraverserFindFirst)
270};
271
272/* static */
273wxString 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}
23b8a262
JS
288
289
290// ----------------------------------------------------------------------------
291// wxDir::GetTotalSize()
292// ----------------------------------------------------------------------------
293
bd08f2f7
VZ
294#if wxUSE_LONGLONG
295
23b8a262
JS
296class wxDirTraverserSumSize : public wxDirTraverser
297{
298public:
a8df8389 299 wxDirTraverserSumSize() { }
23b8a262
JS
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
333protected:
334 wxULongLong m_sz;
335 wxArrayString m_skippedFiles;
336};
337
338wxULongLong 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
bd08f2f7 360#endif // wxUSE_LONGLONG