You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by an...@apache.org on 2006/06/08 15:41:04 UTC

svn commit: r412750 - in /incubator/stdcxx/trunk/tests: include/21.strings.h src/21.strings.cpp strings/21.string.append.cpp strings/21.string.assign.cpp strings/21.string.insert.cpp strings/21.string.replace.cpp

Author: antonp
Date: Thu Jun  8 06:41:03 2006
New Revision: 412750

URL: http://svn.apache.org/viewvc?rev=412750&view=rev
Log:
2006-06-08  Anton Pevtsov  <an...@moscow.vdiweb.com>

	* 21.strings.h (RangeBase): New base class to exercise the range
	template methods overloads - append, assign, insert and replace.
	* 21.strings.cpp (_rw_setvars): append_range and assign_range 
	cases separated from others due to the changes in the 
	corresponding tests.
	* 21.string.append.cpp (AppendRange, AppendRangeOverload): New class
	templates to abstract out the invocation of the append member
	template and its overloads.
	(test_append): Added RangeBase& argument and eliminated
	test_append_range (obviated by the addition of the argument).
	(test_append): Dispatched to the appropriate specialization
	based on the iterator id (if any).
	* 21.string.assign.cpp: Same
	* 21.string.insert.cpp: Same
	* 21.string.replace.cpp (ReplaceBase): moved to 21.strings.h
	and renamed to RangeBase.
	(ReplaceRangeOverload): begin overloads moved to the base class.
	(test_replace): parameter type changed to RangeBase.


Modified:
    incubator/stdcxx/trunk/tests/include/21.strings.h
    incubator/stdcxx/trunk/tests/src/21.strings.cpp
    incubator/stdcxx/trunk/tests/strings/21.string.append.cpp
    incubator/stdcxx/trunk/tests/strings/21.string.assign.cpp
    incubator/stdcxx/trunk/tests/strings/21.string.insert.cpp
    incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp

Modified: incubator/stdcxx/trunk/tests/include/21.strings.h
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/include/21.strings.h?rev=412750&r1=412749&r2=412750&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/include/21.strings.h (original)
+++ incubator/stdcxx/trunk/tests/include/21.strings.h Thu Jun  8 06:41:03 2006
@@ -777,6 +777,71 @@
 }
 
 
+/**************************************************************************/
+
+// base class-functor for the range template overloads testing
+template <class String>
+struct RangeBase {
+
+    typedef typename String::value_type                 StringChar;
+    typedef typename String::pointer                    StringPtr;
+    typedef typename String::const_pointer              StringConstPtr;
+    typedef typename String::iterator                   StringIter;
+    typedef typename String::const_iterator             StringConstIter;
+    typedef typename String::reverse_iterator           StringRevIter;
+    typedef typename String::const_reverse_iterator     StringConstRevIter;
+
+    RangeBase () { }
+
+    virtual ~RangeBase () { /* silence warnings */ }
+
+    static StringPtr
+    begin (String &str, StringPtr*) {
+        return _RWSTD_CONST_CAST (StringPtr, str.data ());
+    }
+
+    static StringConstPtr
+    begin (const String &str, StringConstPtr*) {
+        return str.data ();
+    }
+
+#ifndef _RWSTD_NO_DEBUG_ITER
+
+    // when debugging iterators are enabled string::iterator and
+    // string::pointer are distinct types; otherwise they are the
+    // same type
+
+    static StringIter
+    begin (String &str, StringIter*) {
+        return str.begin ();
+    }
+
+    static StringConstIter
+    begin (const String &str, StringConstIter*) {
+        return str.begin ();
+    }
+
+#endif   // _RWSTD_NO_DEBUG_ITER
+
+    static StringRevIter
+    begin (String &str, StringRevIter*) {
+        return str.rbegin ();
+    }
+
+    static StringConstRevIter
+    begin (const String &str, StringConstRevIter*) {
+        return str.rbegin ();
+    }
+
+    virtual String&
+    operator() (String &str, const StringTestCaseData<StringChar>&) const {
+        RW_ASSERT (!"logic error: should be never called");
+        return str;
+    }
+};
+
+/**************************************************************************/
+
 #define Disabled(which)   \
     StringIds::opt_memfun_disabled [which & ~StringIds::fid_mask]
 

Modified: incubator/stdcxx/trunk/tests/src/21.strings.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/src/21.strings.cpp?rev=412750&r1=412749&r2=412750&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/src/21.strings.cpp (original)
+++ incubator/stdcxx/trunk/tests/src/21.strings.cpp Thu Jun  8 06:41:03 2006
@@ -661,6 +661,17 @@
 
     case StringIds::append_range:
     case StringIds::assign_range:
+        rw_asnprintf (&buf, &bufsize, "%{+}<%{$Iterator:-Iterator}>("
+                      "%{?}begin()%{:}%{$Iterator:-Iterator}(%{#*s})%{;}"
+                      "%{?} + %zu%{;}, "
+                      "%{?}begin()%{:}%{$Iterator:-Iterator}(...)%{;}"
+                      "%{?} + %zu%{;}"
+                      "%{?}, const allocator_type&%{;})",
+                      self, int (arg_len), arg,
+                      0 != pcase->off2, pcase->off2,
+                      self, 0 != range2_end, range2_end, use_alloc);
+        break;
+
     case StringIds::ctor_range:
     case StringIds::ctor_range_alloc:
         rw_asnprintf (&buf, &bufsize, "%{+}<%{$Iterator:-Iterator}>("

Modified: incubator/stdcxx/trunk/tests/strings/21.string.append.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/strings/21.string.append.cpp?rev=412750&r1=412749&r2=412750&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/strings/21.string.append.cpp (original)
+++ incubator/stdcxx/trunk/tests/strings/21.string.append.cpp Thu Jun  8 06:41:03 2006
@@ -281,7 +281,7 @@
 
 #undef TEST
 #define TEST(str, arg, off, size, res, bthrow) {                \
-        __LINE__, off, size, -1, -1, -1,                        \
+        __LINE__, -1, -1, off, size, -1,                        \
         str, sizeof str - 1,                                    \
         arg, sizeof arg - 1, res, sizeof res - 1, bthrow        \
     }
@@ -483,158 +483,97 @@
 
 /**************************************************************************/
 
-template <class charT, class Traits, class Allocator, class Iterator>
-void test_append_range (const charT    *wstr,
-                        std::size_t     wstr_len,
-                        const charT    *warg,
-                        std::size_t     warg_len,
-                        std::size_t     res_len,
-                        Traits*, 
-                        Allocator*,
-                        const Iterator &it,
-                        const StringTestCase &tcase)
-{
-    typedef std::basic_string <charT, Traits, Allocator> String;
-    typedef typename String::iterator                    StringIter;
+// invokes specializations of the member function template
+// on the required iterator categories
+template <class String, class Iterator>
+struct AppendRange: RangeBase<String> {
 
-    const char* const itname =
-        tcase.arg ? type_name (it, (charT*)0) : "basic_string::iterator";
+    typedef typename String::iterator     StringIter;
+    typedef typename String::value_type   StringChar;
 
-    // compute the size of the controlled sequence and the size
-    // of the sequence denoted by the argument keeping in mind
-    // that the latter may refer to the former
-    const std::size_t size1 = wstr_len;
-    const std::size_t size2 = tcase.arg ? warg_len : size1;
+    AppendRange () { }
 
-    // construct the string object to be modified
-    String s_str (wstr, size1);
+    virtual String&
+    operator() (String &str, 
+                const StringTestCaseData<StringChar>& tdata) const {
 
-    // compute the offset and the extent (the number of elements)
-    // of the second range into the argument of the function call
-    const std::size_t off =
-        std::size_t (tcase.off) < size2 ? std::size_t (tcase.off) : size2;
-    const std::size_t ext =
-        off + tcase.size < size2 ? std::size_t (tcase.size) : size2 - off;
-
-    if (tcase.arg) {
-        const charT* const beg = warg + off;
-        const charT* const end = beg + ext;
+        const StringTestCase &tcase = tdata.tcase_;
 
-        const Iterator first (beg, beg, end);
-        const Iterator last  (end, beg, end);
+        const String &cstr = str;
 
-        s_str.append (first, last);
-    }
-    else {
-        // self-referential modification (appending a range
-        // of elements with a subrange of its own elements)
-        const StringIter first (s_str.begin () + off);
-        const StringIter last (first + ext);
+        // when (0 == tcase.arg) exercise self-referential modification
+        // (i.e., replacing a range of elements with a subrange of its
+        // own elements)
+        const StringChar* const beg =
+            (tcase.arg ? tdata.arg_ : cstr.data ()) + tdata.off2_;
 
-        s_str.append (first, last);
-    }
+        const StringChar* const end = beg + tdata.ext2_;
 
-    // detrmine whether the produced sequence matches the exepceted result
-    const std::size_t match = rw_match (tcase.res, s_str.data (), tcase.nres);
+        const Iterator first (beg, beg, end);
+        const Iterator last  (end, beg, end);
 
-    rw_assert (match == res_len, 0, tcase.line,
-               "line %d. %{$FUNCALL} expected %{#*s}, got %{/*.*Gs}, "
-               "difference at offset %zu for %s",
-               __LINE__, int (tcase.nres), tcase.res,
-               int (sizeof (charT)), int (s_str.size ()), s_str.c_str (),
-               match, itname);
-}
+        return str.append (first, last);
+    }
+};
 
 /**************************************************************************/
 
