stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r387687 - in /incubator/stdcxx/trunk/tests: include/rw_char.h self/0.char.cpp src/char.cpp
Date Wed, 22 Mar 2006 01:58:27 GMT
Author: sebor
Date: Tue Mar 21 17:58:27 2006
New Revision: 387687

URL: http://svn.apache.org/viewcvs?rev=387687&view=rev
Log:
2006-03-21  Martin Sebor  <sebor@roguewave.com>

	* rw_char.h (UserCharFmatInit, _rw_user_char_fmat_init): Initializer
	type and object to install a "user-defined" formatting callback for
	arrays of generic characters including UserChar.
	* src/char.cpp (_rw_fmtstring, _rw_fmtstringv): "User-defined"
	formatting callback for arrays of generic characters including
	UserChar.
	* test/0.char.cpp (test_formatting): Exercised the above.

Modified:
    incubator/stdcxx/trunk/tests/include/rw_char.h
    incubator/stdcxx/trunk/tests/self/0.char.cpp
    incubator/stdcxx/trunk/tests/src/char.cpp

Modified: incubator/stdcxx/trunk/tests/include/rw_char.h
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/include/rw_char.h?rev=387687&r1=387686&r2=387687&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/include/rw_char.h (original)
+++ incubator/stdcxx/trunk/tests/include/rw_char.h Tue Mar 21 17:58:27 2006
@@ -316,4 +316,8 @@
 _RWSTD_SIZE_T rw_match (const char*, const UserChar*,
                         _RWSTD_SIZE_T = _RWSTD_SIZE_MAX);
 
+static const struct UserCharFmatInit {
+    UserCharFmatInit ();
+} _rw_user_char_fmat_init;
+
 #endif   // RW_CHAR_INCLUDED

Modified: incubator/stdcxx/trunk/tests/self/0.char.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/self/0.char.cpp?rev=387687&r1=387686&r2=387687&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/self/0.char.cpp (original)
+++ incubator/stdcxx/trunk/tests/self/0.char.cpp Tue Mar 21 17:58:27 2006
@@ -27,8 +27,10 @@
  **************************************************************************/
 
 #include <rw_char.h>
+#include <rw_printf.h>
 #include <driver.h>
 
+#include <stdlib.h>
 #include <string.h>    // for memset, size_t
 
 /***********************************************************************/
@@ -604,7 +606,7 @@
 static size_t
 length (const char *s)
 {
-    return strlen (s);
+    return s ? strlen (s) : 0;
 }
 
 
@@ -658,15 +660,17 @@
     const size_t size_max = _RWSTD_SIZE_MAX;
     size_t result;
 
+#define LEN(T, s, len) \
+  int (size_max == size_t (len) ? length ((const T*)s) : size_t (len))
+
 #undef TEST
-#define TEST(s1, s2, len, expect)                                         \
-  result = rw_match ((const char*)s1, (const char*)s2, size_t (len));     \
-  rw_assert (expect == result,                                            \
-             0, __LINE__,                                                 \
-             "rw_match(%{#*s}, %{#*s}, %zu) == %zu, got %zu",             \
-             int (size_max == len ? length ((const char*)s1) : len), s1,  \
-             int (size_max == len ? length ((const char*)s2) : len), s2,  \
-             len, expect, result)
+#define TEST(s1, s2, len, expect)                                       \
+  result = rw_match ((const char*)s1, (const char*)s2, size_t (len));   \
+  rw_assert (expect == result,                                          \
+             0, __LINE__,                                               \
+             "rw_match(%{#*s}, %{#*s}, %zu) == %zu, got %zu",           \
+             LEN (char, s1, len), s1, LEN (char, s2, len),              \
+             s2, len, expect, result)
 
     TEST (0,      0,        -1, 0);
     TEST ("",     0,        -1, 0);
@@ -706,8 +710,7 @@
   rw_assert (expect == result,                                               \
              0, __LINE__,                                                    \
              "rw_match(%{#*s}, L%{#*ls}, %zu) == %zu, got %zu",              \
-             int (size_max == len ? length ((const char*)s1) : len), s1,     \
-             int (size_max == len ? length ((const wchar_t*)s2) : len), s2,  \
+             LEN (char, s1, len), s1, LEN (wchar_t, s2, len), s2,            \
              len, expect, result)
 
     TEST (0,       0,        -1, 0);
