Anton Pevtsov wrote:
Martin Sebor wrote:

But before committing the rest we need to first settle the issue of

rw_expand().

Martin, in my previous mail I didn't mention that the problem occur when
rw_expand is called from the rw_match function.
Sorry about that. The test which illustrates the problem is here:
http://people.apache.org/~antonp/stdcxx06262006/rwmatch_rwexpand_test.cp
p

Hmm. There are two possible interpretations of the third argument
to rw_match():

1. it gives the maximum number of characters to compare (i.e.,
   after all directives have been expanded)

2. it denotes the number of characters in the first argument
   (i.e., before the expansion of any directives).

It looks like currently we do (2). I missed this and made changes
to implement (1). Needless to say, even though my changes are "good",
they cause many failures in the test suite. I need to go back and
implement (1). It shouldn't be too hard but it means that I won't
be able to commit my changes tonight (what I have is attached so you
can see where I am).

Martin
==== //stdlib/dev/tests/stdlib/src/char.cpp#16 - 
/build/sebor/dev/stdlib/tests/src/char.cpp ====
@@ -678,59 +678,117 @@
 size_t
 rw_match (const char *s1, const char *s2, size_t len /* = SIZE_MAX */)
 {
+    const char* p1 = s1;
+    const char* p2 = s2;
+
+    // the length of the initial subsequence of s1 and s2
+    // consisting solely of characters that compare equal
+    size_t count = 0;
+
     if (0 == s1) {
-        // return the length of s2 if non-null
-        return s2 ? strlen (s2) : 0;
+        s1 = s2;
+        s2 = 0;
     }
 
-    if (0 == s2)
-        return strlen (s1);
+    if (0 == s2) {
+        // when one of the strings is null, compute the length
+        // of the other string when all directives are expanded
+        if (0 == s1 || 0 == *s1)
+            return 0;
+
+        for (const char *pat = s1; ; ) {
+
+            const char* const p = strchr (pat, '@');
 
-    const char* const s1_save = s1;
+            if (p && 0 < p - pat) {
+                if (isdigit (p [1])) {
+                    char* end;
+                    const size_t n = strtoul (p + 1, &end, 10);
+                    pat    = end;
+                    count += n;
+                }
+                else {
+                    count += size_t (p - pat);
+                    pat    = p + 1;
+                }
+            }
+            else {
+                const size_t pat_len = strlen (pat);
+                count += pat_len;
+                pat   += pat_len;
+            }
 
-    char   s1_buf [256];
-    size_t s1_len = sizeof s1_buf;
+            if ('\0' == *pat) {
+                if (_RWSTD_SIZE_MAX == len)
+                    break;
 
-    // see if the first string contains '@' and might need
-    // to be expanded (see rw_expand() for details)
-    bool expand = false;
+                ++pat;
+            }
+        }
 
-    if (_RWSTD_SIZE_MAX == len) {
-        expand = 0 != strchr (s1, '@');
+        return count;
     }
-    else {
-        for (const char *p = s1; *p; ++p) {
-            if (size_t (p - s1) == len)
-                break;
-            if ('@' == *p) {
-                expand = true;
-                break;
+    
+
+    size_t n1 = 0;
+    size_t n2 = 0;
+
+    for (char ch1, ch2; count < len; ) {
+
+        while (0 == n1) {
+            ch1 = *p1++;
+
+            if ('@' == p1 [0] && isdigit (p1 [1])) {
+
+                char* end;
+                n1 = strtoul (p1 + 1, &end, 10);
+                p1 = end;
             }
+            else
+                n1 = 1;
         }
-    }
+
+        while (0 == n2) {
+            ch2 = *p2++;
 
-    if (expand) {
-        s1  = rw_expand (s1_buf, s1, _RWSTD_SIZE_MAX, &s1_len);
-        len = s1_len;
-    }
+            if ('@' == p2 [0] && isdigit (p2 [1])) {
 
-    size_t n = 0;
+                char* end;
+                n2 = strtoul (p2 + 1, &end, 10);
+                p2 = end;
+            }
+            else
+                n2 = 1;
+        }
 
-    for ( ; n != len && s1 [n] == s2 [n]; ++n) {
-        if (_RWSTD_SIZE_MAX == len && '\0' == s1 [n])
+        if (ch1 != ch2)
             break;
-    }
+
+        if (n1 < n2) {
+            // the repeat count specified by the first directive
+            // is less than the repeat count given by the second
+            count += n1;
+            n2    -= n1;
+            n1     = 0;
+
+        }
+        else if (n2 <= n1) {
+            // the repeat count specified by the second directive
+            // is less than or equal than that given by the first
+            count += n2;
+            n1    -= n2;
+            n2     = 0;
+        }
 
-    if (s1 && s1_save != s1 && s1_buf != s1) {
-        // deallocate memory if it was allocated by rw_expand()
-        delete[] s1;
+        if (_RWSTD_SIZE_MAX == len && '\0' == ch1)
+            break;
     }
 
-    return n;
+    return len < count ? len : count;
 }
 
 
-#ifndef _RWSTD_WCHAR_T
+#ifndef _RWSTD_NO_WCHAR_T
 
 _TEST_EXPORT
 wchar_t*
@@ -829,35 +887,63 @@
     }
 
     if (0 == s2)
-        return strlen (s1);
+        return rw_match (s1, (char*)0, len);
+
+    const char*    p1 = s1;
+    const wchar_t* p2 = s2;
+
+    // the length of the initial subsequence of s1 and s2
+    // consisting solely of characters that compare equal
+    size_t count = 0;
+
+    size_t n1 = 0;
+    size_t n2 = 0;
+
+    for (wchar_t ch1, ch2; count < len; ) {
+
+        while (0 == n1) {
+            ch1 = wchar_t (UChar (*p1++));
+
+            if ('@' == p1 [0] && isdigit (p1 [1])) {
+
+                char* end;
+                n1 = strtoul (p1 + 1, &end, 10);
+                p1 = end;
+            }
+            else
+                n1 = 1;
+        }
+
+        ch2 = *p2++;
+        n2  = 1;
 
-    const char* const s1_save = s1;
+        if (ch1 != ch2)
+            break;
 
-    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);
-        len = s1_len;
-    }
+        if (n1 < n2) {
+            // the repeat count specified by the first directive
+            // is less than the repeat count given by the second
+            count += n1;
+            n2    -= n1;
+            n1     = 0;
 
-    size_t n = 0;
+        }
+        else if (n2 <= n1) {
+            // the repeat count specified by the second directive
+            // is less than or equal than that given by the first
+            count += n2;
+            n1    -= n2;
+            n2     = 0;
+        }
 
-    for ( ; n != len && UChar (s1 [n]) == unsigned (s2 [n]); ++n) {
-        if (_RWSTD_SIZE_MAX == len && '\0' == s1 [n])
+        if (_RWSTD_SIZE_MAX == len && L'\0' == ch1)
             break;
     }
 
-    if (s1 && s1_save != s1 && s1_buf != s1)
-        delete[] s1;
-
-    return n;
+    return len < count ? len : count;
 }
 
-#endif   // _RWSTD_WCHAR_T
+#endif   // _RWSTD_NO_WCHAR_T
 
 
 _TEST_EXPORT
@@ -958,32 +1044,62 @@
     }
 
     if (0 == s2)
