]> git.saurik.com Git - wxWidgets.git/commitdiff
Add support for IEC and SI size units to wxFileName::GetHumanReadableSize().
authorVadim Zeitlin <vadim@wxwidgets.org>
Tue, 6 Apr 2010 14:53:04 +0000 (14:53 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Tue, 6 Apr 2010 14:53:04 +0000 (14:53 +0000)
Allow choosing the multiplier to use (1000 or 1024) and the names of the units
(SI or IEC). By default, still use traditional convention, i.e. multiplier of
1024 but SI unit names. This will probably need to be changed to use IEC units
in the future.

Also added unit test for this function.

Closes #10673.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@63870 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
include/wx/filename.h
interface/wx/filename.h
src/common/filename.cpp
tests/filename/filenametest.cpp

index 8ad5b40a3bb5a1015fae0ee8bdc0a5a4f7271c86..ac8bcb5aed8286052f42d00fc62c7b79d66dd71f 100644 (file)
@@ -438,6 +438,7 @@ All:
 - Correct bugs when using wxTextInputStream with wxConvAuto (Leon Buikstra).
 - Don't crash when input is empty in wxFileConfig ctor (Lukasz Michalski).
 - Correct wxSocket::Peek() to not block (Anders Larsen).
+- Added IEC and SI units support to GetHumanReadableSize() (Julien Weinzorn).
 
 Unix:
 
index 1a6abd73ebf23ea0ee19ef5a2a42312b6130af37..cc8806b275ed124df75f49670e191cbece103ace 100644 (file)
@@ -65,6 +65,15 @@ enum wxPathFormat
     wxPATH_MAX // Not a valid value for specifying path format
 };
 
+// different convention that may be used with GetHumanReadableSize()
+enum wxSizeConvention
+{
+    wxSIZE_CONV_TRADIONAL,  // 1024 bytes = 1 KB
+    wxSIZE_CONV_IEC,        // 1024 bytes = 1 KiB
+    wxSIZE_CONV_SI          // 1000 bytes = 1 KB
+};
+
+
 // the kind of normalization to do with the file name: these values can be
 // or'd together to perform several operations at once
 enum wxPathNormalize
@@ -540,11 +549,15 @@ public:
     static wxULongLong GetSize(const wxString &file);
 
         // returns the size in a human readable form
-    wxString GetHumanReadableSize(const wxString &nullsize = wxGetTranslation(wxT("Not available")),
-                                  int precision = 1) const;
-    static wxString GetHumanReadableSize(const wxULongLong &sz,
-                                         const wxString &nullsize = wxGetTranslation(wxT("Not available")),
-                                         int precision = 1);
+    wxString
+    GetHumanReadableSize(const wxString& nullsize = _("Not available"),
+                         int precision = 1,
+                         wxSizeConvention conv = wxSIZE_CONV_TRADIONAL) const;
+    static wxString
+    GetHumanReadableSize(const wxULongLong& sz,
+                         const wxString& nullsize = _("Not available"),
+                         int precision = 1,
+                         wxSizeConvention conv = wxSIZE_CONV_TRADIONAL);
 #endif // wxUSE_LONGLONG
 
 
index 3f40781ab79894e22b073792223f4435b69e9fef..17c783f03c88cf4fcdea3928bc302f70e4ff0bfb 100644 (file)
@@ -28,6 +28,25 @@ enum wxPathFormat
     wxPATH_MAX   //!< Not a valid value for specifying path format
 };
 
+/**
+    Different conventions for human readable sizes.
+
+    @see wxFileName::GetHumanReadableSize().
+
+    @since 2.9.1
+*/
+enum wxSizeConvention
+{
+    /// 1000 bytes = 1KiB.
+    wxSIZE_CONV_REAL_SI,
+
+    /// 1000 bytes = 1KB.
+    wxSIZE_CONV_TRAD_1000,
+
+    /// 1024 bytes = 1KB.
+    wxSIZE_CONV_TRAD_1024
+};
+
 
 /**
     The kind of normalization to do with the file name: these values can be
@@ -522,30 +541,41 @@ public:
     */
     static wxString GetHomeDir();
 