-template <class charT, class Traits, class Allocator>
-void test_append_range (const charT    *wstr,
-                        std::size_t     wstr_len,
-                        const charT    *warg,
-                        std::size_t     warg_len,
-                        std::size_t     res_len,
-                        Traits*,
-                        Allocator*,
-                        const StringTestCase &tcase)
+// invokes possible overloads of the member function template
+// on common RandomAccessIterator types
+template <class String, class Iterator>
+struct AppendRangeOverload: RangeBase<String>
 {
-    if (tcase.bthrow)  // this method doesn't throw
-        return;
+    typedef typename String::iterator     StringIter;
+    typedef typename String::value_type   StringChar;
 
-    test_append_range (wstr, wstr_len, warg, warg_len, res_len, (Traits*)0,
-                       (Allocator*)0, InputIter<charT>(0, 0, 0), tcase);
+    AppendRangeOverload () { }
 
-    // there is no need to call test_append_range
-    // for other iterators in this case
-    if (0 == tcase.arg)
-        return;
-
-    test_append_range (wstr, wstr_len, warg, warg_len, res_len, (Traits*)0,
-                       (Allocator*)0, ConstFwdIter<charT>(0, 0, 0), tcase);
-
-    test_append_range (wstr, wstr_len, warg, warg_len, res_len, (Traits*)0,
-                       (Allocator*)0, ConstBidirIter<charT>(0, 0, 0), tcase);
-
-    test_append_range (wstr, wstr_len, warg, warg_len, res_len, 
-                      (Traits*)0, (Allocator*)0, 
-                       ConstRandomAccessIter<charT>(0, 0, 0), tcase);
-}
-
-/**************************************************************************/
+    virtual String&
+    operator() (String &str, 
+                const StringTestCaseData<StringChar>& tdata) const {
 
-template <class charT, class Traits, class Allocator>
-void test_append (charT, Traits*, Allocator*,
-                  const StringFunc     &func,
-                  const StringTestCase &tcase)
-{
-    typedef std::basic_string <charT, Traits, Allocator> String;
-    typedef typename String::iterator                    StringIter;
-    typedef typename UserTraits<charT>::MemFun           UTMemFun;
+        const StringTestCase &tcase = tdata.tcase_;
 
-    static const std::size_t BUFSIZE = 256;
+        const std::size_t off = tdata.off2_;
+        const std::size_t ext = tdata.ext2_;
 
-    static charT wstr_buf [BUFSIZE];
-    static charT warg_buf [BUFSIZE];
+        if (0 == tcase.arg) {
+            // exercise self-referential modification (i.e., replacing
+            // a range of elements with a subrange of its own elements)
 
-    std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
-    std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
+            const Iterator first (begin (str, (Iterator*)0) + off);
+            const Iterator last (first + ext);
 
-    charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
-    charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
+            return str.append (first, last);
+        }
 
-    static charT wres_buf [BUFSIZE];
-    std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
-    charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);
+        String str_arg (tdata.arg_, tdata.arglen_);
 
-    // special processing for append_range to exercise all iterators
-    if (Append (range) == func.which_) {
-        test_append_range (wstr, str_len, warg, arg_len, res_len, 
-                          (Traits*)0, (Allocator*)0, tcase);
+        const Iterator first (begin (str_arg, (Iterator*)0) + off);
+        const Iterator last (first + ext);
 
-        if (wstr != wstr_buf)
-            delete[] wstr;
+        return str.append (first, last);
+    }
+};
 
-        if (warg != warg_buf)
-            delete[] warg;
+/**************************************************************************/
 
-         if (wres != wres_buf)
-            delete[] wres;
+template <class charT, class Traits, class Allocator>
+void test_append (charT*, Traits*, Allocator*, const RangeBase<
+                      std::basic_string <charT, Traits, Allocator> > &rng,
+                  const StringTestCaseData<charT>                    &tdata)
+{
+    typedef std::basic_string <charT, Traits, Allocator> String;
+    typedef typename String::iterator                    StringIter;
+    typedef typename UserTraits<charT>::MemFun           TraitsFunc;
 
-        return;
-    }
+    const StringFunc     &func  = tdata.func_;
+    const StringTestCase &tcase = tdata.tcase_;
 
     // construct the string object to be modified
     // and the (possibly unused) argument string
-    /* const */ String str (wstr, str_len);
-    const       String arg (warg, arg_len);
-
-    if (wstr != wstr_buf)
-        delete[] wstr;
-
-    if (warg != warg_buf)
-        delete[] warg;
-
-    wstr = 0;
-    warg = 0;
+    /* const */ String str (tdata.str_, tdata.strlen_);
+    const       String arg (tdata.arg_, tdata.arglen_);
 
     // save the state of the string object before the call
     // to detect wxception safety violations (changes to
@@ -650,7 +589,7 @@
     std::size_t* const rg_calls = rw_get_call_counters ((Traits*)0, (charT*)0);
 
     if (rg_calls)
-        total_length_calls = rg_calls [UTMemFun::length];
+        total_length_calls = rg_calls [TraitsFunc::length];
 
     rwt_free_store* const pst = rwt_get_free_store (0);
     SharedAlloc*    const pal = SharedAlloc::instance ();
@@ -686,12 +625,8 @@
 
 #else   // if defined (_RWSTD_NO_EXCEPTIONS)
 
-        if (tcase.bthrow) {
-            if (wres != wres_buf)
-                delete[] wres;
-
+        if (tcase.bthrow)
             return;
-        }
 
 #endif   // _RWSTD_NO_EXCEPTIONS
 
@@ -708,7 +643,7 @@
             case Append (cptr):
                 ret_ptr = &str.append (ptr_arg);
                 if (rg_calls)
-                    n_length_calls = rg_calls [UTMemFun::length];
+                    n_length_calls = rg_calls [TraitsFunc::length];
                 break;
 
             case Append (cstr):
@@ -720,13 +655,17 @@
                 break;
 
             case Append (cstr_size_size):
-                ret_ptr = &str.append (str_arg, tcase.off, tcase.size);
+                ret_ptr = &str.append (str_arg, tcase.off2, tcase.size2);
                 break;
 
             case Append (size_val):
                 ret_ptr = &str.append (tcase.size, val_arg);
                 break;
 
+            case Append (range):
+                ret_ptr = &rng (str, tdata);
+                break;
+
             case PushBack (val):
                 str.push_back (val_arg);
                 ret_ptr = &str;
@@ -746,27 +685,29 @@
                        "line %d. %{$FUNCALL} returned invalid reference, "
                        "offset is %td", __LINE__, ret_off);
 
+            // for convenience
+            static const int cwidth = sizeof (charT);
+
             // verify that strings are of equal length
