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

svn commit: r412250 - /incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp

Author: sebor
Date: Tue Jun  6 18:46:40 2006
New Revision: 412250

URL: http://svn.apache.org/viewvc?rev=412250&view=rev
Log:
2006-06-06  Anton Pevtsov  <an...@moscow.vdiweb.com>
	    Martin Sebor  <se...@roguewave.com>

	* 21.string.replace.cpp: Added test cases.
	(ReplaceBase, ReplaceRange, ReplaceRangeOverload): New class
	templates to abstract out the invocation of the replace member
	template and its overloads.
	(test_replace): Added ReplaceBase& argument and eliminated
	test_replace_range (obviated by the addition of the argument).
	(test_replace): Dispatched to the appropriate specialization
	based on the iterator id (if any).

Modified:
    incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp

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=412250&r1=412249&r2=412250&view=diff
==============================================================================
--- incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp (original)
+++ incubator/stdcxx/trunk/tests/strings/21.string.replace.cpp Tue Jun  6 18:46:40 2006
@@ -25,13 +25,12 @@
  *
  **************************************************************************/
 
-#include <string>       // for string
-#include <stdexcept>    // for out_of_range, length_error
-#include <cstddef>      // for ptrdiff_t, size_t
+#include <string>           // for string
+#include <stdexcept>        // for out_of_range, length_error
+#include <cstddef>          // for ptrdiff_t, size_t
 
 #include <21.strings.h>
 #include <alg_test.h>       // for InputIter
-#include <cmdopt.h>         // for rw_enabled()
 #include <driver.h>         // for rw_test()
 #include <rw_allocator.h>   // for UserAlloc
 #include <rw_new.h>         // for bad_alloc, replacement operator new
@@ -556,13 +555,13 @@
     TEST ("x@4096", 2047, 2048, "x@4096", 0, 2048,  "x@4096",        0),
 
     TEST ("\0",         2, 0, "",           0, 0, "\0",              1),
-    TEST ("\0",         0, 0, "\0",         2, 0, "",                2),
+    TEST ("\0",         0, 0, "\0",         2, 0, "\0",              2),
 
     TEST ("a",         10, 0, "",           0, 0, "a",               1),
-    TEST ("a",          0, 0, "a",         10, 0, "",                2),
+    TEST ("a",          0, 0, "a",         10, 0, "a",               2),
 
     TEST ("x@4096",  4106, 0, "",           0, 0, "x@4096",          1),
-    TEST ("x@4096",     0, 0, "x@4096", 4106, 0, "",                 2),
+    TEST ("x@4096",     0, 0, "x@4096",  4106, 0, "x@4096",          2),
 
     TEST ("a",          0, 1, "x@4096", 0, 4095, "x@4095",           0),
 
@@ -717,90 +716,151 @@
 
 /**************************************************************************/
 
