You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by se...@apache.org on 2006/05/09 03:04:09 UTC

svn commit: r405252 - in /incubator/stdcxx/trunk/tests: self/0.char.cpp src/char.cpp

Author: sebor
Date: Mon May  8 18:04:07 2006
New Revision: 405252

URL: http://svn.apache.org/viewcvs?rev=405252&view=rev
Log:
2006-05-08  Martin Sebor  <se...@roguewave.com>

	* char.cpp (_rw_expand): New "generic" implementation of all three
	rw_expand() overloads. Corrected the handling of empty strings to
	produce a NUL-terminated string of 0 size.
	(rw_expand): Implemented in terms of the generic _rw_expand().
	(rw_match): Used rw_expand() when the first string contains '@'.
	* 0.char.cpp (test_rw_expand): Simplified, verified the correcntess
	of the result size, and added more test cases.

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

Modified: incubator/stdcxx/trunk/tests/self/0.char.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/self/0.char.cpp?rev=405252&r1=405251&r2=405252&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/self/0.char.cpp (original)
+++ incubator/stdcxx/trunk/tests/self/0.char.cpp Mon May  8 18:04:07 2006
@@ -504,69 +504,94 @@
     //////////////////////////////////////////////////////////////////
     rw_info (0, 0, 0, "rw_expand(char*, const char*, size_t, size_t*)");
 
-    char *result;
-    size_t len;
-
 #undef TEST
-#define TEST(str, expstr, size)                                         \
-    result = rw_expand ((char*)0, str, sizeof str - 1, &len);           \
-    rw_assert (0 == memcmp (result, expstr, size + 1), 0, __LINE__,     \
-               "rw_expand(0, %#s, %zu, ...) == %#s, got %#s",           \
-               str, sizeof str -1, expstr, result);
-
-    TEST ("",          "",          0);
-    TEST ("a",         "a",         1);
-    TEST ("ab",        "ab",        2);
-    TEST ("abc",       "abc",       3);
-    TEST ("a\0b",      "a\0b",      3);
-    TEST ("a\0b\0c\0", "a\0b\0c\0", 6);
-
-    TEST ("a@0",       "",          0);
-    TEST ("a@1",       "a",         1);
-    TEST ("a@2",       "aa",        2);
-    TEST ("a@3",       "aaa",       3);
-    TEST ("a@1b",      "ab",        2);
-    TEST ("a@2b",      "aab",       3);
-    TEST ("a@3b",      "aaab",      4);
-    TEST ("a@3bc",     "aaabc",     5);
-    TEST ("a@3b@1c",   "aaabc",     5);
-    TEST ("a@3b@2c",   "aaabbc",    6);
-    TEST ("a@3b@2c@1", "aaabbc",    6);
-    TEST ("a@3b@3c@2", "aaabbbcc",  8);
+#define TEST(str, expstr)                                               \
+    do {                                                                \
+        const size_t str_size = sizeof str - 1;                         \
+        const size_t exp_size = sizeof expstr - 1;                      \
+        size_t len;                                                     \
+        char* const res = rw_expand ((char*)0, str, str_size, &len);    \
+        rw_assert (   0 == memcmp (res, expstr, exp_size)               \
+                   && exp_size == len,                                  \
+                   0, __LINE__,                                         \
+                   "rw_expand((char*)0, %{#*s}, %zu, ...) == "          \
+                   "%{#*s} (length %zu), got %{#*s} (length %zu)",      \
+                   int (str_size), str, str_size,                       \
+                   int (exp_size), expstr, exp_size,                    \
+                   int (len), res, len);                                \
+    } while (0)
+
+    TEST ("",          "");
+    TEST ("\0",        "\0");
+    TEST ("a",         "a");
+    TEST ("a\0",       "a\0");
+    TEST ("ab",        "ab");
+    TEST ("abc",       "abc");
+    TEST ("a\0b",      "a\0b");
+    TEST ("a\0b\0c\0", "a\0b\0c\0");
+
+    TEST ("\0@0",      "");
+    TEST ("a@0",       "");
+    TEST ("\0@1",      "\0");
+    TEST ("a@1",       "a");
+    TEST ("a@2",       "aa");
+    TEST ("a@2\0",     "aa\0");
+    TEST ("a@3",       "aaa");
+    TEST ("a@1b",      "ab");
+    TEST ("a@2b",      "aab");
+    TEST ("a@3b",      "aaab");
+    TEST ("a@3bc",     "aaabc");
+    TEST ("a@3b@1c",   "aaabc");
+    TEST ("a@3b@2c",   "aaabbc");
+    TEST ("a@3b@2c@1", "aaabbc");
+    TEST ("a@3b@3c@2", "aaabbbcc");
 
     //////////////////////////////////////////////////////////////////
     rw_info (0, 0, 0, "rw_expand(wchar_t*, const char*, size_t, size_t*)");
 
 #ifndef _RWSTD_NO_WCHAR_T
 