-        return strlen (s1);
+        return rw_match (s1, (char*)0, len);
+
+    const char*     p1 = s1;
+    const UserChar* p2 = s2;
+
+    // the length of the initial subsequence of s1 and s2
+    // consisting solely of characters that compare equal
+    size_t count = 0;
+
+    size_t n1 = 0;
+    size_t n2 = 0;
+
+    char ch1;
+
+    for (UserChar ch2; count < len; ) {
+
+        while (0 == n1) {
+            ch1 = wchar_t (UChar (*p1++));
+
+            if ('@' == p1 [0] && isdigit (p1 [1])) {
+
+                char* end;
+                n1 = strtoul (p1 + 1, &end, 10);
+                p1 = end;
+            }
+            else
+                n1 = 1;
+        }
+
+        ch2 = *p2++;
+        n2  = 1;
 
-    const char* const s1_save = s1;
+        if (ch1 != ch2.c)
+            break;
 
-    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);
-        len = s1_len;
-    }
+        if (n1 < n2) {
+            // the repeat count specified by the first directive
+            // is less than the repeat count given by the second
+            count += n1;
+            n2    -= n1;
+            n1     = 0;
 
-    size_t n = 0;
+        }
+        else if (n2 <= n1) {
+            // the repeat count specified by the second directive
+            // is less than or equal than that given by the first
+            count += n2;
+            n1    -= n2;
+            n2     = 0;
+        }
 
