From 23b8a2629903027852d7506162b7b0f44bd9f912 Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Fri, 18 Aug 2006 15:30:28 +0000 Subject: [PATCH] Applied patch [ 1531615 ] size support for wxFileName git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@40659 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/dir.tex | 21 +++++++++- docs/latex/wx/filename.tex | 27 +++++++++++++ include/wx/dir.h | 3 ++ src/common/dircmn.cpp | 71 +++++++++++++++++++++++++++++++++ src/common/filename.cpp | 82 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 203 insertions(+), 1 deletion(-) diff --git a/docs/latex/wx/dir.tex b/docs/latex/wx/dir.tex index efc0792a5b..c9b6a29d53 100644 --- a/docs/latex/wx/dir.tex +++ b/docs/latex/wx/dir.tex @@ -137,7 +137,7 @@ See also: \helpref{Traverse}{wxdirtraverse} \constfunc{bool}{GetFirst}{\param{wxString* }{filename}, \param{const wxString\& }{filespec = wxEmptyString}, \param{int }{flags = wxDIR\_DEFAULT}} Start enumerating all files matching {\it filespec} (or all files if it is -empty) and flags, return true on success. +empty) and {\it flags}, return \true on success. \membersection{wxDir::GetName}\label{wxdirgetname} @@ -156,6 +156,25 @@ Continue enumerating files which satisfy the criteria specified by the last call to \helpref{GetFirst}{wxdirgetfirst}. +\membersection{wxDir::GetTotalSize}\label{wxdirgettotalsize} + +\func{static wxULongLong}{GetTotalSize}{\param{const wxString\& }{dir}, \param{wxArrayString* }{filesSkipped = NULL}} + +Returns the size (in bytes) of all files recursively found in {\tt dir} or +{\tt wxInvalidSize} in case of error. + +In case it happens that while traversing folders a file's size can not be read, +that file is added to the {\tt filesSkipped} array, if not \NULL, and then +skipped. +This usually happens with some special folders which are locked by the operating system +or by another process. Remember that when {\tt filesSkipped->GetCount()} is not zero, +then the returned value is not 100\% accurate and, if the skipped files were big, it could be +far from real size of the directory. + +See also: \helpref{wxFileName::GetHumanReadableSize}{wxfilenamegethumanreadablesize}, +\helpref{wxGetDiskSpace}{wxgetdiskspace} + + \membersection{wxDir::HasFiles}\label{wxdirhasfiles} \func{bool}{HasFiles}{\param{const wxString\& }{filespec = wxEmptyString}} diff --git a/docs/latex/wx/filename.tex b/docs/latex/wx/filename.tex index 16dc6935b2..311783e728 100644 --- a/docs/latex/wx/filename.tex +++ b/docs/latex/wx/filename.tex @@ -513,6 +513,33 @@ This is the same as calling \helpref{GetPath}{wxfilenamegetpath} Return the short form of the path (returns identity on non-Windows platforms). +\membersection{wxFileName::GetSize}\label{wxfilenamegetsize} + +\constfunc{wxULongLong}{GetSize}{\void} + +\func{static wxULongLong}{GetSize}{\param{const wxString\& }{filename}} + +Returns the size of this file (first form) or the size of the given file (second form). +If the file does not exist or its size could not be read (because e.g. the file is locked +by another process) the returned value is {\tt wxInvalidSize}. + + +\membersection{wxFileName::GetHumanReadableSize}\label{wxfilenamegethumanreadablesize} + +\constfunc{wxString}{GetHumanReadableSize}{\param{const wxString\& }{failmsg = "Not available"}, \param{int }{precision = 1}} + +\func{static wxString}{GetHumanReadableSize}{\param{const wxULongLong\& }{bytes}, \param{const wxString\& }{nullsize = "Not available"}, \param{int }{precision = 1}} + +Returns the size of this file (first form) or the given number of bytes (second form) +in a human-readable form. + +If the size could not be retrieved the {\tt failmsg} string is returned (first form). +If {\tt bytes} is {\tt wxInvalidSize} or zero, then {\tt nullsize} is returned (second form). + +In case of success, the returned string is a floating-point number with {\tt precision} decimal digits +followed by the size unit (B, kB, MB, GB, TB: respectively bytes, kilobytes, megabytes, gigabytes, terabytes). + + \membersection{wxFileName::GetTimes}\label{wxfilenamegettimes} \constfunc{bool}{GetTimes}{\param{wxDateTime* }{dtAccess}, \param{wxDateTime* }{dtMod}, \param{wxDateTime* }{dtCreate}} diff --git a/include/wx/dir.h b/include/wx/dir.h index 212d0586a2..647a49c2f5 100644 --- a/include/wx/dir.h +++ b/include/wx/dir.h @@ -145,6 +145,9 @@ public: const wxString& filespec, int flags = wxDIR_DEFAULT); + // returns the size of all directories recursively found in given path + static wxULongLong GetTotalSize(const wxString &dir, wxArrayString *filesSkipped = NULL); + private: friend class wxDirData; diff --git a/src/common/dircmn.cpp b/src/common/dircmn.cpp index bed42a56a9..1674029b6d 100644 --- a/src/common/dircmn.cpp +++ b/src/common/dircmn.cpp @@ -33,6 +33,7 @@ #endif //WX_PRECOMP #include "wx/dir.h" +#include "wx/filename.h" // ============================================================================ // implementation @@ -284,3 +285,73 @@ wxString wxDir::FindFirst(const wxString& dirname, return wxEmptyString; } + + +// ---------------------------------------------------------------------------- +// wxDir::GetTotalSize() +// ---------------------------------------------------------------------------- + +class wxDirTraverserSumSize : public wxDirTraverser +{ +public: + wxDirTraverserSumSize() { m_skippedFiles=false; } + + virtual wxDirTraverseResult OnFile(const wxString& filename) + { + wxULongLong sz = wxFileName::GetSize(filename); + + // wxFileName::GetSize won't use this class again as + // we're passing it a file and not a directory; + // thus we are sure to avoid an endless loop + if (sz == wxInvalidSize) + { + // if the GetSize() failed (this can happen because e.g. a + // file is locked by another process), we can proceed but + // we need to at least warn the user that the resulting + // final size could be not reliable (if e.g. the locked + // file is very big). + m_skippedFiles.Add(filename); + return wxDIR_CONTINUE; + } + + m_sz += sz; + return wxDIR_CONTINUE; + } + + virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname)) + { + return wxDIR_CONTINUE; + } + + wxULongLong GetTotalSize() const + { return m_sz; } + wxArrayString &FilesSkipped() + { return m_skippedFiles; } + +protected: + wxULongLong m_sz; + wxArrayString m_skippedFiles; +}; + +wxULongLong wxDir::GetTotalSize(const wxString &dirname, wxArrayString *filesSkipped) +{ + if (!wxDirExists(dirname)) + return wxInvalidSize; + + // to get the size of this directory and its contents we need + // to recursively walk it... + wxDir dir(dirname); + if ( !dir.IsOpened() ) + return wxInvalidSize; + + wxDirTraverserSumSize traverser; + if (dir.Traverse(traverser) == (size_t)-1 || + traverser.GetTotalSize() == 0) + return wxInvalidSize; + + if (filesSkipped) + *filesSkipped = traverser.FilesSkipped(); + + return traverser.GetTotalSize(); +} + diff --git a/src/common/filename.cpp b/src/common/filename.cpp index 12bc12daa7..1be91db75f 100644 --- a/src/common/filename.cpp +++ b/src/common/filename.cpp @@ -139,6 +139,10 @@ #define MAX_PATH _MAX_PATH #endif + +wxULongLong wxInvalidSize = (unsigned)-1; + + // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- @@ -2019,6 +2023,84 @@ bool wxFileName::GetTimes(wxDateTime *dtAccess, #endif // wxUSE_DATETIME + +// ---------------------------------------------------------------------------- +// file size functions +// ---------------------------------------------------------------------------- + +/* static */ +wxULongLong wxFileName::GetSize(const wxString &filename) +{ + if (!wxFileExists(filename)) + return wxInvalidSize; + +#ifdef __WIN32__ + wxFileHandle f(filename, wxFileHandle::Read); + if (!f.IsOk()) + return wxInvalidSize; + + DWORD lpFileSizeHigh; + DWORD ret = GetFileSize(f, &lpFileSizeHigh); + if (ret == INVALID_FILE_SIZE) + return wxInvalidSize; + + // compose the low-order and high-order byte sizes + return wxULongLong(ret | (lpFileSizeHigh << sizeof(WORD)*2)); + +#else // ! __WIN32__ + + wxStructStat st; +#ifndef wxNEED_WX_UNISTD_H + if (wxStat( filename.fn_str() , &st) != 0) +#else + if (wxStat( filename, &st) != 0) +#endif + return wxInvalidSize; + return wxULongLong(st.st_size); +#endif +} + +/* static */ +wxString wxFileName::GetHumanReadableSize(const wxULongLong &bs, + const wxString &nullsize, + int precision) +{ + static const double KILOBYTESIZE = 1024.0; + static const double MEGABYTESIZE = 1024.0*KILOBYTESIZE; + static const double GIGABYTESIZE = 1024.0*MEGABYTESIZE; + static const double TERABYTESIZE = 1024.0*GIGABYTESIZE; + + if (bs == 0 || bs == wxInvalidSize) + return nullsize; + + double bytesize = bs.ToDouble(); + if (bytesize < KILOBYTESIZE) + return wxString::Format(_("%s B"), bs.ToString().c_str()); + if (bytesize < MEGABYTESIZE) + return wxString::Format(_("%.*f kB"), precision, bytesize/KILOBYTESIZE); + if (bytesize < GIGABYTESIZE) + return wxString::Format(_("%.*f MB"), precision, bytesize/MEGABYTESIZE); + if (bytesize < TERABYTESIZE) + return wxString::Format(_("%.*f GB"), precision, bytesize/GIGABYTESIZE); + + return wxString::Format(_("%.*f TB"), precision, bytesize/TERABYTESIZE); +} + +wxULongLong wxFileName::GetSize() const +{ + return GetSize(GetFullPath()); +} + +wxString wxFileName::GetHumanReadableSize(const wxString &failmsg, int precision) const +{ + return GetHumanReadableSize(GetSize(), failmsg, precision); +} + + +// ---------------------------------------------------------------------------- +// Mac-specific functions +// ---------------------------------------------------------------------------- + #ifdef __WXMAC__ const short kMacExtensionMaxLength = 16 ; -- 2.47.2