-    wchar_t *wresult;
-
 #  undef TEST
-#  define TEST(str, expstr, size)                                       \
-      wresult = rw_expand ((wchar_t*)0, str, sizeof str - 1, &len);     \
-      rw_assert (0 == memcmp (wresult, expstr, size + 1), 0, __LINE__,  \
-                 "rw_expand(0, %#s, %zu, ...) == %#ls, got %#ls",       \
-                 str, sizeof str -1, expstr, wresult);
-
-    TEST ("",          L"",          0);
-    TEST ("a",         L"a",         1);
-    TEST ("ab",        L"ab",        2);
-    TEST ("abc",       L"abc",       3);
-    TEST ("a\0b",      L"a\0b",      3);
-    TEST ("a\0b\0c\0", L"a\0b\0c\0", 6);
-
-    TEST ("a@0",       L"",          0);
-    TEST ("a@1",       L"a",         1);
-    TEST ("a@2",       L"aa",        2);
-    TEST ("a@3",       L"aaa",       3);
-    TEST ("a@1b",      L"ab",        2);
-    TEST ("a@2b",      L"aab",       3);
-    TEST ("a@3b",      L"aaab",      4);
-    TEST ("a@3bc",     L"aaabc",     5);
-    TEST ("a@3b@1c",   L"aaabc",     5);
-    TEST ("a@3b@2c",   L"aaabbc",    6);
-    TEST ("a@3b@2c@1", L"aaabbc",    6);
-    TEST ("a@3b@3c@2", L"aaabbbcc",  8);
+#define TEST(str, expstr)                                                  \
+    do {                                                                   \
+        const size_t str_size = sizeof str - 1;                            \
+        const size_t exp_size = sizeof expstr / sizeof *expstr - 1;        \
+        size_t len;                                                        \
+        wchar_t* const res = rw_expand ((wchar_t*)0, str, str_size, &len); \
+        rw_assert (   0 == memcmp (res, expstr, exp_size)                  \
+                   && exp_size == len,                                     \
+                   0, __LINE__,                                            \
+                   "rw_expand((wchar_t*)0, %{#*s}, %zu, ...) == "          \
+                   "%{#*ls} (length %zu), got %{#*ls} (length %zu)",       \
+                   int (str_size), str, str_size,                          \
+                   int (exp_size), expstr, exp_size,                       \
+                   int (len), res, len);                                   \
+    } while (0)
+
+    TEST ("",          L"");
+    TEST ("\0",        L"\0");
+    TEST ("a",         L"a");
+    TEST ("a\0",       L"a\0");
+    TEST ("ab",        L"ab");
+    TEST ("abc",       L"abc");
+    TEST ("a\0b",      L"a\0b");
+    TEST ("a\0b\0c\0", L"a\0b\0c\0");
+
+    TEST ("\0@0",      L"");
+    TEST ("a@0",       L"");
+    TEST ("\0@1",      L"\0");
+    TEST ("a@1",       L"a");
+    TEST ("a@2",       L"aa");
+    TEST ("a@2\0",     L"aa\0");
+    TEST ("a@3",       L"aaa");
+    TEST ("a@1b",      L"ab");
+    TEST ("a@2b",      L"aab");
+    TEST ("a@3b",      L"aaab");
+    TEST ("a@3bc",     L"aaabc");
+    TEST ("a@3b@1c",   L"aaabc");
+    TEST ("a@3b@2c",   L"aaabbc");
+    TEST ("a@3b@2c@1", L"aaabbc");
+    TEST ("a@3b@3c@2", L"aaabbbcc");
 
 #else   // if defined (_RWSTD_NO_WCHAR_T)
 
