Return-Path: Delivered-To: apmail-incubator-stdcxx-commits-archive@www.apache.org Received: (qmail 18566 invoked from network); 25 Jan 2007 20:32:43 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 25 Jan 2007 20:32:43 -0000 Received: (qmail 69127 invoked by uid 500); 25 Jan 2007 20:32:50 -0000 Delivered-To: apmail-incubator-stdcxx-commits-archive@incubator.apache.org Received: (qmail 69072 invoked by uid 500); 25 Jan 2007 20:32:49 -0000 Mailing-List: contact stdcxx-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: stdcxx-dev@incubator.apache.org Delivered-To: mailing list stdcxx-commits@incubator.apache.org Received: (qmail 69061 invoked by uid 99); 25 Jan 2007 20:32:49 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 25 Jan 2007 12:32:49 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 25 Jan 2007 12:32:42 -0800 Received: by eris.apache.org (Postfix, from userid 65534) id 6AB031A981A; Thu, 25 Jan 2007 12:32:22 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r499952 - /incubator/stdcxx/trunk/tests/iostream/27.istream.manip.cpp Date: Thu, 25 Jan 2007 20:32:22 -0000 To: stdcxx-commits@incubator.apache.org From: sebor@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20070125203222.6AB031A981A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 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 +#include + +#include + +/************************************************************************ + + namespace std { + template + basic_istream& ws(basic_istream& 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 +struct Ctype: std::ctype +{ + typedef std::ctype 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 + /* 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 +_RWSTD_SPECIALIZED_CLASS +Ctype::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 +template +struct UserTraits: std::char_traits { }; + + +template +struct Streambuf: std::basic_streambuf +{ + typedef std::basic_streambuf 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 +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 Istream; + typedef typename Istream::sentry Sentry; + + // construct a ctype object that treats `wc' as the only + // whitespace character + const Ctype ctp (1, white); + + // construct a stream buffer object and initialize its read sequence + // with the character buffer + Streambuf 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 +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>) disabled")) + TEST (char, std::char_traits); + + if (rw_note (0 <= opt_char && 0 <= opt_user_traits, 0, __LINE__, + "ws (basic_istream>) disabled")) + TEST (char, UserTraits); + +#ifndef _RWSTD_NO_WCHAR_T + + if (rw_note (0 <= opt_wchar && 0 <= opt_char_traits, 0, __LINE__, + "ws (basic_istream>) disabled")) + TEST (wchar_t, std::char_traits); + + if (rw_note (0 <= opt_wchar && 0 <= opt_user_traits, 0, __LINE__, + "ws (basic_istream>) disabled")) + TEST (wchar_t, UserTraits); + +#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