-    for ( ; n != len && UChar (s1 [n]) == s2 [n].c; ++n) {
-        if (_RWSTD_SIZE_MAX == len && '\0' == s1 [n])
+        if (_RWSTD_SIZE_MAX == len && L'\0' == ch1)
             break;
     }
 
-    if (s1 && s1_save != s1 && s1_buf != s1)
-        delete[] s1;
-
-    return n;
+    return len < count ? len : count;
 }
 
 /**************************************************************************/
==== //stdlib/dev/tests/stdlib/test/char.cpp#11 - 
/build/sebor/dev/stdlib/tests/test/00_char.cpp ====
@@ -732,33 +732,6 @@
 
 /***********************************************************************/
 
-static size_t
-length (const char *s)
-{
-    return s ? strlen (s) : 0;
-}
-
-
-static size_t
-length (const wchar_t *ws)
-{
-    size_t len = 0;
-    if (ws)
-        for (len = 0; ws [len]; ++len);
-    return len;
-}
-
-
-static size_t
-length (const UserChar *us)
-{
-    size_t len = 0;
-    if (us)
-        for (len = 0; us [len].f || us [len].c; ++len);
-    return len;
-}
-
-
 static const UserChar*
 make_user_string (const char *s, size_t len)
 {
@@ -786,48 +759,108 @@
     //////////////////////////////////////////////////////////////////
     rw_info (0, 0, 0, "rw_match(char*, const char*, size_t)");
 
-    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",           \
-             LEN (char, s1, len), s1, LEN (char, s2, len),              \
-             s2, len, expect, result)
+             int (sizeof s1 - 1), s1, int (sizeof s2 - 1), s2, len,     \
+             expect, result)
 
     TEST (0,      0,        -1, 0);
     TEST ("",     0,        -1, 0);
     TEST (0,      "",       -1, 0);
-    TEST ("",     "",       -1, 0);
+    TEST ("",     "",       -1, 1);
+
+    // same as above but using the <char>@<count> directive
+    TEST ("[EMAIL PROTECTED]",  "",       -1, 1);
+    TEST ("",     "[EMAIL PROTECTED]",    -1, 1);
+    TEST ("[EMAIL PROTECTED]",  "[EMAIL PROTECTED]",    -1, 1);
 
-    // when invoked with NULL as the first string returns
-    // the length of the second string (if non-NULL)
+    // when invoked with NULL as the first argument returns
+    // the length of the second string with all directives
+    // expanded
     TEST (0,      "a",      -1, 1);
     TEST (0,      "ab",     -1, 2);
     TEST (0,      "abc",    -1, 3);
+    TEST (0,      "[EMAIL PROTECTED]",    -1, 0);
+    TEST (0,      "[EMAIL PROTECTED]",    -1, 1);
+    TEST (0,      "[EMAIL PROTECTED]",    -1, 2);
+    TEST (0,      "[EMAIL PROTECTED]@0", -1, 2);
+    TEST (0,      "[EMAIL PROTECTED]@1", -1, 3);
+    TEST (0,      "[EMAIL PROTECTED]@2", -1, 4);
 
     // same as above but with the arguments reversed