+    //@{
     /**
-        Returns the size of the file in a human-readable form.
-
-        If the size could not be retrieved the @c failmsg string
-        is returned. In case of success, the returned string is
-        a floating-point number with @c precision decimal digits
-        followed by the size unit (B, kB, MB, GB, TB: respectively
-        bytes, kilobytes, megabytes, gigabytes, terabytes).
-    */
-    wxString GetHumanReadableSize(const wxString& failmsg = "Not available",
-                                  int precision = 1) const;
-
-    /**
-        Returns the size of the given number of bytes in a human-readable form.
-
-        If @a bytes is ::wxInvalidSize or zero, then @a nullsize is returned.
-
-        In case of success, the returned string is a floating-point number with
-        @a precision decimal digits followed by the size unit (B, kB, MB, GB,
-        TB: respectively bytes, kilobytes, megabytes, gigabytes, terabytes).
-    */
-    static wxString GetHumanReadableSize(const wxULongLong& bytes,
-                                         const wxString& nullsize = "Not available",
-                                         int precision = 1);
+        Returns the representation of the file size in a human-readable form.
+
+        In the first version, the size of this file is used. In the second one,
+        the specified size @a bytes is used.
+
+        If the file size could not be retrieved or @a bytes is ::wxInvalidSize
+        or zero, the @c failmsg string is returned.
+
+        Otherwise the returned string is a floating-point number with @c
+        precision decimal digits followed by the abbreviation of the unit used.
+        By default the traditional, although incorrect, convention of using SI
+        units for multiples of 1024 is used, i.e. returned string will use
+        suffixes of B, KB, MB, GB, TB for bytes, kilobytes, megabytes,
+        gigabytes and terabytes respectively. With the IEC convention the names
+        of the units are changed to B, KiB, MiB, GiB and TiB fofr bytes,
+        kibibytes, mebibyes, gibibytes and tebibytes. Finally, with SI
+        convention the same B, KB, MB, GB and TB suffixes are used but in their
+        correct SI meaning, i.e. as multiples of 1000 and not 1024.
+
+        Support for the different size conventions is new in wxWidgets 2.9.1,
+        in previous versions only the traditional convention was implemented.
+    */
+    wxString
+    GetHumanReadableSize(const wxString& failmsg = _("Not available"),
+                         int precision = 1,
+                         wxSizeConvention conv = wxSIZE_CONV_TRADIONAL) const;
+
+    static wxString
+    GetHumanReadableSize(const wxULongLong& bytes,
+                         const wxString& nullsize = _("Not available"),
+                         int precision = 1,
+                         wxSizeConvention conv = wxSIZE_CONV_REAL_SI);
+    //@}
 
     /**
         Return the long form of the path (returns identity on non-Windows platforms).
index 917c89de0f7c5927c1ac7ad8cb5e4f35957a2c77..8fa76ef7bf9f644a3b271d4594af31366501e8f5 100644 (file)
@@ -2647,27 +2647,53 @@ wxULongLong wxFileName::GetSize(const wxString &filename)
 /* static */
 wxString wxFileName::GetHumanReadableSize(const wxULongLong &bs,
                                           const wxString &nullsize,
-                                          int precision)
+                                          int precision,
+                                          wxSizeConvention conv)
 {
-    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)
+    // deal with trivial case first
+    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);
+    // depending on the convention used the multiplier may be either 1000 or
+    // 1024 and the binary infix may be empty (for "KB") or "i" (for "KiB")
+    double multiplier;
+    wxString biInfix;
+
+    switch ( conv )
+    {
+        case wxSIZE_CONV_IEC:
+            biInfix = "i";
+            // fall through
+
+        case wxSIZE_CONV_TRADIONAL:
+            multiplier = 1024.;
+            break;
+
+        case wxSIZE_CONV_SI:
+            multiplier = 1000;
+            break;
+    }
+
+    const double kiloByteSize = multiplier;
+    const double megaByteSize = multiplier * kiloByteSize;
+    const double gigaByteSize = multiplier * megaByteSize;
+    const double teraByteSize = multiplier * gigaByteSize;
+
+    const double bytesize = bs.ToDouble();
+
+    wxString result;
+    if ( bytesize < kiloByteSize )
+        result.Printf("%s B", bs.ToString());
+    else if ( bytesize < megaByteSize )
+        result.Printf("%.*f K%sB", precision, bytesize/kiloByteSize, biInfix);
+    else if (bytesize < gigaByteSize)
+        result.Printf("%.*f M%sB", precision, bytesize/megaByteSize, biInfix);
+    else if (bytesize < teraByteSize)
+        result.Printf("%.*f G%sB", precision, bytesize/gigaByteSize, biInfix);
+    else
+        result.Printf("%.*f T%sB", precision, bytesize/teraByteSize, biInfix);
 