@@ -750,9 +753,8 @@
   rw_assert (expect == result,                                               \
              0, __LINE__,                                                    \
              "rw_match(%{#*s}, %{#*s}, %zu) == %zu, got %zu",                \
-             int (size_max == len ? length ((const char*)s1) : len), s1,     \
-             int (size_max == len ? length ((const char*)s2) : len), s2,     \
-             len, expect, result)
+             LEN (char, s1, len), s1, LEN (UserChar, s2, len),               \
+             s2, len, expect, result)
 
     TEST (0,       0,       -1, 0);
     TEST ("",      0,       -1, 0);
@@ -781,6 +783,61 @@
 
 /***********************************************************************/
 
+static void
+test_formatting ()
+{
+    //////////////////////////////////////////////////////////////////
+    rw_info (0, 0, 0, "\"%s\": formatting directive", "%{/Gs}");
+
+    const int wchsize = int (sizeof (wchar_t));
+    const int usrsize = int (sizeof (UserChar));
+
+    char *str;
+
+#undef TEST
+#define TEST(fmt, arg0, arg1, arg2, expect_str)         \
+    str = rw_sprintfa (fmt, arg0, arg1, arg2);          \
+    rw_assert (str && 0 == strcmp (str, expect_str),    \
+               0, __LINE__,                             \
+               "rw_printf(%#s, ...) == %#s; got %#s",   \
+               fmt, expect_str, str);                   \
+    free (str)
+
+    TEST (">%{/Gs}<", (char*)0, 0, 0, ">(null)<");
+    TEST (">%{/Gs}<", "",       0, 0, ">\"\"<");
+    TEST (">%{/Gs}<", "a",      0, 0, ">\"a\"<");
+    TEST (">%{/Gs}<", "ab",     0, 0, ">\"ab\"<");
+    TEST (">%{/Gs}<", "abc",    0, 0, ">\"abc\"<");
+    TEST (">%{/Gs}<", "x\0z",   0, 0, ">\"x\"<");
+
+    TEST (">%{/*Gs}<",   1, "abc",  0,     ">\"abc\"<");
+    TEST (">%{/*.*Gs}<", 1, 2,      "abc", ">\"ab\"<");
+    TEST (">%{/.*Gs}<",  2, "abc",  0,     ">\"ab\"<");
+    TEST (">%{/.*Gs}<",  3, "x\0z", 0,     ">\"x\\0z\"<");
+
+    TEST (">%{/*Gs}<",   wchsize, (wchar_t*)0, 0,      ">(null)<");
+    TEST (">%{/*Gs}<",   wchsize, L"",         0,      ">\"\"<");
+    TEST (">%{/*Gs}<",   wchsize, L"a",        0,      ">\"a\"<");
+    TEST (">%{/*Gs}<",   wchsize, L"ab",       0,      ">\"ab\"<");
+    TEST (">%{/*Gs}<",   wchsize, L"abc",      0,      ">\"abc\"<");
+    TEST (">%{/*Gs}<",   wchsize, L"x\0z",     0,      ">\"x\"<");
+    TEST (">%{/*.*Gs}<", wchsize, 2,           L"abc", ">\"ab\"<");
+    TEST (">%{/*.*Gs}<", wchsize, 3,           L"x\0z",">\"x\\0z\"<");
+
+#define US(s)   make_user_string (s, sizeof (s))
+
+    TEST (">%{/*Gs}<",   usrsize, (UserChar*)0, 0,           ">(null)<");
+    TEST (">%{/*Gs}<",   usrsize, US (""),      0,           ">\"\"<");
+    TEST (">%{/*Gs}<",   usrsize, US ("a"),     0,           ">\"a\"<");
+    TEST (">%{/*Gs}<",   usrsize, US ("ab"),    0,           ">\"ab\"<");
+    TEST (">%{/*Gs}<",   usrsize, US ("abc"),   0,           ">\"abc\"<");
+    TEST (">%{/*Gs}<",   usrsize, US ("x\0z"),  0,           ">\"x\"<");
+    TEST (">%{/*.*Gs}<", usrsize, 2,            US ("abc"),  ">\"ab\"<");
+    TEST (">%{/*.*Gs}<", usrsize, 3,            US ("x\0z"), ">\"x\\0z\"<");
+}
+
+/***********************************************************************/
+
 static int no_user_traits;
 static int no_user_traits_char;
 static int no_user_traits_wchar_t;
@@ -788,6 +845,7 @@
 static int no_rw_widen;
 static int no_rw_narrow;
 static int no_rw_match;