-            rw_assert (res_len == str.size (), 0, tcase.line,
-                       "line %d. %{$FUNCALL} expected %{#*s}, "
+            rw_assert (tdata.reslen_ == str.size (), 0, tcase.line,
+                       "line %d. %{$FUNCALL} expected %{/*.*Gs}, "
                        "length %zu, got %{/*.*Gs}, length %zu",
-                       __LINE__, int (tcase.nres), tcase.res,
-                       res_len, int (sizeof (charT)),
+                       __LINE__, cwidth, int (tdata.reslen_), tdata.res_,
+                       tdata.reslen_, cwidth,
                        int (str.size ()), str.c_str (), str.size ());
 
-            if (res_len == str.size ()) {
+            if (tdata.reslen_ == str.size ()) {
                 // if the result length matches the expected length
                 // (and only then), also verify that the modified
                 // string matches the expected result
                 const std::size_t match =
                     rw_match (tcase.res, str.c_str (), tcase.nres);
 
-                rw_assert (match == res_len, 0, tcase.line,
-                           "line %d. %{$FUNCALL} expected %{#*s}, "
+                rw_assert (match == tdata.reslen_, 0, tcase.line,
+                           "line %d. %{$FUNCALL} expected %{/*.*Gs}, "
                            "got %{/*.*Gs}, difference at offset %zu",
-                           __LINE__, int (tcase.nres), tcase.res,
-                           int (sizeof (charT)), int (str.size ()),
-                           str.c_str (), match);
+                           __LINE__, cwidth, int (tdata.reslen_), tdata.res_,
+                           cwidth, int (str.size ()), str.c_str (), match);
             }
 
             // verify that Traits::length was used
@@ -859,23 +800,92 @@
 
 #endif   // _RWSTD_NO_REPLACEABLE_NEW_DELETE
 
-    rw_assert (expect_throws == throw_count, 0, tcase.line,
-               "line %d: %{$FUNCALL}: expected exactly 1 %s exception "
-               "while changing capacity from %zu to %zu, got %zu",
-               __LINE__, exceptions [3],
-               str_state.capacity_, str.capacity (), throw_count);
+    // verify number of exceptions thrown
+    // for range version the allocation may take place several times
+    if (Append (range) != func.which_)
+        rw_assert (expect_throws == throw_count, 0, tcase.line,
+                   "line %d: %{$FUNCALL}: expected exactly 1 %s exception "
+                   "while changing capacity from %zu to %zu, got %zu",
+                   __LINE__, exceptions [3],
+                   str_state.capacity_, str.capacity (), throw_count);
+    else
+        rw_assert (expect_throws <= throw_count, 0, tcase.line,
+                   "line %d: %{$FUNCALL}: expected at least 1 %s exception "
+                   "while changing capacity from %zu to %zu, got %zu",
+                   __LINE__, exceptions [3],
+                   str_state.capacity_, str.capacity (), throw_count);
 
     // disable bad_alloc exceptions
     *pst->throw_at_calls_ [0] = 0;
     pal->throw_at_calls_ [pal->m_allocate] = 0;
+}
+
+/**************************************************************************/
+
+template <class charT, class Traits, class Allocator>
+void test_append (charT*, Traits*, Allocator*,
+                  const StringTestCaseData<charT> &tdata)
+{
+    typedef std::basic_string<charT, Traits, Allocator> String;
+
+    if (tdata.func_.which_ == Append (range)) {
+
+        switch (tdata.func_.iter_id_) {
+
+        // exercise possible overloads of the member function template
+        // on common RandomAccessIterator types
+#undef TEST
+#define TEST(Iterator) do {                                                 \
+        typedef typename String::Iterator Iter;                             \
+        static const                                                        \
+        AppendRangeOverload<String, Iter> app;                              \
+        test_append ((charT*)0, (Traits*)0, (Allocator*)0, app, tdata);     \
+    } while (0)
+
+        case StringIds::Pointer: TEST (pointer); break;
+        case StringIds::ConstPointer: TEST (const_pointer); break;
+        case StringIds::Iterator: TEST (iterator); break;
+        case StringIds::ConstIterator: TEST (const_iterator); break;
+
+            // disabled for now
+        case StringIds::ReverseIterator:
+            // TEST (reverse_iterator);
+            break;
+
+        case StringIds::ConstReverseIterator:
+            // TEST (const_reverse_iterator);
+            break;
+
+        // exercise specializations of the member function template
+        // on the required iterator categories
 
-    if (wres != wres_buf)
-        delete[] wres;
+#undef TEST
+#define TEST(Iterator) do {                                                 \
+        typedef Iterator<charT> Iter;                                       \
+        static const                                                        \
+        AppendRange<String, Iter> app;                                      \
+        test_append ((charT*)0, (Traits*)0, (Allocator*)0, app, tdata);     \
+    } while (0)
+
+        case StringIds::Input: TEST (InputIter); break;
+        case StringIds::Forward: TEST (ConstFwdIter); break;
+        case StringIds::Bidir: TEST (ConstBidirIter); break;
+        case StringIds::Random: TEST (ConstRandomAccessIter); break;
+
+        default:
+            rw_error (0, 0, __LINE__, "bad iterator id");
+        }
+    }
+    else {
+        // exercise ordinary overloads of the member function
+        static const RangeBase<String > app;
+        test_append ((charT*)0, (Traits*)0, (Allocator*)0, app, tdata);
+    }
 }
 
 /**************************************************************************/
 
-DEFINE_STRING_TEST_DISPATCH (test_append);
+DEFINE_STRING_TEST_FUNCTIONS (test_append);
 
 int main (int argc, char** argv)
 {
@@ -903,7 +913,10 @@
 
     const std::size_t test_count = sizeof tests / sizeof *tests;
 
-    return rw_run_string_test (argc, argv, __FILE__,
-                               "lib.string.append",
-                               test_append, tests, test_count);
+    const int status =
+        rw_run_string_test (argc, argv, __FILE__,
+                            "lib.string.append",
+                            test_append_func_array, tests, test_count);
+
+    return status;
 }

Modified: incubator/stdcxx/trunk/tests/strings/21.string.assign.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/strings/21.string.assign.cpp?rev=412750&r1=412749&r2=412750&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/strings/21.string.assign.cpp (original)
+++ incubator/stdcxx/trunk/tests/strings/21.string.assign.cpp Thu Jun  8 06:41:03 2006
@@ -278,7 +278,7 @@
 
 #undef TEST
 #define TEST(str, arg, off, size, res, bthrow) {                \
-        __LINE__, off, size, -1, -1, -1,                        \
+        __LINE__, -1, -1, off, size, -1,                        \
         str, sizeof str - 1,                                    \
         arg, sizeof arg - 1, res, sizeof res - 1, bthrow        \
     }
@@ -429,160 +429,100 @@
 
 /**************************************************************************/
 