@@ -642,7 +667,8 @@
                    0, __LINE__,
                    "rw_narrow(char*, L%{#*ls}%{?}, %zu%{;}) == %{#*s}, "
                    "got %{#*s}",
-                   src, i < nsrc, i, int (i), wsrc, int (i + 1), cdst);
+                   int (i), src, i < nsrc, i, int (i), wsrc,
+                   int (i + 1), cdst);
     }
 
     memset (cdst, '@', sizeof cdst);

Modified: incubator/stdcxx/trunk/tests/src/char.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/src/char.cpp?rev=405252&r1=405251&r2=405252&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/src/char.cpp (original)
+++ incubator/stdcxx/trunk/tests/src/char.cpp Mon May  8 18:04:07 2006
@@ -260,19 +260,46 @@
     return dst;
 }
 
+/**************************************************************************/
 
-_TEST_EXPORT
-char*
-rw_expand (char *dst, const char *src, size_t src_len /* = SIZE_MAX */,
-           size_t *dst_len /* = 0 */)
-{
-    size_t bufsize = dst ? _RWSTD_SIZE_MAX : 0;
+static void*
+_rw_expand (void *dst, size_t elemsize,
+            const char *src, size_t src_len /* = SIZE_MAX */,
+            size_t *dst_len /* = 0 */)
+{
+    // create a typedef for "genericity"
+#ifndef _RWSTD_NO_WCHAR_T
+    typedef wchar_t WChar;
+#else   // if defined (_RWSTD_NO_WCHAR_T)
+    // dummy, will never be used
+    typedef int WChar;
+#endif   // _RWSTD_NO_WCHAR_T
+
+    RW_ASSERT (   sizeof (char) == elemsize
+               || sizeof (WChar) == elemsize
+               || sizeof (UserChar) == elemsize);
+
+    if (0 == src) {
+        src     = "";
+        src_len = 0;
+    }
+
+    // save the original value of dst and avoid deallocating
+    // it when a large buffer is needed
+    const void* const dst_save = dst;
+
+    // when both dst and dst_size are non-null use *dst_len
+    // as the size of the destination buffer
+    size_t bufsize = dst ? dst_len ? *dst_len : _RWSTD_SIZE_MAX : 0;
     size_t buflen  = 0;
 
     if (_RWSTD_SIZE_MAX == src_len)
         src_len = strlen (src);
 
-    char *pnext = dst;
+    // remember if src is the empty string
+    const bool empty_string = 0 == src_len;
+
+    void *pnext = dst;
 
     for (const char *psrc = src; ; ) {
 
@@ -309,36 +336,71 @@
                 bufsize = 128;
 
             // allocate larger buffer
-            char* const tmp = new char [bufsize];
+            void* tmp;
+
+            switch (elemsize) {
+            case sizeof (WChar):    tmp = new WChar [bufsize]; break;
+            case sizeof (UserChar): tmp = new UserChar [bufsize]; break;
+            default:                tmp = new char [bufsize]; break;
+            }
 
             // copy old buffer into new one
-            memcpy (tmp, dst, buflen);
+            memcpy (tmp, dst, buflen * elemsize);
 
-            // dispose of old buffer
-            delete[] dst;
+            // dispose of previously allocated buffer
+            if (dst != dst_save) {
+                switch (elemsize) {
+                case sizeof (WChar):    delete[] (WChar*)dst; break;
+                case sizeof (UserChar): delete[] (UserChar*)dst; break;
+                default:                delete[] (char*)dst; break;
+                }
+            }
 
-            dst   = tmp;
-            pnext = dst + buflen;
+            dst = tmp;
+
+            pnext = (char*)dst + buflen * elemsize;
         }
 
         typedef unsigned char UChar;
-        memset (pnext, UChar (c), count);
 
-        pnext += count;
+        if (sizeof (WChar) == elemsize) {
+            for (size_t i = 0; i != count; ++i)
+                ((WChar*)pnext)[i] = WChar (UChar (c));
+        }
+        else if (sizeof (UserChar) == elemsize) {
+            for (size_t i = 0; i != count; ++i) {
+                ((UserChar*)pnext)[i].f = 0;
+                ((UserChar*)pnext)[i].c = UChar (c);
+            }
+        }
+        else
+            memset (pnext, UChar (c), count);
+
+        pnext   = (char*)pnext + count * elemsize;
         buflen += count;
 
         if (0 == src_len)
             break;
     }
 
-    *pnext = '\0';
-
     if (dst_len)
-        *dst_len = buflen;
+        *dst_len = buflen - empty_string;
 
     return dst;
 }
 
