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 <[EMAIL PROTECTED]>
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