-template <class charT, class Traits, class Allocator, class Iterator>
-void test_assign_range (const charT    *wstr,
-                        std::size_t     wstr_len,
-                        const charT    *warg,
-                        std::size_t     warg_len,
-                        std::size_t     res_len,
-                        Traits*,
-                        Allocator*, 
-                        const Iterator &it,
-                        const StringTestCase &tcase)
-{
-    typedef std::basic_string <charT, Traits, Allocator> String;
-    typedef typename String::iterator                    StringIter;
+// invokes specializations of the member function template
+// on the required iterator categories
+template <class String, class Iterator>
+struct AssignRange: RangeBase<String> {
 
-    const char* const itname =
-        tcase.arg ? type_name (it, (charT*)0) : "basic_string::iterator";
+    typedef typename String::iterator       StringIter;
+    typedef typename String::value_type     StringChar;
 
-    // compute the size of the controlled sequence and the size
-    // of the sequence denoted by the argument keeping in mind
-    // that the latter may refer to the former
-    const std::size_t size1 = wstr_len;
-    const std::size_t size2 = tcase.arg ? warg_len : size1;
+    AssignRange () { }
 
-    // construct the string object to be modified
-    String str (wstr, size1);
+    virtual String&
+    operator() (String &str, 
+                const StringTestCaseData<StringChar>& tdata) const {
 
-    // compute the offset and the extent (the number of elements)
-    // of the second range into the argument of the function call
-    const std::size_t off =
-        std::size_t (tcase.off) < size2 ? std::size_t (tcase.off) : size2;
-    const std::size_t ext =
-        off + tcase.size < size2 ? std::size_t (tcase.size) : size2 - off;
-
-    if (tcase.arg) {
-        const charT* const beg = warg + off;
-        const charT* const end = beg + ext;
+        const StringTestCase &tcase = tdata.tcase_;
 
-        const Iterator first (beg, beg, end);
-        const Iterator last  (end, beg, end);
+        const String &cstr = str;
 
-        str.assign (first, last);
-    }
-    else {
-        // self-referential modification (appending a range
-        // of elements with a subrange of its own elements)
-        const StringIter first (str.begin () + off);
-        const StringIter last (first + ext);
+        // when (0 == tcase.arg) exercise self-referential modification
+        // (i.e., replacing a range of elements with a subrange of its
+        // own elements)
+        const StringChar* const beg =
+            (tcase.arg ? tdata.arg_ : cstr.data ()) + tdata.off2_;
 
-        str.assign (first, last);
-    }
+        const StringChar* const end = beg + tdata.ext2_;
 
-    // detrmine whether the produced sequence matches the exepceted result
-    const std::size_t match = rw_match (tcase.res, str.data (), tcase.nres);
+        const Iterator first (beg, beg, end);
+        const Iterator last  (end, beg, end);
 
-    rw_assert (match == res_len, 0, tcase.line,
-               "line %d. %{$FUNCALL} expected %{#*s}, got %{/*.*Gs}, "
-               "difference at off %zu for %s",
-               __LINE__, int (tcase.nres), tcase.res,
-               int (sizeof (charT)), int (str.size ()), str.c_str (),
-               match, itname);
-}
+        return str.assign (first, last);
+    }
+};
 
 /**************************************************************************/
 
-template <class charT, class Traits, class Allocator>
-void test_assign_range (const charT    *wstr,
-                        std::size_t     wstr_len,
-                        const charT    *warg,
-                        std::size_t     warg_len,
-                        std::size_t     res_len,
-                        Traits*,
-                        Allocator*, 
-                        const StringTestCase &tcase)
+// invokes possible overloads of the member function template
+// on common RandomAccessIterator types
+template <class String, class Iterator>
+struct AssignRangeOverload: RangeBase<String>
 {
-    if (tcase.bthrow)  // this method doesn't throw
-        return;
-
-    test_assign_range (wstr, wstr_len, warg, warg_len, res_len, (Traits*)0,
-                       (Allocator*)0, InputIter<charT>(0, 0, 0), tcase);
+    typedef typename String::iterator       StringIter;
+    typedef typename String::value_type     StringChar;
 
-    // there is no need to call test_assign_range
-    // for other iterators in this case
-    if (0 == tcase.arg)
-        return;
-
-    test_assign_range (wstr, wstr_len, warg, warg_len, res_len, (Traits*)0,
-                       (Allocator*)0, ConstFwdIter<charT>(0, 0, 0), tcase);
-
-    test_assign_range (wstr, wstr_len, warg, warg_len, res_len, (Traits*)0,
-                       (Allocator*)0, ConstBidirIter<charT>(0, 0, 0), tcase);
-
-    test_assign_range (wstr, wstr_len, warg, warg_len, res_len, 
-                      (Traits*)0, (Allocator*)0, 
-                       ConstRandomAccessIter<charT>(0, 0, 0), tcase);
-}
+    AssignRangeOverload () { }
 
-/**************************************************************************/
+    virtual String&
+    operator() (String &str, 
+                const StringTestCaseData<StringChar>& tdata) const {
 
-template <class charT, class Traits, class Allocator>
-void test_assign (charT, Traits*, Allocator*,
-                  const StringFunc     &func,
-                  const StringTestCase &tcase)
-{
-    typedef std::basic_string <charT, Traits, Allocator> String;
-    typedef typename String::iterator                    StringIter;
-    typedef typename UserTraits<charT>::MemFun           UTMemFun;
+        const StringTestCase &tcase = tdata.tcase_;
 
-    static const std::size_t BUFSIZE = 256;
+        const std::size_t off = tdata.off2_;
+        const std::size_t ext = tdata.ext2_;
 
-    static charT wstr_buf [BUFSIZE];
-    static charT warg_buf [BUFSIZE];
+        if (0 == tcase.arg) {
+            // exercise self-referential modification (i.e., replacing
+            // a range of elements with a subrange of its own elements)
 
-    std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
-    std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
+            const Iterator first (begin (str, (Iterator*)0) + off);
+            const Iterator last (first + ext);
 
-    charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
-    charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
+            return str.assign (first, last);
+        }
 
-    static charT wres_buf [BUFSIZE];
-    std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
-    charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);
+        String str_arg (tdata.arg_, tdata.arglen_);
 
-    // special processing for assign_range to exercise all iterators
-    if (Assign (range) == func.which_) {
-        test_assign_range (wstr, str_len, warg, arg_len, 
-                           res_len, (Traits*)0, (Allocator*)0, tcase);
+        const Iterator first (begin (str_arg, (Iterator*)0) + off);
+        const Iterator last (first + ext);
 
-        if (wstr != wstr_buf)
-            delete[] wstr;
+        return str.assign (first, last);
+    }
+};
 
-        if (warg != warg_buf)
-            delete[] warg;
+/**************************************************************************/
 
-        if (wres != wres_buf)
-            delete[] wres;
+template <class charT, class Traits, class Allocator>
+void test_assign (charT*, Traits*, Allocator*, const RangeBase<
+                      std::basic_string <charT, Traits, Allocator> > &rng,
+                  const StringTestCaseData<charT>                    &tdata)
+{
+    typedef std::basic_string <charT, Traits, Allocator> String;
+    typedef typename String::iterator                    StringIter;
+    typedef typename UserTraits<charT>::MemFun           TraitsFunc;
 
-        return;
-    }
+    const StringFunc     &func  = tdata.func_;
+    const StringTestCase &tcase = tdata.tcase_;
 
     // construct the string object to be modified
     // and the (possibly unused) argument string
-    /* const */ String str (wstr, str_len);
-    const       String arg (warg, arg_len);
-
-    if (wstr != wstr_buf)
-        delete[] wstr;
+    /* const */ String str (tdata.str_, tdata.strlen_);
+    const       String arg (tdata.arg_, tdata.arglen_);
 
-    if (warg != warg_buf)
-        delete[] warg;
-
-    wstr = 0;
-    warg = 0;
-
-    std::size_t size = tcase.size >= 0 ? tcase.size : str.max_size () + 1;
+    std::size_t size  = tcase.size  >= 0 ? tcase.size  : str.max_size () + 1;
+    std::size_t size2 = tcase.size2 >= 0 ? tcase.size2 : str.max_size () + 1;
 
     // save the state of the string object before the call
     // to detect wxception safety violations (changes to
@@ -598,7 +538,7 @@
     std::size_t* const rg_calls = rw_get_call_counters ((Traits*)0, (charT*)0);
 
     if (rg_calls)
-        total_length_calls = rg_calls [UTMemFun::length];
+        total_length_calls = rg_calls [TraitsFunc::length];
 
     rwt_free_store* const pst = rwt_get_free_store (0);
     SharedAlloc*    const pal = SharedAlloc::instance ();
@@ -634,12 +574,8 @@
 
 #else   // if defined (_RWSTD_NO_EXCEPTIONS)
 
-        if (tcase.bthrow) {
-            if (wres != wres_buf)
-                delete[] wres;
-
+        if (tcase.bthrow) 
             return;
-        }
 
 #endif   // _RWSTD_NO_EXCEPTIONS
 
@@ -655,7 +591,7 @@
             case Assign (cptr):
                 ret_ptr = &str.assign (arg_ptr);
                 if (rg_calls)