+static int no_formatting;
 
 
 static int
@@ -829,6 +887,7 @@
     TEST (rw_widen);
     TEST (rw_narrow);
     TEST (rw_match);
+    TEST (formatting);
 
     return 0;
 }
@@ -847,7 +906,8 @@
                     "|-no-UserTraits<UserChar># "
                     "|-no-rw_widen# "
                     "|-no-rw_narrow# "
-                    "|-no-rw_macth#",
+                    "|-no-rw_macth# "
+                    "|-no-formatting#",
                     &no_user_traits,
                     &no_user_traits_char,
                     &no_user_traits_wchar_t,
@@ -855,5 +915,6 @@
                     &no_rw_widen,
                     &no_rw_narrow,
                     &no_rw_match,
+                    &no_formatting,
                     0);
 }

Modified: incubator/stdcxx/trunk/tests/src/char.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/src/char.cpp?rev=387687&r1=387686&r2=387687&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/src/char.cpp (original)
+++ incubator/stdcxx/trunk/tests/src/char.cpp Tue Mar 21 17:58:27 2006
@@ -29,7 +29,12 @@
 #define _RWSTD_TEST_SRC
 #include <rw_char.h>
 
-#include <string.h>   // for memcpy()
+#include <rw_printf.h>   // for rw_snprintfa()
+
+#include <ctype.h>       // for isdigit()
+#include <stdarg.h>      // for va_arg(), va_list, ...
+#include <stdlib.h>      // for strtol()
+#include <string.h>      // for memcpy(), strlen(), ...
 
 
 size_t
@@ -226,6 +231,7 @@
     return int_type::eof ();
 }
 
+/**************************************************************************/
 
 _TEST_EXPORT
 char*
@@ -497,4 +503,222 @@
     }
 
     return n;