-    return wxString::Format(_("%.*f TB"), precision, bytesize/TERABYTESIZE);
+    return result;
 }
 
 wxULongLong wxFileName::GetSize() const
@@ -2675,9 +2701,11 @@ wxULongLong wxFileName::GetSize() const
     return GetSize(GetFullPath());
 }
 
-wxString wxFileName::GetHumanReadableSize(const wxString &failmsg, int precision) const
+wxString wxFileName::GetHumanReadableSize(const wxString& failmsg,
+                                          int precision,
+                                          wxSizeConvention conv) const
 {
-    return GetHumanReadableSize(GetSize(), failmsg, precision);
+    return GetHumanReadableSize(GetSize(), failmsg, precision, conv);
 }
 
 #endif // wxUSE_LONGLONG
index c1a9c5e6d43fedd42c595f8bce49cbc687f5e8a2..cdeaef074a2536c81d31aa1378ac3b93b363cdbf 100644 (file)
@@ -125,6 +125,7 @@ private:
         CPPUNIT_TEST( TestStrip );
         CPPUNIT_TEST( TestNormalize );
         CPPUNIT_TEST( TestReplace );
+        CPPUNIT_TEST( TestGetHumanReadable );
 #ifdef __WINDOWS__
         CPPUNIT_TEST( TestShortLongPath );
 #endif // __WINDOWS__
@@ -139,6 +140,7 @@ private:
     void TestStrip();
     void TestNormalize();
     void TestReplace();
+    void TestGetHumanReadable();
 #ifdef __WINDOWS__
     void TestShortLongPath();
 #endif // __WINDOWS__
@@ -478,6 +480,39 @@ void FileNameTestCase::TestReplace()
                           fn.GetFullPath(wxPATH_UNIX) );
 }
 
+void FileNameTestCase::TestGetHumanReadable()
+{
+    static const struct TestData
+    {
+        const char *result;
+        wxULongLong size;
+        int prec;
+        wxSizeConvention conv;
+    } testData[] =
+    {
+        { "NA",             0, 1, wxSIZE_CONV_TRADIONAL },
+        { "2.0 KB",      2000, 1, wxSIZE_CONV_TRADIONAL },
+        { "1.953 KiB",   2000, 3, wxSIZE_CONV_IEC       },
+        { "2.000 KB",    2000, 3, wxSIZE_CONV_SI        },
+        { "297 KB",    304351, 0, wxSIZE_CONV_TRADIONAL },
+        { "304 KB",    304351, 0, wxSIZE_CONV_SI        },
+    };
+
+    for ( unsigned n = 0; n < WXSIZEOF(testData); n++ )
+    {
+        const TestData& td = testData[n];
+
+        CPPUNIT_ASSERT_EQUAL
+        (
+            td.result,
+            wxFileName::GetHumanReadableSize(td.size, "NA", td.prec, td.conv)
+        );
+    }
+
+    // also test the default convention value
+    CPPUNIT_ASSERT_EQUAL( "1.4 MB", wxFileName::GetHumanReadableSize(1512993, "") );
+}
+
 void FileNameTestCase::TestStrip()
 {
     CPPUNIT_ASSERT_EQUAL( "", wxFileName::StripExtension("") );