-                    n_length_calls = rg_calls [UTMemFun::length];
+                    n_length_calls = rg_calls [TraitsFunc::length];
                 break;
 
             case Assign (cstr):
@@ -667,7 +603,7 @@
                 break;
 
             case Assign (cstr_size_size):
-                ret_ptr = &str.assign (arg_str, tcase.off, size);
+                ret_ptr = &str.assign (arg_str, tcase.off2, size2);
                 break;
 
             case Assign (size_val): {
@@ -676,6 +612,10 @@
                 break;
             }
 
+            case Assign (range):
+                ret_ptr = &rng (str, tdata);
+                break;
+
             default:
                 RW_ASSERT (!"test logic error: unknown assign overload");
             }
@@ -690,27 +630,28 @@
                        "line %d. %{$FUNCALL} returned invalid reference, "
                        "offset is %td", __LINE__, ret_off);
 
+            // for convenience
+            static const int cwidth = sizeof (charT);
+
             // verfiy that strings length are equal
-            rw_assert (res_len == str.size (), 0, tcase.line,
-                       "line %d. %{$FUNCALL}: expected %{#*s} with length "
+            rw_assert (tdata.reslen_ == str.size (), 0, tcase.line,
+                       "line %d. %{$FUNCALL}: expected %{/*.*Gs} with length "
                        "%zu, got %{/*.*Gs} with length %zu", __LINE__, 
-                       int (tcase.nres), tcase.res, res_len, 
-                       int (sizeof (charT)), int (str.size ()), 
-                       str.c_str (), str.size ());
+                       cwidth, int (tdata.reslen_), tdata.res_, tdata.reslen_,
+                       cwidth, int (str.size ()), str.c_str (), str.size ());
 
-            if (res_len == str.size ()) {
+            if (tdata.reslen_ == str.size ()) {
                 // if the result length matches the expected length
                 // (and only then), also verify that the modified
                 // string matches the expected result
                 const std::size_t match =
                     rw_match (tcase.res, str.c_str(), tcase.nres);
 
-                rw_assert (match == res_len, 0, tcase.line,
-                           "line %d. %{$FUNCALL}: expected %{#*s}, "
+                rw_assert (match == tdata.reslen_, 0, tcase.line,
+                           "line %d. %{$FUNCALL}: expected %{/*.*Gs}, "
                            "got %{/*.*Gs}, difference at off %zu",
-                           __LINE__, int (tcase.nres), tcase.res,
-                           int (sizeof (charT)), int (str.size ()), 
-                           str.c_str (), match);
+                           __LINE__, cwidth, int (tdata.reslen_), tdata.res_,
+                           cwidth, int (str.size ()), str.c_str (), match);
             }
 
             // verify that Traits::length was used
@@ -812,24 +753,92 @@
     }
 #endif
 
-    rw_assert (expect_throws == throw_count, 0, tcase.line,
-               "line %d: %{$FUNCALL}: expected exactly 1 %s exception "
-               "while changing capacity from %zu to %zu, got %zu",
-               __LINE__, exceptions [3],
-               str_state.capacity_, str.capacity (), throw_count);
+    // verify number of exceptions thrown
+    // for range version the allocation may take place several times
+    if (Assign (range) != func.which_)
+        rw_assert (expect_throws == throw_count, 0, tcase.line,
+                   "line %d: %{$FUNCALL}: expected exactly 1 %s exception "
+                   "while changing capacity from %zu to %zu, got %zu",
+                   __LINE__, exceptions [3],
+                   str_state.capacity_, str.capacity (), throw_count);
+    else
+        rw_assert (expect_throws <= throw_count, 0, tcase.line,
+                   "line %d: %{$FUNCALL}: expected at least 1 %s exception "
+                   "while changing capacity from %zu to %zu, got %zu",
+                   __LINE__, exceptions [3],
+                   str_state.capacity_, str.capacity (), throw_count);
 
     // disable bad_alloc exceptions
     *pst->throw_at_calls_ [0] = 0;
     pal->throw_at_calls_ [pal->m_allocate] = 0;
+}
+
+/**************************************************************************/
 
-    if (wres != wres_buf)
-        delete[] wres;
+template <class charT, class Traits, class Allocator>
+void test_assign (charT*, Traits*, Allocator*,
+                  const StringTestCaseData<charT> &tdata)
+{
+    typedef std::basic_string<charT, Traits, Allocator> String;
+
+    if (tdata.func_.which_ == Assign (range)) {
+
+        switch (tdata.func_.iter_id_) {
+
+        // exercise possible overloads of the member function template
+        // on common RandomAccessIterator types
+#undef TEST
+#define TEST(Iterator) do {                                                 \
+        typedef typename String::Iterator Iter;                             \
+        static const                                                        \
+        AssignRangeOverload<String, Iter> app;                              \
+        test_assign ((charT*)0, (Traits*)0, (Allocator*)0, app, tdata);     \
+    } while (0)
+
+        case StringIds::Pointer: TEST (pointer); break;
+        case StringIds::ConstPointer: TEST (const_pointer); break;
+        case StringIds::Iterator: TEST (iterator); break;
+        case StringIds::ConstIterator: TEST (const_iterator); break;
+
+            // disabled for now
+        case StringIds::ReverseIterator:
+            // TEST (reverse_iterator);
+            break;
+
+        case StringIds::ConstReverseIterator:
+            // TEST (const_reverse_iterator);
+            break;
+
+        // exercise specializations of the member function template
+        // on the required iterator categories
 
+#undef TEST
+#define TEST(Iterator) do {                                                 \
+        typedef Iterator<charT> Iter;                                       \
+        static const                                                        \
+        AssignRange<String, Iter> app;                                      \
+        test_assign ((charT*)0, (Traits*)0, (Allocator*)0, app, tdata);     \
+    } while (0)
+
+        case StringIds::Input: TEST (InputIter); break;
+        case StringIds::Forward: TEST (ConstFwdIter); break;
+        case StringIds::Bidir: TEST (ConstBidirIter); break;
+        case StringIds::Random: TEST (ConstRandomAccessIter); break;
+
+        default:
+            rw_error (0, 0, __LINE__, "bad iterator id");
+        }
+    }
+    else {
+        // exercise ordinary overloads of the member function
+        static const RangeBase<String> app;
+        test_assign ((charT*)0, (Traits*)0, (Allocator*)0, app, tdata);
+    }
 }
 
 /**************************************************************************/
 
-DEFINE_STRING_TEST_DISPATCH (test_assign);
+DEFINE_STRING_TEST_FUNCTIONS (test_assign);
 
 int main (int argc, char** argv)
 {
@@ -852,7 +861,10 @@
 
     const std::size_t test_count = sizeof tests / sizeof *tests;
 
-    return rw_run_string_test (argc, argv, __FILE__,
-                               "lib.string.assign",
-                               test_assign, tests, test_count);
+    const int status =
+        rw_run_string_test (argc, argv, __FILE__,
+                            "lib.string.assign",
+                            test_assign_func_array, tests, test_count);
+
+    return status;
 }

Modified: incubator/stdcxx/trunk/tests/strings/21.string.insert.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/strings/21.string.insert.cpp?rev=412750&r1=412749&r2=412750&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/strings/21.string.insert.cpp (original)
+++ incubator/stdcxx/trunk/tests/strings/21.string.insert.cpp Thu Jun  8 06:41:03 2006
@@ -299,13 +299,13 @@
     TEST ("x@1411",  872, "x@3695",  128, 2284, "x@3695",        0),
     TEST ("x@1412",    0, "x@2284",    0, 2284, "x@3696",        0),
 
-    TEST ("\0",        2, "",          0,    0,  "",             1),
+    TEST ("\0",        2, "",          0,    0,  "\0",           1),
     TEST ("",          0, "\0",        2,    0,  "",             2),
 
-    TEST ("a",         2, "",          0,    0,  "",             1),
+    TEST ("a",         2, "",          0,    0,  "a",            1),
     TEST ("",          0, "a",         2,    0,  "",             2),
 