+}
+
+/**************************************************************************/
+
+static int
+_rw_fmtstringv (char **pbuf, size_t *pbufsize, const char *fmt, va_list va)
+{
+    RW_ASSERT (0 != pbuf);
+    RW_ASSERT (0 != pbufsize);
+    RW_ASSERT (0 != fmt);
+
+    // directive syntax:
+    // '/' [ '#' ] { '*' | <n> } [ '.' '*' | <n> ] "Gs"
+
+    // NOTE:
+    // leading slash (or any other violation of the "standard" directive
+    // syntax) prevents the caller from extracting width and precision
+    // (etc.) from its variable argument list and allows us to do so
+
+    static int nested_call;
+
+    if (nested_call || '/' != fmt [0])
+        return _RWSTD_INT_MIN;
+
+    ++nested_call;
+    ++fmt;
+
+    va_list* pva      =  0;
+    bool     fl_pound = false;
+    int      nelems   = -1;
+    int      paramno  = -1;
+    int      elemsize = -1;
+
+    union UPtr {
+        const char     *pc;
+        const wchar_t  *pwc;
+        const UserChar *puc;
+    };
+
+    if ('#' == *fmt) {
+        fl_pound = true;
+        ++fmt;
+    }
+
+    // saved caller's va_list in case it needs to be restored
+    // to its orginal state after extracting argument from it
+    va_list va_save;
+
+    if ('*' == *fmt) {
+        // process element width (i.e., sizeof(charT))
+        pva = va_arg (va, va_list*);
+
+        RW_ASSERT (0 != pva);
+        va_save = *pva;
+
+        // extract the width from rw_snprintfa's variable argument
+        // list pass through to us by the caller
+        elemsize = va_arg (*pva, int);
+        ++fmt;
+    }
+    else if (isdigit (*fmt)) {
+        // process positional parameter or width
+        char* end = 0;
+        const int arg = strtol (fmt, &end, 10);
+        if ('$' == *end)
+            paramno = arg;
+        else
+            elemsize = arg;
+
+        fmt = end;
+    }
+
+    if ('.' == *fmt) {
+        // process precision (the length of the array in elements)
+        if ('*' == *++fmt) {
+            if (0 == pva) {
+                pva = va_arg (va, va_list*);
+
+                RW_ASSERT (0 != pva);
+
+                va_save = *pva;
+            }
+
+            // extract the width from rw_snprintfa's variable argument
+            // list passed through to us by the caller
+            nelems = va_arg (*pva, int);
+            ++fmt;
+        }
+        else if (isdigit (*fmt)) {
+            char* end = 0;
+            nelems = int (strtol (fmt, &end, 10));
+            fmt    = end;
+        }
+    }
+
+    // extract the address of the caller's variable argument list
+    if (0 == pva) {
+        pva = va_arg (va, va_list*);
+
+        RW_ASSERT (0 != pva);
+
+        va_save = *pva;
+    }
+
+    if ('G' != fmt [0] || 's' != fmt [1] || '\0' != fmt [2]) {
+
+        // restore caller's (potentially modified) va_list
+        *pva = va_save;
+
+        --nested_call;
+
+        // uknown directive, let caller process
+        return _RWSTD_INT_MIN;
+    }
+
+    // extract a pointer to the first character from rw_snprintfa's
+    // variable argument list pass through to us by the caller 
+    const UPtr beg = { va_arg (*pva, char*) };
+
+    {
+        // extract the address where to store the extracted argument
+        // for use by any subsequent positional paramaters
+        const char** const pparam = va_arg (va, const char**);
+
+        RW_ASSERT (0 != pparam);
+
+        // store the extracted argument
+        *pparam = beg.pc;
+    }
+
+    // compute the length of the buffer formatted so far
+    const size_t buflen_0 = *pbuf ? strlen (*pbuf) : 0;
+
+    int nbytes = 0;
+
+    //////////////////////////////////////////////////////////////////
+    // invoke rw_asnprintf() recursively to format our arguments
+    // and append the result to the end of the buffer; pass the
+    // value returned from rw_asnprintf() (i.e., the number of
+    // bytes appended) back to the caller
+
+    if (-1 == elemsize || 1 == elemsize) {
+        if (nelems < 0)
+            nelems = beg.pc ? strlen (beg.pc) : 0;
+
+        nbytes = rw_asnprintf (pbuf, pbufsize, "%{+}%{#*s}", nelems, beg.pc);
+    }
+    else if (_RWSTD_WCHAR_T_SIZE == elemsize) {
+        if (nelems < 0)
+            nbytes = rw_asnprintf (pbuf, pbufsize, "%{+}%{#ls}", beg.pwc);
+        else
+            nbytes = rw_asnprintf (pbuf, pbufsize, "%{+}%{#*ls}",
+                                   nelems, beg.pwc);
+    }
+    else if (sizeof (UserChar) == size_t (elemsize)) {
+
+        // narrow the argument into a local buffer of sufficient size
+        // (dynamically allocating memory only when the length of the
+        // string exceeds the size of the buffer for efficiency) and formt
+        // the resulting narrow string
+        char smallbuf [256];
+        const size_t len = nelems < 0 ? rw_match (0, beg.puc) : size_t (nelems);
+        char* const pb = len < sizeof smallbuf ? smallbuf : new char [len + 1];
+        rw_narrow (pb, beg.puc, len);
+
+        if (nelems < 0)
+            nelems = int (len);
+
+        nbytes = rw_asnprintf (pbuf, pbufsize, "%{+}%{#*s}",
+                               nelems, beg.pc ? pb : beg.pc);
+
+        if (pb != smallbuf)
+            delete[] pb;
+    }
+    else {
+        nbytes = rw_asnprintf (pbuf, pbufsize,
+                               "*** %%{/Gs}: bad element size: %d ***",
+                               elemsize);
+    }
+
+    //////////////////////////////////////////////////////////////////
+
+    // compute the new length of the buffer
+    const size_t buflen_1 = *pbuf ? strlen (*pbuf) : 0;
+
+    // assert that the function really appended as many characters
+    // as it said it did (assumes no NULs embedded in the output)
+    // and that it didn't write past the end of the buffer
+    RW_ASSERT (buflen_1 == buflen_0 + nbytes);
+    RW_ASSERT (buflen_1 < *pbufsize);
+
+    --nested_call;
+
+    return nbytes;
+}
+
+
+static int
+_rw_fmtstring (char **pbuf, size_t *pbufsize, const char *fmt, ...)
+{
+    va_list va;
+    va_start (va, fmt);
+
+    const int nbytes = _rw_fmtstringv (pbuf, pbufsize, fmt, va);
+
+    va_end (va);
+
+    return nbytes;
+}
+
+
+UserCharFmatInit::
+UserCharFmatInit ()
+{
+    // install the formatting callback function
+    static int format_init = rw_printf ("%{+!}", _rw_fmtstring);
+
+    _RWSTD_UNUSED (format_init);
 }



Mime
View raw message