stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r502088 - /incubator/stdcxx/trunk/tests/iostream/27.istream.fmar.arith.cpp
Date Thu, 01 Feb 2007 02:44:00 GMT
Author: sebor
Date: Wed Jan 31 18:43:59 2007
New Revision: 502088

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

	* 27.istream.fmat.arith.cpp: New test exercising arithmetic extractor
	operators [istream.formatted.arithmetic]. The test reveals a number
	of known bugs.

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

Added: incubator/stdcxx/trunk/tests/iostream/27.istream.fmar.arith.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/iostream/27.istream.fmar.arith.cpp?view=auto&rev=502088
==============================================================================
--- incubator/stdcxx/trunk/tests/iostream/27.istream.fmar.arith.cpp (added)
+++ incubator/stdcxx/trunk/tests/iostream/27.istream.fmar.arith.cpp Wed Jan 31 18:43:59 2007
@@ -0,0 +1,1374 @@
+/************************************************************************
+ *
+ * 27.istream.fmat.arith.cpp - test exercising basic_istream
+ *                             arithmetic extractors
+ *
+ * $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.
+ *
+ **************************************************************************/
+
+#include <cstddef>
+#include <istream>
+
+#include <rw_char.h>
+#include <rw_ctype.h>
+#include <rw_exception.h>
+#include <rw_printf.h>
+#include <rw_streambuf.h>
+#include <driver.h>
+
+/***********************************************************************/
+
+struct LocaleData {
+    const char *whitespace;
+    int         decimal_point;
+    int         thousands_sep;
+    const char *grouping;
+    const char *truename;
+    const char *falsename;
+};
+
+
+template <class CharT>
+const std::locale
+make_locale (const CharT*, const LocaleData &data)
+{
+    // determine the number of classic characters (expecting 256)
+    static const std::size_t N = std::ctype<char>::table_size;
+
+    // derive a class so we can call the protected classic_table()
+    struct ClassicTable: std::ctype<char> {
+        static const std::ctype_base::mask* get () {
+            return classic_table ();
+        }
+    };
+
+    // get the classic C table of masks
+    const std::ctype_base::mask* const classic = ClassicTable::get ();
+
+    static int chars [N + 1];
+    static int masks [N + 1];
+
+    // -1 denotes end of characters (can't use 0 since it's a valid value)
+    chars [N] = -1;
+
+    // copy the classic table clearing the space bit of each mask
+    for (std::size_t i = 0; i != N; ++i) {
+        chars [i] = int (i);
+        masks [i] = classic [i] & ~std::ctype_base::space;
+    }
+
+    typedef unsigned char UChar;
+
+    // set the space bit for all characters in whitespace
+    for (const char *ws = data.whitespace; *ws; ++ws)
+        masks [UChar (*ws)] |= std::ctype_base::space;
+
+    // create a user-defined ctype-derived facet and initialize
+    // it with the character set and the specified masks
+    const std::ctype<CharT>* const ctp =
+        new UserCtype<CharT>(chars, masks);
+
+    struct NumPunct: std::numpunct<CharT> {
+
+        typedef std::numpunct<CharT> Base;
+
+        int          dp_;
+        int          ts_;
+        const char  *grp_;
+        const CharT *fn_;
+        const CharT *tn_;
+
+        NumPunct (int dp, int ts, const char *grp,
+                  const CharT *fn, const CharT *tn)
+            : Base (), dp_ (dp), ts_ (ts), grp_ (grp ? grp : ""),
+              fn_ (fn), tn_ (tn) { /* empty */ }
+
+        CharT do_decimal_point () const {
+            return -1 == dp_ ? Base::do_decimal_point ()
+                              : make_char (char (dp_), (CharT*)0);
+        }
+
+        CharT do_thousands_sep () const {
+            return -1 == ts_ ? Base::do_thousands_sep ()
+                             : make_char (char (ts_), (CharT*)0);
+        }
+
+        std::string do_grouping () const {
+            return 0 == grp_ ? Base::do_grouping ()
+                             : std::string (grp_);
+        }
+
+        std::basic_string<CharT> do_truename () const {
+            return 0 == tn_ ? Base::do_truename ()
+                            : std::basic_string<CharT>(tn_);
+        }
+
+        std::basic_string<CharT> do_falsename () const {
+            return 0 == fn_ ? Base::do_falsename ()
+                            : std::basic_string<CharT>(fn_);
+        }
+    };
+
+    static CharT names [2][64];
+
+    names [false][0] = CharT ();
+    names [true][0]  = CharT ();
+
+    if (data.falsename) {
+        for (std::size_t i = 0; data.falsename [i]; ++i) {
+            names [false][i]     = data.falsename [i];
+            names [false][i + 1] = CharT ();
+        }
+    }
+
+    if (data.truename) {
+        for (std::size_t i = 0; data.truename [i]; ++i) {
+            names [true][i]     = data.truename [i];
+            names [true][i + 1] = CharT ();
+        }
+    }
+
+    // create a user-defined numpunct-derived facet and initialize
+    // its members with the specified parameters
+    const std::numpunct<CharT>* const np =
+        new NumPunct (data.decimal_point,
+                      data.thousands_sep,
+                      data.grouping,
+                      data.falsename ? names [false] : 0,
+                      data.truename ? names [true] : 0);
+
+    // install the new nupunct facet in a temporary locale,
+    // replacing the original (if CharT=char or CharT=wchar_t)
+    const std::locale tmp (std::locale::classic (), np);
+
+    // install the new ctype facet in a locale, replacing
+    // the original (if CharT=char or CharT=wchar_t)
+    return std::locale (tmp, ctp);
+}
+
+/***********************************************************************/
+
+template <class CharT, class Traits>
+const std::locale
+make_locale (const CharT*, const Traits*,  const LocaleData &data)
+{
+    // construct a locale with the appropriate ctype and numpunct
+    // facets installed
+    const std::locale tmp (make_locale ((CharT*)0, data));
+
+    typedef std::istreambuf_iterator<CharT, Traits> Iterator;
+    typedef std::num_get<CharT, Iterator>           NumGet;
+
+    // check to see if num_get for this charater type and traits
+    // is installed and install it if it isn't (i.e., when Traits
+    // is other than std::char_traits<CharT>)
+    if (std::has_facet<NumGet>(tmp))
+        return tmp;
+
+    return std::locale (tmp, new NumGet);
+}
+
+/***********************************************************************/
+
+/* extern */ int opt_no_gcount;
+
+
+template <class CharT, class Traits, class ArithmeticType>
+void
+test_extractor (CharT*, Traits*, ArithmeticType*,
+                const char     *cname,
+                const char     *tname,
+                const char     *aname,
+                int             line,
+                // printf formatting directive for ArithmeticType
+                const char *valfmt,
+                // character buffer (input sequence)
+                const char *cbuf,
+                // number of characters in buffer:
+                std::size_t cbuf_size,
+                // ctype and numpunct data
+                const LocaleData &locale_data,
+                // stream flags():
+                int flags,
+                // initial stream rdstate():
+                int init_state,
+                // unmasked exceptions:
+                int exceptions,
+                // expected exception:
+                int expect_exception,
+                // expected stream state after extraction:
+                int expect_state,
+                // expected number of extracted characters:
+                int expect_extract,
+                // have streambuf fail (or throw) after so many calls
+                // to underflow() (each call extracts a single chracter):
+                int fail_when,
+                // initial value of the argument to extractor:
+                ArithmeticType init_value,
+                // expected value of the argument after extraction:
+                ArithmeticType expect_value)
+{
+    _RWSTD_UNUSED (cname);
+    _RWSTD_UNUSED (tname);
+
+    typedef std::basic_istream<CharT, Traits> Istream;
+    typedef MyStreambuf<CharT, Traits>        Streambuf;
+
+    const char *fail_desc = 0;
+
+    int fail_how = 0;
+
+    if (fail_when < 0) {
+        // have the stream buffer object's underflow() fail (by throwing
+        // an exception if possible) after `fail_when' characters have
+        // been extracted (this object calls underflow() for every char)
+        fail_how  = Underflow | Throw;
+        fail_when = -fail_when;
+        fail_desc = "threw";
+    }
+    else if (0 < fail_when) {
+        // have the stream buffer object's underflow() fail by returning
+        // eof after `fail_when' characters have been extracted (this
+        // object calls underflow() for every char)
+        fail_how  = Underflow;
+        fail_desc = "returned EOF";
+    }
+
+    // construct a stream buffer object and initialize its read sequence
+    // with the character buffer
+    Streambuf sb (cbuf, cbuf_size, fail_how, fail_when);
+
+    // construct an istream object and initialize it with the user
+    // defined streambuf object
+    Istream is (&sb);
+
+    if (-1 == flags) {
+        // get the initial stream object's format control flags
+        flags = is.flags ();
+    }
+    else {
+        // set the stream object's format control flags
+        is.flags (std::ios::fmtflags (flags));
+    }
+
+    if (-1 == exceptions) {
+        // get the initial stream object's exceptions
+        exceptions = is.exceptions ();
+    }
+    else {
+        // unmask the stream objects exceptions (must be done
+        // before calling setstate() to prevent the latter from
+        // throwing ios::failure)
+        is.exceptions (std::ios::iostate (exceptions));
+    }
+
+    if (-1 == init_state) {
+        // get the initial stream object's state
+        init_state = is.rdstate ();
+    }
+    else {
+        // set the stream object's initial state
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+        try {
+            is.setstate (std::ios::iostate (init_state));
+        }
+        catch (...) {
+            // ignore exceptions
+        }
+#else   // if defined ( _RWSTD_NO_EXCEPTIONS)
+        is.setstate (std::ios::iostate (init_state));
+#endif   //  _RWSTD_NO_EXCEPTIONS
+    }
+
+    // construct a locale object that treats only the specified `white'
+    // characters as whitespace (all others are treated normally)
+    const std::locale loc =
+        is.imbue (make_locale ((CharT*)0, (Traits*)0, locale_data));
+
+    // 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);
+
+    // initialize the variable to the initial value to detect
+    // the extractor setting it when it's not supposed to
+    ArithmeticType value = init_value;
+
+    // format the FUNCALL environment variable w/o writing out any output
+    rw_fprintf (0,
+                "%{$FUNCALL!:@}",
+                "%{$CLASS}(%{*Ac}).operator>>(%s& = %{@}): "
+                "initial flags() = %{If}, rdstate() = %{Is}, "
+                "exceptions() = %{Is}, whitespace = %{#s}, numpunct = { "
+                ".dp=%{#c}, .ts=%{#c}, .grp=%{#s}, .fn=%{#s}, .tn=%{#s} }",
+                int (sizeof *cbuf), cbuf, aname, valfmt, init_value,
+                flags, init_state,
+                exceptions, locale_data.whitespace,
+                locale_data.decimal_point, locale_data.thousands_sep,
+                locale_data.grouping, locale_data.falsename,
+                locale_data.truename);
+
+#ifndef _RWSTD_NO_EXCEPTIONS
+
+    int caught = 0;
+
+    try {
+        is >> value;
+    }
+    catch (Exception&) {
+        caught = 1;
+    }
+    catch (std::ios_base::failure &ex) {
+        caught = 2;
+        rw_assert (caught == expect_exception, 0, line,
+                   "line %d. %{$FUNCALL}: unexpectedly threw "
+                   "ios_base::failure(%{#s})", __LINE__, ex.what ());
+    }
+    catch (...) {
+        caught = -1;
+        rw_assert (false, 0, line,
+                   "line %d. %{$FUNCALL}: unexpectely threw an exception "
+                   "of unknown type", __LINE__);
+    }
+
+    //////////////////////////////////////////////////////////////////
+    // 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 == expect_exception, 0, line,
+               "line %d. %{$FUNCALL}: "
+               "%{?}failed to throw"
+               "%{:}unexpectedly propagated"
+               "%{;} exception",
+               __LINE__, expect_exception);
+
+#else   // if defined (_RWSTD_NO_EXCEPTIONS)
+
+    is >> value;
+
+#endif   // _RWSTD_NO_EXCEPTIONS
+
+    // clear the text describing the type of failure when streambuf
+    // didn't actually fail (or throw)
+    if (sb.failed_ == None && sb.threw_ == None)
+        fail_desc = 0;
+
+    //////////////////////////////////////////////////////////////////
+    // verify that the expected number of characters have been
+    // extracted from the stream
+
+    const int extracted = int (sb.pubgptr () - sb.pubeback ());
+
+    rw_assert (expect_extract == extracted, 0, line,
+               "%d. %{$FUNCALL}: expected to extract %d characters, "
+               "got %d%{?} (underflow() %s at extraction %u)%{;}",
+               __LINE__, expect_extract,
+               extracted, 0 != fail_desc, fail_desc, fail_when);
+
+    //////////////////////////////////////////////////////////////////
+    // verify that gcount() is not affected
+
+    if (0 == opt_no_gcount)
+        rw_assert (0 == is.gcount (), 0, line,
+                   "%d. %{$FUNCALL}: gcount() == 0, got %d "
+                   "%{?} (underflow() %s at extraction %u)%{;}",
+                   __LINE__, is.gcount (),
+                   0 != fail_desc, fail_desc, fail_when);
+
+    //////////////////////////////////////////////////////////////////
+    // verify the state of the stream object after the function call
+
+    rw_assert (is.rdstate () == expect_state, 0, line,
+               "line %d. %{$FUNCALL}: rdstate() == %{Is}, got %{Is}"
+               "%{?} (underflow() %s at extraction %u)%{;}",
+               __LINE__, expect_state, is.rdstate(),
+               0 != fail_desc, fail_desc, fail_when);
+
+    //////////////////////////////////////////////////////////////////
+    // verify the extracted value matches the expected value
+
+    rw_assert (expect_value == value, 0, line,
+               "line %d. %{$FUNCALL}: expected value %{@}, got %{@}",
+               __LINE__, valfmt, expect_value, valfmt, value);
+}
+
+/***********************************************************************/
+
+// state abbreviations for brevity
+const int ___ =                0;
+const int __f =                0 |                0 | std::ios::failbit;
+const int _e_ =                0 | std::ios::eofbit |                 0;
+const int _ef =                0 | std::ios::eofbit | std::ios::failbit;
+const int b__ = std::ios::badbit |                0 |                 0;
+const int b_f = std::ios::badbit |                0 | std::ios::failbit;
+const int be_ = std::ios::badbit | std::ios::eofbit |                 0;
+const int bef = std::ios::badbit | std::ios::eofbit | std::ios::failbit;
+
+const int DEC = std::ios::dec;
+const int OCT = std::ios::oct;
+const int HEX = std::ios::hex;
+
+
+template <class CharT, class Traits, class ArithmeticType>
+void
+test_extractor (CharT*, Traits*, ArithmeticType*,
+                const char *cname,
+                const char *tname,
+                const char *aname,
+                const char *fmt)
+{
+    typedef ArithmeticType T;
+
+    LocaleData locale_data = {
+        0, -1, -1, 0, 0, 0
+    };
+
+    static const volatile T zero = T ();
+    static const volatile T negative_one = T (-1);
+
+    const bool is_signed   = negative_one < zero;
+    const bool is_floating = zero > negative_one / 2;
+
+    // avoid test cases designed to exercise the extraction of negative
+    // values when ArithmeticType is an unsigned type
+#undef TEST
+#define TEST(str, fl, is, ex, ee, es, ne, fw, iv, ev)                        \
+    if (is_signed || 0 <= ev)                                                \
+        test_extractor ((CharT*)0, (Traits*)0, (T*)0, cname, tname, aname,   \
+                        __LINE__, fmt, str, sizeof str - 1, locale_data,     \
+                        fl, is, ex, ee, es, ne, fw, (T)(iv), (T)ev)
+
+    locale_data.whitespace = "";
+
+    //    +-- subject sequence
+    //    |     +-- initial flags (-1 for default)
+    //    |     |    +-- initial state (-1 for default)
+    //    |     |    |   +-- exceptions (-1 for default)
+    //    |     |    |   |  +-- expected exception
+    //    |     |    |   |  |   +-- expected rdstate()
+    //    |     |    |   |  |   |   +-- extracted characters
+    //    |     |    |   |  |   |   |   +-- fail when? (0 to not)
+    //    |     |    |   |  |   |   |   |  +-- initial value
+    //    |     |    |   |  |   |   |   |  |  +-- expected value
+    //    |     |    |   |  |   |   |   |  |  |
+    //    V     V    V   V  V   V   V   V  V  V
+    TEST ("",  -1,  -1, -1, 0, _ef, 0,  0, 1, 1);
+    TEST (" ", -1,  -1, -1, 0, __f, 0,  0, 2, 2);
+    TEST (" ", -1,  -1, -1, 0, _ef, 0,  1, 3, 3);   // fail
+    TEST (" ", -1,  -1, -1, 0, b__, 0, -1, 4, 4);   // throw
+
+    // exercise behavior when the initial state is other than good
+    TEST (" ",   -1, __f, -1, 0, __f, 0, -1,  5,  5);
+    TEST (" ",   -1, _e_, -1, 0, _ef, 0, -1,  6,  6);
+    TEST (" ",   -1, _ef, -1, 0, _ef, 0, -1,  7,  7);
+    TEST (" ",   -1, b__, -1, 0, b_f, 0, -1,  8,  8);
+    TEST (" ",   -1, b_f, -1, 0, b_f, 0, -1,  9,  9);
+    TEST (" ",   -1, be_, -1, 0, bef, 0, -1, 10, 10);
+    TEST (" ",   -1, bef, -1, 0, bef, 0, -1, 11, 11);
+
+    // verify that when the initial state isn't good the extractors
+    // do not attempt to obtain the requested input but call setstate()
+    // to set failbit (which causes failure to be thrown when failbit
+    // or any other bit is set in exceptions) (see LWG issue 419)
+    TEST (" ",   -1, __f, __f, 2, __f, 0, -1, 9, 9);
+    TEST (" ",   -1, _e_, __f, 2, _ef, 0, -1, 9, 9);
+    TEST (" ",   -1, _e_, _e_, 2, _ef, 0, -1, 9, 9);
+    TEST (" ",   -1, _ef, _e_, 2, _ef, 0, -1, 9, 9);
+    TEST (" ",   -1, b__, __f, 2, b_f, 0, -1, 9, 9);
+    TEST (" ",   -1, b_f, __f, 2, b_f, 0, -1, 9, 9);
+    TEST (" ",   -1, b_f, b__, 2, b_f, 0, -1, 9, 9);
+
+    locale_data.whitespace = " ";
+    TEST (" ",   -1,  -1, -1, 0, _ef, 1,  0, 9, 9);
+    TEST (" ",   -1,  -1, -1, 0, _ef, 0,  1, 9, 9);   // fail
+    TEST (" ",   -1,  -1, -1, 0, b__, 0, -1, 9, 9);   // throw
+    TEST (" ",   -1,  -1, -1, 0, _ef, 1,  2, 9, 9);   // fail
+    TEST (" ",   -1,  -1, -1, 0, b__, 1, -2, 9, 9);   // throw
+    TEST ("_",   -1,  -1, -1, 0, __f, 0,  0, 9, 9);
+
+    TEST (" ",    0,  -1, -1, 0, __f, 0,  0, 9, 9);
+
+    locale_data.whitespace = "_";
+    TEST (" ",   -1, -1, -1, 0, __f, 0, 0, 9, 9);
+    TEST ("_",   -1, -1, -1, 0, _ef, 1, 0, 9, 9);
+
+    locale_data.whitespace = "";
+    TEST ("0",   -1, -1, -1, 0, _e_, 1, 0, 9,  0);
+    TEST ("1",   -1, -1, -1, 0, _e_, 1, 0, 9,  1);
+    TEST ("+0",  -1, -1, -1, 0, _e_, 2, 0, 9,  0);
+    TEST ("-0",  -1, -1, -1, 0, _e_, 2, 0, 9,  0);
+    TEST ("+1",  -1, -1, -1, 0, _e_, 2, 0, 9,  1);
+    TEST ("-1",  -1, -1, -1, 0, _e_, 2, 0, 1, -1);
+    TEST ("+2 ", -1, -1, -1, 0, ___, 2, 0, 9,  2);
+    TEST ("-2 ", -1, -1, -1, 0, ___, 2, 0, 9, -2);
+
+    if (is_floating) {
+        TEST ("3.",  -1, -1, -1, 0, _e_, 2, 0, 9,  3);
+        TEST ("+3.", -1, -1, -1, 0, _e_, 3, 0, 9,  3);
+        TEST ("-3.", -1, -1, -1, 0, _e_, 3, 0, 9, -3);
+    }
+    else { 
+        TEST ("3.",  -1, -1, -1, 0, ___, 1, 0, 9,  3);
+        TEST ("+3.", -1, -1, -1, 0, ___, 2, 0, 9,  3);
+        TEST ("-3.", -1, -1, -1, 0, ___, 2, 0, 9, -3);
+   }
+
+    // set '#' as the only whitespace character
+    locale_data.whitespace = "#";
+    TEST ("#+3",  -1, -1, -1, 0, _e_, 3, 0,  9,  3);
+    TEST ("#-4",  -1, -1, -1, 0, _e_, 3, 0,  9, -4);
+    TEST ("#+5",  -1, -1, -1, 0, _e_, 3, 0,  9,  5);
+    TEST ("#-6",  -1, -1, -1, 0, _e_, 3, 0,  9, -6);
+    TEST ("#+7#", -1, -1, -1, 0, ___, 3, 0,  9,  7);
+    TEST ("#-8#", -1, -1, -1, 0, ___, 3, 0,  9, -8);
+    TEST (" -9",  -1, -1, -1, 0, __f, 0, 0, -9, -9);
+
+    // set 'X', 'Y', and 'Z' as the only whitespace characters
+    locale_data.whitespace = "XYZ";
+    TEST ("X10",   -1, -1, -1, 0, _e_, 3, 0, 9, 10);
+    TEST ("XY11",  -1, -1, -1, 0, _e_, 4, 0, 9, 11);
+    TEST ("XYZ12", -1, -1, -1, 0, _e_, 5, 0, 9, 12);
+
+    // set '9' as the whitespace character
+    locale_data.whitespace = "9";
+    TEST ("9",    -1, -1, -1, 0, _ef, 1, 0, 8, 8);
+    TEST ("99",   -1, -1, -1, 0, _ef, 2, 0, 8, 8);
+    TEST ("999",  -1, -1, -1, 0, _ef, 3, 0, 8, 8);
+    TEST ("9991", -1, -1, -1, 0, _e_, 4, 0, 8, 1);
+
+    // exercise grouping
+    locale_data.whitespace    = "_";
+    locale_data.thousands_sep = ';';
+    locale_data.grouping      = "\1";
+
+    TEST ("0;0",       -1, -1, -1, 0, _e_, 3, 0, 9,  0);
+    TEST ("+0;0",      -1, -1, -1, 0, _e_, 4, 0, 9,  0);
+    TEST ("-0;0",      -1, -1, -1, 0, _e_, 4, 0, 9,  0);
+    TEST ("+0;1",      -1, -1, -1, 0, _e_, 4, 0, 9,  1);
+    TEST ("-0;1",      -1, -1, -1, 0, _e_, 4, 0, 9, -1);
+    TEST ("0;1",       -1, -1, -1, 0, _e_, 3, 0, 9,  1);
+    TEST ("1;0",       -1, -1, -1, 0, _e_, 3, 0, 9,  10);
+    TEST ("1;2",       -1, -1, -1, 0, _e_, 3, 0, 9,  12);
+    TEST ("_1;2",      -1, -1, -1, 0, _e_, 4, 0, 9,  12);
+    TEST ("_1;2_",     -1, -1, -1, 0, ___, 4, 0, 9,  12);
+    TEST ("_1_;2",     -1, -1, -1, 0, ___, 2, 0, 9,  1);
+    TEST ("12345",     -1, -1, -1, 0, _e_, 5, 0, 9,  12345);
+    TEST ("1;2;3;4;5", -1, -1, -1, 0, _e_, 9, 0, 9,  12345);
+    TEST ("12;3;4;5",  -1, -1, -1, 0, _ef, 8, 0, 9,  12345);
+
+    // exercise thousands_sep that's a space
+    locale_data.whitespace    = " ";
+    locale_data.thousands_sep = ' ';
+    locale_data.grouping      = "\2";
+    TEST (" 0",        -1, -1, -1, 0, _e_, 2, 0, 9,  0);
+    TEST ("  0",       -1, -1, -1, 0, _e_, 3, 0, 9,  0);
+    TEST ("   0",      -1, -1, -1, 0, _e_, 4, 0, 9,  0);
+    TEST (" 0 00",     -1, -1, -1, 0, _e_, 5, 0, 9,  0);
+    TEST ("+0 00",     -1, -1, -1, 0, _e_, 5, 0, 9,  0);
+    TEST ("-0 00",     -1, -1, -1, 0, _e_, 5, 0, 9,  0);
+    TEST (" +0 00",    -1, -1, -1, 0, _e_, 6, 0, 9,  0);
+    TEST (" -0 00",    -1, -1, -1, 0, _e_, 6, 0, 9,  0);
+    TEST ("  +0 00",   -1, -1, -1, 0, _e_, 7, 0, 9,  0);
+    TEST ("  -0 00",   -1, -1, -1, 0, _e_, 7, 0, 9,  0);
+    TEST (" +00 00",   -1, -1, -1, 0, _e_, 7, 0, 9,  0);
+    TEST (" -00 00",   -1, -1, -1, 0, _e_, 7, 0, 9,  0);
+    TEST ("  00 01",   -1, -1, -1, 0, _e_, 7, 0, 9,  1);
+    TEST (" +00 01",   -1, -1, -1, 0, _e_, 7, 0, 9,  1);
+    TEST (" -00 01",   -1, -1, -1, 0, _e_, 7, 0, 1, -1);
+    TEST ("0 01 02",   -1, -1, -1, 0, _e_, 7, 0, 9,  102);
+    TEST ("1 02 03",   -1, -1, -1, 0, _e_, 7, 0, 9,  10203);
+    TEST ("2 03 04",   -1, -1, -1, 0, _e_, 7, 0, 9,  20304);
+    TEST ("304 05",    -1, -1, -1, 0, _ef, 6, 0, 9,  30405);
+    TEST ("4 0 5 0",   -1, -1, -1, 0, _ef, 7, 0, 9,  4050);
+
+    // according to the grammar in locale.numpunct, a valid number
+    // cannot start or end with a thousands separator (and all pairs
+    // of thousands separator must be separated by at least one
+    // digit)
+    locale_data.whitespace    = "_";
+    locale_data.thousands_sep = ';';
+    locale_data.grouping      = "\1";
+    TEST (";",         -1, -1, -1, 0, __f, 0, 0, 9, 9);
+    TEST (";;",        -1, -1, -1, 0, __f, 0, 0, 9, 9);
+    TEST ("_;",        -1, -1, -1, 0, __f, 1, 0, 9, 9);
+    TEST ("+;",        -1, -1, -1, 0, __f, 1, 0, 9, 9);
+    TEST ("-;",        -1, -1, -1, 0, __f, 1, 0, 9, 9);
+    TEST ("0;",        -1, -1, -1, 0, _ef, 2, 0, 9, 9);
+    TEST ("+0;",       -1, -1, -1, 0, _ef, 3, 0, 9, 9);
+    TEST ("-0;",       -1, -1, -1, 0, _ef, 3, 0, 9, 9);
+    TEST ("+1;",       -1, -1, -1, 0, _ef, 3, 0, 9, 9);
+    TEST ("-1;",       -1, -1, -1, 0, _ef, 3, 0, 9, 9);
+    TEST ("1;",        -1, -1, -1, 0, _ef, 2, 0, 9, 9);
+    TEST ("0;_",       -1, -1, -1, 0, __f, 2, 0, 9, 9);
+    TEST ("1;_",       -1, -1, -1, 0, __f, 2, 0, 9, 9);
+    TEST ("_0;",       -1, -1, -1, 0, _ef, 3, 0, 9, 9);
+    TEST ("_1;",       -1, -1, -1, 0, _ef, 3, 0, 9, 9);
+    TEST ("0;;",       -1, -1, -1, 0, __f, 2, 0, 9, 9);
+    TEST ("1;;",       -1, -1, -1, 0, __f, 2, 0, 9, 9);
+    TEST (";0",        -1, -1, -1, 0, __f, 0, 0, 9, 9);
+    TEST (";1",        -1, -1, -1, 0, __f, 0, 0, 9, 9);
+    TEST ("_;0",       -1, -1, -1, 0, __f, 1, 0, 9, 9);
+    TEST ("_;1",       -1, -1, -1, 0, __f, 1, 0, 9, 9);
+
+    // exercise errors when thousands_sep that's a space
+    locale_data.whitespace    = " ";
+    locale_data.thousands_sep = ' ';
+    locale_data.grouping      = "\2";
+    TEST (" ",         -1, -1, -1, 0, _ef, 1, 0, 9, 9);
+    TEST (" +",        -1, -1, -1, 0, _ef, 2, 0, 9, 9);
+    TEST (" -",        -1, -1, -1, 0, _ef, 2, 0, 9, 9);
+    TEST (" + ",       -1, -1, -1, 0, __f, 2, 0, 9, 9);
+    TEST (" - ",       -1, -1, -1, 0, __f, 2, 0, 9, 9);
+    TEST (" 0 ",       -1, -1, -1, 0, _ef, 3, 0, 9, 9);
+    TEST (" +0 ",      -1, -1, -1, 0, _ef, 4, 0, 9, 9);
+    TEST (" -0 ",      -1, -1, -1, 0, _ef, 4, 0, 9, 9);
+    TEST (" 123 ",     -1, -1, -1, 0, _ef, 5, 0, 9, 9);
+    TEST (" +123 ",    -1, -1, -1, 0, _ef, 6, 0, 9, 9);
+    TEST (" -123 ",    -1, -1, -1, 0, _ef, 6, 0, 9, 9);
+}
+
+/***********************************************************************/
+
+void info (const char *cname, const char *tname, const char *type)
+{
+    // format the CLASS environment variable w/o writing out any output
+    rw_fprintf (0,
+                "%{$CLASS!:@}",
+                "%{?}istream%{:}%{?}wistream"
+                "%{:}basic_istream<%s, %s>%{;}%{;}",
+                'c' == *cname && 's' == *tname, 
+                'w' == *cname && 's' == *tname,
+                cname, tname);
+
+    rw_info (0, 0, __LINE__, "std::%{$CLASS}::operator>>(%s&)", type);
+}
+
+/***********************************************************************/
+
+#undef TEST
+#define TEST(T, fmt, str, fl, is, ex, ee, es, ne, fw, iv, ev)              \
+        test_extractor ((CharT*)0, (Traits*)0, (T*)0, cname, tname, #T,    \
+                        __LINE__, fmt, str, sizeof str - 1, locale_data,   \
+                        fl, is, ex, ee, es, ne, fw, (T)(iv), (T)ev)
+
+/***********************************************************************/
+
+template <class CharT, class Traits>
+void
+test_bool (CharT*, Traits*,
+           const char *cname,
+           const char *tname)
+{
+    info (cname, tname, "bool");
+
+#define TEST_BOOL(ss, fl, is, ex, ee, es, ne, fw, iv, ev)   \
+    TEST (bool, "%b", ss, fl, is, ex, ee, es, ne, fw, iv, ev)
+
+    const int ba    = std::ios::boolalpha;
+    const int ba_ws = ba | std::ios::skipws;
+
+    LocaleData locale_data = { 0, -1, -1, 0, 0, 0 };
+    locale_data.whitespace = "_";
+    locale_data.falsename = "NO";
+    locale_data.truename  = "YES";
+
+    TEST_BOOL ("",      -1, -1, -1, 0, _ef, 0, 0, false, false);
+    TEST_BOOL ("",      -1, -1, -1, 0, _ef, 0, 0, true,  true);
+    TEST_BOOL ("0",     -1, -1, -1, 0, _e_, 1, 0, true,  false);
+    TEST_BOOL ("1",     -1, -1, -1, 0, _e_, 1, 0, false, true);
+    TEST_BOOL ("+0",    -1, -1, -1, 0, _e_, 2, 0, true,  false);
+    TEST_BOOL ("-0",    -1, -1, -1, 0, _e_, 2, 0, true,  false);
+    TEST_BOOL ("+1",    -1, -1, -1, 0, _e_, 2, 0, false, true);
+    TEST_BOOL ("00",    -1, -1, -1, 0, _e_, 2, 0, true,  false);
+    TEST_BOOL ("01",    -1, -1, -1, 0, _e_, 2, 0, false, true);
+    TEST_BOOL ("_000",  -1, -1, -1, 0, _e_, 4, 0, true,  false);
+    TEST_BOOL ("_001",  -1, -1, -1, 0, _e_, 4, 0, false, true);
+
+    TEST_BOOL ("NO",    -1, -1, -1, 0, __f, 0, 0, true,  true);
+    TEST_BOOL ("YES",   -1, -1, -1, 0, __f, 0, 0, false, false);
+    TEST_BOOL ("_NO",   -1, -1, -1, 0, __f, 1, 0, true,  true);
+    TEST_BOOL ("_YES",  -1, -1, -1, 0, __f, 1, 0, false, false);
+
+    TEST_BOOL ("NO",    ba,    -1, -1, 0, ___, 2, 0, false, false);
+    TEST_BOOL ("YES",   ba,    -1, -1, 0, ___, 3, 0, true,  true);
+    TEST_BOOL ("_NO",   ba_ws, -1, -1, 0, ___, 3, 0, false, false);
+    TEST_BOOL ("_YES",  ba_ws, -1, -1, 0, ___, 4, 0, true,  true);
+    TEST_BOOL ("_NO_",  ba_ws, -1, -1, 0, ___, 3, 0, false, false);
+    TEST_BOOL ("_YES_", ba_ws, -1, -1, 0, ___, 4, 0, true,  true);
+
+    locale_data.falsename = "bool:0";
+    locale_data.truename  = "bool:1";
+
+    TEST_BOOL ("bool:0", ba, -1, -1, 0, ___, 6, 0, false, false);
+    TEST_BOOL ("bool:1", ba, -1, -1, 0, ___, 6, 0, true,  true);
+    TEST_BOOL ("bool:2", ba, -1, -1, 0, __f, 5, 0, true,  true);
+}
+
+/***********************************************************************/
+
+template <class CharT, class Traits>
+void
+test_shrt (CharT*, Traits*,
+           const char *cname,
+           const char *tname)
+{
+    info (cname, tname, "short");
+
+    test_extractor ((CharT*)0, (Traits*)0, (short*)0,
+                    cname, tname, "short", "%hi");
+    
+#define TEST_SHRT(ss, fl, is, ex, ee, es, ne, fw, iv, ev)   \
+    TEST (short, "%hi", ss, fl, is, ex, ee, es, ne, fw, iv, ev)
+
+    LocaleData locale_data = { 0, -1, -1, 0, 0, 0 };
+    locale_data.whitespace = "";
+
+#if 2 == _RWSTD_SHRT_SIZE
+    const short smax = +32767;
+    const short smin = -smax - 1;
+
+    TEST_SHRT ("-32768", -1, -1, -1, 0, _e_, 6, 0, -1, smin);
+    TEST_SHRT ("-32769", -1, -1, -1, 0, _ef, 6, 0, -1, smin);
+    TEST_SHRT ("-99999", -1, -1, -1, 0, _ef, 6, 0, -1, smin);
+
+    TEST_SHRT ("+32767", -1, -1, -1, 0, _e_, 6, 0, -1, smax);
+    TEST_SHRT ("+32768", -1, -1, -1, 0, _ef, 6, 0, -1, smax);
+    TEST_SHRT ("+99999", -1, -1, -1, 0, _ef, 6, 0, -1, smax);
+    TEST_SHRT ("999999", -1, -1, -1, 0, _ef, 6, 0, -1, smax);
+
+#elif 4 == _RWSTD_SHRT_SIZE
+    const short smax = +2147483647;
+    const short smin = -smax - 1;
+
+    TEST_SHRT ("-2147483648", -1, -1, -1, 0, _e_, 11, 0, -1, smin);
+    TEST_SHRT ("-2147483649", -1, -1, -1, 0, _ef, 11, 0, -1, smin);
+    TEST_SHRT ("-9999999999", -1, -1, -1, 0, _ef, 11, 0, -1, smin);
+
+    TEST_SHRT ("+2147483647", -1, -1, -1, 0, _e_, 11, 0, -1, smax);
+    TEST_SHRT ("+2147483648", -1, -1, -1, 0, _ef, 11, 0, -1, smax);
+    TEST_SHRT ("+9999999999", -1, -1, -1, 0, _ef, 11, 0, -1, smax);
+    TEST_SHRT ("99999999999", -1, -1, -1, 0, _ef, 11, 0, -1, smax);
+#endif   // _RWSTD_SHRT_SIZE
+
+}
+
+/***********************************************************************/
+
+template <class CharT, class Traits>
+void
+test_ushrt (CharT*, Traits*,
+            const char *cname,
+            const char *tname)
+{
+    info (cname, tname, "unsigned short");
+
+    test_extractor ((CharT*)0, (Traits*)0, (unsigned short*)0,
+                    cname, tname, "unsigned short", "%hu");
+
+#define TEST_USHRT(ss, fl, is, ex, ee, es, ne, fw, iv, ev)   \
+    TEST (unsigned short, "%hu", ss, fl, is, ex, ee, es, ne, fw, iv, ev)
+
+    LocaleData locale_data = { 0, -1, -1, 0, 0, 0 };
+    locale_data.whitespace = "";
+
+#if 2 == _RWSTD_USHRT_SIZE
+    const unsigned short usmax = 65535U;
+
+    TEST_SHRT ("65535",  -1, -1, -1, 0, _e_, 5, 0,  1, usmax);
+    TEST_SHRT ("65536",  -1, -1, -1, 0, _ef, 5, 0,  1, usmax);
+    TEST_SHRT ("99999",  -1, -1, -1, 0, _ef, 5, 0,  1, usmax);
+#elif 4 == _RWSTD_USHRT_SIZE
+    const unsigned short usmax = 4294967295U;
+    
+    TEST_SHRT ("4294967295", -1, -1, -1, 0, _e_, 10, 0, -1, usmax);
+    TEST_SHRT ("4294967296", -1, -1, -1, 0, _ef, 10, 0, -1, usmax);
+    TEST_SHRT ("9999999999", -1, -1, -1, 0, _ef, 10, 0, -1, usmax);
+#endif   // _RWSTD_USHRT_SIZE
+
+}
+
+/***********************************************************************/
+
+template <class CharT, class Traits>
+void
+test_int (CharT*, Traits*,
+          const char *cname,
+          const char *tname)
+{
+    info (cname, tname, "int");
+
+    test_extractor ((CharT*)0, (Traits*)0, (int*)0,
+                    cname, tname, "int", "%i");
+
+#define TEST_INT(ss, fl, is, ex, ee, es, ne, fw, iv, ev)   \
+    TEST (int, "%i", ss, fl, is, ex, ee, es, ne, fw, iv, ev)
+
+    LocaleData locale_data = { 0, -1, -1, 0, 0, 0 };
+    locale_data.whitespace = "";
+
+#if 2 == _RWSTD_INT_SIZE
+    const int imax = +32767;
+    const int imin = -imax - 1;
+
+    TEST_INT ("-32768",  -1, -1, -1, 0, _e_, 6, 0,  1, imin);
+    TEST_INT ("-32769",  -1, -1, -1, 0, _ef, 6, 0,  1, imin);
+    TEST_INT ("-99999",  -1, -1, -1, 0, _ef, 6, 0,  1, imin);
+
+    TEST_INT ("+32767",  -1, -1, -1, 0, _e_, 6, 0,  1, imax);
+    TEST_INT ("+32768",  -1, -1, -1, 0, _ef, 6, 0,  1, imax);
+    TEST_INT ("+99999",  -1, -1, -1, 0, _ef, 6, 0,  1, imax);
+#elif 4 == _RWSTD_INT_SIZE
+    const int imax = +2147483647;
+    const int imin = -imax - 1;
+
+    TEST_INT ("-2147483648", -1, -1, -1, 0, _e_, 11, 0, -1, imin);
+    TEST_INT ("-2147483649", -1, -1, -1, 0, _ef, 11, 0, -1, imin);
+    TEST_INT ("-9999999999", -1, -1, -1, 0, _ef, 11, 0, -1, imin);
+
+    TEST_INT ("+2147483647", -1, -1, -1, 0, _e_, 11, 0, -1, imax);
+    TEST_INT ("+2147483648", -1, -1, -1, 0, _ef, 11, 0, -1, imax);
+    TEST_INT ("99999999999", -1, -1, -1, 0, _ef, 11, 0, -1, imax);
+#elif 8 == _RWSTD_INT_SIZE
+    const int imax = +9223372036854775807;
+    const int imin = -imax - 1;
+
+    TEST_INT ("-9223372036854775808", -1, -1, -1, 0, _e_, 20, 0, -1, imin);
+    TEST_INT ("-9223372036854775809", -1, -1, -1, 0, _ef, 20, 0, -1, imin);
+    TEST_INT ("-9999999999999999999", -1, -1, -1, 0, _ef, 20, 0, -1, imin);
+
+    TEST_INT ("+9223372036854775807", -1, -1, -1, 0, _e_, 20, 0, -1, imax);
+    TEST_INT ("+9223372036854775808", -1, -1, -1, 0, _ef, 20, 0, -1, imax);
+    TEST_INT ("99999999999999999999", -1, -1, -1, 0, _ef, 20, 0, -1, imax);
+#endif   // _RWSTD_INT_SIZE
+
+}
+
+/***********************************************************************/
+
+template <class CharT, class Traits>
+void
+test_uint (CharT*, Traits*,
+           const char *cname,
+           const char *tname)
+{
+    info (cname, tname, "unsigned int");
+
+    test_extractor ((CharT*)0, (Traits*)0, (unsigned int*)0,
+                     cname, tname, "unsigned int", "%u");
+
+#define TEST_UINT(ss, fl, is, ex, ee, es, ne, fw, iv, ev)   \
+    TEST (int, "%u", ss, fl, is, ex, ee, es, ne, fw, iv, ev)
+
+    LocaleData locale_data = { 0, -1, -1, 0, 0, 0 };
+    locale_data.whitespace = "";
+
+#if 2 == _RWSTD_UINT_SIZE
+    const unsigned uimax = 65535U;
+
+    TEST_INT ("65535",  -1, -1, -1, 0, _e_, 5, 0,  1, uimax);
+    TEST_INT ("65536",  -1, -1, -1, 0, _ef, 5, 0,  1, uimax);
+    TEST_INT ("99999",  -1, -1, -1, 0, _ef, 5, 0,  1, uimax);
+#elif 4 == _RWSTD_UINT_SIZE
+    const unsigned uimax = 4294967295U;
+
+    TEST_INT ("4294967295", -1, -1, -1, 0, _e_, 10, 0, -1, uimax);
+    TEST_INT ("4294967296", -1, -1, -1, 0, _ef, 10, 0, -1, uimax);
+    TEST_INT ("9999999999", -1, -1, -1, 0, _ef, 10, 0, -1, uimax);
+#elif 8 == _RWSTD_UINT_SIZE
+    const unsigned uimax = 9223372036854775807U;
+
+    TEST_INT ("9223372036854775807", -1, -1, -1, 0, _e_, 10, 0, -1, uimax);
+    TEST_INT ("9223372036854775808", -1, -1, -1, 0, _ef, 10, 0, -1, uimax);
+    TEST_INT ("9999999999999999999", -1, -1, -1, 0, _ef, 10, 0, -1, uimax);
+#endif   // _RWSTD_UINT_SIZE
+
+}
+
+/***********************************************************************/
+
+template <class CharT, class Traits>
+void
+test_long (CharT*, Traits*,
+           const char *cname,
+           const char *tname)
+{
+    info (cname, tname, "long");
+
+    test_extractor ((CharT*)0, (Traits*)0, (long*)0,
+                    cname, tname, "long", "%li");
+
+#define TEST_LONG(ss, fl, is, ex, ee, es, ne, fw, iv, ev)   \
+    TEST (long, "%li", ss, fl, is, ex, ee, es, ne, fw, iv, ev)
+
+    LocaleData locale_data = { 0, -1, -1, 0, 0, 0 };
+    locale_data.whitespace = "";
+
+#if 2 == _RWSTD_LONG_SIZE
+    const long lmax = +32767L;
+    const long lmin = -lmax - 1;
+
+    TEST_LONG ("-32768",  -1, -1, -1, 0, _e_, 6, 0,  1, lmin);
+    TEST_LONG ("-32769",  -1, -1, -1, 0, _ef, 6, 0,  1, lmin);
+    TEST_LONG ("-99999",  -1, -1, -1, 0, _ef, 6, 0,  1, lmin);
+
+    TEST_LONG ("+32767",  -1, -1, -1, 0, _e_, 6, 0,  1, lmax);
+    TEST_LONG ("+32768",  -1, -1, -1, 0, _ef, 6, 0,  1, lmax);
+    TEST_LONG ("+99999",  -1, -1, -1, 0, _ef, 6, 0,  1, lmax);
+#elif 4 == _RWSTD_LONG_SIZE
+    const long lmax = +2147483647L;
+    const long lmin = -lmax - 1;
+
+    TEST_LONG ("-2147483648", -1, -1, -1, 0, _e_, 11, 0, -1, lmin);
+    TEST_LONG ("-2147483649", -1, -1, -1, 0, _ef, 11, 0, -1, lmin);
+    TEST_LONG ("-9999999999", -1, -1, -1, 0, _ef, 11, 0, -1, lmin);
+
+    TEST_LONG ("+2147483647", -1, -1, -1, 0, _e_, 11, 0, -1, lmax);
+    TEST_LONG ("+2147483648", -1, -1, -1, 0, _ef, 11, 0, -1, lmax);
+    TEST_LONG ("99999999999", -1, -1, -1, 0, _ef, 11, 0, -1, lmax);
+#elif 8 == _RWSTD_LONG_SIZE
+    const long lmax = +9223372036854775807L;
+    const long lmin = -lmax - 1;
+
+    TEST_LONG ("-9223372036854775808", -1, -1, -1, 0, _e_, 20, 0, -1, lmin);
+    TEST_LONG ("-9223372036854775809", -1, -1, -1, 0, _ef, 20, 0, -1, lmin);
+    TEST_LONG ("-9999999999999999999", -1, -1, -1, 0, _ef, 20, 0, -1, lmin);
+
+    TEST_LONG ("+9223372036854775807", -1, -1, -1, 0, _e_, 20, 0, -1, lmax);
+    TEST_LONG ("+9223372036854775808", -1, -1, -1, 0, _ef, 20, 0, -1, lmax);
+    TEST_LONG ("99999999999999999999", -1, -1, -1, 0, _ef, 20, 0, -1, lmax);
+#endif   // _RWSTD_LONG_SIZE
+
+}
+
+/***********************************************************************/
+
+template <class CharT, class Traits>
+void
+test_ulong (CharT*, Traits*,
+            const char *cname,
+            const char *tname)
+{
+    info (cname, tname, "unsigned long");
+
+    test_extractor ((CharT*)0, (Traits*)0, (unsigned long*)0,
+                     cname, tname, "unsigned long", "%lu");
+
+#define TEST_ULONG(ss, fl, is, ex, ee, es, ne, fw, iv, ev)   \
+    TEST (unsigned long, "%lu", ss, fl, is, ex, ee, es, ne, fw, iv, ev)
+
+    LocaleData locale_data = { 0, -1, -1, 0, 0, 0 };
+    locale_data.whitespace = "";
+
+#if 2 == _RWSTD_ULONG_SIZE
+    const unsigned ulmax = 65535UL;
+
+    TEST_ULONG ("65535",  -1, -1, -1, 0, _e_, 5, 0,  1, ulmax);
+    TEST_ULONG ("65536",  -1, -1, -1, 0, _ef, 5, 0,  1, ulmax);
+    TEST_ULONG ("99999",  -1, -1, -1, 0, _ef, 5, 0,  1, ulmax);
+#elif 4 == _RWSTD_ULONG_SIZE
+    const unsigned ulmax = 4294967295UL;
+
+    TEST_ULONG ("4294967295", -1, -1, -1, 0, _e_, 10, 0, -1, ulmax);
+    TEST_ULONG ("4294967296", -1, -1, -1, 0, _ef, 10, 0, -1, ulmax);
+    TEST_ULONG ("9999999999", -1, -1, -1, 0, _ef, 10, 0, -1, ulmax);
+#elif 8 == _RWSTD_ULONG_SIZE
+    const unsigned ulmax = 9223372036854775807UL;
+
+    TEST_ULONG ("9223372036854775807", -1, -1, -1, 0, _e_, 10, 0, -1, ulmax);
+    TEST_ULONG ("9223372036854775808", -1, -1, -1, 0, _ef, 10, 0, -1, ulmax);
+    TEST_ULONG ("9999999999999999999", -1, -1, -1, 0, _ef, 10, 0, -1, ulmax);
+#endif   // _RWSTD_ULONG_SIZE
+
+}
+
+/***********************************************************************/
+
+template <class CharT, class Traits>
+void
+test_llong (CharT*, Traits*,
+            const char *cname,
+            const char *tname)
+{
+    info (cname, tname, "long long");
+
+    test_extractor ((CharT*)0, (Traits*)0, (long*)0,
+                    cname, tname, "long", "%lli");
+
+#define TEST_LLONG(ss, fl, is, ex, ee, es, ne, fw, iv, ev)   \
+    TEST (long long, "%lli", ss, fl, is, ex, ee, es, ne, fw, iv, ev)
+
+    LocaleData locale_data = { 0, -1, -1, 0, 0, 0 };
+    locale_data.whitespace = "";
+
+#if 2 == _RWSTD_LLONG_SIZE
+    const long long llmax = +32767LL;
+    const long long llmin = -llmax - 1;
+
+    TEST_LLONG ("-32768",  -1, -1, -1, 0, _e_, 6, 0,  1, llmin);
+    TEST_LLONG ("-32769",  -1, -1, -1, 0, _ef, 6, 0,  1, llmin);
+    TEST_LLONG ("-99999",  -1, -1, -1, 0, _ef, 6, 0,  1, llmin);
+
+    TEST_LLONG ("+32767",  -1, -1, -1, 0, _e_, 6, 0,  1, llmax);
+    TEST_LLONG ("+32768",  -1, -1, -1, 0, _ef, 6, 0,  1, llmax);
+    TEST_LLONG ("+99999",  -1, -1, -1, 0, _ef, 6, 0,  1, llmax);
+#elif 4 == _RWSTD_LLONG_SIZE
+    const long long llmax = +2147483647LL;
+    const long long llmin = -llmax - 1;
+
+    TEST_LLONG ("-2147483648", -1, -1, -1, 0, _e_, 11, 0, -1, llmin);
+    TEST_LLONG ("-2147483649", -1, -1, -1, 0, _ef, 11, 0, -1, llmin);
+    TEST_LLONG ("-9999999999", -1, -1, -1, 0, _ef, 11, 0, -1, llmin);
+
+    TEST_LLONG ("+2147483647", -1, -1, -1, 0, _e_, 11, 0, -1, llmax);
+    TEST_LLONG ("+2147483648", -1, -1, -1, 0, _ef, 11, 0, -1, llmax);
+    TEST_LLONG ("99999999999", -1, -1, -1, 0, _ef, 11, 0, -1, llmax);
+#elif 8 == _RWSTD_LLONG_SIZE
+    const long long llmax = +9223372036854775807LL;
+    const long long llmin = -llmax - 1;
+
+    TEST_LLONG ("-9223372036854775808", -1, -1, -1, 0, _e_, 20, 0, -1, llmin);
+    TEST_LLONG ("-9223372036854775809", -1, -1, -1, 0, _ef, 20, 0, -1, llmin);
+    TEST_LLONG ("-9999999999999999999", -1, -1, -1, 0, _ef, 20, 0, -1, llmin);
+
+    TEST_LLONG ("+9223372036854775807", -1, -1, -1, 0, _e_, 20, 0, -1, llmax);
+    TEST_LLONG ("+9223372036854775808", -1, -1, -1, 0, _ef, 20, 0, -1, llmax);
+    TEST_LLONG ("99999999999999999999", -1, -1, -1, 0, _ef, 20, 0, -1, llmax);
+#endif   // _RWSTD_LLONG_SIZE
+
+}
+
+/***********************************************************************/
+
+template <class CharT, class Traits>
+void
+test_ullong (CharT*, Traits*,
+             const char *cname,
+             const char *tname)
+{
+    info (cname, tname, "unsigned long long");
+
+    test_extractor ((CharT*)0, (Traits*)0, (unsigned long long*)0,
+                     cname, tname, "unsigned long long", "%llu");
+
+#define TEST_ULLONG(ss, fl, is, ex, ee, es, ne, fw, iv, ev)   \
+    TEST (long long, "%llu", ss, fl, is, ex, ee, es, ne, fw, iv, ev)
+
+    LocaleData locale_data = { 0, -1, -1, 0, 0, 0 };
+    locale_data.whitespace = "";
+
+#if 2 == _RWSTD_ULLONG_SIZE
+    const unsigned long long ullmax = 65535ULL;
+
+    TEST_ULLONG ("65535",  -1, -1, -1, 0, _e_, 5, 0,  1, ullmax);
+    TEST_ULLONG ("65536",  -1, -1, -1, 0, _ef, 5, 0,  1, ullmax);
+    TEST_ULLONG ("99999",  -1, -1, -1, 0, _ef, 5, 0,  1, ullmax);
+#elif 4 == _RWSTD_ULLONG_SIZE
+    const unsigned long long ullmax = 4294967295ULL;
+
+    TEST_ULLONG ("4294967295", -1, -1, -1, 0, _e_, 10, 0, -1, ullmax);
+    TEST_ULLONG ("4294967296", -1, -1, -1, 0, _ef, 10, 0, -1, ullmax);
+    TEST_ULLONG ("9999999999", -1, -1, -1, 0, _ef, 10, 0, -1, ullmax);
+#elif 8 == _RWSTD_ULLONG_SIZE
+    const unsigned long long ullmax = 9223372036854775807ULL;
+
+    TEST_ULLONG ("9223372036854775807", -1, -1, -1, 0, _e_, 10, 0, -1, ullmax);
+    TEST_ULLONG ("9223372036854775808", -1, -1, -1, 0, _ef, 10, 0, -1, ullmax);
+    TEST_ULLONG ("9999999999999999999", -1, -1, -1, 0, _ef, 10, 0, -1, ullmax);
+#endif   // _RWSTD_ULLONG_SIZE
+
+}
+
+/***********************************************************************/
+
+template <class CharT, class Traits, class FloatingType>
+void
+test_floating (CharT*, Traits*, FloatingType*,
+               const char *cname,
+               const char *tname,
+               const char *fname,
+               const char *fmt)
+{
+    typedef FloatingType T;
+
+    test_extractor ((CharT*)0, (Traits*)0, (FloatingType*)0,
+                    cname, tname, fname, fmt);
+
+#define TEST_FLOATING(ss, fl, is, ex, ee, es, ne, fw, iv, ev)   \
+    TEST (T, fmt, ss, fl, is, ex, ee, es, ne, fw, T (iv), T (ev))
+
+    LocaleData locale_data = { 0, -1, -1, 0, 0, 0 };
+    locale_data.whitespace = "";
+
+    TEST_FLOATING ("", -1, -1, -1, 0, _ef, 0, 0, 1.0,  1.0);
+}
+
+/***********************************************************************/
+
+template <class CharT, class Traits>
+void
+test_flt (CharT*, Traits*,
+          const char *cname,
+          const char *tname)
+{
+    const char fmt[]   = "%g";
+    const char fname[] = "float";
+
+    info (cname, tname, fname);
+
+    test_floating ((CharT*)0, (Traits*)0, (float*)0,
+                   cname, tname, fname, fmt);
+
+#define TEST_FLT(ss, fl, is, ex, ee, es, ne, fw, iv, ev)   \
+    TEST (float, fmt, ss, fl, is, ex, ee, es, ne, fw, iv, ev)
+
+    LocaleData locale_data = { 0, -1, -1, 0, 0, 0 };
+    locale_data.whitespace = "";
+
+    TEST_FLT ("", -1, -1, -1, 0, _ef, 0, 0, 1.0f,  1.0f);
+
+    rw_warn (0, 0, __LINE__,
+             "%{$CLASS}::operator>>(%s&) insufficiently exercised", fname);
+}
+
+/***********************************************************************/
+
+template <class CharT, class Traits>
+void
+test_dbl (CharT*, Traits*,
+          const char *cname,
+          const char *tname)
+{
+    const char fmt[]   = "%g";
+    const char fname[] = "double";
+
+    info (cname, tname, fname);
+
+    test_floating ((CharT*)0, (Traits*)0, (double*)0,
+                   cname, tname, fname, fmt);
+
+#define TEST_DBL(ss, fl, is, ex, ee, es, ne, fw, iv, ev)   \
+    TEST (double, fmt, ss, fl, is, ex, ee, es, ne, fw, iv, ev)
+
+    LocaleData locale_data = { 0, -1, -1, 0, 0, 0 };
+    locale_data.whitespace = "";
+
+    TEST_DBL ("", -1, -1, -1, 0, _ef, 0, 0, 1.0,  1.0);
+
+    rw_warn (0, 0, __LINE__,
+             "%{$CLASS}::operator>>(%s&) insufficiently exercised", fname);
+}
+
+/***********************************************************************/
+
+template <class CharT, class Traits>
+void
+test_ldbl (CharT*, Traits*,
+           const char *cname,
+           const char *tname)
+{
+    const char fmt[]   = "%Lg";
+    const char fname[] = "long double";
+
+    info (cname, tname, fname);
+
+    test_floating ((CharT*)0, (Traits*)0, (long double*)0,
+                   cname, tname, fname, fmt);
+
+#define TEST_LDBL(ss, fl, is, ex, ee, es, ne, fw, iv, ev)   \
+    TEST (long double, fmt, ss, fl, is, ex, ee, es, ne, fw, iv, ev)
+
+    LocaleData locale_data = { 0, -1, -1, 0, 0, 0 };
+    locale_data.whitespace = "";
+
+    TEST_LDBL ("", -1, -1, -1, 0, _ef, 0, 0, 1.0L,  1.0L);
+
+    rw_warn (0, 0, __LINE__,
+             "%{$CLASS}::operator>>(%s&) insufficiently exercised", fname);
+}
+
+/***********************************************************************/
+
+int opt_bool;
+int opt_shrt;
+int opt_ushrt;
+int opt_int;
+int opt_uint;
+int opt_long;
+int opt_ulong;
+int opt_llong;
+int opt_ullong;
+int opt_flt;
+int opt_dbl;
+int opt_ldbl;
+
+
+template <class CharT, class Traits>
+void
+test_extractor (CharT*, Traits*,
+                const char *cname,
+                const char *tname)
+{
+    // silence unused variable warnings
+    (void)(___+__f+_e_+_ef+b__+b_f+be_+bef+DEC+OCT+HEX);
+
+#undef TEST
+#define TEST(T)                                                          \
+    if (rw_note (0 == opt_ ## T, 0, __LINE__, "%s tests disabld", #T))   \
+        test_ ## T ((CharT*)0, (Traits*)0, cname, tname)
+
+    //////////////////////////////////////////////////////////////////
+    // basic_istream::operator>>(bool&)
+    TEST (bool);
+
+    //////////////////////////////////////////////////////////////////
+    // basic_istream::operator>>(short&)
+    TEST (shrt);
+
+    //////////////////////////////////////////////////////////////////
+    // basic_istream::operator>>(unsigned short&)
+    TEST (ushrt);
+
+    //////////////////////////////////////////////////////////////////
+    // basic_istream::operator>>(int&)
+    TEST (int);
+
+    //////////////////////////////////////////////////////////////////
+    // basic_istream::operator>>(unsigned int&)
+    TEST (uint);
+
+    //////////////////////////////////////////////////////////////////
+    // basic_istream::operator>>(long&)
+    TEST (long);
+
+    //////////////////////////////////////////////////////////////////
+    // basic_istream::operator>>(unsigned long&)
+    TEST (ulong);
+
+    //////////////////////////////////////////////////////////////////
+    // basic_istream::operator>>(long long&)
+    TEST (llong);
+
+    //////////////////////////////////////////////////////////////////
+    // basic_istream::operator>>(unsigned long long&)
+    TEST (ullong);
+
+    //////////////////////////////////////////////////////////////////
+    // basic_istream::operator>>(float&)
+    TEST (flt);
+
+    //////////////////////////////////////////////////////////////////
+    // basic_istream::operator>>(double&)
+    TEST (dbl);
+
+    //////////////////////////////////////////////////////////////////
+    // basic_istream::operator>>(long double&)
+    TEST (ldbl);
+}
+
+/***********************************************************************/
+
+static int opt_char;
+static int opt_wchar;
+static int opt_char_traits;
+static int opt_user_traits;
+
+
+static int
+run_test (int, char**)
+{
+#undef TEST
+#define TEST(CharT, Traits) \
+    test_extractor ((CharT*)0, (Traits*)0, #CharT, #Traits)
+
+    if (rw_note (0 <= opt_char && 0 <= opt_char_traits, 0, __LINE__,
+                 "basic_istream<char, char_traits<char>>::operator>>() "
+                 "tests disabled"))
+        TEST (char, std::char_traits<char>);
+
+    if (rw_note (0 <= opt_char && 0 <= opt_user_traits, 0, __LINE__,
+                 "basic_istream<char, UserTraits<char>>::operator>>() "
+                 "tests disabled"))
+        TEST (char, UserTraits<char>);
+
+#ifndef _RWSTD_NO_WCHAR_T
+
+    if (rw_note (0 <= opt_wchar && 0 <= opt_char_traits, 0, __LINE__,
+                 "basic_istream<wchar_t, char_traits<wchar_t>>::operator>>() "
+                 "tests disabled"))
+        TEST (wchar_t, std::char_traits<wchar_t>);
+
+    if (rw_note (0 <= opt_wchar && 0 <= opt_user_traits, 0, __LINE__,
+                 "basic_istream<wchar_t, UserTraits<wchar_t>>::operator>>() "
+                 "tests 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.formatted.arithmetic",
+                    0 /* no comment */,
+                    run_test,
+                    "|-char~ "
+                    "|-wchar_t~ "
+                    "|-char_traits~ "
+                    "|-UserTraits~ "
+                    "|-bool~ "
+                    "|-short~ "
+                    "|-unsigned-short~ "
+                    "|-int~ "
+                    "|-unsigned-int~ "
+                    "|-long~ "
+                    "|-unsigned-long~ "
+                    "|-long-long~ "
+                    "|-unsigned-long-long~ "
+                    "|-float~ "
+                    "|-double~ "
+                    "|-long-double~ "
+                    "|-no-gcount# ",
+                    &opt_char,
+                    &opt_wchar,
+                    &opt_char_traits,
+                    &opt_user_traits,
+                    &opt_bool,
+                    &opt_shrt,
+                    &opt_ushrt,
+                    &opt_int,
+                    &opt_uint,
+                    &opt_long,
+                    &opt_ulong,
+                    &opt_llong,
+                    &opt_ullong,
+                    &opt_flt,
+                    &opt_dbl,
+                    &opt_ldbl,
+                    &opt_no_gcount,
+                    (void*)0   /* sentinel */);
+}

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

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



Mime
View raw message