-    TEST ("a",    0,        -1, 1);
-    TEST ("ab",   0,        -1, 2);
-    TEST ("abc",  0,        -1, 3);
+    TEST ("a",      0,      -1, 1);
+    TEST ("ab",     0,      -1, 2);
+    TEST ("abc",    0,      -1, 3);
+    TEST ("[EMAIL PROTECTED]",    0,      -1, 0);
+    TEST ("[EMAIL PROTECTED]",    0,      -1, 1);
+    TEST ("[EMAIL PROTECTED]",    0,      -1, 2);
+    TEST ("[EMAIL PROTECTED]@0", 0,      -1, 2);
+    TEST ("[EMAIL PROTECTED]@1", 0,      -1, 3);
+    TEST ("[EMAIL PROTECTED]@2", 0,      -1, 4);
 
     TEST ("",     "a",      -1, 0);
     TEST ("a",    "",       -1, 0);
-    TEST ("a",    "a",      -1, 1);
+    TEST ("a",    "a",      -1, 2);
+
+    // same as above but using the <char>@<count> directive
+    TEST ("",     "[EMAIL PROTECTED]",    -1, 0);
+    TEST ("[EMAIL PROTECTED]",  "",       -1, 0);
+    TEST ("a",    "[EMAIL PROTECTED]",    -1, 2);
+    TEST ("[EMAIL PROTECTED]",  "a",      -1, 2);
+    TEST ("[EMAIL PROTECTED]",  "[EMAIL PROTECTED]",    -1, 2);
+
+    TEST ("\0ab",       "\0ac",   2, 2);
+    TEST ("[EMAIL PROTECTED]",     "ab",     2, 2);
+    TEST ("[EMAIL PROTECTED]@0b", "ab",     2, 2);
+    TEST ("[EMAIL PROTECTED]",     "[EMAIL PROTECTED]", 2, 2);
+    TEST ("[EMAIL PROTECTED]",     "[EMAIL PROTECTED]", 2, 2);
 
-    TEST ("a\0bc", "a\0bd", -1, 1);
+    TEST ("a\0bc", "a\0bd", -1, 2);
     TEST ("a\0bc", "a\0bd",  0, 0);
     TEST ("a\0bc", "a\0bd",  1, 1);
     TEST ("a\0bc", "a\0bd",  2, 2);
     TEST ("a\0bc", "a\0bd",  3, 3);
     TEST ("a\0bc", "a\0bd",  4, 3);
 
