stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r499952 - /incubator/stdcxx/trunk/tests/iostream/27.istream.manip.cpp
Date Thu, 25 Jan 2007 20:32:22 GMT
Author: sebor
Date: Thu Jan 25 12:32:21 2007
New Revision: 499952

URL: http://svn.apache.org/viewvc?view=rev&rev=499952
Log:
2007-01-25  Martin Sebor  <sebor@roguewave.com>

	STDCXX-4
	* 27.istream.manip.cpp: New test exercising istream.manip.

Added:
    incubator/stdcxx/trunk/tests/iostream/27.istream.manip.cpp   (with props)

Added: incubator/stdcxx/trunk/tests/iostream/27.istream.manip.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/iostream/27.istream.manip.cpp?view=auto&rev=499952
==============================================================================
--- incubator/stdcxx/trunk/tests/iostream/27.istream.manip.cpp (added)
+++ incubator/stdcxx/trunk/tests/iostream/27.istream.manip.cpp Thu Jan 25 12:32:21 2007
@@ -0,0 +1,470 @@
+/************************************************************************
+ *
+ * 27.istream.manip.cpp - test exercising the basic_istream ws manipulator
+ *
+ * $Id$
+ *
+ ************************************************************************
+ *
+ * Licensed to the Apache Software  Foundation (ASF) under one or more
+ * contributor  license agreements.  See  the NOTICE  file distributed
+ * with  this  work  for  additional information  regarding  copyright
+ * ownership.   The ASF  licenses this  file to  you under  the Apache
+ * License, Version  2.0 (the  "License"); you may  not use  this file
+ * except in  compliance with the License.   You may obtain  a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the  License is distributed on an  "AS IS" BASIS,
+ * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
+ * implied.   See  the License  for  the  specific language  governing
+ * permissions and limitations under the License.
+ *
+ * Copyright 2003-2006 Rogue Wave Software.
+ * 
+ **************************************************************************/
+
+#include <cstddef>
+#include <istream>
+
+#include <driver.h>
+
+/************************************************************************
+
+    namespace std {
+        template <class charT, class traits>
+        basic_istream<charT,traits>& ws(basic_istream<charT,traits>&
is);
+    }
+
+    -1- Effects: Extracts characters as long as the next available
+        character c is whitespace or until there are no more characters
+        in the sequence. Whitespace characters are distinguished with
+        the same criterion as used by sentry::sentry (27.6.1.1.2). If
+        ws stops extracting characters because there are no more
+        available it sets eofbit, but not failbit.
+    -2- Returns: is
+
+************************************************************************/
+
+template <class charT>
+struct Ctype: std::ctype<charT>
+{
+    typedef std::ctype<charT> Base;
+
+    const charT ws_;   // whitespace character
+
+    std::ctype_base::mask table_ [256];
+
+    Ctype (std::size_t ref, charT white)
+        : Base (ref), ws_ (white) { }
+
+    // used by ctype<wchar_t>
+    /* virtual */ bool
+    do_is (std::ctype_base::mask m, charT c) const {
+        if (m & std::ctype_base::space)
+            return ws_ == c;
+        return Base::is (m, c);
+    }
+
+    // not used by the test, defined only to silence compiler warnings
+    // about the overload above hiding the base function overloaded below
+    /* virtual */ const charT*
+    do_is (const charT *lo, const charT *hi, std::ctype_base::mask *m) const {
+        return Base::do_is (lo, hi, m);
+    }
+};
+
+
+// specialized for ctype<char>
+_RWSTD_SPECIALIZED_CLASS
+Ctype<char>::Ctype (std::size_t ref, char white)
+    : Base (table_, false, ref), ws_ (white)
+{
+    for (std::size_t i = 0; i != sizeof table_ / sizeof *table_; ++i)
+        table_ [i] = std::ctype_base::mask ();
+
+    typedef unsigned char UChar;
+
+    table_ [UChar (ws_)] = std::ctype_base::space;
+}
+
+
+// user-defined Traits type exercises the ability to instantiate
+// std::ws and any supporting templates on types other than the
+// default std::char_traits<charT>
+template <class charT>
+struct UserTraits: std::char_traits<charT> { };
+
+
+template <class charT, class Traits>
+struct Streambuf: std::basic_streambuf<charT, Traits>
+{
+    typedef std::basic_streambuf<charT, Traits> Base;
+
+    typedef typename Base::traits_type          traits_type;
+    typedef typename Base::int_type             int_type;
+
+    int nsyncs_;       // number of calls to sync()
+
+    // overflow() will return eof () after extracting this many chars
+    int fail_after_;
+
+    // overflow() will throw am exception after extracting this many chars
+    int throw_after_;
+
+    const charT *end_;          // the end of the buffer (future eback())
+
+    Streambuf (const charT *gbeg, const charT *gend)
+        : Base (),
+          nsyncs_ (0),
+          fail_after_ (-1),    // never fail
+          throw_after_ (-1),   // never throw
+          end_ (gend) {
+        this->setg (_RWSTD_CONST_CAST (charT*, gbeg),
+                    _RWSTD_CONST_CAST (charT*, gbeg),
+                    _RWSTD_CONST_CAST (charT*, gbeg));
+    }
+
+    const charT* pubeback () const {
+        return this->eback ();
+    }
+
+    const charT* pubgptr () const {
+        return this->gptr ();
+    }
+
+    const charT* pubegptr () const {
+        return this->egptr ();
+    }
+
+    /* virtual */ int sync () {
+        ++nsyncs_;
+        return Base::sync ();
+    }
+
+    /* virtual */ int_type underflow () {
+        if (this->gptr () == end_)
+            return traits_type::eof ();
+
+        if (throw_after_ == this->gptr () - this->eback ()) {
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+            throw throw_after_;
+
+#else   // if defined (_RWSTD_NO_EXCEPTIONS)
+
+            return traits_type::eof ();
+
+#endif   // _RWSTD_NO_EXCEPTIONS
+
+        }
+
+        if (fail_after_ == this->gptr () - this->eback ())
+            return traits_type::eof ();
+
+        this->setg (this->eback (), this->gptr (), this->gptr () + 1);
+        return traits_type::to_int_type (*this->gptr ());
+    }
+};
+
+/***********************************************************************/
+
+template <class charT, class Traits>
+void
+test_ws (const Traits*           /* dummy */,
+         const char             *cname,
+         const char             *tname,
+         std::size_t             iter,
+         const charT            *cbuf,
+         std::size_t             cbuf_size,
+         std::ios_base::iostate  state,
+         std::size_t             j,
+         bool                    skipws,
+         charT                   white)
+{
+    typedef std::basic_istream<charT, Traits>   Istream;
+    typedef typename Istream::sentry            Sentry;
+
+    // construct a ctype object that treats `wc' as the only
+    // whitespace character
+    const Ctype<charT> ctp (1, white);
+
+    // construct a stream buffer object and initialize its read sequence
+    // with the character buffer
+    Streambuf<charT, Traits> sb (cbuf, cbuf + cbuf_size - 1);
+
+    // set err_after to the number of successful extractions from
+    // the stream; subsequent extraction will cause an error
+    const std::size_t err_after = j % (cbuf_size - 1);
+    const char *err_type;
+
+    if (j < cbuf_size - 1) {
+        // have the stream buffer object's underflow() fail (by throwing
+        // an exception if possible) after j characters have been extracted
+        // (this object calls underflow() for every char)
+        sb.throw_after_ = err_after;
+        err_type        = "threw";
+    }
+    else {
+        // have the stream buffer object's underflow() fail by returning
+        // eof after j characters have been extracted (this object calls
+        // underflow() for every char)
+        sb.fail_after_ = err_after;
+        err_type       = "returned EOF";
+    }
+
+    // construct an istream object and initialize it with the user
+    // defined streambuf object
+    Istream is (&sb);
+
+    // set the stream object's initial state
+    is.setstate (state);
+
+    // set or clear the skipws bit
+    if (skipws)
+        is.setf (std::ios_base::skipws);
+    else
+        is.unsetf (std::ios_base::skipws);
+
+    // construct a locale object containing the user-defined ctype object
+    const std::locale loc = is.imbue (std::locale (is.getloc (), &ctp));
+
+    // imbue the previous locale into the stream buffer to verify that
+    // the ws manipulator uses the locale imbued in the stream object
+    // and not the one in the stream buffer
+    sb.pubimbue (loc);
+
+    // the number of extracted whitespace characters expected to
+    // be reported by gcount() must equal the number of successful
+    // extractions computed by the the stream buffer overridden
+    // underflow member function
+    const int extract = is.good () && white == cbuf [0] ? int (err_after) : 0;
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+    bool caught = false;
+
+    // on every other iteration set badbit in exceptions to check
+    // that the thrown object is propagated by the function
+    if (err_after % 2 && !is.bad ())
+        is.exceptions (std::ios_base::badbit);
+
+    try {
+        std::ws (is);
+    }
+    catch (int) {
+        caught = true;
+    }
+    catch (...) {
+
+        caught = true;
+
+        rw_assert (false, 0, __LINE__,
+                   "%u. std::ws (basic_istream<%s, %s >&);"
+                   " threw exception of unexpected type",
+                   iter, cname, tname);
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // verify that the function propagates exceptions thrown from the
+    // streambuf object only when badbit is set in the stream object's
+    // exceptions()
+
+    rw_assert (!(caught && !(err_after % 2)), 0, __LINE__,
+               "%u. std::ws (basic_istream<%s, %s>&);"
+               " unexpectedly propagated exception",
+               iter, cname, tname);
+
+#else   // if defined (_RWSTD_NO_EXCEPTIONS)
+
+    std::ws (is);
+
+#endif   // _RWSTD_NO_EXCEPTIONS
+
+    //////////////////////////////////////////////////////////////////
+    // verify that the expected number of whitespace characters have
+    // been extracted from the stream
+
+    rw_assert (cbuf + extract == sb.pubgptr (), 0, __LINE__,
+               "%u. std::ws (basic_istream<%s, %s>&);"
+               " expected to extract %d "
+               "whitespace chars ('%c') from %{*Ac}, "
+               "extracted %u; initial rdstate() = %{Is}, "
+               "is.flags() & ios::skipws = %d, "
+               "underflow %s at extraction %u",
+               iter, cname, tname, extract, (char)(white),
+               int (sizeof *cbuf), cbuf,
+               sb.pubgptr () - sb.pubeback (), state,
+               skipws, err_type, err_after);
+
+    //////////////////////////////////////////////////////////////////
+    // verify that gcount() correctly reflects the number of whitespace
+    // characters extracted from the stream
+
+    rw_assert (extract == is.gcount (), 0, __LINE__,
+               "%u. std::ws (basic_istream<%s, %s >&)."
+               "gcount() == %d, got %d; whitespace is"
+               " '%c', input is %{*Ac}, initial rdstate() = %{Is}, "
+               "flags() & ios::skipws = %d,"
+               " underflow %s at extraction %u",
+               iter, cname, tname, extract, is.gcount (),
+               (char)(white), int (sizeof *cbuf), cbuf, state,
+               skipws, err_type, err_after);
+
+    //////////////////////////////////////////////////////////////////
+    // verify the state of the stream object after the function call
+
+    // expected stream state after the function call is unchanged
+    // (i.e., the initial stream state), // except...
+    std::ios_base::iostate expect_state = state;
+
+    if (!state && (white == cbuf [0] || !err_after)) {
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+        // ...when any whitespace characters are extracted, or the
+        // first character on the stream is peeked at, even if it's
+        // not a space, and an exception is thrown during input,
+        // badbit should be set, otherwise eofbit (bot not failbit)
+        // should be set
+        if (j < cbuf_size - 1)
+            expect_state = std::ios_base::badbit;
+        else
+            expect_state = std::ios_base::eofbit;
+
+#else   // if defined (_RWSTD_NO_EXCEPTIONS)
+
+        expect_state = std::ios_base::eofbit;
+
+#endif   // _RWSTD_NO_EXCEPTIONS
+    }
+
+    rw_assert (is.rdstate () == expect_state, 0, __LINE__,
+               "%u. std::ws (basic_istream<%s, %s >&)."
+               "rdstate() == %{Is}, got %{Is}; "
+               "extracting whitespace ('%c') from %{*Ac}, "
+               "extracted %u; initial is.rdstate() = %{Is}, "
+               "is.flags() & ios::skipws = %d, underflow %s "
+               "at extraction %u",
+               iter, cname, tname,
+               expect_state, is.rdstate(),
+               (char)(white), int (sizeof *cbuf), cbuf,
+               sb.pubgptr () - sb.pubeback (), state,
+               skipws, err_type, err_after);
+}
+
+/***********************************************************************/
+
+
+template <class charT, class Traits>
+void test_ws (charT*, Traits*, const char *cname, const char *tname)
+{
+    rw_info (0, 0, __LINE__, "std::basic_istream<%s, %s>& "
+             "std::ws (std::basic_istream<%1$s, %2$s>&)",
+             cname, tname);
+
+    const charT cbuf[] = { 'a', 'a', 'a', '\0' };
+    const std::size_t cbuf_size = sizeof cbuf / sizeof *cbuf;
+
+    const std::ios_base::iostate states[] = {
+        std::ios_base::badbit,
+        std::ios_base::eofbit,
+        std::ios_base::failbit,
+        std::ios_base::goodbit,
+        std::ios_base::badbit | std::ios_base::eofbit,
+        std::ios_base::badbit | std::ios_base::failbit,
+        std::ios_base::eofbit | std::ios_base::failbit,
+        std::ios_base::badbit | std::ios_base::eofbit | std::ios_base::failbit
+    };
+
+    const std::size_t nstates = sizeof states / sizeof *states;
+
+    {   //////////////////////////////////////////////////////////////
+        // exercise 27.6.1.4, p1
+
+        std::size_t iter = 0;     // iteration counter
+
+        // iterate over all possible settings of the stream state
+        for (std::size_t i = 0; i != nstates; ++i) {
+
+            // iterate twice over all characters in the character buffer,
+            // once to trigger an exception at each iteration (except
+            // the last one), and then again to have underflow() fail
+            // by returning EOF at each iteration (except the last one)
+            for (std::size_t j = 0; j != 2 * cbuf_size - 1; ++j) {
+
+                // iterate over the ios_base::skipws setting
+                for (std::size_t k = 0; k != 2; ++k /* skipws */) {
+
+                    // iterate over two whitespace characters
+                    for (charT wc = charT ('a'); wc != charT ('c'); ++wc) {
+
+                        test_ws ((Traits*)0, cname, tname, iter,
+                                 cbuf, cbuf_size, states [i], j, !!k, wc);
+
+                        ++iter;
+                    }
+                }
+            }
+        }
+    }
+}
+
+/***********************************************************************/
+
+static int opt_char;
+static int opt_wchar;
+static int opt_char_traits;
+static int opt_user_traits;
+
+
+static int
+run_test (int, char**)
+{
+#define TEST(charT, Traits) \
+    test_ws ((charT*)0, (Traits*)0, #charT, #Traits)
+
+    if (rw_note (0 <= opt_char && 0 <= opt_char_traits, 0, __LINE__,
+                 "ws (basic_istream<char, char_traits<char>>) disabled"))
+        TEST (char, std::char_traits<char>);
+
+    if (rw_note (0 <= opt_char && 0 <= opt_user_traits, 0, __LINE__,
+                 "ws (basic_istream<char, UserTraits<char>>) disabled"))
+        TEST (char, UserTraits<char>);
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+    if (rw_note (0 <= opt_wchar && 0 <= opt_char_traits, 0, __LINE__,
+                 "ws (basic_istream<wchar_t, char_traits<wchar_t>>) disabled"))
+        TEST (wchar_t, std::char_traits<wchar_t>);
+
+    if (rw_note (0 <= opt_wchar && 0 <= opt_user_traits, 0, __LINE__,
+                 "ws (basic_istream<wchar_t, UserTraits<wchar_t>>) disabled"))
+        TEST (wchar_t, UserTraits<wchar_t>);
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+    return 0;
+}
+
+/***********************************************************************/
+
+int main (int argc, char *argv[])
+{
+    return rw_test (argc, argv, __FILE__,
+                    "istream.manip",
+                    0 /* no comment */,
+                    run_test,
+                    "|-char~ "
+                    "|-wchar_t~ "
+                    "|-char_traits~ "
+                    "|-UserTraits~ ",
+                    &opt_char,
+                    &opt_wchar,
+                    &opt_char_traits,
+                    &opt_user_traits,
+                    (void*)0   /* sentinel */);
+}

Propchange: incubator/stdcxx/trunk/tests/iostream/27.istream.manip.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/stdcxx/trunk/tests/iostream/27.istream.manip.cpp
------------------------------------------------------------------------------
    svn:keywords = Id



Mime
View raw message