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: dircmn.cpp 40665 2006-08-19 08:45:31Z JS $ 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 46wxDirTraverseResult 47wxDirTraverser::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 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 65#if (defined(__CYGWIN__) && defined(__WINDOWS__)) || !defined(__UNIX_LIKE__) || defined(__WXMAC__) || defined(__EMX__) || defined(__WINE__) 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// ---------------------------------------------------------------------------- 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; 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 198class wxDirTraverserSimple : public wxDirTraverser 199{ 200public: 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 214private: 215 wxArrayString& m_files; 216 217 DECLARE_NO_COPY_CLASS(wxDirTraverserSimple) 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} 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} 288 289 290// ---------------------------------------------------------------------------- 291// wxDir::GetTotalSize() 292// ---------------------------------------------------------------------------- 293 294class wxDirTraverserSumSize : public wxDirTraverser 295{ 296public: 297 wxDirTraverserSumSize() { } 298 299 virtual wxDirTraverseResult OnFile(const wxString& filename) 300 { 301 wxULongLong sz = wxFileName::GetSize(filename); 302 303 // wxFileName::GetSize won't use this class again as 304 // we're passing it a file and not a directory; 305 // thus we are sure to avoid an endless loop 306 if (sz == wxInvalidSize) 307 { 308 // if the GetSize() failed (this can happen because e.g. a 309 // file is locked by another process), we can proceed but 310 // we need to at least warn the user that the resulting 311 // final size could be not reliable (if e.g. the locked 312 // file is very big). 313 m_skippedFiles.Add(filename); 314 return wxDIR_CONTINUE; 315 } 316 317 m_sz += sz; 318 return wxDIR_CONTINUE; 319 } 320 321 virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname)) 322 { 323 return wxDIR_CONTINUE; 324 } 325 326 wxULongLong GetTotalSize() const 327 { return m_sz; } 328 wxArrayString &FilesSkipped() 329 { return m_skippedFiles; } 330 331protected: 332 wxULongLong m_sz; 333 wxArrayString m_skippedFiles; 334}; 335 336wxULongLong wxDir::GetTotalSize(const wxString &dirname, wxArrayString *filesSkipped) 337{ 338 if (!wxDirExists(dirname)) 339 return wxInvalidSize; 340 341 // to get the size of this directory and its contents we need 342 // to recursively walk it... 343 wxDir dir(dirname); 344 if ( !dir.IsOpened() ) 345 return wxInvalidSize; 346 347 wxDirTraverserSumSize traverser; 348 if (dir.Traverse(traverser) == (size_t)-1 || 349 traverser.GetTotalSize() == 0) 350 return wxInvalidSize; 351 352 if (filesSkipped) 353 *filesSkipped = traverser.FilesSkipped(); 354 355 return traverser.GetTotalSize(); 356} 357 358