-    TEST ("x@4096", 4106, "",          0,    0,  "",             1),
+    TEST ("x@4096", 4106, "",          0,    0,  "x@4096",       1),
     TEST ("",          0, "x@4096", 4106,    0,  "",             2),
 
     TEST ("last",      4, "test",      0,    4,  "lasttest",     0)
@@ -546,163 +546,105 @@
 
 /**************************************************************************/
 
-template <class charT, class Traits, class Allocator, class Iterator>
-void test_insert_range (const charT    *wstr,
-                        std::size_t     wstr_len,
-                        const charT    *warg,
-                        std::size_t     warg_len,
-                        std::size_t     res_len,
-                        Traits*,
-                        Allocator*, 
-                        const Iterator &it,
-                        const StringTestCase &tcase)
-{
-    typedef std::basic_string <charT, Traits, Allocator> String;
-    typedef typename String::iterator                    StringIter;
+// invokes specializations of the member function template
+// on the required iterator categories
+template <class String, class Iterator>
+struct InsertRange: RangeBase<String> {
 
-    const char* const itname =
-        tcase.arg ? type_name (it, (charT*)0) : "basic_string::iterator";
+    typedef typename String::iterator       StringIter;
+    typedef typename String::value_type     StringChar;
 
-    // compute the size of the controlled sequence and the size
-    // of the sequence denoted by the argument keeping in mind
-    // that the latter may refer to the former
-    const std::size_t size1 = wstr_len;
-    const std::size_t size2 = tcase.arg ? warg_len : size1;
+    InsertRange () { }
 
-    // construct the string object to be modified
-    String str (wstr, size1);
+    virtual String&
+    operator() (String &str, 
+                const StringTestCaseData<StringChar>& tdata) const {
 
-    // compute the offset and the extent (the number of elements)
-    // of the first range into the string object being modified
-    const std::size_t off1 =
-        std::size_t (tcase.off) < size1 ? std::size_t (tcase.off) : size1;
+        const StringTestCase &tcase = tdata.tcase_;
 
-    // compute the offset and the extent (the number of elements)
-    // of the second range into the argument of the function call
-    const std::size_t off2 =
-        std::size_t (tcase.off2) < size2 ? std::size_t (tcase.off2) : size2;
-    const std::size_t ext2 =
-        off2 + tcase.size2 < size2 ? std::size_t (tcase.size2) : size2 - off2;
-
-    // create an iterator into the string object being modified
-    StringIter iter (str.begin () + off1);
-
-    if (tcase.arg) {
-        const charT* const beg = warg + off2;
-        const charT* const end = beg + ext2;
+        // create a pair of iterators into the string object being modified
+        const StringIter first1 (str.begin () + tdata.off1_);
 
-        const Iterator first (beg, beg, end);
-        const Iterator last  (end, beg, end);
+        const String &cstr = str;
 
-        str.insert (iter, first, last);
-    }
-    else {
-        // self-referential modification (inserting a range
-        // of elements with a subrange of its own elements)
-        const StringIter first (str.begin () + off2);
-        const StringIter last (first + ext2);
+        // when (0 == tcase.arg) exercise self-referential modification
+        // (i.e., replacing a range of elements with a subrange of its
+        // own elements)
+        const StringChar* const beg =
+            (tcase.arg ? tdata.arg_ : cstr.data ()) + tdata.off2_;
 
-        str.insert (iter, first, last);
-    }
+        const StringChar* const end = beg + tdata.ext2_;
 
-    // detrmine whether the produced sequence matches the exepceted result
-    const std::size_t match = rw_match (tcase.res, str.data (), tcase.nres);
+        const Iterator first2 (beg, beg, end);
+        const Iterator last2  (end, beg, end);
 
-    rw_assert (match == res_len, 0, tcase.line,
-               "line %d. %{$FUNCALL} expected %{#*s}, got %{/*.*Gs}, "
-               "difference at pos %zu for %s",
-               __LINE__, int (tcase.nres), tcase.res,
-               int (sizeof (charT)), int (str.size ()), str.c_str (),
-               match, itname);
-}
+        str.insert (first1, first2, last2);
+        return str;
+    }
+};
 
-/**************************************************************************/
 
-template <class charT, class Traits, class Allocator>
-void test_insert_range (const charT    *wstr,
-                        std::size_t     wstr_len,
-                        const charT    *warg,
-                        std::size_t     warg_len,
-                        std::size_t     res_len,
-                        Traits*,
-                        Allocator*,
-                        const StringTestCase &tcase)
+// invokes possible overloads of the member function template
+// on common RandomAccessIterator types
+template <class String, class Iterator>
+struct InsertRangeOverload: RangeBase<String>
 {
-    if (tcase.bthrow)  // this method doesn't throw
-        return;
-
-    test_insert_range (wstr, wstr_len, warg, warg_len, res_len, (Traits*)0,
-                       (Allocator*)0, InputIter<charT>(0, 0, 0), tcase);
+    typedef typename String::iterator       StringIter;
+    typedef typename String::value_type     StringChar;
 
-    // there is no need to call test_insert_range
-    // for other iterators in this case
-    if (0 == tcase.arg)
-        return;
-
-    test_insert_range (wstr, wstr_len, warg, warg_len, res_len, (Traits*)0,
-                       (Allocator*)0, ConstFwdIter<charT>(0, 0, 0), tcase);
-
-    test_insert_range (wstr, wstr_len, warg, warg_len, res_len, (Traits*)0,
-                       (Allocator*)0, ConstBidirIter<charT>(0, 0, 0), tcase);
-
-    test_insert_range (wstr, wstr_len, warg, warg_len, res_len, 
-                      (Traits*)0, (Allocator*)0, 
-                       ConstRandomAccessIter<charT>(0, 0, 0), tcase);
-}
-
-/**************************************************************************/
+    InsertRangeOverload () { }
 