+    TEST ("aaaaa",    "[EMAIL PROTECTED]",  -1, 6);
+    TEST ("[EMAIL PROTECTED]", "[EMAIL PROTECTED]",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",  "[EMAIL PROTECTED]",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",   "[EMAIL PROTECTED]",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",    "[EMAIL PROTECTED]",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",     "[EMAIL PROTECTED]",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",      "[EMAIL PROTECTED]",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",     "[EMAIL PROTECTED]",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",    "[EMAIL PROTECTED]",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",   "[EMAIL PROTECTED]",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",  "[EMAIL PROTECTED]",  -1, 6);
+    TEST ("[EMAIL PROTECTED]", "[EMAIL PROTECTED]",  -1, 6);
+
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "[EMAIL PROTECTED]@[EMAIL 
PROTECTED]@0", -1, 7);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "[EMAIL PROTECTED]@[EMAIL 
PROTECTED]@0",  0, 0);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "[EMAIL PROTECTED]@[EMAIL 
PROTECTED]@0",  1, 1);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "[EMAIL PROTECTED]@[EMAIL 
PROTECTED]@0",  2, 2);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "[EMAIL PROTECTED]@[EMAIL 
PROTECTED]@0",  3, 3);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "[EMAIL PROTECTED]@[EMAIL 
PROTECTED]@0",  4, 4);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "[EMAIL PROTECTED]@[EMAIL 
PROTECTED]@0",  5, 5);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "[EMAIL PROTECTED]@[EMAIL 
PROTECTED]@0",  6, 6);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "[EMAIL PROTECTED]@[EMAIL 
PROTECTED]@0",  7, 7);
+
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3\0", "[EMAIL PROTECTED]@[EMAIL 
PROTECTED]@0\0", 10, 10);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3\0",  "[EMAIL 
PROTECTED]@[EMAIL PROTECTED]@0\0", 10,  0);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3\0",  "[EMAIL 
PROTECTED]@[EMAIL PROTECTED]@0\0", 10,  4);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3*",  "[EMAIL PROTECTED]@[EMAIL 
PROTECTED]@0\0", 10,  8);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]",   "[EMAIL PROTECTED]@[EMAIL 
PROTECTED]",   -1, 39);
+
+    // invalid directives
+    TEST ("[EMAIL PROTECTED]",   "[EMAIL PROTECTED]@b",   -1, 4);
+    TEST ("[EMAIL PROTECTED]@c", "[EMAIL PROTECTED]@[EMAIL PROTECTED]", -1, 6);
+
     //////////////////////////////////////////////////////////////////
     rw_info (0, 0, 0, "rw_match(char*, const wchar_t*, size_t)");
 
@@ -839,33 +872,92 @@
   rw_assert (expect == result,                                               \
              0, __LINE__,                                                    \
              "rw_match(%{#*s}, L%{#*ls}, %zu) == %zu, got %zu",              \
-             LEN (char, s1, len), s1, LEN (wchar_t, s2, len), s2,            \
-             len, expect, result)
+             int (sizeof s1 - 1), s1,                                        \
+             int (sizeof (s2) / sizeof *(s2) - 1), s2, len,                  \
+             expect, result)
+
+    TEST (0,      (wchar_t*)0, -1, 0);
+    TEST ("",     (wchar_t*)0, -1, 0);
+    TEST (0,      L"",         -1, 0);
+    TEST ("",     L"",         -1, 1);
+
+    // same as above but using the <char>@<count> directive
+    TEST ("[EMAIL PROTECTED]",  L"",       -1, 1);
+    TEST ("",     L"",       -1, 1);
+    TEST ("[EMAIL PROTECTED]",  L"",       -1, 1);
+
+    // when invoked with NULL as the first argument returns
+    // the length of the second string with all directives
+    // expanded
+    TEST (0, L"a",      -1, 1);
+    TEST (0, L"ab",     -1, 2);
+    TEST (0, L"abc",    -1, 3);
+    TEST (0, L"abcd",   -1, 4);
+    TEST (0, L"abcde",  -1, 5);
+    TEST (0, L"abcdef", -1, 6);
 
-    TEST (0,       0,        -1, 0);
-    TEST ("",      0,        -1, 0);
-    TEST (0,       L"",      -1, 0);
-    TEST ("",      L"",      -1, 0);
+    // same as above but with the arguments reversed
+    TEST ("a",      (wchar_t*)0, -1, 1);
+    TEST ("ab",     (wchar_t*)0, -1, 2);
+    TEST ("abc",    (wchar_t*)0, -1, 3);
+    TEST ("[EMAIL PROTECTED]",    (wchar_t*)0, -1, 0);
+    TEST ("[EMAIL PROTECTED]",    (wchar_t*)0, -1, 1);
+    TEST ("[EMAIL PROTECTED]",    (wchar_t*)0, -1, 2);
+    TEST ("[EMAIL PROTECTED]@0", (wchar_t*)0, -1, 2);
+    TEST ("[EMAIL PROTECTED]@1", (wchar_t*)0, -1, 3);
+    TEST ("[EMAIL PROTECTED]@2", (wchar_t*)0, -1, 4);
 
