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;
}