]> git.saurik.com Git - wxWidgets.git/commitdiff
fixes and workarounds to return value of our own wxVsnprintf_() implementation: handl...
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 7 Jan 2007 16:17:28 +0000 (16:17 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 7 Jan 2007 16:17:28 +0000 (16:17 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@44122 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/wxchar.h
src/common/string.cpp
src/common/wxchar.cpp
tests/strings/vsnprintf.cpp

index 1068c3dd69580ee0912365ba73e838561dae488a..84e8ee28f2bbc76c14bcc94958441757cb35f876 100644 (file)
@@ -982,13 +982,18 @@ WXDLLIMPEXP_BASE bool wxOKlibc(); /* for internal use */
 #endif /* wxUSE_PRINTF_POS_PARAMS/!wxUSE_PRINTF_POS_PARAMS */
 
 #ifndef wxSnprintf_
-    /* no [v]snprintf(), cook our own */
+    /* no snprintf(), cook our own */
     WXDLLIMPEXP_BASE int
     wxSnprintf_(wxChar *buf, size_t len, const wxChar *format, ...) ATTRIBUTE_PRINTF_3;
 #endif
 #ifndef wxVsnprintf_
+    /* no (suitable) vsnprintf(), cook our own */
     WXDLLIMPEXP_BASE int
     wxVsnprintf_(wxChar *buf, size_t len, const wxChar *format, va_list argptr);
+
+    #define wxUSE_WXVSNPRINTF 1
+#else
+    #define wxUSE_WXVSNPRINTF 0
 #endif
 
 /*
index 2a989467876a4c82b3dfe172459a1165019b5ae3..78008c79a79d6e01b7902583142fa184f3d7bd66 100644 (file)
@@ -1837,15 +1837,29 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr)
         // buffer were large enough (newer standards such as Unix98)
         if ( len < 0 )
         {
+#if wxUSE_WXVSNPRINTF
+            // we know that our own implementation of wxVsnprintf() returns -1
+            // only for a format error - thus there's something wrong with
+            // the user's format string
+            return -1;
+#else // assume that system version only returns error if not enough space
             // still not enough, as we don't know how much we need, double the
             // current size of the buffer
             size *= 2;
+#endif // wxUSE_WXVSNPRINTF/!wxUSE_WXVSNPRINTF
         }
         else if ( len >= size )
         {
+#if wxUSE_WXVSNPRINTF
+            // we know that our own implementation of wxVsnprintf() returns 
+            // size+1 when there's not enough space but that's not the size
+            // of the required buffer!
+            size *= 2;      // so we just double the current size of the buffer
+#else
             // some vsnprintf() implementations NUL-terminate the buffer and
             // some don't in len == size case, to be safe always add 1
             size = len + 1;
+#endif
         }
         else // ok, there was enough space
         {
index 962a705dcda45b434e9bb74916a71b8416d1e039..8176058d0d2a772e718fc000b4b11d619a800004 100644 (file)
@@ -167,6 +167,10 @@ bool WXDLLEXPORT wxOKlibc()
 
 #if !defined(wxVsnprintf_)
 
+#if !wxUSE_WXVSNPRINTF
+    #error wxUSE_WXVSNPRINTF must be 1 if our wxVsnprintf_ is used
+#endif
+
 // wxUSE_STRUTILS says our wxVsnprintf_ implementation to use or not to
 // use wxStrlen and wxStrncpy functions over one-char processing loops.
 //
@@ -1124,6 +1128,7 @@ int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax,
     va_end(ap);
 
     // something failed while loading arguments from the variable list...
+    // (e.g. the user repeated twice the same positional argument)
     if (!ok)
     {
         buf[0] = 0;
@@ -1143,7 +1148,7 @@ int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax,
         if (lenCur == lenMax)
         {
             buf[lenMax - 1] = 0;
-            return -1;
+            return lenMax+1;      // not enough space in the output buffer !
         }
 
         // process this specifier directly in the output buffer
@@ -1151,7 +1156,7 @@ int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax,
         if (n == -1)
         {
             buf[lenMax-1] = wxT('\0');  // be sure to always NUL-terminate the string
-            return -1;      // not enough space in the output buffer !
+            return lenMax+1;      // not enough space in the output buffer !
         }
         lenCur += n;
 
@@ -1171,7 +1176,7 @@ int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax,
     if (buf[lenCur])
     {
         buf[lenCur] = 0;
-        return -1;
+        return lenMax+1;     // not enough space in the output buffer !
     }
 
     wxASSERT(lenCur == wxStrlen(buf));
@@ -1182,7 +1187,13 @@ int WXDLLEXPORT wxVsnprintf_(wxChar *buf, size_t lenMax,
 #undef APPEND_STR
 #undef CHECK_PREC
 
-#endif // !wxVsnprintfA
+#else    // wxVsnprintf_ is defined
+
+#if wxUSE_WXVSNPRINTF
+    #error wxUSE_WXVSNPRINTF must be 0 if our wxVsnprintf_ is not used
+#endif
+
+#endif // !wxVsnprintf_
 
 #if !defined(wxSnprintf_)
 int WXDLLEXPORT wxSnprintf_(wxChar *buf, size_t len, const wxChar *format, ...)
index fc77afe626e04f7501c73aa677fc463c27398a4d..4d913d1d39bf3c526a4eb2577f8b0ead40b57868 100644 (file)
 
 // temporary buffers
 static wxChar buf[MAX_TEST_LEN];
+int r;
 
 // these macros makes it possible to write all tests without repeating a lot of times wxT() macro
 
 #define ASSERT_STR_EQUAL( a, b ) \
     CPPUNIT_ASSERT_EQUAL( wxString(a), wxString(b) );
 
-#define CMP5(expected, x, y, z, w)                  \
-    wxSnprintf(buf, MAX_TEST_LEN, wxT(x), y, z, w); \
-                                                    \
+#define CMP5(expected, x, y, z, w)                    \
+    r=wxSnprintf(buf, MAX_TEST_LEN, wxT(x), y, z, w); \
+    CPPUNIT_ASSERT( r > 0 );                          \
     ASSERT_STR_EQUAL( wxT(expected), buf );
 
 #define CMP4(expected, x, y, z)                     \
-    wxSnprintf(buf, MAX_TEST_LEN, wxT(x), y, z);    \
-                                                    \
+    r=wxSnprintf(buf, MAX_TEST_LEN, wxT(x), y, z);  \
+    CPPUNIT_ASSERT( r > 0 );                        \
     ASSERT_STR_EQUAL( wxT(expected), buf );
 
 #define CMP3(expected, x, y)                        \
-    wxSnprintf(buf, MAX_TEST_LEN, wxT(x), y);       \
-                                                    \
+    r=wxSnprintf(buf, MAX_TEST_LEN, wxT(x), y);     \
+    CPPUNIT_ASSERT( r > 0 );                        \
     ASSERT_STR_EQUAL( wxT(expected), buf );
 
 #define CMP2(expected, x)                           \
-    wxSnprintf(buf, MAX_TEST_LEN, wxT(x));          \
-                                                    \
+    r=wxSnprintf(buf, MAX_TEST_LEN, wxT(x));        \
+    CPPUNIT_ASSERT( r > 0 );                        \
     ASSERT_STR_EQUAL( wxT(expected), buf );
 
 #define CMPTOSIZE(buffer, size, expected, fmt, x, y, z, w)          \
-    wxSnprintf(buffer, size, wxT(fmt), x, y, z, w);                 \
-                                                                    \
+    r=wxSnprintf(buffer, size, wxT(fmt), x, y, z, w);               \
+    CPPUNIT_ASSERT( r > 0 );                                        \
     CPPUNIT_ASSERT_EQUAL( wxString(wxT(expected)).Left(size - 1),   \
                           wxString(buffer) )
 
@@ -92,6 +93,7 @@ private:
 #endif
 
         CPPUNIT_TEST( BigToSmallBuffer );
+        CPPUNIT_TEST( WrongFormatStrings );
         CPPUNIT_TEST( Miscellaneous );
     CPPUNIT_TEST_SUITE_END();
 
@@ -112,6 +114,7 @@ private:
     void Unicode();
 
     void BigToSmallBuffer();
+    void WrongFormatStrings();
     void Miscellaneous();
     void Misc(wxChar *buffer, int size);
 
@@ -321,9 +324,12 @@ void VsnprintfTestCase::Misc(wxChar *buffer, int size)
     //     value can be the number of characters required for the output buffer
     //     (conforming to ISO C99; implemented in e.g. GNU libc >= 2.1), or
     //     just a negative number, usually -1; (this is how e.g. MSVC's
-    //     *printf() behaves).  Fortunately, in all implementations, when the
+    //     *printf() behaves). Luckily, in all implementations, when the
     //     output buffer is too small, it's nonetheless filled up to its max
     //     size.
+    //
+    //     Note that in the second case (i.e. when we're using our own implementation),
+    //     wxVsnprintf() will always return the number of characters which 
 
     // test without positionals
     CMPTOSIZE(buffer, size, "123 444444444 - test - 555 -0.666",
@@ -350,6 +356,31 @@ void VsnprintfTestCase::Misc(wxChar *buffer, int size)
               L"unicode!!", L'W', "ansi!!", 'w');
 }
 
+void VsnprintfTestCase::WrongFormatStrings()
+{
+    // test how wxVsnprintf() behaves with wrong format string:
+
+#if wxUSE_PRINTF_POS_PARAMS
+
+    // two positionals with the same index:
+    r = wxSnprintf(buf, MAX_TEST_LEN, wxT("%1$s %1$s"), "hello");
+    CPPUNIT_ASSERT(r == -1);
+
+    // three positionals with the same index mixed with other pos args:
+    r = wxSnprintf(buf, MAX_TEST_LEN, wxT("%4$d %2$f %1$s %2$s %3$d"), "hello", "world", 3, 4);
+    CPPUNIT_ASSERT(r == -1);
+
+    // a missing positional arg:
+    r = wxSnprintf(buf, MAX_TEST_LEN, wxT("%1$d %3$d"), 1, 2, 3);
+    CPPUNIT_ASSERT(r == -1);
+
+    // positional and non-positionals in the same format string:
+    r = wxSnprintf(buf, MAX_TEST_LEN, wxT("%1$d %d %3$d"), 1, 2, 3);
+    CPPUNIT_ASSERT(r == -1);
+
+#endif // wxUSE_PRINTF_POS_PARAMS
+}
+
 void VsnprintfTestCase::BigToSmallBuffer()
 {
     wxChar buf[1024], buf2[16], buf3[4], buf4;