+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>
-void test_replace_range (const StringTestCaseData<charT> &tdata,
-                         Traits*, Allocator*, const Iterator &it)
-{
-    typedef std::basic_string <charT, Traits, Allocator> String;
-    typedef typename String::iterator                    StringIter;
+struct ReplaceRange: ReplaceBase<charT, Traits, Allocator> {
+    typedef std::basic_string<charT, Traits, Allocator> String;
+    typedef typename String::iterator                   StringIter;
 
-    const StringTestCase &tcase = tdata.tcase_;
+    ReplaceRange () { }
 
-    const char* const itname =
-        tcase.arg ? type_name (it, (charT*)0) : "basic_string::iterator";
+    virtual String&
+    operator() (String &str, const StringTestCaseData<charT>& tdata) const {
 
-    // construct the string object to be modified
-    String str (tdata.str_, tdata.strlen_);
+        const StringTestCase &tcase = tdata.tcase_;
+
+        // create a pair of iterators into the string object being modified
+        const StringIter first1 (str.begin () + tdata.off1_);
+        const StringIter last1  (first1 + tdata.ext1_);
 
-    // create a pair of iterators into the string object being modified
-    const StringIter first1 (str.begin () + tdata.off1_);
-    const StringIter last1  (first1 + tdata.ext1_);
+        const String &cstr = str;
+
+        // 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 =
+            (tcase.arg ? tdata.arg_ : cstr.data ()) + tdata.off2_;
 
-    if (tcase.arg) {
-        const charT* const beg = tdata.arg_ + tdata.off2_;
         const charT* const end = beg + tdata.ext2_;
 
         const Iterator first2 (beg, beg, end);
         const Iterator last2  (end, beg, end);
 
-        str.replace (first1, last1, first2, last2);
+        return str.replace (first1, last1, first2, last2);
     }
-    else {
-        // self-referential modification (replacing a range
-        // of elements with a subrange of its own elements)
-        const StringIter first2 (str.begin () + tdata.off2_);
-        const StringIter last2 (first2 + tdata.ext2_);
+};
+
+/**************************************************************************/
 
-        str.replace (first1, last1, first2, last2);
+// 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>
+{
+    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;
+
+    ReplaceRangeOverload () { }
+
+    static StringPtr
+    begin (String &str, StringPtr*) {
+        return _RWSTD_CONST_CAST (StringPtr, str.data ());
     }
 
-    // detrmine whether the produced sequence matches the exepceted result
-    const std::size_t match = rw_match (tcase.res, str.data (), tcase.nres);
+    static StringConstPtr
+    begin (const String &str, StringConstPtr*) {
+        return str.data ();
+    }
 
-    rw_assert (match == tdata.reslen_, 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 (str.size ()), str.c_str (),
-               match, itname);
-}
+#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 ();
+    }
 
-template <class charT, class Traits, class Allocator>
-void test_replace_range (const StringTestCaseData<charT> &tdata,
-                         Traits*, Allocator*)
-{
-    if (tdata.tcase_.bthrow) {
-        // FIXME: exercise exceptions
-        return;
+    static StringConstIter
+    begin (const String &str, StringConstIter*) {
+        return str.begin ();
     }
 
-    // exercise InputIterator *or* string::iterator (i.e., self
-    // referential modification), depending on the value of tcase.arg
-    test_replace_range (tdata, (Traits*)0, (Allocator*)0,
-                        InputIter<charT>(0, 0, 0));
-
-    if (0 == tdata.tcase_.arg) {
-        // avoid exercising the same function multiple times
-        return;
+#endif   // _RWSTD_NO_DEBUG_ITER
+
+    static StringRevIter
+    begin (String &str, StringRevIter*) {
+        return str.rbegin ();
     }
 
-    test_replace_range (tdata, (Traits*)0, (Allocator*)0,
-                        ConstFwdIter<charT>(0, 0, 0));
+    static StringConstRevIter
+    begin (const String &str, StringConstRevIter*) {
+        return str.rbegin ();
+    }
 
-    test_replace_range (tdata, (Traits*)0, (Allocator*)0,
-                        ConstBidirIter<charT>(0, 0, 0));
+    virtual String&
+    operator() (String &str, const StringTestCaseData<charT>& tdata) const {
 
-    test_replace_range (tdata, (Traits*)0, (Allocator*)0,
-                        ConstRandomAccessIter<charT>(0, 0, 0));
-}
+        const StringTestCase &tcase = tdata.tcase_;
+
+        // create a pair of iterators into the string object being modified
+        const StringIter first1 (str.begin () + tdata.off1_);
+        const StringIter last1  (first1 + tdata.ext1_);
+
+        const std::size_t off = tdata.off2_;
+        const std::size_t ext = tdata.ext2_;
+
+        if (0 == tcase.arg) {
+            // exercise self-referential modification (i.e., replacing
+            // a range of elements with a subrange of its own elements)
+
+            const Iterator first2 (begin (str, (Iterator*)0) + off);
+            const Iterator last2 (first2 + ext);
+
+            return str.replace (first1, last1, first2, last2);
+        }
+
+        String str_arg (tdata.arg_, tdata.arglen_);
+
+        const Iterator first2 (begin (str_arg, (Iterator*)0) + off);
+        const Iterator last2 (first2 + ext);
+
+        return str.replace (first1, last1, first2, last2);
+    }
+};
 
 /**************************************************************************/
 
 template <class charT, class Traits, class Allocator>
 void test_replace (charT*, Traits*, Allocator*,
-                   const StringTestCaseData<charT> &tdata)
+                   const ReplaceBase<charT, Traits, Allocator> &rep,
+                   const StringTestCaseData<charT>             &tdata)
 {
     typedef std::basic_string <charT, Traits, Allocator> String;
     typedef typename String::iterator                    StringIter;
@@ -809,13 +869,6 @@
     const StringFunc     &func  = tdata.func_;
     const StringTestCase &tcase = tdata.tcase_;
 
-    if (Replace (iter_iter_range) == func.which_) {
-        // special processing for the replace() template member
-        // function to exercise all iterator categories
-        test_replace_range (tdata, (Traits*)0, (Allocator*)0);
-        return;
-    }
-
     // construct the string object to be modified
     // and the (possibly unused) argument string
     /* const */ String str (tdata.str_, tdata.strlen_);
@@ -879,7 +932,7 @@
 
         if (1 == tcase.bthrow && !use_iters)
             expected = exceptions [1];      // out_of_range
-        else if (2 == tcase.bthrow)
+        else if (2 == tcase.bthrow && !use_iters)
             expected = exceptions [1];      // out_of_range
         else if (3 == tcase.bthrow && !use_iters)
             expected = exceptions [2];      // length_error
@@ -948,6 +1001,10 @@
                 ret_ptr = &str.replace (first, last, arg_size2, arg_val);
                 break;
 
+            case Replace (iter_iter_range):
+                ret_ptr = &rep (str, tdata);
+                break;
+
             default:
                 RW_ASSERT (!"logic error: unknown replace overload");
             }
@@ -970,7 +1027,7 @@
                        "line %d. %{$FUNCALL} expected %{/*.*Gs} with "
                        "length %zu, got %{/*.*Gs} with length %zu",
                        __LINE__,
-                       cwidth, int (tdata.reslen_), tdata.res_, 
+                       cwidth, int (tdata.reslen_), tdata.res_,
                        tdata.reslen_, cwidth, int (str.size ()), str.data (),
                        str.size ());
 
@@ -1074,19 +1131,90 @@
 #else   // if defined (_RWSTD_NO_REPLACEABLE_NEW_DELETE)
 
     const std::size_t expect_throws = StringIds::UserAlloc == func.alloc_id_ ?
-        str_state.capacity_ < str.capacity (): 0;
+        str_state.capacity_ < str.capacity () : 0;
 
 #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 (Replace (iter_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;
+}
+
+/**************************************************************************/
+
+template <class charT, class Traits, class Allocator>
+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;
+
+        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                                                        \
+        ReplaceRangeOverload<charT, Traits, Allocator, Iter> rep;           \
+        test_replace ((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                                                        \
+        ReplaceRange<charT, Traits, Allocator, Iter> rep;                   \
+        test_replace ((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 ReplaceBase<charT, Traits, Allocator> rep;
+        test_replace ((charT*)0, (Traits*)0, (Allocator*)0, rep, tdata);
+    }
 }
 
 /**************************************************************************/