+/**************************************************************************/
+
+_TEST_EXPORT
+char*
+rw_expand (char *dst, const char *src, size_t src_len /* = SIZE_MAX */,
+           size_t *dst_len /* = 0 */)
+{
+    void* const result = _rw_expand (dst, sizeof *dst, src, src_len, dst_len);
+
+    return _RWSTD_STATIC_CAST (char*, result);
+}
+
 
 _TEST_EXPORT
 char*
@@ -360,6 +422,17 @@
     if (0 == s2)
         return strlen (s1);
 
+    const char* const s1_save = s1;
+
+    char   s1_buf [256];
+    size_t s1_len = sizeof s1_buf;
+
+    // see if the first string contains '@' and might need
+    // to be expanded  (see rw_expand() for details)
+    if (   _RWSTD_SIZE_MAX == len && strchr (s1, '@')
+        || _RWSTD_SIZE_MAX != len && memchr (s1, '@', len))
+        s1 = rw_expand (s1_buf, s1, len, &s1_len);
+
     size_t n = 0;
 
     for ( ; n != len && s1 [n] == s2 [n]; ++n) {
@@ -367,6 +440,11 @@
             break;
     }
 
+    if (s1 && s1_save != s1 && s1_buf != s1) {
+        // deallocate memory if it was allocated by rw_expand()
+        delete[] s1;
+    }
+
     return n;
 }
 
@@ -413,77 +491,9 @@
 rw_expand (wchar_t *dst, const char *src, size_t src_len /* = SIZE_MAX */,
            size_t *dst_len /* = 0 */)
 {
-    size_t bufsize = dst ? _RWSTD_SIZE_MAX : 0;
-    size_t buflen  = 0;
-
-    if (_RWSTD_SIZE_MAX == src_len)
-        src_len = strlen (src);
-
-    wchar_t *pnext = dst;
-
-    for (const char *psrc = src; ; ) {
-
-        const char c = *psrc;
-
-        unsigned long count;
-
-        if ('@' == psrc [1] && isdigit (psrc [2])) {
-            // process directive 
-           psrc += 2;
-
-            char *end = 0;
-            count = strtoul (psrc, &end, 10);
-
-            src_len -= (end - psrc) + 2;
-
-            psrc = end;
-
-        }
-        else {
-            count = 1;
-
-            // decrement length unless it's already 0
-            if (src_len)
-                --src_len;
-
-            ++psrc;
-        }
-
-        if (bufsize - buflen <= count) {
-            // increase the size of the buffer
-            bufsize = (bufsize + count) * 2;
-            if (bufsize < 128)
-                bufsize = 128;
-
-            // allocate larger buffer
-            wchar_t* const tmp = new wchar_t [bufsize];
-
-            // copy old buffer into new one
-            memcpy (tmp, dst, buflen * sizeof *tmp);
-
-            // dispose of old buffer
-            delete[] dst;
-
-            dst   = tmp;
-            pnext = dst + buflen;
-        }
-
-        typedef unsigned char UChar;
-        for (size_t i = 0; i != count; ++i)
-            *pnext++ = wchar_t (UChar (c));
-
-        buflen += count;
-
-        if (0 == src_len)
-            break;
-    }
-
-    *pnext = L'\0';
-
-    if (dst_len)
-        *dst_len = buflen;
+    void* const result = _rw_expand (dst, sizeof *dst, src, src_len, dst_len);
 
-    return dst;
+    return _RWSTD_STATIC_CAST (wchar_t*, result);
 }
 
 
