Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Restore old-fashioned unsafe format as "format_raw", for those rare

times when you must have every last feature of printf, including those
that tinyformat doesn't handle (and are willing to trade type safety and
expandability to do it).

What do you know, we need this for Strutil::memformat and Strutil::timeintervalformat!

Which we didn't notice because we had no unit tests for them, which I also have
now added.
  • Loading branch information...
commit 1f9bdb763f4663f42a911e1b4e2546b4040e88ce 1 parent 30ac930
Larry Gritz authored April 21, 2012
11  src/include/strutil.h
@@ -89,8 +89,17 @@ namespace Strutil {
89 89
 TINYFORMAT_WRAP_FORMAT (std::string, format, /**/,
90 90
     std::ostringstream msg;, msg, return msg.str();)
91 91
 
  92
+/// Return a std::string formatted from printf-like arguments.  Like the
  93
+/// real sprintf, this is not guaranteed type-safe and is not extensible
  94
+/// like format().  You would only want to use this instead of the safe
  95
+/// format() in rare situations where you really need to use obscure
  96
+/// printf features that aren't supported by tinyformat.
  97
+std::string DLLPUBLIC format_raw (const char *fmt, ...)
  98
+                                         OPENIMAGEIO_PRINTF_ARGS(1,2);
  99
+
92 100
 /// Return a std::string formatted from printf-like arguments -- passed
93  
-/// already as a va_list.
  101
+/// already as a va_list.  Like vsprintf, this is not guaranteed
  102
+/// type-safe and is not extensible like format().
94 103
 std::string DLLPUBLIC vformat (const char *fmt, va_list ap)
95 104
                                          OPENIMAGEIO_PRINTF_ARGS(1,0);
96 105
 
29  src/libOpenImageIO/strutil_test.cpp
@@ -28,11 +28,36 @@
28 28
   (This is the Modified BSD License)
29 29
 */
30 30
 
31  
-#include "imageio.h"
  31
+#include "strutil.h"
32 32
 #include "unittest.h"
33 33
 
34 34
 OIIO_NAMESPACE_USING;
35 35
 
  36
+
  37
+
  38
+void test_memformat ()
  39
+{
  40
+    OIIO_CHECK_EQUAL (Strutil::memformat (15), "15 B");
  41
+    OIIO_CHECK_EQUAL (Strutil::memformat (15LL*1024), "15 KB");
  42
+    OIIO_CHECK_EQUAL (Strutil::memformat (15LL*1024*1024), "15.0 MB");
  43
+    OIIO_CHECK_EQUAL (Strutil::memformat (15LL*1024*1024*1024), "15.0 GB");
  44
+    OIIO_CHECK_EQUAL (Strutil::memformat (15LL*1024*1024+200000), "15.2 MB");
  45
+    OIIO_CHECK_EQUAL (Strutil::memformat (15LL*1024*1024+200000, 3), "15.191 MB");
  46
+}
  47
+
  48
+
  49
+
  50
+void test_timeintervalformat ()
  51
+{
  52
+    OIIO_CHECK_EQUAL (Strutil::timeintervalformat (15.321), "15.3s");
  53
+    OIIO_CHECK_EQUAL (Strutil::timeintervalformat (150.321), "2m 30.3s");
  54
+    OIIO_CHECK_EQUAL (Strutil::timeintervalformat (15000.321), "4h 10m 0.3s");
  55
+    OIIO_CHECK_EQUAL (Strutil::timeintervalformat (150000.321), "1d 17h 40m 0.3s");
  56
+    OIIO_CHECK_EQUAL (Strutil::timeintervalformat (150.321, 2), "2m 30.32s");
  57
+}
  58
+
  59
+
  60
+
36 61
 void test_get_rest_arguments ()
37 62
 {
38 63
     int ret;
@@ -111,6 +136,8 @@ void test_escape_sequences ()
111 136
 
112 137
 int main (int argc, char *argv[])
113 138
 {
  139
+    test_memformat ();
  140
+    test_timeintervalformat ();
114 141
     test_get_rest_arguments ();
115 142
     test_escape_sequences ();
116 143
 
32  src/libutil/strutil.cpp
@@ -48,6 +48,18 @@ OIIO_NAMESPACE_ENTER
48 48
 {
49 49
 
50 50
 std::string
  51
+Strutil::format_raw (const char *fmt, ...)
  52
+{
  53
+    va_list ap;
  54
+    va_start (ap, fmt);
  55
+    std::string buf = vformat (fmt, ap);
  56
+    va_end (ap);
  57
+    return buf;
  58
+}
  59
+
  60
+
  61
+
  62
+std::string
51 63
 Strutil::vformat (const char *fmt, va_list ap)
52 64
 {
53 65
     // Allocate a buffer on the stack that's big enough for us almost
@@ -115,7 +127,11 @@ Strutil::memformat (off_t bytes, int digits)
115 127
         // Just bytes, don't bother with decimalization
116 128
         return format ("%lld B", (long long)bytes);
117 129
     }
118  
-    return format ("%1.*f %s", digits, d, units);
  130
+    // N.B. We use format_raw below because format() (due to its
  131
+    // dependence on 'tinyformat') does not support variable precision.
  132
+    // If tinyformat is extended to handle this, we will no longer
  133
+    // need format_raw.
  134
+    return format_raw ("%1.*f %s", digits, d, units);
119 135
 }
120 136
 
121 137
 
@@ -135,13 +151,17 @@ Strutil::timeintervalformat (double secs, int digits)
135 151
     int m = (int) floor (secs / mins);
136 152
     secs = fmod (secs, mins);
137 153
     if (d)
138  
-        out += format ("%dd ", d);
139  
-    if (h || d)
140  
-        out += format ("%2dh ", h);
  154
+        out += format ("%dd %dh ", d, h);
  155
+    else if (h)
  156
+        out += format ("%dh ", h);
  157
+    // N.B. We use format_raw below because format() (due to its
  158
+    // dependence on 'tinyformat') does not support variable precision.
  159
+    // If tinyformat is extended to handle this, we will no longer
  160
+    // need format_raw.
141 161
     if (m || h || d)
142  
-        out += format ("%dm %1.*fs", m, digits, secs);
  162
+        out += format_raw ("%dm %1.*fs", m, digits, secs);
143 163
     else
144  
-        out += format ("%1.*fs", digits, secs);
  164
+        out += format_raw ("%1.*fs", digits, secs);
145 165
     return out;
146 166
 }
147 167
 

0 notes on commit 1f9bdb7

Please sign in to comment.
Something went wrong with that request. Please try again.