-    TEST (0,       L"a",     -1, 1);
-    TEST (0,       L"ab",    -1, 2);
-    TEST (0,       L"abc",   -1, 3);
+    TEST ("",     L"a",      -1, 0);
+    TEST ("a",    L"",       -1, 0);
+    TEST ("a",    L"a",      -1, 2);
 
-    TEST ("a",     0,        -1, 1);
-    TEST ("ab",    0,        -1, 2);
-    TEST ("abc",   0,        -1, 3);
+    // same as above but using the <char>@<count> directive
+    TEST ("[EMAIL PROTECTED]",  L"",       -1, 0);
+    TEST ("[EMAIL PROTECTED]",  L"a",      -1, 2);
 
-    TEST ("",      L"a",     -1, 0);
-    TEST ("a",     L"",      -1, 0);
-    TEST ("a",     L"a",     -1, 1);
+    TEST ("\0ab",       L"\0ac",   2, 2);
+    TEST ("[EMAIL PROTECTED]",     L"ab",     2, 2);
+    TEST ("[EMAIL PROTECTED]@0b", L"ab",     2, 2);
 
-    TEST ("a\0bc", L"a\0bd", -1, 1);
+    TEST ("a\0bc", L"a\0bd", -1, 2);
     TEST ("a\0bc", L"a\0bd",  0, 0);
     TEST ("a\0bc", L"a\0bd",  1, 1);
     TEST ("a\0bc", L"a\0bd",  2, 2);
     TEST ("a\0bc", L"a\0bd",  3, 3);
     TEST ("a\0bc", L"a\0bd",  4, 3);
 
+    TEST ("aaaaa",    L"aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]", L"aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",  L"aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",   L"aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",    L"aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",     L"aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",      L"aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",     L"aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",    L"aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",   L"aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",  L"aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]", L"aaaaa",  -1, 6);
+
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", L"aaaaaa", -1, 7);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", L"aaaaaa",  0, 0);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", L"aaaaaa",  1, 1);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", L"aaaaaa",  2, 2);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", L"aaaaaa",  3, 3);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", L"aaaaaa",  4, 4);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", L"aaaaaa",  5, 5);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", L"aaaaaa",  6, 6);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", L"aaaaaa",  7, 7);
+
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3\0", L"\0aaa\0aaa\0", 10, 10);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3\0",  L"\0aaa\0aaa\0", 10,  0);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3\0",  L"\0aaa\0aaa\0", 10,  4);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3*",  L"\0aaa\0aaa\0", 10,  8);
+
+    // invalid directives
+    TEST ("[EMAIL PROTECTED]",   L"[EMAIL PROTECTED]",   -1, 4);
+    TEST ("[EMAIL PROTECTED]@c", L"[EMAIL PROTECTED]@c", -1, 6);
+
 #else   // if defined (_RWSTD_NO_WCHAR_T)
 
     rw_note (0, 0, 0, "_RWSTD_NO_WCHAR_T #defined, wchar_t test disabled");
@@ -876,38 +968,86 @@
     rw_info (0, 0, 0, "rw_match(char*, const UserChar*, size_t)");
 
 #undef TEST