@@ -544,6 +554,17 @@
     if (0 == s2)
         return strlen (s1);
 
+    const char* const s1_save = s1;
+
+    char   s1_buf [256];
+    size_t s1_len = sizeof s1_buf;
+    
+    // see if the first string contains '@' and might need
+    // to be expanded  (see rw_expand() for details)
+    if (   _RWSTD_SIZE_MAX == len && strchr (s1, '@')
+        || _RWSTD_SIZE_MAX != len && memchr (s1, '@', len))
+        s1 = rw_expand (s1_buf, s1, len, &s1_len);
+
     typedef unsigned char UChar;
 
     size_t n = 0;
@@ -553,6 +574,9 @@
             break;
     }
 
+    if (s1 && s1_save != s1 && s1_buf != s1)
+        delete[] s1;
+
     return n;
 }
 
@@ -600,80 +624,9 @@
 rw_expand (UserChar *dst, const char *src, size_t src_len /* = SIZE_MAX */,
            size_t *dst_len /* = 0 */)
 {
-    size_t bufsize = dst ? _RWSTD_SIZE_MAX : 0;
-    size_t buflen  = 0;
-
-    if (_RWSTD_SIZE_MAX == src_len)
-        src_len = strlen (src);
-
-    UserChar *pnext = dst;
+    void* const result = _rw_expand (dst, sizeof *dst, src, src_len, dst_len);
 
-    for (const char *psrc = src; ; ) {
-
-        const char c = *psrc;
-
-        unsigned long count;
-
-        if ('@' == psrc [1] && isdigit (psrc [2])) {
-            // process directive 
-            psrc += 2;
-
-            char *end = 0;
-            count = strtoul (psrc, &end, 10);
-
-            src_len -= (end - psrc) + 2;
-
-            psrc = end;
-
-        }
-        else {
-            count = 1;
-
-            // decrement length unless it's already 0
-            if (src_len)
-                --src_len;
-
-            ++psrc;
-        }
-
-        if (bufsize - buflen <= count) {
-            // increase the size of the buffer
-            bufsize = (bufsize + count) * 2;
-            if (bufsize < 128)
-                bufsize = 128;
-
-            // allocate larger buffer
-            UserChar* const tmp = new UserChar [bufsize];
-
-            // copy old buffer into new one
-            memcpy (tmp, dst, buflen * sizeof *tmp);
-
-            // dispose of old buffer
-            delete[] dst;
-
-            dst   = tmp;
-            pnext = dst + buflen;
-        }
-
-        typedef unsigned char UChar;
-        for (size_t i = 0; i != count; ++i) {
-            pnext->f = 0;
-            pnext->c = UChar (c);
-            ++pnext;
-        }
-
-        buflen += count;
-
-        if (0 == src_len)
-            break;
-    }
-
-    *pnext = UserChar::eos ();
-
-    if (dst_len)
-        *dst_len = buflen;
-
-    return dst;
+    return _RWSTD_STATIC_CAST (UserChar*, result);
 }
 
 
@@ -734,6 +687,17 @@
     if (0 == s2)
         return strlen (s1);
 
+    const char* const s1_save = s1;
+
+    char   s1_buf [256];
+    size_t s1_len = sizeof s1_buf;
+    
+    // see if the first string contains '@' and might need
+    // to be expanded  (see rw_expand() for details)
+    if (   _RWSTD_SIZE_MAX == len && strchr (s1, '@')
+        || _RWSTD_SIZE_MAX != len && memchr (s1, '@', len))
+        s1 = rw_expand (s1_buf, s1, len, &s1_len);
+
     typedef unsigned char UChar;
 
     size_t n = 0;
@@ -742,6 +706,9 @@
         if (_RWSTD_SIZE_MAX == len && '\0' == s1 [n])
             break;
     }
+
+    if (s1 && s1_save != s1 && s1_buf != s1)
+        delete[] s1;
 
     return n;
 }