-template <class charT, class Traits, class Allocator>
-void test_insert (charT, Traits*, Allocator*,
-                  const StringFunc     &func,
-                  const StringTestCase &tcase)
-{
-    typedef std::basic_string <charT, Traits, Allocator> String;
-    typedef typename String::iterator                    StringIter;
-    typedef typename UserTraits<charT>::MemFun           UTMemFun;
+    virtual String&
+    operator() (String &str, 
+                const StringTestCaseData<StringChar>& tdata) const {
 
-    static const std::size_t BUFSIZE = 256;
+        const StringTestCase &tcase = tdata.tcase_;
 
-    static charT wstr_buf [BUFSIZE];
-    static charT warg_buf [BUFSIZE];
+        // create a pair of iterators into the string object being modified
+        const StringIter first1 (str.begin () + tdata.off1_);
 
-    std::size_t str_len = sizeof wstr_buf / sizeof *wstr_buf;
-    std::size_t arg_len = sizeof warg_buf / sizeof *warg_buf;
+        const std::size_t off = tdata.off2_;
+        const std::size_t ext = tdata.ext2_;
 
-    charT* wstr = rw_expand (wstr_buf, tcase.str, tcase.str_len, &str_len);
-    charT* warg = rw_expand (warg_buf, tcase.arg, tcase.arg_len, &arg_len);
+        if (0 == tcase.arg) {
+            // exercise self-referential modification (i.e., replacing
+            // a range of elements with a subrange of its own elements)
 
-    static charT wres_buf [BUFSIZE];
-    std::size_t res_len = sizeof wres_buf / sizeof *wres_buf;
-    charT* wres = rw_expand (wres_buf, tcase.res, tcase.nres, &res_len);
+            const Iterator first2 (begin (str, (Iterator*)0) + off);
+            const Iterator last2 (first2 + ext);
 
-    // special processing for insert_range to exercise all iterators
-    if (Insert (iter_range) == func.which_) {
-        test_insert_range (wstr, str_len, warg, arg_len, 
-                           res_len, (Traits*)0, (Allocator*)0, tcase);
-        if (wstr != wstr_buf)
-            delete[] wstr;
+            str.insert (first1, first2, last2);
+            return str;
+        }
 
-        if (warg != warg_buf)
-            delete[] warg;
+        String str_arg (tdata.arg_, tdata.arglen_);
 
-         if (wres != wres_buf)
-            delete[] wres;
+        const Iterator first2 (begin (str_arg, (Iterator*)0) + off);
+        const Iterator last2 (first2 + ext);
 
-        return;
+        str.insert (first1, first2, last2);
+        return str;
     }
+};
 
-    /* const */ String str (wstr, str_len);
-    const       String arg (warg, arg_len);
+/**************************************************************************/
 
-    if (wstr != wstr_buf)
-        delete[] wstr;
+template <class charT, class Traits, class Allocator>
+void test_insert (charT*, Traits*, Allocator*, const RangeBase<
+                      std::basic_string <charT, Traits, Allocator> > &rng,
+                  const StringTestCaseData<charT>                    &tdata)
+{
+    typedef std::basic_string <charT, Traits, Allocator> String;
+    typedef typename String::iterator                    StringIter;
+    typedef typename UserTraits<charT>::MemFun           TraitsFunc;
 
-    if (warg != warg_buf)
-        delete[] warg;
+    const StringFunc     &func  = tdata.func_;
+    const StringTestCase &tcase = tdata.tcase_;
 
-    wstr = 0;
-    warg = 0;
+    // construct the string object to be modified
+    // and the (possibly unused) argument string
+    /* const */ String str (tdata.str_, tdata.strlen_);
+    const       String arg (tdata.arg_, tdata.arglen_);
 
     // save the state of the string object before the call
     // to detect wxception safety violations (changes to
@@ -713,7 +655,7 @@
 
     // compute the offset and the extent (the number of elements)
     // of the first range into the string object being modified
-    const std::size_t size1 = str_len;
+    const std::size_t size1 = tdata.strlen_;
     const std::size_t off1 =
         std::size_t (tcase.off) < size1 ? std::size_t (tcase.off) : size1;
 
@@ -726,7 +668,7 @@
     std::size_t* const rg_calls = rw_get_call_counters ((Traits*)0, (charT*)0);
 
     if (rg_calls)
-        total_length_calls = rg_calls [UTMemFun::length];
+        total_length_calls = rg_calls [TraitsFunc::length];
 
     rwt_free_store* const pst = rwt_get_free_store (0);
     SharedAlloc*    const pal = SharedAlloc::instance ();
@@ -768,12 +710,8 @@
 
 #else   // if defined (_RWSTD_NO_EXCEPTIONS)
 
-        if (tcase.bthrow) {
-            if (wres != wres_buf)
-                delete[] wres;
-
+        if (tcase.bthrow) 
             return;
-        }
 
 #endif   // _RWSTD_NO_EXCEPTIONS
 
@@ -789,7 +727,7 @@
             case Insert (size_cptr):
                 ret_ptr = &str.insert (tcase.off, arg_ptr);
                 if (rg_calls)
-                    n_length_calls = rg_calls [UTMemFun::length];
+                    n_length_calls = rg_calls [TraitsFunc::length];
                 break;
 
             case Insert (size_cstr):
@@ -823,6 +761,11 @@
                 break;
             }
 
+            case Insert (iter_range): {
+                ret_ptr = &rng (str, tdata);  // function returns void
+                break;
+            }
+
             default:
                 RW_ASSERT (!"logic error: unknown insert overload");
                 return;
@@ -841,27 +784,28 @@
                        exp_off, ret_off,
                        Insert (iter_val) != func.which_, ret_off);
 
+            // for convenience
+            static const int cwidth = sizeof (charT);
+
             // verfiy that strings length are equal
-            rw_assert (res_len == str.size (), 0, tcase.line,
-                       "line %d. %{$FUNCALL} expected %{#*s} with length "
+            rw_assert (tdata.reslen_ == str.size (), 0, tcase.line,
+                       "line %d. %{$FUNCALL} expected %{/*.*Gs} with length "
                        "%zu, got %{/*.*Gs} with length %zu", __LINE__, 
-                       int (tcase.nres), tcase.res, res_len, 
-                       int (sizeof (charT)), int (str.size ()), 
-                       str.c_str (), str.size ());
+                       cwidth, int (tdata.reslen_), tdata.res_, tdata.reslen_, 
+                       cwidth, int (str.size ()), str.c_str (), str.size ());
 
-            if (res_len == str.size ()) {
+            if (tdata.reslen_ == str.size ()) {
                 // if the result length matches the expected length
                 // (and only then), also verify that the modified
                 // string matches the expected result
                 const std::size_t match =
                     rw_match (tcase.res, str.c_str(), tcase.nres);
 
-                rw_assert (match == res_len, 0, tcase.line,
-                           "line %d. %{$FUNCALL} expected %{#*s}, "
+                rw_assert (match == tdata.reslen_, 0, tcase.line,
+                           "line %d. %{$FUNCALL} expected %{/*.*Gs}, "
                            "got %{/*.*Gs}, difference at offset %zu",
-                           __LINE__, int (tcase.nres), tcase.res,
-                           int (sizeof (charT)), int (str.size ()),
-                           str.c_str (), match);
+                           __LINE__, cwidth, int (tdata.reslen_), tdata.res_,
+                           cwidth, int (str.size ()), str.c_str (), match);
             }
 
             // verify that Traits::length was used
@@ -954,23 +898,91 @@
 
 #endif   // _RWSTD_NO_REPLACEABLE_NEW_DELETE
 
-    rw_assert (expect_throws == throw_count, 0, tcase.line,
-               "line %d: %{$FUNCALL}: expected exactly 1 %s exception "
-               "while changing capacity from %zu to %zu, got %zu",
-               __LINE__, exceptions [3],
-               str_state.capacity_, str.capacity (), throw_count);
+    // verify number of exceptions thrown
+    // for range version the allocation may take place several times
+    if (Insert (iter_range) != func.which_)
+        rw_assert (expect_throws == throw_count, 0, tcase.line,
+                   "line %d: %{$FUNCALL}: expected exactly 1 %s exception "
+                   "while changing capacity from %zu to %zu, got %zu",
+                   __LINE__, exceptions [3],
+                   str_state.capacity_, str.capacity (), throw_count);
+    else
+        rw_assert (expect_throws <= throw_count, 0, tcase.line,
+                   "line %d: %{$FUNCALL}: expected at least 1 %s exception "
+                   "while changing capacity from %zu to %zu, got %zu",
+                   __LINE__, exceptions [3],
+                   str_state.capacity_, str.capacity (), throw_count);
 
     // disable bad_alloc exceptions
     *pst->throw_at_calls_ [0] = 0;
     pal->throw_at_calls_ [pal->m_allocate] = 0;
+}
+
+/**************************************************************************/
 
-    if (wres != wres_buf)
-        delete[] wres;
+template <class charT, class Traits, class Allocator>
+void test_insert (charT*, Traits*, Allocator*,
+                  const StringTestCaseData<charT> &tdata)
+{
+    typedef std::basic_string<charT, Traits, Allocator> String;
+
+    if (tdata.func_.which_ == Insert (iter_range)) {
+
+        switch (tdata.func_.iter_id_) {
+
+        // exercise possible overloads of the member function template
+        // on common RandomAccessIterator types
+#undef TEST
+#define TEST(Iterator) do {                                                 \
+        typedef typename String::Iterator Iter;                             \
+        static const                                                        \
+        InsertRangeOverload<String, Iter> rep;                              \
+        test_insert ((charT*)0, (Traits*)0, (Allocator*)0, rep, tdata);     \
+    } while (0)
+
+        case StringIds::Pointer: TEST (pointer); break;
+        case StringIds::ConstPointer: TEST (const_pointer); break;
+        case StringIds::Iterator: TEST (iterator); break;
+        case StringIds::ConstIterator: TEST (const_iterator); break;
+
+            // disabled for now
+        case StringIds::ReverseIterator:
+            // TEST (reverse_iterator);
+            break;
+
+        case StringIds::ConstReverseIterator:
+            // TEST (const_reverse_iterator);
+            break;
+
+        // exercise specializations of the member function template
+        // on the required iterator categories
+#undef TEST
+#define TEST(Iterator) do {                                                 \
+        typedef Iterator<charT> Iter;                                       \
+        static const                                                        \
+        InsertRange<String, Iter> rep;                                      \
+        test_insert ((charT*)0, (Traits*)0, (Allocator*)0, rep, tdata);     \
+    } while (0)
+
+        case StringIds::Input: TEST (InputIter); break;
+        case StringIds::Forward: TEST (ConstFwdIter); break;
+        case StringIds::Bidir: TEST (ConstBidirIter); break;
+        case StringIds::Random: TEST (ConstRandomAccessIter); break;
+
+        default:
+            rw_error (0, 0, __LINE__, "bad iterator id");
+        }
+    }
+    else {
+        // exercise ordinary overloads of the member function
+        static const RangeBase<String> rep;
+        test_insert ((charT*)0, (Traits*)0, (Allocator*)0, rep, tdata);
+    }
 }
 
 /**************************************************************************/
 