-#define TEST(s1, s2, len, expect)                                            \
-  result = rw_match ((const char*)s1,                                        \
-                     make_user_string (s2, sizeof (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,               \
+#define TEST(s1, s2, len, expect)                                       \
+  result = rw_match ((const char*)s1,                                   \
+                     make_user_string (s2, sizeof (s2)), size_t (len)); \
+  rw_assert (expect == result,                                          \
+             0, __LINE__,                                               \
+             "rw_match(%{#*s}, %{#*s}, %zu) == %zu, got %zu",           \
+             int (sizeof s1 - 1), s1, int (sizeof s2 - 1), s2, len,     \
              expect, result)
 
-    TEST (0,       0,       -1, 0);
-    TEST ("",      0,       -1, 0);
-    TEST (0,       "",      -1, 0);
-    TEST ("",      "",      -1, 0);
+    TEST (0,      0,  -1, 0);
+    TEST ("",     0,  -1, 0);
+    TEST (0,      "", -1, 0);
+    TEST ("",     "", -1, 1);
+
+    // same as above but using the <char>@<count> directive
+    TEST ("[EMAIL PROTECTED]",  "",       -1, 1);
+    TEST ("",     "",       -1, 1);
+    TEST ("[EMAIL PROTECTED]",  "",       -1, 1);
+
+    // when invoked with NULL as the first string returns
+    // the length of the second string (if non-NULL)
+    TEST (0,      "a",      -1, 1);
+    TEST (0,      "ab",     -1, 2);
+    TEST (0,      "abc",    -1, 3);
+
+    // same as above but with the arguments reversed
+    TEST ("a",   0, -1, 1);
+    TEST ("ab",  0, -1, 2);
+    TEST ("abc", 0, -1, 3);
 
-    TEST (0,       "a",     -1, 1);
-    TEST (0,       "ab",    -1, 2);
-    TEST (0,       "abc",   -1, 3);
+    TEST ("",     "a",      -1, 0);
+    TEST ("a",    "",       -1, 0);
+    TEST ("a",    "a",      -1, 2);
 
-    TEST ("a",     0,       -1, 1);
-    TEST ("ab",    0,       -1, 2);
-    TEST ("abc",   0,       -1, 3);
+    // same as above but using the <char>@<count> directive
+    TEST ("[EMAIL PROTECTED]",  "",       -1, 0);
+    TEST ("[EMAIL PROTECTED]",  "a",      -1, 2);
 
-    TEST ("",      "a",     -1, 0);
-    TEST ("a",     "",      -1, 0);
-    TEST ("a",     "a",     -1, 1);
+    TEST ("\0ab",       "\0ac",   2, 2);
+    TEST ("[EMAIL PROTECTED]",     "ab",     2, 2);
+    TEST ("[EMAIL PROTECTED]@0b", "ab",     2, 2);
 
-    TEST ("a\0bc", "a\0bd", -1, 1);
+    TEST ("a\0bc", "a\0bd", -1, 2);
     TEST ("a\0bc", "a\0bd",  0, 0);
     TEST ("a\0bc", "a\0bd",  1, 1);
     TEST ("a\0bc", "a\0bd",  2, 2);
     TEST ("a\0bc", "a\0bd",  3, 3);
     TEST ("a\0bc", "a\0bd",  4, 3);
+
+    TEST ("aaaaa",    "aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]", "aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",  "aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",   "aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",    "aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",     "aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",      "aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",     "aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",    "aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",   "aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]",  "aaaaa",  -1, 6);
+    TEST ("[EMAIL PROTECTED]", "aaaaa",  -1, 6);
+
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "aaaaaa", -1, 7);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "aaaaaa",  0, 0);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "aaaaaa",  1, 1);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "aaaaaa",  2, 2);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "aaaaaa",  3, 3);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "aaaaaa",  4, 4);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "aaaaaa",  5, 5);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "aaaaaa",  6, 6);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3", "aaaaaa",  7, 7);
+
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3\0", "\0aaa\0aaa\0", 10, 10);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3\0",  "\0aaa\0aaa\0", 10,  0);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3\0",  "\0aaa\0aaa\0", 10,  4);
+    TEST ("[EMAIL PROTECTED]@[EMAIL PROTECTED]@3*",  "\0aaa\0aaa\0", 10,  8);
+
+    // invalid directives
+    TEST ("[EMAIL PROTECTED]",   "[EMAIL PROTECTED]",   -1, 4);
+    TEST ("[EMAIL PROTECTED]@c", "[EMAIL PROTECTED]@c", -1, 6);
 }
 
 /***********************************************************************/
  • rw_match() bus (was: Re: test for lib.string.io) Martin Sebor

Reply via email to