stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r501688 - /incubator/stdcxx/trunk/tests/iostream/27.istream.sentry.cpp
Date Wed, 31 Jan 2007 01:42:55 GMT
Author: sebor
Date: Tue Jan 30 17:42:52 2007
New Revision: 501688

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

	STDCXX-4
	* 27.istream.sentry.cpp: New test exercising [istream.sentry].

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

Added: incubator/stdcxx/trunk/tests/iostream/27.istream.sentry.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/iostream/27.istream.sentry.cpp?view=auto&rev=501688
==============================================================================
--- incubator/stdcxx/trunk/tests/iostream/27.istream.sentry.cpp (added)
+++ incubator/stdcxx/trunk/tests/iostream/27.istream.sentry.cpp Tue Jan 30 17:42:52 2007
@@ -0,0 +1,483 @@
+/************************************************************************
+ *
+ * istream_sentry.cpp - test exercising basic_istream<charT>::sentry
+ *
+ * $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 <istream>
+#include <locale>      // for ctype
+#include <streambuf>   // for streambuf
+
+#include <driver.h>
+
+/************************************************************************
+
+    27.6.1.1.2   Class basic_istream::sentry   [lib.istream::sentry]
+
+    namespace std {
+        template <class charT, class traits = char_traits<charT> >
+        class basic_istream<charT, traits>::sentry {
+            typedef traits traits_type;
+            bool ok_;                            // exposition only
+        public:
+            explicit
+            sentry (basic_istream<charT, traits>& is, bool noskipws = false);
+            ~sentry ();
+            operator bool() const { return ok_; }
+        private:
+            sentry (const sentry&);              // not defined
+            sentry& operator= (const sentry&);   // not defined
+        };
+    }
+
+    -1- The class sentry defines a class that is responsible for doing
+        exception safe prefix and suffix operations.
+
+    explicit sentry(basic_istream<charT, traits>& is, bool noskipws = false);
+    -2- Effects: If is.good() is true, prepares for formatted or unformatted
+        input. First, if is.tie() is not a null pointer, the function calls
+        is.tie()­>flush() to synchronize the output sequence with any
+        associated external C stream. Except that this call can be suppressed
+        if the put area of is.tie() is empty. Further an implementation is
+        allowed to defer the call to flush until a call of
+        is->rdbuf()­>underflow occurs. If no such call occurs before the
+        sentry object is destroyed, the call to flush may be eliminated
+        entirely(279). If noskipws is zero and is.flags() & ios_base::skipws
+        is nonzero, the function extracts and discards each character as long
+        as the next available input character c is a whitespace character.
+    -3- Notes: The constructor explicit sentry(basic_istream<charT, traits>&
+        is, bool noskipws = false) uses the currently imbued locale in is,
+        to determine whether the next input character is whitespace or not.
+    -4- To decide if the character cis a whitespace character, the constructor
+        performs "as if" it executes the following code fragment:
+        const ctype<charT>& ctype = use_facet<ctype<charT> >(is.getloc());
+        if (ctype.is (ctype.space,c) != 0)
+            // c is a whitespace character.
+    -5- If, after any preparation is completed, is.good() is true,
+        ok_ != false otherwise, ok_ == false. During preparation, the
+        constructor may call setstate(failbit) (which may throw
+        ios_base::failure (27.4.4.3))(280)
+    __________________
+    279) This will be possible only in functions that are part of the
+         library. The semantics of the constructor used in user code is
+         as specified.
+    280) The sentry constructor and destructor can also perform additional
+         implementation-dependent operations.
+
+    -6- [Example: A typical implementation of the sentry constructor might
+        include code such as:
+
+        template <class charT, class traits = char_traits<charT> >
+        basic_istream<charT,traits>::sentry(
+            basic_istream<charT,traits>& is, bool noskipws = false) {
+            ...
+            int_type c;
+            typedef ctype<charT> ctype_type;
+            const ctype_type& ctype = use_facet<ctype_type>(is.getloc());
+            while ((c = is.rdbuf()­>snextc()) != traits::eof()) {
+                if (ctype.is(ctype.space,c)==0) {
+                    is.rdbuf()­>sputbackc (c);
+                    break;
+                }
+            }
+            ...
+        }
+        --end example]
+
+    ~sentry();
+    -7- Effects: None.
+
+    operator bool() const;
+    -8- Effects: Returns ok_.
+
+************************************************************************/
+
+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 (unsigned ref, charT white)
+        : Base (ref), ws_ (white) { }
+
+    // virtuals overridden below used by ctype<wchar_t>
+    // ctype<char> uses the table() member instead
+
+    /* 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);
+    }
+
+    /* virtual */ const charT*
+    do_is (const charT *from, const charT *to,
+           std::ctype_base::mask *m) const {
+        return Base::is (from, to, m);
+    }
+
+    /* virtual */ const charT*
+    do_scan_is (std::ctype_base::mask m,
+                 const charT *from, const charT *to) const {
+        for (; from != to && !do_is (m, *from); ++from);
+        return from;
+    }
+
+    /* virtual */ const charT*
+    do_scan_not (std::ctype_base::mask m,
+                 const charT *from, const charT *to) const {
+        for (; from != to && do_is (m, *from); ++from);
+        return from;
+    }
+};
+
+
+// specialized for ctype<char>
+_RWSTD_SPECIALIZED_CLASS
+Ctype<char>::Ctype (unsigned ref, char white)
+    : Base (table_, false, ref), ws_ (white)
+{
+    for (unsigned 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;
+}
+
+
+template <class charT>
+struct Streambuf: std::basic_streambuf<charT, std::char_traits<charT> >
+{
+    typedef std::basic_streambuf<charT, std::char_traits<charT> > Base;
+
+    int nsyncs_;
+
+    Streambuf (const charT *gbeg, const charT *gend)
+        : Base (), nsyncs_ (0) {
+        this->setg (_RWSTD_CONST_CAST (charT*, gbeg),
+                    _RWSTD_CONST_CAST (charT*, gbeg),
+                    _RWSTD_CONST_CAST (charT*, gend));
+    }
+
+    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 ();
+    }
+};
+
+
+template <class charT>
+void test_ctor (const charT*, const char *tname)
+{
+    typedef std::char_traits<charT>             Traits;
+    typedef std::basic_istream<charT, Traits>   Istream;
+    typedef typename Istream::sentry            Sentry;
+
+    rw_info (0, 0, __LINE__, "std::basic_istream<%s>::sentry"
+             "::sentry (basic_istream&, bool)", tname);
+
+    const charT cbuf[] = { 'a', 'b', 'c', 'd', 'e', ' ', 'f', '\0' };
+
+    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
+    };
+
+    {   //////////////////////////////////////////////////////////////
+        // exercise 27.6.1.1.2, p1:
+        //     -  is.good() is true
+        //     -  is.tie() is not null
+        //     =  the function calls is.tie().flush()
+
+        rw_info (0, 0, __LINE__,
+                 "std::basic_istream<%s>::sentry() calls is.tie()->flush()",
+                 tname);
+
+        unsigned iter = 0;     // iteration counter
+
+        for (unsigned i = 0; i != sizeof states / sizeof *states; ++i) {
+            for (unsigned j = 0; j != 2; ++j /* noskipws */) {
+                Streambuf<charT>
+                    sb (cbuf, cbuf + sizeof cbuf / sizeof *cbuf);
+
+                Istream is (&sb);
+
+                // flush() is called iff
+                // all of the following conditions hold
+                const bool flush_called = is.good () && 0 != is.tie ();
+
+                const Sentry guard (is, 0 != j);
+
+                _RWSTD_UNUSED (guard);
+
+                rw_assert (flush_called == sb.nsyncs_, 0, __LINE__,
+                           "%u. basic_istream<%s>::sentry::sentry"
+                           "(basic_istream &is, bool noskipws = %d); "
+                           "expected to call is.flush () %d times, got %d"
+                           "initial is.state () = %{Is}, is.flags() & "
+                           "ios::skipws = %d",
+                           iter, tname, 0 != j, flush_called, sb.nsyncs_,
+                           states [i], is.flags () & std::ios_base::skipws);
+
+                ++iter;
+            }
+        }
+    }
+
+    {   //////////////////////////////////////////////////////////////
+        // exercise 27.6.1.1.2, p1:
+        //     -  is.good() is true
+        //     -  noskipws is zero
+        //     -  is.flags() & ios_base::skipws
+        //     =  the function extracts and discards each character as long
+        //        as the next available input character c is a whitespace
+        //        character.
+
+        rw_info (0, 0, __LINE__,
+                 "std::basic_istream<%s>::sentry() extracts whitespace",
+                 tname);
+
+        unsigned iter = 0;     // iteration counter
+
+        for (unsigned i = 0; i != sizeof states / sizeof *states; ++i) {
+            for (unsigned j = 0; j != 2; ++j /* noskipws */) {
+                for (unsigned k = 0; k != 2; ++k /* ios_base::skipws */) {
+                    for (charT wc = charT ('a'); wc != charT ('c'); ++wc) {
+
+                        const Ctype<charT> ctp (1, wc);
+
+                        Streambuf<charT>
+                            sb (cbuf, cbuf + sizeof cbuf / sizeof *cbuf);
+
+                        Istream is (&sb);
+
+                        is.setstate (states [i]);
+
+                        if (k)
+                            is.setf (std::ios_base::skipws);
+                        else
+                            is.unsetf (std::ios_base::skipws);
+
+                        const std::locale loc = 
+                            is.imbue (std::locale (is.getloc (), &ctp));
+
+                        // imbue the previous locale into the stream
+                        // buffer to verify that the sentry ctor uses
+                        // the locale imbued in the stream object and
+                        // not the one in the stream buffer
+                        sb.pubimbue (loc);
+
+                        // a whitespace character is extracted iff
+                        // all of the following conditions hold
+                        const bool extract =
+                               is.good ()
+                            && 0 == j
+                            && is.flags () & std::ios_base::skipws
+                            && cbuf [0] == wc;
+
+                        const Sentry guard (is, 0 != j);
+
+                        _RWSTD_UNUSED (guard);
+
+                        rw_assert (cbuf + extract == sb.pubgptr (),
+                                   0, __LINE__, 
+                                   "%u. basic_istream<%s>::sentry::sentry"
+                                   "(basic_istream &is, bool noskipws "
+                                   "= %d); expected to extract %d "
+                                   "whitespace chars ('%c') from %{*Ac}, "
+                                   "extracted %u; initial is.state () = "
+                                   "%{Is}, is.flags() & ios::skipws = %d",
+                                   iter, tname, j, extract + 0, char (wc),
+                                   int (sizeof (*cbuf)), cbuf,
+                                   sb.pubgptr () - sb.pubeback (),
+                                   states [i], k);
+
+                        ++iter;
+                    }
+                }
+            }
+        }
+    }
+}
+
+/***********************************************************************/
+
+
+template <class charT>
+void test_ok (const charT*, const char *tname)
+{
+    typedef std::char_traits<charT>             Traits;
+    typedef std::basic_istream<charT, Traits>   Istream;
+    typedef typename Istream::sentry            Sentry;
+
+    rw_info (0, 0, __LINE__,
+             "std::basic_istream<%s>::sentry::"
+             "operator bool () const", tname);
+
+    const charT cbuf[] = { 'a', 'b', 'c', 'd', 'e', ' ', 'f', '\0' };
+
+    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
+    };
+
+    {   //////////////////////////////////////////////////////////////
+        // exercise 27.6.1.1.2, p5:
+        //     -  is.good() is true
+        //     -  noskipws is zero
+        //     -  is.flags() & ios_base::skipws
+        //     -  the function extracts and discards each character as long
+        //        as the next available input character c is a whitespace
+        //        character
+        //     =  if, after any preparation is completed, is.good() is true,
+        //        ok_ != false otherwise, ok_ == false.
+
+        unsigned iter = 0;     // iteration counter
+
+        for (unsigned i = 0; i != sizeof states / sizeof *states; ++i) {
+            for (unsigned j = 0; j != 2; ++j /* noskipws */) {
+                for (unsigned k = 0; k != 2; ++k /* ios_base::skipws */) {
+                    for (charT wc = charT ('a'); wc != charT ('c'); ++wc) {
+
+                        const Ctype<charT> ctp (1, wc);
+
+                        Streambuf<charT>
+                            sb (cbuf, cbuf + sizeof cbuf / sizeof *cbuf);
+
+                        Istream is (&sb);
+
+                        is.setstate (states [i]);
+
+                        if (k)
+                            is.setf (std::ios_base::skipws);
+                        else
+                            is.unsetf (std::ios_base::skipws);
+
+                        const std::locale loc = 
+                            is.imbue (std::locale (is.getloc (), &ctp));
+
+                        // imbue the previous locale into the stream
+                        // buffer to verify that the sentry ctor uses
+                        // the locale imbued in the stream object and
+                        // not the one in the stream buffer
+                        sb.pubimbue (loc);
+
+                        const Sentry guard (is, 0 != j);
+
+                        _RWSTD_UNUSED (guard);
+
+                        const bool success =
+                               is.good () && guard
+                            || !is.good () && !guard;
+
+                        rw_assert (success, 0, __LINE__,
+                                   "%u. basic_istream<%s>::sentry"
+                                   "(basic_istream &is, bool noskipws "
+                                   "= %d).operator bool() == %d; initial "
+                                   "is.state() = %{Is}, is.flags() & "
+                                   "ios::skipws = %d",
+                                   iter, tname, j, is.good (),
+                                   states [i], k);
+
+                        ++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**)
+{
+    test_ctor ((char*)0, "char");
+    test_ok ((char*)0, "char");
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+    test_ctor ((wchar_t*)0, "wchar_t");
+    test_ok ((wchar_t*)0, "wchar_t");
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+    return 0;
+
+}
+
+/***********************************************************************/
+
+int main (int argc, char *argv[])
+{
+    return rw_test (argc, argv, __FILE__,
+                    "istream.sentry",
+                    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.sentry.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

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



Mime
View raw message