-DEFINE_STRING_TEST_DISPATCH (test_insert);
+DEFINE_STRING_TEST_FUNCTIONS (test_insert);
 
 int main (int argc, char** argv)
 {
@@ -995,7 +1007,10 @@
 
     const std::size_t test_count = sizeof tests / sizeof *tests;
 
-    return rw_run_string_test (argc, argv, __FILE__,
-                               "lib.string.insert",
-                               test_insert, tests, test_count);
+    const int status =
+        rw_run_string_test (argc, argv, __FILE__,
+                            "lib.string.insert",
+                            test_insert_func_array, tests, test_count);
+
+    return status;
 }

Modified: incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp?rev=412750&r1=412749&r2=412750&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp (original)
+++ incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp Thu Jun  8 06:41:03 2006
@@ -716,35 +716,19 @@
 
 /**************************************************************************/
 
-template <class charT, class Traits, class Allocator>
-struct ReplaceBase {
-    typedef std::basic_string<charT, Traits, Allocator> String;
-    typedef typename String::iterator                   StringIter;
-
-    ReplaceBase () { }
-
-    virtual ~ReplaceBase () { /* silence warnings */ }
-
-    virtual String&
-    operator() (String &str, const StringTestCaseData<charT>&) const {
-        RW_ASSERT (!"logic error: should be never called");
-        return str;
-    }
-};
-
-/**************************************************************************/
-
 // invokes specializations of the member function template
 // on the required iterator categories
-template <class charT, class Traits, class Allocator, class Iterator>
-struct ReplaceRange: ReplaceBase<charT, Traits, Allocator> {
-    typedef std::basic_string<charT, Traits, Allocator> String;
-    typedef typename String::iterator                   StringIter;
+template <class String, class Iterator>
+struct ReplaceRange: RangeBase<String> {
+
+    typedef typename String::iterator       StringIter;
+    typedef typename String::value_type     StringChar;
 
     ReplaceRange () { }
 
     virtual String&
-    operator() (String &str, const StringTestCaseData<charT>& tdata) const {
+    operator() (String &str, 
+                const StringTestCaseData<StringChar>& tdata) const {
 
         const StringTestCase &tcase = tdata.tcase_;
 
@@ -757,10 +741,10 @@
         // when (0 == tcase.arg) exercise self-referential modification
         // (i.e., replacing a range of elements with a subrange of its
         // own elements)
-        const charT* const beg =
+        const StringChar* const beg =
             (tcase.arg ? tdata.arg_ : cstr.data ()) + tdata.off2_;
 
-        const charT* const end = beg + tdata.ext2_;
+        const StringChar* const end = beg + tdata.ext2_;
 
         const Iterator first2 (beg, beg, end);
         const Iterator last2  (end, beg, end);
@@ -769,63 +753,20 @@
     }
 };
 
-/**************************************************************************/
 
 // invokes possible overloads of the member function template
 // on common RandomAccessIterator types
-template <class charT, class Traits, class Allocator, class Iterator>
-struct ReplaceRangeOverload: ReplaceBase<charT, Traits, Allocator>
+template <class String, class Iterator>
+struct ReplaceRangeOverload: RangeBase<String>
 {
-    typedef std::basic_string<charT, Traits, Allocator> String;
-    typedef typename String::pointer                    StringPtr;
-    typedef typename String::const_pointer              StringConstPtr;
-    typedef typename String::iterator                   StringIter;
-    typedef typename String::const_iterator             StringConstIter;
-    typedef typename String::reverse_iterator           StringRevIter;
-    typedef typename String::const_reverse_iterator     StringConstRevIter;
+    typedef typename String::iterator       StringIter;
+    typedef typename String::value_type     StringChar;
 
     ReplaceRangeOverload () { }
 
-    static StringPtr
-    begin (String &str, StringPtr*) {
-        return _RWSTD_CONST_CAST (StringPtr, str.data ());
-    }
-
-    static StringConstPtr
-    begin (const String &str, StringConstPtr*) {
-        return str.data ();
-    }
-
-#ifndef _RWSTD_NO_DEBUG_ITER
-
-    // when debugging iterators are enabled string::iterator and
-    // string::pointer are distinct types; otherwise they are the
-    // same type
-
-    static StringIter
-    begin (String &str, StringIter*) {
-        return str.begin ();
-    }
-
-    static StringConstIter
-    begin (const String &str, StringConstIter*) {
-        return str.begin ();
-    }
-
-#endif   // _RWSTD_NO_DEBUG_ITER
-
-    static StringRevIter
-    begin (String &str, StringRevIter*) {
-        return str.rbegin ();
-    }
-
-    static StringConstRevIter
-    begin (const String &str, StringConstRevIter*) {
-        return str.rbegin ();
-    }
-
     virtual String&
-    operator() (String &str, const StringTestCaseData<charT>& tdata) const {
+    operator() (String &str, 
+                const StringTestCaseData<StringChar>& tdata) const {
 
         const StringTestCase &tcase = tdata.tcase_;
 
@@ -858,9 +799,9 @@
 /**************************************************************************/
 
 template <class charT, class Traits, class Allocator>
-void test_replace (charT*, Traits*, Allocator*,
-                   const ReplaceBase<charT, Traits, Allocator> &rep,
-                   const StringTestCaseData<charT>             &tdata)
+void test_replace (charT*, Traits*, Allocator*, const RangeBase<
+                       std::basic_string <charT, Traits, Allocator> > &rep,
+                   const StringTestCaseData<charT>                    &tdata)
 {
     typedef std::basic_string <charT, Traits, Allocator> String;
     typedef typename String::iterator                    StringIter;
@@ -1161,9 +1102,9 @@
 void test_replace (charT*, Traits*, Allocator*,
                    const StringTestCaseData<charT> &tdata)
 {
-    if (tdata.func_.which_ == Replace (iter_iter_range)) {
+    typedef std::basic_string<charT, Traits, Allocator> String;
 
-        typedef std::basic_string<charT, Traits, Allocator> String;
+    if (tdata.func_.which_ == Replace (iter_iter_range)) {
 
         switch (tdata.func_.iter_id_) {
 
@@ -1173,7 +1114,7 @@
 #define TEST(Iterator) do {                                                 \
         typedef typename String::Iterator Iter;                             \
         static const                                                        \
-        ReplaceRangeOverload<charT, Traits, Allocator, Iter> rep;           \
+        ReplaceRangeOverload<String, Iter> rep;                             \
         test_replace ((charT*)0, (Traits*)0, (Allocator*)0, rep, tdata);    \
     } while (0)
 
@@ -1197,7 +1138,7 @@
 #define TEST(Iterator) do {                                                 \
         typedef Iterator<charT> Iter;                                       \
         static const                                                        \
-        ReplaceRange<charT, Traits, Allocator, Iter> rep;                   \
+        ReplaceRange<String, Iter> rep;                                     \
         test_replace ((charT*)0, (Traits*)0, (Allocator*)0, rep, tdata);    \
     } while (0)
 
@@ -1212,7 +1153,7 @@
     }
     else {
         // exercise ordinary overloads of the member function
-        static const ReplaceBase<charT, Traits, Allocator> rep;
+        static const RangeBase<String> rep;
         test_replace ((charT*)0, (Traits*)0, (Allocator*)0, rep, tdata);
     }
 }