1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/dircmn.cpp
3 // Purpose: wxDir methods common to all implementations
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // License: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
28 #include "wx/string.h"
31 #include "wx/filefn.h"
32 #include "wx/arrstr.h"
36 #include "wx/filename.h"
38 // error code of wxFileName::GetSize()
39 extern wxULongLong wxInvalidSize
;
41 // ============================================================================
43 // ============================================================================
45 // ----------------------------------------------------------------------------
47 // ----------------------------------------------------------------------------
50 wxDirTraverser
::OnOpenError(const wxString
& WXUNUSED(dirname
))
55 // ----------------------------------------------------------------------------
56 // wxDir::HasFiles() and HasSubDirs()
57 // ----------------------------------------------------------------------------
59 // dumb generic implementation
61 bool wxDir
::HasFiles(const wxString
& spec
)
64 return GetFirst(&s
, spec
, wxDIR_FILES
| wxDIR_HIDDEN
);
67 // we have a (much) faster version for Unix
68 #if (defined(__CYGWIN__) && defined(__WINDOWS__)) || !defined(__UNIX_LIKE__) || defined(__WXMAC__) || defined(__EMX__) || defined(__WINE__)
70 bool wxDir
::HasSubDirs(const wxString
& spec
)
73 return GetFirst(&s
, spec
, wxDIR_DIRS
| wxDIR_HIDDEN
);
78 // ----------------------------------------------------------------------------
80 // ----------------------------------------------------------------------------
82 size_t wxDir
::Traverse(wxDirTraverser
& sink
,
83 const wxString
& filespec
,
86 wxCHECK_MSG( IsOpened(), (size_t)-1,
87 _T("dir must be opened before traversing it") );
89 // the total number of files found
92 // the name of this dir with path delimiter at the end
93 wxString prefix
= GetName();
94 prefix
+= wxFILE_SEP_PATH
;
96 // first, recurse into subdirs
97 if ( flags
& wxDIR_DIRS
)
100 for ( bool cont
= GetFirst(&dirname
, wxEmptyString
, wxDIR_DIRS
| (flags
& wxDIR_HIDDEN
) );
102 cont
= cont
&& GetNext(&dirname
) )
104 const wxString fulldirname
= prefix
+ dirname
;
106 switch ( sink
.OnDir(fulldirname
) )
109 wxFAIL_MSG(_T("unexpected OnDir() return value") );
120 // don't give the error messages for the directories
121 // which we can't open: there can be all sorts of good
122 // reason for this (e.g. insufficient privileges) and
123 // this shouldn't be treated as an error -- instead
124 // let the user code decide what to do
129 ok
= subdir
.Open(fulldirname
);
132 // ask the user code what to do
134 switch ( sink
.OnOpenError(fulldirname
) )
137 wxFAIL_MSG(_T("unexpected OnOpenError() return value") );
160 nFiles
+= subdir
.Traverse(sink
, filespec
, flags
);
172 // now enum our own files
173 if ( flags
& wxDIR_FILES
)
175 flags
&= ~wxDIR_DIRS
;
178 bool cont
= GetFirst(&filename
, filespec
, flags
);
181 wxDirTraverseResult res
= sink
.OnFile(prefix
+ filename
);
182 if ( res
== wxDIR_STOP
)
185 wxASSERT_MSG( res
== wxDIR_CONTINUE
,
186 _T("unexpected OnFile() return value") );
190 cont
= GetNext(&filename
);
197 // ----------------------------------------------------------------------------
198 // wxDir::GetAllFiles()
199 // ----------------------------------------------------------------------------
201 class wxDirTraverserSimple
: public wxDirTraverser
204 wxDirTraverserSimple(wxArrayString
& files
) : m_files(files
) { }
206 virtual wxDirTraverseResult
OnFile(const wxString
& filename
)
208 m_files
.push_back(filename
);
209 return wxDIR_CONTINUE
;
212 virtual wxDirTraverseResult
OnDir(const wxString
& WXUNUSED(dirname
))
214 return wxDIR_CONTINUE
;
218 wxArrayString
& m_files
;
220 DECLARE_NO_COPY_CLASS(wxDirTraverserSimple
)
224 size_t wxDir
::GetAllFiles(const wxString
& dirname
,
225 wxArrayString
*files
,
226 const wxString
& filespec
,
229 wxCHECK_MSG( files
, (size_t)-1, _T("NULL pointer in wxDir::GetAllFiles") );
234 if ( dir
.IsOpened() )
236 wxDirTraverserSimple
traverser(*files
);
238 nFiles
+= dir
.Traverse(traverser
, filespec
, flags
);
244 // ----------------------------------------------------------------------------
245 // wxDir::FindFirst()
246 // ----------------------------------------------------------------------------
248 class wxDirTraverserFindFirst
: public wxDirTraverser
251 wxDirTraverserFindFirst() { }
253 virtual wxDirTraverseResult
OnFile(const wxString
& filename
)
259 virtual wxDirTraverseResult
OnDir(const wxString
& WXUNUSED(dirname
))
261 return wxDIR_CONTINUE
;
264 const wxString
& GetFile() const
272 DECLARE_NO_COPY_CLASS(wxDirTraverserFindFirst
)
276 wxString wxDir
::FindFirst(const wxString
& dirname
,
277 const wxString
& filespec
,
281 if ( dir
.IsOpened() )
283 wxDirTraverserFindFirst traverser
;
285 dir
.Traverse(traverser
, filespec
, flags
| wxDIR_FILES
);
286 return traverser
.GetFile();
289 return wxEmptyString
;
293 // ----------------------------------------------------------------------------
294 // wxDir::GetTotalSize()
295 // ----------------------------------------------------------------------------
297 class wxDirTraverserSumSize
: public wxDirTraverser
300 wxDirTraverserSumSize() { }
302 virtual wxDirTraverseResult
OnFile(const wxString
& filename
)
304 wxULongLong sz
= wxFileName
::GetSize(filename
);
306 // wxFileName::GetSize won't use this class again as
307 // we're passing it a file and not a directory;
308 // thus we are sure to avoid an endless loop
309 if (sz
== wxInvalidSize
)
311 // if the GetSize() failed (this can happen because e.g. a
312 // file is locked by another process), we can proceed but
313 // we need to at least warn the user that the resulting
314 // final size could be not reliable (if e.g. the locked
315 // file is very big).
316 m_skippedFiles
.Add(filename
);
317 return wxDIR_CONTINUE
;
321 return wxDIR_CONTINUE
;
324 virtual wxDirTraverseResult
OnDir(const wxString
& WXUNUSED(dirname
))
326 return wxDIR_CONTINUE
;
329 wxULongLong
GetTotalSize() const
331 wxArrayString
&FilesSkipped()
332 { return m_skippedFiles
; }
336 wxArrayString m_skippedFiles
;
339 wxULongLong wxDir
::GetTotalSize(const wxString
&dirname
, wxArrayString
*filesSkipped
)
341 if (!wxDirExists(dirname
))
342 return wxInvalidSize
;
344 // to get the size of this directory and its contents we need
345 // to recursively walk it...
347 if ( !dir
.IsOpened() )
348 return wxInvalidSize
;
350 wxDirTraverserSumSize traverser
;
351 if (dir
.Traverse(traverser
) == (size_t)-1 ||
352 traverser
.GetTotalSize() == 0)
353 return wxInvalidSize
;
356 *filesSkipped
= traverser
.FilesSkipped();
358 return traverser
.GetTotalSize();