blob: f3088db344b2dd0bbda868f232fe283e17ef7ba7 [file] [log] [blame]
/***************************************************************************
*
* 22.locale.num.put.cpp - tests exercising the std::num_put facet
*
* $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 2001-2006 Rogue Wave Software.
*
**************************************************************************/
#ifdef __GNUG__
// prevent gcc -Wshadow warnings for convenience types
# define ushort __rw_ushort
# define uint __rw_uint
# define ulong __rw_ulong
# include <sys/types.h>
# undef ushort
# undef uint
# undef ulong
#endif // __GNUG__
#include <ios>
#include <locale>
#include <cerrno> // for ERANGE, errno
#include <cfloat> // for floating limits macros
#include <climits> // for integral limits macros
#include <clocale> // for LC_NUMERIC, setlocale()
#include <cstdio> // for sprintf()
#include <cstring> // for strcmp(), strlen()
#include <any.h> // for TOSTR()
#include <cmdopt.h> // for rw_enabled
#include <driver.h> // for rw_test
#include <rw_locale.h> // for rw_locales
#include <valcmp.h> // for rw_equal
/**************************************************************************/
// set by the command line option handler in response to:
static int rw_opt_enable_num_get = 0; // --enable-num_get
static int rw_opt_no_errno = 0; // --no-errno
static int rw_opt_no_grouping = 0; // --no-grouping
static int rw_opt_no_widen = 0; // --no-widen
/**************************************************************************/
// replacement ctype facet
template <class charT>
struct Ctype: std::ctype<charT>
{
typedef std::ctype<charT> Base;
typedef typename Base::char_type char_type;
static int n_widen_;
Ctype (): Base (0, 0, 1) { }
virtual char_type do_widen (char c) const {
++n_widen_;
switch (c) {
case '0': c = '9'; break;
case '1': c = '8'; break;
case '2': c = '7'; break;
case '3': c = '6'; break;
case '4': c = '5'; break;
case '5': c = '4'; break;
case '6': c = '3'; break;
case '7': c = '2'; break;
case '8': c = '1'; break;
case '9': c = '0'; break;
default: break;
}
return char_type (c);
}
virtual const char_type*
do_widen (const char *lo, const char *hi, char_type *dst) const {
return Base::do_widen (lo, hi, dst);
}
};
template <class charT>
int Ctype<charT>::n_widen_;
/**************************************************************************/
// replacement numpunct facet
template <class charT>
struct Punct: std::numpunct<charT>
{
typedef typename std::numpunct<charT>::char_type char_type;
typedef typename std::numpunct<charT>::string_type string_type;
static char_type decimal_point_;
static char_type thousands_sep_;
static const char *grouping_;
static const char_type *truename_;
static const char_type *falsename_;
static int n_objs_; // number of facet objects in existence
static int n_thousands_sep_; // number of calls to do_thousands_sep()
Punct (std::size_t ref = 0)
: std::numpunct<charT>(ref) {
++n_objs_;
}
~Punct () {
--n_objs_;
}
virtual char_type do_decimal_point () const {
return decimal_point_;
}
virtual std::string do_grouping () const {
return grouping_;
}
virtual char_type do_thousands_sep () const {
++n_thousands_sep_;
return thousands_sep_;
}
virtual string_type do_truename () const {
return truename_ ? string_type (truename_) : string_type ();
}
virtual string_type do_falsename () const {
return falsename_ ? string_type (falsename_) : string_type ();
}
};
template <class charT>
const char* Punct<charT>::grouping_ = "";
template <class charT>
typename Punct<charT>::char_type Punct<charT>::decimal_point_ = '.';
template <class charT>
typename Punct<charT>::char_type Punct<charT>::thousands_sep_ = ',';
template <class charT>
const typename Punct<charT>::char_type* Punct<charT>::truename_;
template <class charT>
const typename Punct<charT>::char_type* Punct<charT>::falsename_;
template <class charT>
int Punct<charT>::n_thousands_sep_;
template <class charT>
int Punct<charT>::n_objs_;
/**************************************************************************/
template <class charT>
struct Ios: std::basic_ios<charT>
{
Ios () { this->init (0); }
};
template <class charT>
struct NumGet: std::num_get<charT, const charT*> { NumGet () { } };
template <class charT>
struct NumPut: std::num_put<charT, charT*>
{
typedef std::num_put<charT, charT*> Base;
typedef typename Base::char_type char_type;
typedef typename Base::iter_type iter_type;
enum {
test_bool, test_short, test_ushort, test_int, test_uint,
test_long, test_ulong, test_llong, test_ullong,
test_pvoid, test_float, test_double, test_ldouble
};
static int ncalls_ [13];
NumPut (std::size_t ref = 0): Base (ref) { }
#ifndef _RWSTD_NO_BOOL
virtual iter_type
do_put (iter_type it, std::ios_base &f, char_type fill, bool v) const {
++ncalls_ [test_bool];
return Base::do_put (it, f, fill, v);
}
#endif // _RWSTD_NO_BOOL
virtual iter_type
do_put (iter_type it, std::ios_base &f, char_type fill, long v) const {
++ncalls_ [test_long];
return Base::do_put (it, f, fill, v);
}
virtual iter_type
do_put (iter_type it, std::ios_base &f, char_type fill,
unsigned long v) const {
++ncalls_ [test_ulong];
return Base::do_put (it, f, fill, v);
}
#ifdef _RWSTD_LONG_LONG
// provided as an extension unless _RWSTD_NO_LONG_LONG is #defined
virtual iter_type
do_put (iter_type it, std::ios_base &f, char_type fill,
unsigned _RWSTD_LONG_LONG v) const {
++ncalls_ [test_ullong];
return Base::do_put (it, f, fill, v);
}
// provided as an extension unless _RWSTD_NO_LONG_LONG is #defined
virtual iter_type
do_put (iter_type it, std::ios_base &f, char_type fill,
_RWSTD_LONG_LONG v) const {
++ncalls_ [test_llong];
return Base::do_put (it, f, fill, v);
}
#endif // _RWSTD_LONG_LONG
virtual iter_type
do_put (iter_type it, std::ios_base &f, char_type fill, double v) const {
++ncalls_ [test_double];
return Base::do_put (it, f, fill, v);
}
#ifndef _RWSTD_NO_LONG_DOUBLE
virtual iter_type
do_put (iter_type it, std::ios_base &f, char_type fill,
long double v) const {
++ncalls_ [test_ldouble];
return Base::do_put (it, f, fill, v);
}
#endif // _RWSTD_NO_LONG_DOUBLE
virtual iter_type
do_put (iter_type it, std::ios_base &f, char_type fill,
const void *v) const {
++ncalls_ [test_pvoid];
return Base::do_put (it, f, fill, v);
}
};
// explicit initialization of the static array below used
// to work around a SunPro 5.4 bug (PR #27293)
template <class charT>
/* static */ int NumPut<charT>::ncalls_ [13] = { 0 };
/**************************************************************************/
template <class charT, class T>
void do_test (charT /* dummy */,
const char *cname, // charT name
const char *tname, // T name
int lineno, // line number
T val, // value to format
int flags, // ios flags
std::streamsize prec, // precision
std::streamsize width, // field width
char fill, // fill character
const char *grouping, // grouping string
const char *str, // expected output
int err_expect = -1, // expected iostate
T val_expect = T () /* expected num_get result */)
{
if (!rw_enabled (lineno)) {
rw_note (0, __FILE__, __LINE__, "test on line %d disabled", lineno);
return;
}
// create a distinct punctuation facet for each iteration to make sure
// any data cached in between successive calls to the facet's public
// member functions are flushed
const Punct<charT> pun (1);
Ios<charT> ios;
NumPut<charT> np;
ios.imbue (std::locale (ios.getloc (), (const std::numpunct<charT>*)&pun));
ios.flags (std::ios_base::fmtflags (flags));
ios.precision (prec);
ios.width (width);
pun.grouping_ = grouping;
#if defined (_RWSTD_LDBL_MAX_10_EXP)
charT buf [_RWSTD_LDBL_MAX_10_EXP + 2] = { 0 };
#else // if !defined (_RWSTD_LDBL_MAX_10_EXP)
charT buf [4096] = { 0 };
#endif // _RWSTD_LDBL_MAX_10_EXP
const charT* const bufend = np.put (buf, ios, fill, val);
// verify 22.2.2.2.2, p21
if (ios.width ()) {
static int width_fail = 0;
// fail at most once for each specialization
rw_assert (!width_fail++, 0, lineno,
"%line d: num_put<%s>::put (..., %s = %s) "
"failed to reset width from %d; width() = %d",
__LINE__, cname, tname, TOSTR (val),
TOSTR (buf), width, ios.width ());
}
/******************************************************************/
if (str) {
char cbuf [sizeof buf / sizeof *buf] = { '\0' };
if ('%' == *str) {
std::sprintf (cbuf, str, val);
str = cbuf;
#if defined (_WIN32) || defined (_WIN64)
std::size_t len = std::strlen (str);
if ( ('e' == cbuf [len - 5] || 'E' == cbuf [len - 5])
&& ('-' == cbuf [len - 4] || '+' == cbuf [len - 4])
&& ('0' == cbuf [len - 3])) {
cbuf [len - 3] = cbuf [len - 2];
cbuf [len - 2] = cbuf [len - 1];
cbuf [len - 1] = cbuf [len];
}
#endif // _WIN{32,64}
}
// compare output produced by num_put with that produced by printf()
rw_assert (0 == rw_strncmp (buf, str), 0, lineno,
"line %d: num_put<%s>::put (..., %s = %s) "
"wrote %{*Ac}, expected %{*Ac}, "
"flags = %{If}, precision = %d"
"%{?}, grouping = \"%#s\"%{;}",
__LINE__, cname, tname, TOSTR (val),
sizeof *buf, buf, sizeof *str, str,
flags, prec,
grouping && *grouping, grouping);
}
/******************************************************************/
#ifndef NO_NUM_GET
if (!rw_opt_enable_num_get)
return;
// skip negative precision (extension requiring special treatment)
if (prec < 0)
return;
const charT *next = buf;
// skip leading fill characters (if any)
for ( ; *next == fill; ++next);
// find the first non-fill character if it exists
const charT *last = next;
for ( ; *last && *last != fill; ++last);
for ( ; *last && *last == fill; ++last);
// do not perform extraction if there are any fill characters
// in the middle of output (they serve as punctuators and break
// up the input sequence)
if (next != last && *last)
return;
// do not perform extraction if the fill character is the minus
// sign, the plus sign, the thousands separator, the decimal point,
// or a digit
if ( '-' == fill
|| '+' == fill
|| pun.thousands_sep_ == fill
|| pun.decimal_point_ == fill
|| fill >= '0' && fill <= '9')
return;
// do not perform extraction if there is no data to extract
// (unless this is an extraction-only test)
if (!*next && str)
return;
NumGet<charT> ng;
T x = T ();
std::ios_base::iostate err = std::ios_base::goodbit;
if (-1 == err_expect) {
// lwg issue 17: special treatment for bool:
// The in iterator is always left pointing one position beyond
// the last character successfully matched. If val is set, then
// err is set to str.goodbit; or to str.eofbit if, when seeking
// another character to match, it is found that (in==end). If
// val is not set, then err is set to str.failbit; or to
// (str.failbit|str.eofbit) if the reason for the failure was
// that (in==end). [Example: for targets true:"a" and false:"abb",
// the input sequence "a" yields val==true and err==str.eofbit;
// the input sequence "abc" yields err=str.failbit, with in ending
// at the 'c' element. For targets true:"1" and false:"0", the
// input sequence "1" yields val==true and err=str.goodbit. For
// empty targets (""), any input sequence yields err==str.failbit.
// --end example]
err_expect = T (1) == T (2) && flags & std::ios::boolalpha
? std::ios::goodbit
: last == bufend && last [-1] != fill
? std::ios::eofbit : std::ios::goodbit;
val_expect = val;
}
last = ng.get (next, bufend, ios, err, x);
// verify the state
rw_assert (err == err_expect, 0, lineno,
"line %d: num_get<%s>::get (%s, ..., %s&) "
"flags = %{If}, "
"%{?}grouping = \"%#s\", %{;}"
"iostate = %{Is}, expected %{Is}",
__LINE__, cname,
TOSTR (next), tname,
flags,
grouping && *grouping, grouping,
err, err_expect);
// verify the parsed value
rw_assert (rw_equal (x, val_expect), 0, lineno,
"line %d: num_get<%s>::get (%s, ..., %s&) got %s, "
"expected %s, flags = %{If}, "
"%{?}grouping = \"%#s\", %{;}",
__LINE__, cname,
TOSTR (next), tname,
TOSTR (x), TOSTR (val_expect),
flags,
grouping && *grouping, grouping);
#else
_RWSTD_UNUSED (bufend);
_RWSTD_UNUSED (err_expect);
_RWSTD_UNUSED (val_expect);
#endif // NO_NUM_GET
}
/**************************************************************************/
template <class charT>
struct Streambuf: std::basic_streambuf<charT, std::char_traits<charT> > { };
template <class charT>
void direct_use_test (charT, const char *cname)
{
_RWSTD_UNUSED (cname);
// verify that num_put objects can be used directly w/o first
// having been installed in a locale object; the behavior of
// such facets is unspecified (but not undefined)
Ios<charT> ios;
const std::num_put<charT> np;
Streambuf<charT> sb;
#define DIRECT_USE_TEST(T) \
np.put (std::ostreambuf_iterator<charT>(&sb), ios, charT (), (T)0)
#ifndef _RWSTD_NO_BOOL
DIRECT_USE_TEST (bool);
#endif // _RWSTD_NO_BOOL
DIRECT_USE_TEST (unsigned long);
DIRECT_USE_TEST (long);
DIRECT_USE_TEST (double);
#ifndef _RWSTD_NO_LONG_DOUBLE
DIRECT_USE_TEST (long double);
#endif
DIRECT_USE_TEST (void*);
}
/**************************************************************************/
// for convenience
#define boolalpha std::ios_base::boolalpha
#define dec std::ios_base::dec
#define fixed std::ios_base::fixed
#define hex std::ios_base::hex
#define internal std::ios_base::internal
#define left std::ios_base::left
#define oct std::ios_base::oct
#define right std::ios_base::right
#define scientific std::ios_base::scientific
#define showbase std::ios_base::showbase
#define showpoint std::ios_base::showpoint
#define showpos std::ios_base::showpos
#define skipws std::ios_base::skipws
#define unitbuf std::ios_base::unitbuf
#define uppercase std::ios_base::uppercase
#define bin std::ios_base::bin
#define adjustfield std::ios_base::adjustfield
#define basefield std::ios_base::basefield
#define floatfield std::ios_base::floatfield
#define nolock std::ios_base::nolock
#define nolockbuf std::ios_base::nolockbuf
#define Bad std::ios_base::badbit
#define Eof std::ios_base::eofbit
#define Fail std::ios_base::failbit
#define Good std::ios_base::goodbit
template <class charT>
void bool_test (charT, const char *cname)
{
#ifndef _RWSTD_NO_BOOL
rw_info (0, 0, __LINE__, "std::num_put<%s>::put (..., bool)", cname);
const char* const tname = "bool";
static const charT boolnames[][4] = {
{ 'y', 'e', 's', '\0' }, { 'n', 'o', '.', '\0' },
// unusual strings to try to trip up the formatting algorithm
{ '+', '1', '\0' }, { '-', '2', '\0' },
{ '-', '+', '1', '\0' }, { '+', '-', '0', '\0' },
{ '\001', '\0' }, { '\0' }
};
Punct<charT>::decimal_point_ = '*';
Punct<charT>::truename_ = boolnames [0];
Punct<charT>::falsename_ = boolnames [1];
// set line number to __LINE__ and perform test so that
// assertion output will point to the failed TEST line
#define TEST do_test
#define T charT (), cname, tname, __LINE__
TEST (T, false, 0, 0, 0, ' ', "", "0");
TEST (T, true, 0, 0, 0, ' ', "", "1");
TEST (T, false, 0, 0, 0, ' ', "", "%d");
TEST (T, true, 0, 0, 0, ' ', "", "%d");
TEST (T, false, showpos, 0, 0, ' ', "", "%+d");
TEST (T, true, showpos, 0, 0, ' ', "", "%+d");
TEST (T, false, oct, 0, 0, ' ', "", "%o");
TEST (T, true, oct, 0, 0, ' ', "", "%o");
TEST (T, false, dec, 0, 0, ' ', "", "%d");
TEST (T, true, dec, 0, 0, ' ', "", "%d");
TEST (T, false, hex, 0, 0, ' ', "", "%x");
TEST (T, true, hex, 0, 0, ' ', "", "%x");
rw_info (0, 0, __LINE__, "std::ios::boolalpha");
TEST (T, false, boolalpha, 0, 0, ' ', "", "no.");
TEST (T, true, boolalpha, 0, 0, ' ', "", "yes");
// left justified boolalpha
TEST (T, false, boolalpha | left, 0, 6, ' ', "", "no. ");
TEST (T, true, boolalpha | left, 0, 6, ' ', "", "yes ");
// right justified boolalpha
TEST (T, false, boolalpha | right, 0, 6, ' ', "", " no.");
TEST (T, true, boolalpha | right, 0, 6, ' ', "", " yes");
// implied right justified boolalpha (internal bit set)
TEST (T, false, boolalpha | internal, 0, 4, ' ', "", " no.");
TEST (T, true, boolalpha | internal, 0, 4, ' ', "", " yes");
Punct<charT>::truename_ = boolnames [2];
Punct<charT>::falsename_ = boolnames [3];
TEST (T, false, boolalpha, 0, 1, ' ', "", "-2");
TEST (T, true, boolalpha, 0, 1, ' ', "", "+1");
TEST (T, false, boolalpha | internal, 0, 4, ' ', "", " -2");
TEST (T, true, boolalpha | internal, 0, 4, ' ', "", " +1");
Punct<charT>::truename_ = boolnames [4];
Punct<charT>::falsename_ = boolnames [5];
TEST (T, false, boolalpha, 0, 1, ' ', "", "+-0");
TEST (T, true, boolalpha, 0, 1, ' ', "", "-+1");
TEST (T, false, boolalpha | internal, 0, 4, ' ', "", " +-0");
TEST (T, true, boolalpha | internal, 0, 4, ' ', "", " -+1");
Punct<charT>::truename_ = boolnames [6];
Punct<charT>::falsename_ = boolnames [7];
TEST (T, false, boolalpha, 0, 0, ' ', "", "");
TEST (T, true, boolalpha, 0, 0, ' ', "", "\001");
TEST (T, false, boolalpha, 0, 1, ' ', "", " ");
TEST (T, true, boolalpha, 0, 1, ' ', "", "\001");
TEST (T, false, boolalpha, 0, 1, ',', "", ",");
TEST (T, true, boolalpha, 0, 1, ',', "", "\001");
TEST (T, false, boolalpha | internal, 0,4, ',', "", ",,,,");
TEST (T, true, boolalpha | internal, 0,4, ',', "", ",,,\001");
#endif // _RWSTD_NO_BOOL
}
/**************************************************************************/
template <class charT>
void long_test (charT, const char *cname)
{
const char* const tname = "long";
rw_info (0, 0, __LINE__, "std::num_put<%s>::put (..., %s)", cname, tname);
// working around a VAC++/AIX bug where LONG_{MIN,MAX} are
// of type int rather than long as required (see PR #28798)
#undef LONG_MIN
#define LONG_MIN _RWSTD_LONG_MIN
#undef LONG_MAX
#define LONG_MAX _RWSTD_LONG_MAX
#undef GET_FAIL
#define GET_FAIL (Eof | Fail), LONG_MAX
//////////////////////////////////////////////////////////////////
// implicit decimal output
rw_info (0, 0, __LINE__, "std::ios::fmtflags ()");
TEST (T, 0L, 0, 0, 0, ' ', "", "%ld");
TEST (T, 1L, 0, 0, 0, ' ', "", "%ld");
TEST (T, 2L, 0, 0, 0, ' ', "", "%ld");
TEST (T, -3L, 0, 0, 0, ' ', "", "%ld");
TEST (T, 12L, 0, 0, 0, ' ', "", "%ld");
TEST (T, -13L, 0, 0, 0, ' ', "", "%ld");
TEST (T, 345L, 0, 0, 0, ' ', "", "%ld");
TEST (T, -456L, 0, 0, 0, ' ', "", "%ld");
TEST (T, 6789L, 0, 0, 0, ' ', "", "%ld");
TEST (T, -7890L, 0, 0, 0, ' ', "", "%ld");
TEST (T, 98765L, 0, 0, 0, ' ', "", "%ld");
TEST (T, -98766L, 0, 0, 0, ' ', "", "%ld");
TEST (T, LONG_MAX, 0, 0, 0, ' ', "", "%ld");
TEST (T, LONG_MIN, 0, 0, 0, ' ', "", "%ld");
//////////////////////////////////////////////////////////////////
// explicit decimal ouptut
rw_info (0, 0, __LINE__, "std::ios::dec");
TEST (T, 0L, dec, 0, 0, ' ', "", "%ld");
TEST (T, 1L, dec, 0, 0, ' ', "", "%ld");
TEST (T, 2L, dec, 0, 0, ' ', "", "%ld");
TEST (T, 12L, dec, 0, 0, ' ', "", "%ld");
TEST (T, 345L, dec, 0, 0, ' ', "", "%ld");
TEST (T, 6789L, dec, 0, 0, ' ', "", "%ld");
TEST (T, 98765L, dec, 0, 0, ' ', "", "%ld");
TEST (T, LONG_MAX, dec, 0, 0, ' ', "", "%ld");
TEST (T, ~0L, dec, 0, 0, ' ', "", "%ld");
TEST (T, -1L, dec, 0, 0, ' ', "", "%ld");
TEST (T, -2L, dec, 0, 0, ' ', "", "%ld");
TEST (T, -12L, dec, 0, 0, ' ', "", "%ld");
TEST (T, -345L, dec, 0, 0, ' ', "", "%ld");
TEST (T, -6789L, dec, 0, 0, ' ', "", "%ld");
TEST (T, -98765L, dec, 0, 0, ' ', "", "%ld");
TEST (T, LONG_MIN, dec, 0, 0, ' ', "", "%ld");
rw_info (0, 0, __LINE__, "std::ios::dec | std::ios::showbase");
TEST (T, 0L, dec | showbase, 0, 0, ' ', "", "%#ld");
TEST (T, 1234L, dec | showbase, 0, 0, ' ', "", "%#ld");
TEST (T, -1235L, dec | showbase, 0, 0, ' ', "", "%#ld");
TEST (T, LONG_MAX, dec | showbase, 0, 0, ' ', "", "%#ld");
TEST (T, LONG_MIN, dec | showbase, 0, 0, ' ', "", "%#ld");
rw_info (0, 0, __LINE__, "std::ios::dec | std::ios::showpos");
TEST (T, 0L, dec | showpos, 0, 0, ' ', "", "%+ld");
TEST (T, 1236L, dec | showpos, 0, 0, ' ', "", "%+ld");
TEST (T, -1237L, dec | showpos, 0, 0, ' ', "", "%+ld");
TEST (T, LONG_MAX, dec | showpos, 0, 0, ' ', "", "%+ld");
TEST (T, LONG_MIN, dec | showpos, 0, 0, ' ', "", "%+ld");
rw_info (0, 0, __LINE__,
"std::ios::dec | std::ios::showbase | std::ios::showpos");
TEST (T, 0L, dec | showbase | showpos, 0, 0, ' ', "", "%#+ld");
TEST (T, 1238L, dec | showbase | showpos, 0, 0, ' ', "", "%#+ld");
TEST (T, -1239L, dec | showbase | showpos, 0, 0, ' ', "", "%#+ld");
TEST (T, LONG_MAX, dec | showbase | showpos, 0, 0, ' ', "", "%#+ld");
TEST (T, LONG_MIN, dec | showbase | showpos, 0, 0, ' ', "", "%#+ld");
// left justfication
rw_info (0, 0, __LINE__, "std::ios::dec | std::ios::left");
TEST (T, 0L, dec | left, 0, 10, ' ', "", "%-10ld");
TEST (T, 1L, dec | left, 0, 10, ' ', "", "%-10ld");
TEST (T, 12L, dec | left, 0, 10, ' ', "", "%-10ld");
TEST (T, 123L, dec | left, 0, 10, ' ', "", "%-10ld");
TEST (T, 1234L, dec | left, 0, 10, ' ', "", "%-10ld");
TEST (T, 12345L, dec | left, 0, 10, ' ', "", "%-10ld");
TEST (T, 123456L, dec | left, 0, 10, ' ', "", "%-10ld");
TEST (T, 1234567L, dec | left, 0, 10, ' ', "", "%-10ld");
TEST (T, 12345678L, dec | left, 0, 10, ' ', "", "%-10ld");
TEST (T, 123456789L, dec | left, 0, 10, ' ', "", "%-10ld");
// left justfication, signed dec
TEST (T, -1L, dec | left, 0, 10, ' ', "", "-1 ");
TEST (T, -12L, dec | left, 0, 10, ' ', "", "-12 ");
TEST (T, -123L, dec | left, 0, 10, ' ', "", "-123 ");
TEST (T, -1234L, dec | left, 0, 10, ' ', "", "-1234 ");
TEST (T, -12345L, dec | left, 0, 10, ' ', "", "-12345 ");
TEST (T, -123456L, dec | left, 0, 10, ' ', "", "-123456 ");
TEST (T, -1234567L, dec | left, 0, 10, ' ', "", "-1234567 ");
TEST (T, -12345678L, dec | left, 0, 10, ' ', "", "-12345678 ");
TEST (T, -123456789L, dec | left, 0, 10, ' ', "", "-123456789");
// left justification with fill char
TEST (T, -1L, dec | left, 0, 10, '#', "", "-1########");
TEST (T, -12L, dec | left, 0, 10, '@', "", "-12@@@@@@@");
TEST (T, -123L, dec | left, 0, 10, '*', "", "-123******");
TEST (T, -1234L, dec | left, 0, 10, '=', "", "-1234=====");
TEST (T, -12345L, dec | left, 0, 10, '.', "", "-12345....");
TEST (T, -123456L, dec | left, 0, 10, ',', "", "-123456,,,");
TEST (T, -1234567L, dec | left, 0, 10, '-', "", "-1234567--");
TEST (T, -12345678L, dec | left, 0, 10, '+', "", "-12345678+");
TEST (T, -123456789L, dec | left, 0, 10, ';', "", "-123456789");
// left justfication with grouping
TEST (T, 1L, dec | left, 0, 14, ' ', "\2", "1 ");
TEST (T, 12L, dec | left, 0, 14, ' ', "\2", "12 ");
TEST (T, 123L, dec | left, 0, 14, ' ', "\2", "1,23 ");
TEST (T, 1234L, dec | left, 0, 14, ' ', "\2", "12,34 ");
TEST (T, 12345L, dec | left, 0, 14, ' ', "\2", "1,23,45 ");
TEST (T, 123456L, dec | left, 0, 14, ' ', "\2", "12,34,56 ");
TEST (T, 1234567L, dec | left, 0, 14, ' ', "\2", "1,23,45,67 ");
TEST (T, 12345678L, dec | left, 0, 14, ' ', "\2", "12,34,56,78 ");
TEST (T, 123456789L, dec | left, 0, 14, ' ', "\2", "1,23,45,67,89 ");
TEST (T, 123456789L, dec | left, 0, 14, ',', "\2", "1,23,45,67,89,");
TEST (T, 1L, dec | left, 0, 14, ' ', "\2\1\3", "1 ");
TEST (T, 12L, dec | left, 0, 14, ' ', "\2\1\3", "12 ");
TEST (T, 123L, dec | left, 0, 14, ' ', "\2\1\3", "1,23 ");
TEST (T, 1234L, dec | left, 0, 14, ' ', "\2\1\3", "1,2,34 ");
TEST (T, 12345L, dec | left, 0, 14, ' ', "\2\1\3", "12,3,45 ");
TEST (T, 123456L, dec | left, 0, 14, ' ', "\2\1\3", "123,4,56 ");
TEST (T, 1234567L, dec | left, 0, 14, ' ', "\2\1\3", "1,234,5,67 ");
TEST (T, 12345678L, dec | left, 0, 14, ' ', "\2\1\3", "12,345,6,78 ");
TEST (T, 123456789L, dec | left, 0, 14, ' ', "\2\1\3", "123,456,7,89 ");
TEST (T, 123456789L, dec | left, 0, 14, '0', "\2\1\3", "123,456,7,8900");
TEST (T, -1L, dec | left, 0, 14, ' ', "\1\2\3", "-1 ");
TEST (T, -12L, dec | left, 0, 14, ' ', "\1\2\3", "-1,2 ");
TEST (T, -123L, dec | left, 0, 14, ' ', "\1\2\3", "-12,3 ");
TEST (T, -1234L, dec | left, 0, 14, ' ', "\1\2\3", "-1,23,4 ");
TEST (T, -12345L, dec | left, 0, 14, ' ', "\1\2\3", "-12,34,5 ");
TEST (T, -123456L, dec | left, 0, 14, ' ', "\1\2\3", "-123,45,6 ");
TEST (T, -1234567L, dec | left, 0, 14, ' ', "\1\2\3", "-1,234,56,7 ");
TEST (T, -12345678L, dec | left, 0, 14, ' ', "\1\2\3", "-12,345,67,8 ");
TEST (T, -123456789L, dec | left, 0, 14, ' ', "\1\2\3", "-123,456,78,9 ");
TEST (T, -123456789L, dec | left, 0, 14, ' ', "\3\1\2", "-1,23,45,6,789");
TEST (T, -123456780L, dec | left, 0, 14, ' ', "\x1", "-1,2,3,4,5,6,7,8,0");
TEST (T, -123456781L, dec | left, 0, 14, ' ', "\x2", "-1,23,45,67,81");
TEST (T, -123456782L, dec | left, 0, 14, ' ', "\x3", "-123,456,782 ");
TEST (T, -123456783L, dec | left, 0, 14, ' ', "\x4", "-1,2345,6783 ");
TEST (T, -123456784L, dec | left, 0, 14, ' ', "\x5", "-1234,56784 ");
TEST (T, -123456785L, dec | left, 0, 14, ' ', "\x6", "-123,456785 ");
TEST (T, -123456786L, dec | left, 0, 14, ' ', "\x7", "-12,3456786 ");
TEST (T, -123456787L, dec | left, 0, 14, ' ', "\x8", "-1,23456787 ");
TEST (T, -123456788L, dec | left, 0, 14, ' ', "\x9", "-123456788 ");
#ifndef _RWSTD_NO_EXT_BIN_IO
rw_info (0, 0, __LINE__, "std::ios::dec | std::ios::bin [extension]");
TEST (T, 33333333L, bin | dec, 0, 0, ' ', "", "%ld");
#endif // _RWSTD_NO_EXT_BIN_IO
//////////////////////////////////////////////////////////////////
// explicit octal ouptut
rw_info (0, 0, __LINE__, "std::ios::oct");
TEST (T, 0L, oct, 0, 0, ' ', "", "%lo");
TEST (T, 1L, oct, 0, 0, ' ', "", "%lo");
TEST (T, 2L, oct, 0, 0, ' ', "", "%lo");
TEST (T, 12L, oct, 0, 0, ' ', "", "%lo");
TEST (T, 345L, oct, 0, 0, ' ', "", "%lo");
TEST (T, 6789L, oct, 0, 0, ' ', "", "%lo");
TEST (T, 98765L, oct, 0, 0, ' ', "", "%lo");
TEST (T, LONG_MAX, oct, 0, 0, ' ', "", "%lo");
TEST (T, LONG_MAX - 1, oct, 0, 0, ' ', "", "%lo");
// negative values formatted as oct cause overflow on input (lwg issue 23)
TEST (T, ~0L, oct, 0, 0, ' ', "", "%lo", GET_FAIL);
TEST (T, -1L, oct, 0, 0, ' ', "", "%lo", GET_FAIL);
TEST (T, -2L, oct, 0, 0, ' ', "", "%lo", GET_FAIL);
TEST (T, -12L, oct, 0, 0, ' ', "", "%lo", GET_FAIL);
TEST (T, -345L, oct, 0, 0, ' ', "", "%lo", GET_FAIL);
TEST (T, -6789L, oct, 0, 0, ' ', "", "%lo", GET_FAIL);
TEST (T, -98765L, oct, 0, 0, ' ', "", "%lo", GET_FAIL);
TEST (T, LONG_MIN, oct, 0, 0, ' ', "", "%lo", GET_FAIL);
rw_info (0, 0, __LINE__, "std::ios::oct | std::ios::dec");
TEST (T, 13579L, oct | dec, 0, 0, ' ', "", "%ld");
rw_info (0, 0, __LINE__, "std::ios::oct | std::ios::showbase");
TEST (T, 0L, oct | showbase, 0, 0, ' ', "", "%#lo");
TEST (T, 2345L, oct | showbase, 0, 0, ' ', "", "%#lo");
TEST (T, -2346L, oct | showbase, 0, 0, ' ', "", "%#lo", GET_FAIL);
TEST (T, LONG_MAX, oct | showbase, 0, 0, ' ', "", "%#+lo");
TEST (T, LONG_MIN, oct | showbase, 0, 0, ' ', "", "%#+lo", GET_FAIL);
rw_info (0, 0, __LINE__, "std::ios::oct | std::ios::showpos");
TEST (T, 0L, oct | showpos, 0, 0, ' ', "", "%+lo");
TEST (T, 2347L, oct | showpos, 0, 0, ' ', "", "%+lo");
TEST (T, -2348L, oct | showpos, 0, 0, ' ', "", "%+lo", GET_FAIL);
TEST (T, LONG_MAX, oct | showpos, 0, 0, ' ', "", "%+lo");
TEST (T, LONG_MIN, oct | showpos, 0, 0, ' ', "", "%+lo", GET_FAIL);
rw_info (0, 0, __LINE__,
"std::ios::oct | std::ios::showbase | std::ios::showpos");
TEST (T, 0L, oct | showbase | showpos, 0, 0, ' ', "", "%#+lo");
TEST (T, 2349L, oct | showbase | showpos, 0, 0, ' ', "", "%#+lo");
TEST (T, -2350L, oct | showbase | showpos, 0, 0, ' ', "", "%#+lo",
GET_FAIL);
TEST (T, LONG_MAX, oct | showbase | showpos, 0, 0, ' ', "", "%#+lo");
TEST (T, LONG_MIN, oct | showbase | showpos, 0, 0, ' ', "", "%#+lo",
GET_FAIL);
#ifndef _RWSTD_NO_EXT_BIN_IO
rw_info (0, 0, __LINE__, "std::ios::oct | std::ios::bin [extension]");
TEST (T, 22222222L, bin | oct, 0, 0, ' ', "", "%ld");
#endif // _RWSTD_NO_EXT_BIN_IO
//////////////////////////////////////////////////////////////////
// explicit hexadecimal ouptut
rw_info (0, 0, __LINE__, "std::ios::hex");
TEST (T, 0L, hex, 0, 0, ' ', "", "%lx");
TEST (T, 1L, hex, 0, 0, ' ', "", "%lx");
TEST (T, 2L, hex, 0, 0, ' ', "", "%lx");
TEST (T, 12L, hex, 0, 0, ' ', "", "%lx");
TEST (T, 345L, hex, 0, 0, ' ', "", "%lx");
TEST (T, 6789L, hex, 0, 0, ' ', "", "%lx");
TEST (T, 98765L, hex, 0, 0, ' ', "", "%lx");
TEST (T, LONG_MAX, hex, 0, 0, ' ', "", "%lx");
TEST (T, LONG_MAX - 1, hex, 0, 0, ' ', "", "%lx");
TEST (T, LONG_MAX - 2, hex, 0, 0, ' ', "", "%lx");
// negative values formatted as hex cause overflow on input (lwg issue 23)
TEST (T, ~0L, hex, 0, 0, ' ', "", "%lx", GET_FAIL);
TEST (T, -1L, hex, 0, 0, ' ', "", "%lx", GET_FAIL);
TEST (T, -2L, hex, 0, 0, ' ', "", "%lx", GET_FAIL);
TEST (T, -12L, hex, 0, 0, ' ', "", "%lx", GET_FAIL);
TEST (T, -345L, hex, 0, 0, ' ', "", "%lx", GET_FAIL);
TEST (T, -6789L, hex, 0, 0, ' ', "", "%lx", GET_FAIL);
TEST (T, -98765L, hex, 0, 0, ' ', "", "%lx", GET_FAIL);
TEST (T, LONG_MIN, hex, 0, 0, ' ', "", "%lx", GET_FAIL);
rw_info (0, 0, __LINE__, "std::ios::hex | std::ios::uppercase");
TEST (T, 0L, hex | uppercase, 0, 0, ' ', "", "%lX");
TEST (T, 1L, hex | uppercase, 0, 0, ' ', "", "%lX");
TEST (T, 0XABCDL, hex | uppercase, 0, 0, ' ', "", "%lX");
TEST (T, 0XBCDEL, hex | uppercase, 0, 0, ' ', "", "%lX");
TEST (T, 0XCDEFL, hex | uppercase, 0, 0, ' ', "", "%lX");
rw_info (0, 0, __LINE__, "std::ios::hex | std::ios::showbase");
TEST (T, 0L, hex | showbase, 0, 0, ' ', "", "%#lx");
TEST (T, 1L, hex | showbase, 0, 0, ' ', "", "%#lx");
TEST (T, 0xdef1L, hex | showbase, 0, 0, ' ', "", "%#lx");
rw_info (0, 0, __LINE__,
"std::ios::hex | std::ios::uppercase | std::ios::showbase");
TEST (T, 0L, hex | uppercase | showbase, 0, 0, ' ', "", "%#lX");
TEST (T, 1L, hex | uppercase | showbase, 0, 0, ' ', "", "%#lX");
TEST (T, 0XEF02L, hex | uppercase | showbase, 0, 0, ' ', "", "%#lX");
rw_info (0, 0, __LINE__, "std::ios::hex | std::ios::oct");
TEST (T, 0L, oct | hex, 0, 0, ' ', "", "%ld");
TEST (T, 97531L, oct | hex, 0, 0, ' ', "", "%ld");
rw_info (0, 0, __LINE__, "std::ios::hex | std::ios::dec");
TEST (T, 86420L, dec | hex, 0, 0, ' ', "", "%ld");
rw_info (0, 0, __LINE__, "std::ios::hex | std::ios::dec | std::ios::oct");
TEST (T, 11111111L, oct | dec | hex, 0, 0, ' ', "", "%ld");
#ifndef _RWSTD_NO_EXT_BIN_IO
rw_info (0, 0, __LINE__, "std::ios::hex | std::ios::bin [extension]");
TEST (T, 44444444L, bin | hex, 0, 0, ' ', "", "%ld");
rw_info (0, 0, __LINE__, "std::ios::hex | std::ios::dec | "
"std::ios::oct | std::ios::bin [extension]");
TEST (T, 55555555L, bin | oct | dec | hex, 0, 0, ' ', "", "%ld");
#endif // _RWSTD_NO_EXT_BIN_IO
//////////////////////////////////////////////////////////////////
// extension: fixed and negative precision
rw_info (0, 0, __LINE__,
"std::ios::fixed with negative precision [extension]");
TEST (T, 987654321L, 0, -1, 0, ' ', "", "987654321");
TEST (T, 987654322L, fixed, 0, 0, ' ', "", "987654322");
TEST (T, 987654323L, fixed, -1, 0, ' ', "", "98765432*3");
TEST (T, -987654323L, fixed, -1, 0, ' ', "", "-98765432*3");
TEST (T, 987654324L, fixed, -2, 0, ' ', "", "9876543*24");
TEST (T, -987654324L, fixed, -2, 0, ' ', "", "-9876543*24");
TEST (T, 987654325L, fixed, -3, 0, ' ', "", "987654*325");
TEST (T, -987654325L, fixed, -3, 0, ' ', "", "-987654*325");
TEST (T, 987654326L, fixed, -4, 0, ' ', "", "98765*4326");
TEST (T, -987654326L, fixed, -4, 0, ' ', "", "-98765*4326");
TEST (T, 987654327L, fixed, -5, 0, ' ', "", "9876*54327");
TEST (T, -987654327L, fixed, -5, 0, ' ', "", "-9876*54327");
TEST (T, 987654328L, fixed, -6, 0, ' ', "", "987*654328");
TEST (T, -987654328L, fixed, -6, 0, ' ', "", "-987*654328");
TEST (T, 987654329L, fixed, -7, 0, ' ', "", "98*7654329");
TEST (T, -987654329L, fixed, -7, 0, ' ', "", "-98*7654329");
TEST (T, 987654330L, fixed, -8, 0, ' ', "", "9*87654330");
TEST (T, -987654330L, fixed, -8, 0, ' ', "", "-9*87654330");
TEST (T, 987654331L, fixed, -9, 0, ' ', "", "0*987654331");
TEST (T, -987654331L, fixed, -9, 0, ' ', "", "-0*987654331");
TEST (T, 987654332L, fixed, -10, 0, ' ', "", "0*0987654332");
TEST (T, -987654332L, fixed, -10, 0, ' ', "", "-0*0987654332");
TEST (T, 987654333L, fixed, -11, 0, ' ', "", "0*00987654333");
TEST (T, -987654333L, fixed, -11, 0, ' ', "", "-0*00987654333");
TEST (T, 0L, fixed, -12, 0, ' ', "", "0*000000000000");
//////////////////////////////////////////////////////////////////
// second group is the last group (i.e., prevent repetition)
#if CHAR_MAX == UCHAR_MAX
# define GROUPING "\2\1\xff"
#else
# define GROUPING "\2\1\x7f"
#endif
TEST (T, 123456789L, dec | left, 0, 0, ' ', GROUPING, "123456,7,89");
TEST (T, -123456789L, dec | left, 0, 0, ' ', GROUPING, "-123456,7,89");
#undef GROUPING
#if CHAR_MAX == UCHAR_MAX
# define GROUPING "\2\3\xff"
#else
# define GROUPING "\2\3\x7f"
#endif
TEST (T, 123456789L, dec | left, 0, 0, ' ', GROUPING, "1234,567,89");
TEST (T, -123456789L, dec | left, 0, 0, ' ', GROUPING, "-1234,567,89");
TEST (T, 0x12345678L, hex | showbase, 0, 0, ' ', GROUPING, "0x123,456,78");
//////////////////////////////////////////////////////////////////
// right justfication
rw_info (0, 0, __LINE__, "std::ios::right");
TEST (T, 1L, dec | right, 0, 10, ' ', "", " 1");
TEST (T, 12L, dec | right, 0, 10, ' ', "", " 12");
TEST (T, 123L, dec | right, 0, 10, ' ', "", " 123");
TEST (T, 1234L, dec | right, 0, 10, ' ', "", " 1234");
TEST (T, 12345L, dec | right, 0, 10, ' ', "", " 12345");
TEST (T, 123456L, dec | right, 0, 10, ' ', "", " 123456");
TEST (T, 1234567L, dec | right, 0, 10, ' ', "", " 1234567");
TEST (T, 12345678L, dec | right, 0, 10, ' ', "", " 12345678");
TEST (T, 123456789L, dec | right, 0, 10, ' ', "", " 123456789");
TEST (T, 123456789L, dec | right, 0, 10, '0', "", "0123456789");
TEST (T, 123456789L, dec | right, 0, 10, '+', "", "+123456789");
TEST (T, 123456789L, dec | right, 0, 10, '-', "", "-123456789");
// right justification, oct
TEST (T, 0L, oct | right, 0, 10, ' ', "", " 0");
TEST (T, 01L, oct | right, 0, 10, ' ', "", " 1");
TEST (T, 012L, oct | right, 0, 10, ' ', "", " 12");
TEST (T, 0123L, oct | right, 0, 10, ' ', "", " 123");
TEST (T, 01234L, oct | right, 0, 10, ' ', "", " 1234");
TEST (T, 012345L, oct | right, 0, 10, ' ', "", " 12345");
TEST (T, 0123456L, oct | right, 0, 10, ' ', "", " 123456");
TEST (T, 01234567L, oct | right, 0, 10, ' ', "", " 1234567");
TEST (T, 012345670L, oct | right, 0, 10, ' ', "", " 12345670");
TEST (T, 012345670L, oct | right, 0, 10, '1', "", "1112345670");
// right justification with grouping
TEST (T, 0L, oct | right, 0, 10, ' ', "\2", " 0");
TEST (T, 01L, oct | right, 0, 10, ' ', "\2", " 1");
TEST (T, 012L, oct | right, 0, 10, ' ', "\2", " 12");
TEST (T, 0123L, oct | right, 0, 10, ' ', "\2", " 1,23");
TEST (T, 01234L, oct | right, 0, 10, ' ', "\2", " 12,34");
TEST (T, 012345L, oct | right, 0, 10, ' ', "\2", " 1,23,45");
TEST (T, 0123456L, oct | right, 0, 10, ' ', "\2", " 12,34,56");
TEST (T, 01234567L, oct | right, 0, 10, ' ', "\2", "1,23,45,67");
TEST (T, 012345670L, oct | right, 0, 10, ' ', "\2", "12,34,56,70");
#undef FLAGS
#define flags hex | showbase | internal
#define FLAGS flags | uppercase
// internal justfication, hex
rw_info (0, 0, __LINE__, "std::ios::internal");
TEST (T, 0X1L, FLAGS, 0, 10, ' ', "", "0X 1");
TEST (T, 0x12L, flags, 0, 10, ' ', "", "0x 12");
TEST (T, 0X123L, FLAGS, 0, 10, ' ', "", "0X 123");
TEST (T, 0x1234L, flags, 0, 10, ' ', "", "0x 1234");
TEST (T, 0X12345L, FLAGS, 0, 10, ' ', "", "0X 12345");
TEST (T, 0x123abcL, flags, 0, 10, ' ', "", "0x 123abc");
TEST (T, 0x123abcL, flags, 0, 10, '0', "", "0x00123abc");
TEST (T, 0X1234ABCL, FLAGS, 0, 10, ' ', "", "0X 1234ABC");
TEST (T, 0X12345678L, FLAGS, 0, 10, ' ', "", "0X12345678");
TEST (T, 0X12345678L, FLAGS, 0, 10, '0', "", "0X12345678");
// internal justfication, hex, grouping
TEST (T, 0X1L, FLAGS, 0, 10, ' ', "\1\2", "0X 1");
TEST (T, 0x12L, flags, 0, 10, ' ', "\1\2", "0x 1,2");
TEST (T, 0X123L, FLAGS, 0, 10, ' ', "\1\2", "0X 12,3");
TEST (T, 0x1234L, flags, 0, 10, ' ', "\1\2", "0x 1,23,4");
TEST (T, 0X12345L, FLAGS, 0, 10, ' ', "\1\2", "0X 12,34,5");
TEST (T, 0X12345L, FLAGS, 0, 10, ',', "\1\2", "0X,12,34,5");
TEST (T, 0x123abcL, flags, 0, 10, ' ', "\1\2", "0x1,23,ab,c");
TEST (T, 0X1234ABCL, FLAGS, 0, 10, ' ', "\1\2", "0X12,34,AB,C");
TEST (T, 0X12345678L, FLAGS, 0, 10, ' ', "\1\2", "0X1,23,45,67,8");
TEST (T, 0X12345678L, FLAGS, 0, 10, '0', "\1\2", "0X1,23,45,67,8");
#undef flags
#undef FLAGS
#define FLAGS dec | showpos | internal
// internal justfication, signed dec
TEST (T, 0L, FLAGS, 0, 10, ' ', "", "+ 0");
TEST (T, -1L, FLAGS, 0, 10, ' ', "", "- 1");
TEST (T, +12L, FLAGS, 0, 10, ' ', "", "+ 12");
TEST (T, -123L, FLAGS, 0, 10, ' ', "", "- 123");
TEST (T, +1234L, FLAGS, 0, 10, ' ', "", "+ 1234");
TEST (T, -12345L, FLAGS, 0, 10, ' ', "", "- 12345");
TEST (T, +123456L, FLAGS, 0, 10, ' ', "", "+ 123456");
TEST (T, -1234567L, FLAGS, 0, 10, ' ', "", "- 1234567");
TEST (T, +12345678L, FLAGS, 0, 10, ' ', "", "+ 12345678");
TEST (T, -123456789L, FLAGS, 0, 10, '0', "", "-123456789");
TEST (T, +1L, FLAGS, 0, 10, '-', "", "+--------1");
TEST (T, -12L, FLAGS, 0, 10, '-', "", "--------12");
TEST (T, +123L, FLAGS, 0, 10, '+', "", "+++++++123");
TEST (T, -1234L, FLAGS, 0, 10, '+', "", "-+++++1234");
TEST (T, +12345L, FLAGS, 0, 10, '0', "", "+000012345");
TEST (T, -123456L, FLAGS, 0, 10, '1', "", "-111123456");
TEST (T, +1234567L, FLAGS, 0, 10, '2', "", "+221234567");
TEST (T, -12345678L, FLAGS, 0, 10, '3', "", "-312345678");
TEST (T, +123456789L, FLAGS, 0, 10, '4', "", "+123456789");
#ifndef _RWSTD_NO_EXT_BIN_IO
// bin
rw_info (0, 0, __LINE__, "std::ios::bin [extension]");
TEST (T, 0L, bin, 0, 16, '.', "\4", "...............0");
TEST (T, 1L, bin, 0, 16, '.', "\4", "...............1");
TEST (T, 2L, bin, 0, 16, '.', "\4", "..............10");
TEST (T, 3L, bin, 0, 16, '.', "\4", "..............11");
TEST (T, 4L, bin, 0, 16, '.', "\4", ".............100");
TEST (T, 5L, bin, 0, 16, '.', "\4", ".............101");
TEST (T, 6L, bin, 0, 16, '.', "\4", ".............110");
TEST (T, 7L, bin, 0, 16, '.', "\4", ".............111");
TEST (T, 8L, bin, 0, 16, '.', "\4", "............1000");
TEST (T, 9L, bin, 0, 16, '.', "\4", "............1001");
TEST (T, 0x0aL, bin, 0, 16, '.', "\4", "............1010");
TEST (T, 0x0bL, bin, 0, 16, '.', "\4", "............1011");
TEST (T, 0x0cL, bin, 0, 16, '.', "\4", "............1100");
TEST (T, 0x0dL, bin, 0, 16, '.', "\4", "............1101");
TEST (T, 0x0eL, bin, 0, 16, '.', "\4", "............1110");
TEST (T, 0x0fL, bin, 0, 16, '.', "\4", "............1111");
TEST (T, 0xf0L, bin, 0, 16, '.', "\4", ".......1111,0000");
TEST (T, 0xf1L, bin, 0, 16, '.', "\4", ".......1111,0001");
TEST (T, 0xf2L, bin, 0, 16, '.', "\4", ".......1111,0010");
TEST (T, 0xf3L, bin, 0, 16, '.', "\4", ".......1111,0011");
TEST (T, 0xf4L, bin, 0, 16, '.', "\4", ".......1111,0100");
TEST (T, 0xf5L, bin, 0, 16, '.', "\4", ".......1111,0101");
TEST (T, 0x12345678L, bin, 0, 0, '.', "\4",
"1,0010,0011,0100,0101,0110,0111,1000");
TEST (T, 0xfedcba98L, bin, 0, 0, '\0', "\010",
"11111110,11011100,10111010,10011000");
#endif // _RWSTD_NO_EXT_BIN_IO
// locale 3.0 extension
#define BASE(n) ((n) << _RWSTD_IOS_BASEOFF)
// bases 0 and 10 are both base 10
// base 1 is roman (values 1 through 4999)
// bases 2 through 36 are what they are
// anything else is unspecified
rw_info (0, 0, __LINE__, "base 1 (Roman), and 2 through 36 [extension]");
TEST (T, 1234L, BASE ( 0), 0, 0, '\0', "", "1234");
TEST (T, 1234L, BASE ( 1), 0, 0, '\0', "", "mccxxxiv");
TEST (T, 0x1234L, BASE ( 2), 0, 0, '\0', "", "1001000110100");
TEST (T, 01234L, oct | BASE ( 8), 0, 0, '\0', "", "1234");
TEST (T, 1234L, dec | BASE (10), 0, 0, '\0', "", "1234");
TEST (T, 0x1234L, hex | BASE (16), 0, 0, '\0', "", "1234");
TEST (T, 1234L, BASE ( 2), 0, 0, '\0', "", "10011010010");
TEST (T, 1234L, BASE ( 3), 0, 0, '\0', "", "1200201");
TEST (T, 1234L, BASE ( 4), 0, 0, '\0', "", "103102");
TEST (T, 1234L, BASE ( 5), 0, 0, '\0', "", "14414");
TEST (T, 1234L, BASE ( 6), 0, 0, '\0', "", "5414");
TEST (T, 1234L, BASE ( 7), 0, 0, '\0', "", "3412");
TEST (T, 1234L, BASE ( 9), 0, 0, '\0', "", "1621");
TEST (T, 1234L, dec | BASE (10), 0, 0, '\0', "", "1234");
TEST (T, 1234L, BASE (11), 0, 0, '\0', "", "a22");
TEST (T, 1234L, BASE (12), 0, 0, '\0', "", "86a");
TEST (T, 1234L, BASE (13), 0, 0, '\0', "", "73c");
TEST (T, 1234L, BASE (14), 0, 0, '\0', "", "642");
TEST (T, 1234L, BASE (15), 0, 0, '\0', "", "574");
TEST (T, 1234L, hex | BASE (16), 0, 0, '\0', "", "4d2");
TEST (T, 1234L, BASE (17), 0, 0, '\0', "", "44a");
TEST (T, 1234L, BASE (18), 0, 0, '\0', "", "3ea");
TEST (T, 1234L, BASE (19), 0, 0, '\0', "", "37i");
TEST (T, 1234L, BASE (20), 0, 0, '\0', "", "31e");
TEST (T, 1234L, BASE (21), 0, 0, '\0', "", "2gg");
TEST (T, 1234L, BASE (22), 0, 0, '\0', "", "2c2");
TEST (T, 1234L, BASE (23), 0, 0, '\0', "", "27f");
TEST (T, 1234L, BASE (24), 0, 0, '\0', "", "23a");
TEST (T, 1234L, BASE (25), 0, 0, '\0', "", "1o9");
TEST (T, 1234L, BASE (26), 0, 0, '\0', "", "1lc");
TEST (T, 1234L, BASE (27), 0, 0, '\0', "", "1ij");
TEST (T, 1234L, BASE (28), 0, 0, '\0', "", "1g2");
TEST (T, 1234L, BASE (29), 0, 0, '\0', "", "1dg");
TEST (T, 1234L, BASE (30), 0, 0, '\0', "", "1b4");
TEST (T, 1234L, BASE (31), 0, 0, '\0', "", "18p");
TEST (T, 1234L, BASE (32), 0, 0, '\0', "", "16i");
TEST (T, 1234L, BASE (33), 0, 0, '\0', "", "14d");
TEST (T, 1234L, BASE (34), 0, 0, '\0', "", "12a");
TEST (T, 1234L, BASE (35), 0, 0, '\0', "", "109");
TEST (T, 1234L, BASE (36), 0, 0, '\0', "", "ya");
// effect of non-empty grouping is unspecified
TEST (T, 0L, BASE (1), 0, 0, '\0', "", "0");
TEST (T, 1L, BASE (1), 0, 0, '\0', "", "i");
TEST (T, 2L, BASE (1), 0, 0, '\0', "", "ii");
TEST (T, 3L, BASE (1), 0, 0, '\0', "", "iii");
TEST (T, 4L, BASE (1), 0, 0, '\0', "", "iv");
TEST (T, 5L, BASE (1), 0, 0, '\0', "", "v");
TEST (T, 6L, BASE (1), 0, 0, '\0', "", "vi");
TEST (T, 7L, BASE (1), 0, 0, '\0', "", "vii");
TEST (T, 8L, BASE (1), 0, 0, '\0', "", "viii");
TEST (T, 9L, BASE (1), 0, 0, '\0', "", "ix");
TEST (T, 10L, BASE (1), 0, 0, '\0', "", "x");
TEST (T, 50L, BASE (1), 0, 0, '\0', "", "l");
TEST (T, 100L, BASE (1), 0, 0, '\0', "", "c");
TEST (T, 500L, BASE (1), 0, 0, '\0', "", "d");
TEST (T, 1000L, BASE (1), 0, 0, '\0', "", "m");
TEST (T, 49L, BASE (1), 0, 0, '\0', "", "xlix");
TEST (T, 88L, BASE (1), 0, 0, '\0', "", "lxxxviii");
TEST (T, 99L, BASE (1), 0, 0, '\0', "", "xcix");
TEST (T, 1999L, BASE (1), 0, 0, '\0', "", "mcmxcix");
TEST (T, 2000L, BASE (1), 0, 0, '\0', "", "mm");
TEST (T, 2001L, BASE (1), 0, 0, '\0', "", "mmi");
TEST (T, 4999L, BASE (1), 0, 0, '\0', "", "mmmmcmxcix");
TEST (T, 5000L, BASE (1), 0, 0, '\0', "", "5000");
TEST (T, 1492L, BASE (1), 0, 10, '*', "", "***mcdxcii");
TEST (T, 1776L, BASE (1) | uppercase, 0, 0, '\0', "", "MDCCLXXVI");
}
/**************************************************************************/
template <class charT>
void ulong_test (charT, const char *cname)
{
const char* const tname = "unsigned long";
rw_info (0, 0, __LINE__, "std::num_put<%s>::put (..., %s)", cname, tname);
typedef unsigned long ULong;
//////////////////////////////////////////////////////////////////
rw_info (0, 0, __LINE__, "std::ios::dec");
TEST (T, 0UL, dec, 0, 0, ' ', "", "%lu");
TEST (T, ULong (LONG_MAX), dec, 0, 0, ' ', "", "%lu");
rw_info (0, 0, __LINE__, "std::ios::dec | std::ios::shopos");
TEST (T, 0UL, dec | showpos, 0, 0, ' ', "", "%+lu");
TEST (T, 1UL, dec | showpos, 0, 0, ' ', "", "%+lu");
TEST (T, ULong (LONG_MAX), dec | showpos, 0, 0, ' ', "", "%+lu");
//////////////////////////////////////////////////////////////////
rw_info (0, 0, __LINE__, "std::ios::oct");
TEST (T, ULong (CHAR_MAX), oct, 0, 0, ' ', "", "%lo");
TEST (T, ULong (UCHAR_MAX), oct, 0, 0, ' ', "", "%lo");
TEST (T, ULong (SCHAR_MAX), oct, 0, 0, ' ', "", "%lo");
TEST (T, ULong (SHRT_MAX), oct, 0, 0, ' ', "", "%lo");
TEST (T, ULong (USHRT_MAX), oct, 0, 0, ' ', "", "%lo");
TEST (T, ULong (INT_MAX), oct, 0, 0, ' ', "", "%lo");
TEST (T, ULong (UINT_MAX), oct, 0, 0, ' ', "", "%lo");
TEST (T, ULong (LONG_MAX), oct, 0, 0, ' ', "", "%lo");
TEST (T, ULong (CHAR_MIN), oct, 0, 0, ' ', "", "%lo");
TEST (T, ULong (SCHAR_MIN), oct, 0, 0, ' ', "", "%lo");
TEST (T, ULong (SHRT_MIN), oct, 0, 0, ' ', "", "%lo");
TEST (T, ULong (INT_MIN), oct, 0, 0, ' ', "", "%lo");
TEST (T, ULong (LONG_MIN), oct, 0, 0, ' ', "", "%lo");
// no overflow
TEST (T, 1UL, oct, 0, 0, ' ', "", "%lo");
TEST (T, ~0UL, oct, 0, 0, ' ', "", "%lo");
TEST (T, ULong (ULONG_MAX), oct, 0, 0, ' ', "", "%lo");
//////////////////////////////////////////////////////////////////
rw_info (0, 0, __LINE__, "std::ios::hex");
TEST (T, ULong (CHAR_MAX), hex, 0, 0, ' ', "", "%lx");
TEST (T, ULong (UCHAR_MAX), hex, 0, 0, ' ', "", "%lx");
TEST (T, ULong (SCHAR_MAX), hex, 0, 0, ' ', "", "%lx");
TEST (T, ULong (SHRT_MAX), hex, 0, 0, ' ', "", "%lx");
TEST (T, ULong (USHRT_MAX), hex, 0, 0, ' ', "", "%lx");
TEST (T, ULong (INT_MAX), hex, 0, 0, ' ', "", "%lx");
TEST (T, ULong (UINT_MAX), hex, 0, 0, ' ', "", "%lx");
TEST (T, ULong (LONG_MAX), hex, 0, 0, ' ', "", "%lx");
TEST (T, ULong (CHAR_MIN), hex, 0, 0, ' ', "", "%lx");
TEST (T, ULong (SCHAR_MIN), hex, 0, 0, ' ', "", "%lx");
TEST (T, ULong (SHRT_MIN), hex, 0, 0, ' ', "", "%lx");
TEST (T, ULong (INT_MIN), hex, 0, 0, ' ', "", "%lx");
TEST (T, ULong (LONG_MIN), hex, 0, 0, ' ', "", "%lx");
TEST (T, 1UL, hex, 0, 0, ' ', "", "%lx");
TEST (T, ~0UL, hex, 0, 0, ' ', "", "%lx");
TEST (T, ULong (ULONG_MAX), hex, 0, 0, ' ', "", "%lx");
}
/**************************************************************************/
template <class charT>
void llong_test (charT, const char *cname)
{
const char* const tname = "long long";
rw_info (0, 0, 0, "std::num_put<%s>::put (..., %s)", cname, tname);
#ifndef _RWSTD_NO_LONG_LONG
# define STDIO_FMAT "%" _RWSTD_LLONG_PRINTF_PREFIX "d"
# ifndef _MSC_VER
# define LL(number) number ## LL
# else // if defined (_MSC_VER)
// MSVC 7.0 doesn't recognize the LL suffix
# define LL(number) number ## I64
# endif // _MSC_VER
TEST (T, LL (0), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, LL (1), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, LL (21), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, LL (321), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, LL (4321), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, LL (54321), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, LL (654321), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, LL (7654321), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, LL (87654321), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, LL (987654321), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, ~LL (0), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, -LL (1), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, -LL (21), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, -LL (321), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, -LL (4321), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, -LL (54321), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, -LL (654321), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, -LL (7654321), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, -LL (87654321), dec, 0, 0, ' ', "", STDIO_FMAT);
TEST (T, -LL (987654321), dec, 0, 0, ' ', "", STDIO_FMAT);
# undef FLAGS
# define FLAGS hex | showbase | internal
# undef OPTS
# define OPTS FLAGS, 0, 20, ' ', "\1\2\3\4\1\2\3\4"
// internal justfication, hex format, grouping
TEST (T, LL (0), OPTS, " 0");
TEST (T, LL (0x1), OPTS, "0x 1");
TEST (T, LL (0x12), OPTS, "0x 1,2");
TEST (T, LL (0x123), OPTS, "0x 12,3");
TEST (T, LL (0x1234), OPTS, "0x 1,23,4");
TEST (T, LL (0x12345), OPTS, "0x 12,34,5");
TEST (T, LL (0x123456), OPTS, "0x 123,45,6");
TEST (T, LL (0x1234567), OPTS, "0x 1,234,56,7");
TEST (T, LL (0x12345678), OPTS, "0x 12,345,67,8");
TEST (T, LL (0x123456789), OPTS, "0x 123,456,78,9");
TEST (T, LL (0x123456789a), OPTS, "0x 1234,567,89,a");
TEST (T, LL (0x123456789ab), OPTS, "0x 1,2345,678,9a,b");
TEST (T, LL (0x123456789abc), OPTS, "0x 1,2,3456,789,ab,c");
TEST (T, LL (0x123456789abcd), OPTS, "0x12,3,4567,89a,bc,d");
TEST (T, LL (0x123456789abcde), OPTS, "0x1,23,4,5678,9ab,cd,e");
TEST (T, LL (0x123456789abcdef), OPTS, "0x12,34,5,6789,abc,de,f");
TEST (T, LL (0x123456789abcdef0), OPTS, "0x123,45,6,789a,bcd,ef,0");
#else // if defined (_RWSTD_NO_LONG_LONG)
rw_note (0, 0, __LINE__, "num_put<%s>::put (..., %s) not exercised, "
"macro _RWSTD_NO_LONG_LONG #defined",
cname, tname);
#endif // _RWSTD_LONG_LONG
}
/**************************************************************************/
template <class charT>
void ullong_test (charT, const char *cname)
{
const char* const tname = "unsigned long long";
rw_info (0, 0, 0, "std::num_put<%s>::put (..., %s)", cname, tname);
#ifndef _RWSTD_NO_LONG_LONG
rw_warn (0, 0, __LINE__, "num_put<%s>::put (..., %s) not exercised",
cname, tname);
#else // if defined (_RWSTD_NO_LONG_LONG)
rw_note (0, 0, __LINE__, "num_put<%s>::put (..., %s) not exercised, "
"macro _RWSTD_NO_LONG_LONG #defined",
cname, tname);
#endif // _RWSTD_NO_LONG_LONG
}
/**************************************************************************/
// use a volatile variable to fool optimizers into not issuing
// warnings about division by zero
volatile double zero;
template <class charT, class floatT>
void inf_nan_test (charT, floatT, const char *cname, const char *tname)
{
rw_info (0, 0, 0, "std::num_put<%s>::put (..., %s) formatting "
"infinities", cname, tname);
// compute infinity
const floatT inf = 1 / zero;
//////////////////////////////////////////////////////////////////
// exercise the formatting of positive and negative infinities
// +-- value to format
// | +-- fmtflags
// | | +-- precision
// | | | +-- field width
// | | | | +-- fill character
// | | | | | +-- grouping
// | | | | | | +-- expected output
// | | | | | | |
// V V V V V V V
TEST (T, inf, 0, 0, 0, ' ', "", "inf");
TEST (T, inf, showpos, 0, 0, ' ', "", "+inf");
TEST (T, inf, uppercase, 0, 0, ' ', "", "INF");
TEST (T, inf, showpos | uppercase, 0, 0, ' ', "", "+INF");
TEST (T, -inf, 0, 0, 0, ' ', "", "-inf");
TEST (T, -inf, showpos, 0, 0, ' ', "", "-inf");
TEST (T, -inf, uppercase, 0, 0, ' ', "", "-INF");
TEST (T, -inf, showpos | uppercase, 0, 0, ' ', "", "-INF");
TEST (T, inf, 0, 1, 0, ' ', "", "inf");
TEST (T, inf, showpos, 1, 0, ' ', "", "+inf");
TEST (T, inf, uppercase, 1, 0, ' ', "", "INF");
TEST (T, inf, showpos | uppercase, 1, 0, ' ', "", "+INF");
TEST (T, -inf, 0, 1, 0, ' ', "", "-inf");
TEST (T, -inf, showpos, 1, 0, ' ', "", "-inf");
TEST (T, -inf, uppercase, 1, 0, ' ', "", "-INF");
TEST (T, -inf, showpos | uppercase, 1, 0, ' ', "", "-INF");
TEST (T, inf, 0, 3, 0, ' ', "", "inf");
TEST (T, inf, showpos, 3, 0, ' ', "", "+inf");
TEST (T, inf, uppercase, 3, 0, ' ', "", "INF");
TEST (T, inf, showpos | uppercase, 3, 0, ' ', "", "+INF");
TEST (T, -inf, 0, 3, 0, ' ', "", "-inf");
TEST (T, -inf, showpos, 3, 0, ' ', "", "-inf");
TEST (T, -inf, uppercase, 3, 0, ' ', "", "-INF");
TEST (T, -inf, showpos | uppercase, 3, 0, ' ', "", "-INF");
TEST (T, inf, 0, 4, 0, ' ', "", "inf");
TEST (T, inf, showpos, 4, 0, ' ', "", "+inf");
TEST (T, inf, uppercase, 4, 0, ' ', "", "INF");
TEST (T, inf, showpos | uppercase, 4, 0, ' ', "", "+INF");
TEST (T, -inf, 0, 4, 0, ' ', "", "-inf");
TEST (T, -inf, showpos, 4, 0, ' ', "", "-inf");
TEST (T, -inf, uppercase, 4, 0, ' ', "", "-INF");
TEST (T, -inf, showpos | uppercase, 4, 0, ' ', "", "-INF");
TEST (T, inf, 0, 9, 0, ' ', "", "inf");
TEST (T, inf, showpos, 9, 0, ' ', "", "+inf");
TEST (T, inf, uppercase, 9, 0, ' ', "", "INF");
TEST (T, inf, showpos | uppercase, 9, 0, ' ', "", "+INF");
TEST (T, -inf, 0, 9, 0, ' ', "", "-inf");
TEST (T, -inf, showpos, 9, 0, ' ', "", "-inf");
TEST (T, -inf, uppercase, 9, 0, ' ', "", "-INF");
TEST (T, -inf, showpos | uppercase, 9, 0, ' ', "", "-INF");
TEST (T, inf, 0, 0, 1, ' ', "", "inf");
TEST (T, inf, showpos, 0, 1, ' ', "", "+inf");
TEST (T, inf, uppercase, 0, 1, ' ', "", "INF");
TEST (T, inf, showpos | uppercase, 0, 1, ' ', "", "+INF");
TEST (T, -inf, 0, 0, 1, ' ', "", "-inf");
TEST (T, -inf, showpos, 0, 1, ' ', "", "-inf");
TEST (T, -inf, uppercase, 0, 1, ' ', "", "-INF");
TEST (T, -inf, showpos | uppercase, 0, 1, ' ', "", "-INF");
TEST (T, inf, 0, 0, 3, ' ', "", "inf");
TEST (T, inf, showpos, 0, 3, ' ', "", "+inf");
TEST (T, inf, uppercase, 0, 3, ' ', "", "INF");
TEST (T, inf, showpos | uppercase, 0, 3, ' ', "", "+INF");
TEST (T, -inf, 0, 0, 3, ' ', "", "-inf");
TEST (T, -inf, showpos, 0, 3, ' ', "", "-inf");
TEST (T, -inf, uppercase, 0, 3, ' ', "", "-INF");
TEST (T, -inf, showpos | uppercase, 0, 3, ' ', "", "-INF");
TEST (T, inf, 0, 0, 4, ' ', "", " inf");
TEST (T, inf, showpos, 0, 4, ' ', "", "+inf");
TEST (T, inf, uppercase, 0, 4, ' ', "", " INF");
TEST (T, inf, showpos | uppercase, 0, 4, ' ', "", "+INF");
TEST (T, -inf, 0, 0, 4, ' ', "", "-inf");
TEST (T, -inf, showpos, 0, 4, ' ', "", "-inf");
TEST (T, -inf, uppercase, 0, 4, ' ', "", "-INF");
TEST (T, -inf, showpos | uppercase, 0, 4, ' ', "", "-INF");
TEST (T, inf, 0, 0, 8, ' ', "", " inf");
TEST (T, inf, showpos, 0, 8, ' ', "", " +inf");
TEST (T, inf, uppercase, 0, 8, ' ', "", " INF");
TEST (T, inf, showpos | uppercase, 0, 8, ' ', "", " +INF");
TEST (T, -inf, 0, 0, 8, ' ', "", " -inf");
TEST (T, -inf, showpos, 0, 8, ' ', "", " -inf");
TEST (T, -inf, uppercase, 0, 8, ' ', "", " -INF");
TEST (T, -inf, showpos | uppercase, 0, 8, ' ', "", " -INF");
TEST (T, inf, left, 0, 9, ' ', "", "inf ");
TEST (T, inf, left | showpos, 0, 9, ' ', "", "+inf ");
TEST (T, inf, left | uppercase, 0, 9, ' ', "", "INF ");
TEST (T, inf, left | showpos | uppercase, 0, 9, ' ', "", "+INF ");
TEST (T, -inf, left, 0, 9, ' ', "", "-inf ");
TEST (T, -inf, left | showpos, 0, 9, ' ', "", "-inf ");
TEST (T, -inf, left | uppercase, 0, 9, ' ', "", "-INF ");
TEST (T, -inf, left | showpos | uppercase, 0, 9, ' ', "", "-INF ");
TEST (T, inf, right, 0, 9, ' ', "", " inf");
TEST (T, inf, right | showpos, 0, 9, ' ', "", " +inf");
TEST (T, inf, right | uppercase, 0, 9, ' ', "", " INF");
TEST (T, inf, right | showpos | uppercase, 0, 9, ' ', "", " +INF");
TEST (T, -inf, right, 0, 9, ' ', "", " -inf");
TEST (T, -inf, right | showpos, 0, 9, ' ', "", " -inf");
TEST (T, -inf, right | uppercase, 0, 9, ' ', "", " -INF");
TEST (T, -inf, right | showpos | uppercase, 0, 9, ' ', "", " -INF");
//////////////////////////////////////////////////////////////////
// exercise the formatting of positive and negative (quiet) NaNs
rw_info (0, 0, 0, "std::num_put<%s>::put (..., %s) formatting "
"NaN's", cname, tname);
// compute a quiet NaN
#if 0
// temporarily disabled (NAN format is platform specific
// and subject to bugs -- see for example STDCXX-460)
const floatT nan = 0 / zero;
TEST (T, nan, 0, 0, 0, ' ', "", "nan");
TEST (T, nan, showpos, 0, 0, ' ', "", "+nan");
TEST (T, nan, uppercase, 0, 0, ' ', "", "NAN");
TEST (T, nan, showpos | uppercase, 0, 0, ' ', "", "+NAN");
TEST (T, -nan, 0, 0, 0, ' ', "", "-nan");
TEST (T, -nan, showpos, 0, 0, ' ', "", "-nan");
TEST (T, -nan, uppercase, 0, 0, ' ', "", "-NAN");
TEST (T, -nan, showpos | uppercase, 0, 0, ' ', "", "-NAN");
TEST (T, nan, 0, 1, 0, ' ', "", "nan");
TEST (T, nan, showpos, 1, 0, ' ', "", "+nan");
TEST (T, nan, uppercase, 1, 0, ' ', "", "NAN");
TEST (T, nan, showpos | uppercase, 1, 0, ' ', "", "+NAN");
TEST (T, -nan, 0, 1, 0, ' ', "", "-nan");
TEST (T, -nan, showpos, 1, 0, ' ', "", "-nan");
TEST (T, -nan, uppercase, 1, 0, ' ', "", "-NAN");
TEST (T, -nan, showpos | uppercase, 1, 0, ' ', "", "-NAN");
TEST (T, nan, 0, 3, 0, ' ', "", "nan");
TEST (T, nan, showpos, 3, 0, ' ', "", "+nan");
TEST (T, nan, uppercase, 3, 0, ' ', "", "NAN");
TEST (T, nan, showpos | uppercase, 3, 0, ' ', "", "+NAN");
TEST (T, -nan, 0, 3, 0, ' ', "", "-nan");
TEST (T, -nan, showpos, 3, 0, ' ', "", "-nan");
TEST (T, -nan, uppercase, 3, 0, ' ', "", "-NAN");
TEST (T, -nan, showpos | uppercase, 3, 0, ' ', "", "-NAN");
TEST (T, nan, 0, 4, 0, ' ', "", "nan");
TEST (T, nan, showpos, 4, 0, ' ', "", "+nan");
TEST (T, nan, uppercase, 4, 0, ' ', "", "NAN");
TEST (T, nan, showpos | uppercase, 4, 0, ' ', "", "+NAN");
TEST (T, -nan, 0, 4, 0, ' ', "", "-nan");
TEST (T, -nan, showpos, 4, 0, ' ', "", "-nan");
TEST (T, -nan, uppercase, 4, 0, ' ', "", "-NAN");
TEST (T, -nan, showpos | uppercase, 4, 0, ' ', "", "-NAN");
TEST (T, nan, 0, 9, 0, ' ', "", "nan");
TEST (T, nan, showpos, 9, 0, ' ', "", "+nan");
TEST (T, nan, uppercase, 9, 0, ' ', "", "NAN");
TEST (T, nan, showpos | uppercase, 9, 0, ' ', "", "+NAN");
TEST (T, -nan, 0, 9, 0, ' ', "", "-nan");
TEST (T, -nan, showpos, 9, 0, ' ', "", "-nan");
TEST (T, -nan, uppercase, 9, 0, ' ', "", "-NAN");
TEST (T, -nan, showpos | uppercase, 9, 0, ' ', "", "-NAN");
TEST (T, nan, 0, 0, 1, ' ', "", "nan");
TEST (T, nan, showpos, 0, 1, ' ', "", "+nan");
TEST (T, nan, uppercase, 0, 1, ' ', "", "NAN");
TEST (T, nan, showpos | uppercase, 0, 1, ' ', "", "+NAN");
TEST (T, -nan, 0, 0, 1, ' ', "", "-nan");
TEST (T, -nan, showpos, 0, 1, ' ', "", "-nan");
TEST (T, -nan, uppercase, 0, 1, ' ', "", "-NAN");
TEST (T, -nan, showpos | uppercase, 0, 1, ' ', "", "-NAN");
TEST (T, nan, 0, 0, 3, ' ', "", "nan");
TEST (T, nan, showpos, 0, 3, ' ', "", "+nan");
TEST (T, nan, uppercase, 0, 3, ' ', "", "NAN");
TEST (T, nan, showpos | uppercase, 0, 3, ' ', "", "+NAN");
TEST (T, -nan, 0, 0, 3, ' ', "", "-nan");
TEST (T, -nan, showpos, 0, 3, ' ', "", "-nan");
TEST (T, -nan, uppercase, 0, 3, ' ', "", "-NAN");
TEST (T, -nan, showpos | uppercase, 0, 3, ' ', "", "-NAN");
TEST (T, nan, 0, 0, 4, ' ', "", " nan");
TEST (T, nan, showpos, 0, 4, ' ', "", "+nan");
TEST (T, nan, uppercase, 0, 4, ' ', "", " NAN");
TEST (T, nan, showpos | uppercase, 0, 4, ' ', "", "+NAN");
TEST (T, -nan, 0, 0, 4, ' ', "", "-nan");
TEST (T, -nan, showpos, 0, 4, ' ', "", "-nan");
TEST (T, -nan, uppercase, 0, 4, ' ', "", "-NAN");
TEST (T, -nan, showpos | uppercase, 0, 4, ' ', "", "-NAN");
TEST (T, nan, 0, 0, 5, ' ', "", " nan");
TEST (T, nan, showpos, 0, 5, ' ', "", " +nan");
TEST (T, nan, uppercase, 0, 5, ' ', "", " NAN");
TEST (T, nan, showpos | uppercase, 0, 5, ' ', "", " +NAN");
TEST (T, -nan, 0, 0, 5, ' ', "", " -nan");
TEST (T, -nan, showpos, 0, 5, ' ', "", " -nan");
TEST (T, -nan, uppercase, 0, 5, ' ', "", " -NAN");
TEST (T, -nan, showpos | uppercase, 0, 5, ' ', "", " -NAN");
TEST (T, nan, 0, 0, 8, ' ', "", " nan");
TEST (T, nan, showpos, 0, 8, ' ', "", " +nan");
TEST (T, nan, uppercase, 0, 8, ' ', "", " NAN");
TEST (T, nan, showpos | uppercase, 0, 8, ' ', "", " +NAN");
TEST (T, -nan, 0, 0, 8, ' ', "", " -nan");
TEST (T, -nan, showpos, 0, 8, ' ', "", " -nan");
TEST (T, -nan, uppercase, 0, 8, ' ', "", " -NAN");
TEST (T, -nan, showpos | uppercase, 0, 8, ' ', "", " -NAN");
TEST (T, nan, left, 0, 9, ' ', "", "nan ");
TEST (T, nan, left | showpos, 0, 9, ' ', "", "+nan ");
TEST (T, nan, left | uppercase, 0, 9, ' ', "", "NAN ");
TEST (T, nan, left | showpos | uppercase, 0, 9, ' ', "", "+NAN ");
TEST (T, -nan, left, 0, 9, ' ', "", "-nan ");
TEST (T, -nan, left | showpos, 0, 9, ' ', "", "-nan ");
TEST (T, -nan, left | uppercase, 0, 9, ' ', "", "-NAN ");
TEST (T, -nan, left | showpos | uppercase, 0, 9, ' ', "", "-NAN ");
TEST (T, nan, right, 0, 9, ' ', "", " nan");
TEST (T, nan, right | showpos, 0, 9, ' ', "", " +nan");
TEST (T, nan, right | uppercase, 0, 9, ' ', "", " NAN");
TEST (T, nan, right | showpos | uppercase, 0, 9, ' ', "", " +NAN");
TEST (T, -nan, right, 0, 9, ' ', "", " -nan");
TEST (T, -nan, right | showpos, 0, 9, ' ', "", " -nan");
TEST (T, -nan, right | uppercase, 0, 9, ' ', "", " -NAN");
TEST (T, -nan, right | showpos | uppercase, 0, 9, ' ', "", " -NAN");
#else
rw_info (0, 0, 0, "std::num_put<%s>::put (..., %s) formatting "
"NaN's disabled due to platform bugs", cname, tname);
#endif // 0/1
}
/**************************************************************************/
template <class charT>
void dbl_test (charT, const char *cname)
{
const char* const tname = "double";
rw_info (0, 0, 0, "std::num_put<%s>::put (..., %s)", cname, tname);
Punct<charT>::decimal_point_ = '.';
TEST (T, 0.0, 0, 0, 0, ' ', "", "%g");
TEST (T, -0.0, 0, 0, 0, ' ', "", "%g");
TEST (T, 1.0, 0, 0, 0, ' ', "", "%g");
TEST (T, 1.0, 0, 0, 0, ' ', "", "1");
TEST (T, -1.0, 0, 0, 0, ' ', "", "%g");
TEST (T, -1.0, 0, 0, 0, ' ', "", "-1");
TEST (T, 1.1, 0, 0, 0, ' ', "", "%g");
TEST (T, 1.1, 0, 0, 0, ' ', "", "1.1");
TEST (T, -1.1, 0, 0, 0, ' ', "", "%g");
TEST (T, -1.1, 0, 0, 0, ' ', "", "-1.1");
// exercise formatting of very large numbers in a fixed notation
// using '+' as the fill character to disable num_get tests
TEST (T, 1.0e+128, fixed, 0, 0, '+', "", "%.0f", Eof);
TEST (T, 1.0e+256, fixed, 0, 0, '+', "", "%.0f", Eof);
#undef CAT
#undef CONCAT
#define CAT(a, b) CONCAT (a, b)
#define CONCAT(a, b) a ## b
const double d = CAT (1.0e+, _RWSTD_DBL_MAX_10_EXP);
TEST (T, d, fixed, 0, 0, '+', "", "%.0f", Eof);
{
char stdiofmt [8];
const std::streamsize prec = std::streamsize (DBL_DIG + 3);
std::sprintf (stdiofmt, "%%.%dg", int (prec));
TEST (T, DBL_MIN, 0, prec, 0, ' ', "", stdiofmt);
TEST (T, DBL_MAX, 0, prec, 0, ' ', "", stdiofmt);
}
if (1) {
// verify that the global LC_NUMERIC setting has no impact on the facet
for (const char *name = rw_locales (LC_NUMERIC, 0); name && *name;
name += std::strlen (name) + 1) {
// find the first locale whose decimal_point character
// is different than in the classic C locale (i.e., than '.')
if (0 == std::setlocale (LC_NUMERIC, name))
continue;
const std::lconv* const conv = std::localeconv ();
if (!conv)
continue;
if (conv->decimal_point && '.' != *conv->decimal_point)
break;
}
Punct<charT>::decimal_point_ = '*';
Punct<charT>::thousands_sep_ = '/';
TEST (T, 12345.678900, fixed, 6, 0, ' ', "\000", "12345*678900");
TEST (T, 123456.78900, fixed, 5, 0, ' ', "\002", "12/34/56*78900");
TEST (T, 1234567.8900, fixed, 4, 0, ' ', "\003", "1/234/567*8900");
Punct<charT>::decimal_point_ = '.';
TEST (T, 12345678.900, fixed, 3, 0, ' ', "\004", "1234/5678.900");
// reset the global locale
std::setlocale (LC_NUMERIC, "C");
}
inf_nan_test (charT (), double (), cname, tname);
}
/**************************************************************************/
template <class charT>
void ldbl_test (charT, const char *cname)
{
#ifndef _RWSTD_NO_LONG_DOUBLE
const char* const tname = "long double";
rw_info (0, 0, 0, "std::num_put<%s>::put (..., %s) "
"[sizeof (long double) = %u]",
cname, tname, sizeof (long double));
typedef long double LDbl;
Punct<charT>::decimal_point_ = '.';
TEST (T, 0.0L, 0, 0, 0, ' ', "", "%Lg");
TEST (T, 1.0L, 0, 0, 0, ' ', "", "%Lg");
TEST (T, 2.1L, 0, 0, 0, ' ', "", "%Lg");
TEST (T, -3.2L, 0, 0, 0, ' ', "", "%Lg");
TEST (T, -4.3L, 0, 0, 0, ' ', "", "%Lg");
TEST (T, 1.0e+10L, 0, 0, 0, ' ', "", "%Lg");
TEST (T, 2.0e+20L, 0, 0, 0, ' ', "", "%Lg");
TEST (T, 4.0e+30L, 0, 0, 0, ' ', "", "%Lg");
TEST (T, 1.0e-10L, 0, 0, 0, ' ', "", "%Lg");
TEST (T, 2.0e-20L, 0, 0, 0, ' ', "", "%Lg");
TEST (T, 4.0e-30L, 0, 0, 0, ' ', "", "%Lg");
TEST (T, LDbl (CHAR_MAX), 0, 0, 0, ' ', "", "%Lg");
TEST (T, LDbl (UCHAR_MAX), 0, 0, 0, ' ', "", "%Lg");
TEST (T, LDbl (SCHAR_MAX), 0, 0, 0, ' ', "", "%Lg");
TEST (T, LDbl (SHRT_MAX), 0, 0, 0, ' ', "", "%Lg");
TEST (T, LDbl (USHRT_MAX), 0, 0, 0, ' ', "", "%Lg");
// specify greater precision than the default 6 for large numbers
TEST (T, LDbl (INT_MAX), 0, 32, 0, ' ', "", "%.32Lg");
TEST (T, LDbl (UINT_MAX), 0, 32, 0, ' ', "", "%.32Lg");
TEST (T, LDbl (LONG_MAX), 0, 32, 0, ' ', "", "%.32Lg");
TEST (T, LDbl (ULONG_MAX), 0, 32, 0, ' ', "", "%.32Lg");
TEST (T, LDbl (FLT_MIN), 0, 32, 0, ' ', "", "%.32Lg");
TEST (T, LDbl (FLT_MAX), 0, 32, 0, ' ', "", "%.32Lg");
TEST (T, LDbl (DBL_MIN), 0, 32, 0, ' ', "", "%.32Lg");
TEST (T, LDbl (DBL_MAX), 0, 32, 0, ' ', "", "%.32Lg");
{
char stdiofmt [8];
const std::streamsize prec = std::streamsize (LDBL_DIG + 3);
std::sprintf (stdiofmt, "%%.%d" _RWSTD_LDBL_PRINTF_PREFIX "g",
int (prec));
TEST (T, LDbl (LDBL_MIN), 0, prec, 0, ' ', "", stdiofmt);
TEST (T, LDbl (LDBL_MAX), 0, prec, 0, ' ', "", stdiofmt);
}
const long double Pi = 3.14159265358979323846L;
// some test cases below that use precision in conjuction with
// scientific in the libc format specifier in order to exercise
// the proposed resolution of lwg issue 231
TEST (T, Pi, 0, 32, 0, ' ', "", "%.32Lg");
TEST (T, Pi, fixed, 0, 0, ' ', "", "%.0Lf", Eof, 3.0L);
TEST (T, Pi, scientific, 0, 0, ' ', "", "%.0Le", Eof, 3.0L);
TEST (T, Pi, fixed, 0, 0, ' ', "", "3", Eof, 3.0L);
TEST (T, Pi, scientific, 0, 0, ' ', "", "3e+00", Eof, 3.0L);
TEST (T, Pi, uppercase, 32, 0, ' ', "", "%.32LG");
TEST (T, Pi, uppercase | fixed, 0, 0, ' ', "", "%.0Lf", Eof, 3.0L);
TEST (T, Pi, uppercase | scientific, 0, 0, ' ', "", "%.0LE", Eof, 3.0L);
TEST (T, Pi, uppercase | scientific, 0, 0, ' ', "", "3E+00", Eof, 3.0L);
#define Showpos(f) (showpos | f)
TEST (T, Pi, Showpos (0), 32, 0, ' ', "", "%+.32Lg");
TEST (T, Pi, Showpos (fixed), 0, 0, ' ', "", "%+.0Lf", Eof, 3.0L);
TEST (T, Pi, Showpos (scientific), 0, 0, ' ', "", "%+.0Le", Eof, 3.0L);
TEST (T, Pi, Showpos (fixed), 0, 0, ' ', "", "+3", Eof, 3.0L);
TEST (T, Pi, Showpos (scientific), 0, 0, ' ', "", "+3e+00", Eof, 3.0L);
#define SHOWPOS(f) (showpos | uppercase | f)
TEST (T, Pi, SHOWPOS (0), 32, 0, ' ', "", "%+.32LG");
TEST (T, Pi, SHOWPOS (fixed), 0, 0, ' ', "", "%+.0Lf", Eof, 3.0L);
TEST (T, Pi, SHOWPOS (scientific), 0, 0, ' ', "", "%+.0LE", Eof, 3.0L);
TEST (T, Pi, SHOWPOS (fixed), 0, 0, ' ', "", "+3", Eof, 3.0L);
TEST (T, Pi, SHOWPOS (scientific), 0, 0, ' ', "", "+3E+00", Eof, 3.0L);
#define Showpoint(f) (showpoint | f)
TEST (T, Pi, Showpoint (0), 32, 0, ' ', "", "%#.32Lg");
TEST (T, Pi, Showpoint (fixed), 0, 0, ' ', "", "%#.0Lf", Eof, 3.0L);
TEST (T, Pi, Showpoint (scientific), 0, 0, ' ', "", "%#.0Le", Eof, 3.0L);
TEST (T, Pi, Showpoint (fixed), 0, 0, ' ', "", "3.", Eof, 3.0L);
TEST (T, Pi, Showpoint (scientific), 0, 0, ' ', "", "3.e+00", Eof, 3.0L);
#define SHOWPOINT(f) (showpoint | uppercase | f)
TEST (T, Pi, SHOWPOINT (0), 32, 0, ' ', "", "%#.32LG");
TEST (T, Pi, SHOWPOINT (fixed), 0, 0, ' ', "", "%#.0Lf", Eof, 3.0L);
TEST (T, Pi, SHOWPOINT (scientific), 0, 0, ' ', "", "%#.0LE", Eof, 3.0L);
TEST (T, Pi, SHOWPOINT (scientific), 0, 0, ' ', "", "3.E+00", Eof, 3.0L);
#define Showall(f) (showpoint | showpos | f)
TEST (T, Pi, Showall (0), 32, 0, ' ', "", "%#+.32Lg");
TEST (T, Pi, Showall (fixed), 0, 0, ' ', "", "%#+.0Lf", Eof, 3.0L);
TEST (T, Pi, Showall (scientific), 0, 0, ' ', "", "%#+.0Le", Eof, 3.0L);
TEST (T, Pi, Showall (fixed), 0, 0, ' ', "", "+3.", Eof, 3.0L);
TEST (T, Pi, Showall (scientific), 0, 0, ' ', "", "+3.e+00", Eof, 3.0L);
#define SHOWALL(f) (showpoint | showpos | uppercase | f)
TEST (T, Pi, SHOWALL (0), 32, 0, ' ', "", "%#+.32LG");
TEST (T, Pi, SHOWALL (fixed), 0, 0, ' ', "", "%#+.0Lf", Eof, 3.0L);
TEST (T, Pi, SHOWALL (scientific), 0, 0, ' ', "", "%#+.0LE", Eof, 3.0L);
TEST (T, Pi, SHOWALL (scientific), 0, 0, ' ', "", "+3.E+00", Eof, 3.0L);
// with {g,G}, precision indicates the number of significant digits
TEST (T, Pi, 0, 1, 0, ' ', "", "%.1Lg", Eof, 3.0L);
TEST (T, Pi, 0, 2, 0, ' ', "", "%.2Lg", Eof, 3.1L);
TEST (T, Pi, 0, 3, 0, ' ', "", "%.3Lg", Eof, 3.14L);
TEST (T, Pi, 0, 10, 0, ' ', "", "%.10Lg", Eof, 3.141592654L);
// C89 and C99 both specify that (only if specified using the asterisk)
// negative precision is treated the same as no precision at all; verify
// that num_put handles negative precision gracefully (i.e., ignores it)
TEST (T, Pi, 0, -1, 0, ' ', "", "%Lg");
TEST (T, Pi, 0, -9, 0, ' ', "", "%Lg");
// with {e,E,f,F}, precision indicates the number of fractional digits
TEST (T, Pi, fixed, 1, 0, ' ', "", "%.1Lf", Eof, 3.1L);
TEST (T, Pi, fixed, 2, 0, ' ', "", "%.2Lf", Eof, 3.14L);
TEST (T, Pi, fixed, 3, 0, ' ', "", "%.3Lf", Eof, 3.142L);
TEST (T, Pi, fixed, 10, 0, ' ', "", "%.10Lf", Eof, 3.1415926536L);
// exercise formatting of very large numbers in a fixed notation
// using '-' as the fill character to disable num_get tests
TEST (T, 2.0e+128L, fixed, 0, 0, '-', "", "%.0Lf", Eof);
TEST (T, 3.0e+256L, fixed, 0, 0, '-', "", "%.0Lf", Eof);
TEST (T, 4.0e+300L, fixed, 0, 0, '-', "", "%.0Lf", Eof);
// extension: fixed format and negative precision
TEST (T, Pi, fixed, -2, 0, ' ', "", "0.03");
TEST (T, Pi, fixed, -8, 0, ' ', "", "0.00000003");
#undef CAT
#undef CONCAT
#define CAT(a, b) CONCAT (a, b)
#define CONCAT(a, b) a ## b
const long double ld = CAT (CAT (1.0e+, _RWSTD_LDBL_MAX_10_EXP), L);
TEST (T, ld, fixed, 0, 0, '-', "", "%.0Lf", Eof);
TEST (T, Pi, scientific, 2, 0, ' ', "", "%.2Le", Eof, 3.14L);
TEST (T, Pi, scientific, 4, 0, ' ', "", "%.4Le", Eof, 3.1416L);
TEST (T, Pi, scientific, 6, 0, ' ', "", "%.6Le", Eof, 3.141593L);
TEST (T, Pi, scientific, 12, 0, ' ', "", "%.12Le", Eof, 3.14159265359L);
TEST (T, Pi, scientific, -3, 0, ' ', "", "%Le");
TEST (T, Pi, scientific, -7, 0, ' ', "", "%Le");
inf_nan_test (charT (), (long double)0, cname, tname);
#endif // _RWSTD_NO_LONG_DOUBLE
}
/**************************************************************************/
template <class charT>
void pvoid_test (charT, const char *cname)
{
const char* const tname = "const void*";
rw_info (0, 0, 0, "std::num_put<%s>::put (..., %s)", cname, tname);
typedef void* PVoid;
int foo = 0;
int bar = 0;
// use "0" rather than "%p" for null pointers to avoid
// having to deal with GNU libc's "(nil)" format
TEST (T, PVoid ( 0), 0, 0, 0, ' ', "", "0");
TEST (T, PVoid ( 1), 0, 0, 0, ' ', "", "%p");
TEST (T, PVoid ( &foo), 0, 0, 0, ' ', "", "%p");
TEST (T, PVoid ( &bar), 0, 0, 0, ' ', "", "%p");
TEST (T, PVoid ( ~0L), 0, 0, 0, ' ', "", "%p");
// 22.2.2.2.2, p16 and lwg issue 282: grouping and thousands_sep
// is only used in arithmetic types
TEST (T, PVoid ( 0), 0, 0, 0, ' ', "\1", "0");
TEST (T, PVoid ( 1), 0, 0, 0, ' ', "\1", "%p");
TEST (T, PVoid ( &foo), 0, 0, 0, ' ', "\1\1", "%p");
TEST (T, PVoid ( &bar), 0, 0, 0, ' ', "\1\2", "%p");
TEST (T, PVoid ( ~0L), 0, 0, 0, ' ', "\1\3", "%p");
TEST (T, PVoid ( SHRT_MAX), 0, 0, 0, ' ', "", "%p");
TEST (T, PVoid ( SHRT_MIN), 0, 0, 0, ' ', "", "%p");
TEST (T, PVoid (USHRT_MAX), 0, 0, 0, ' ', "", "%p");
TEST (T, PVoid ( INT_MAX), 0, 0, 0, ' ', "", "%p");
TEST (T, PVoid ( INT_MIN), 0, 0, 0, ' ', "", "%p");
TEST (T, PVoid ( UINT_MAX), 0, 0, 0, ' ', "", "%p");
TEST (T, PVoid ( LONG_MAX), 0, 0, 0, ' ', "", "%p");
TEST (T, PVoid ( LONG_MIN), 0, 0, 0, ' ', "", "%p");
TEST (T, PVoid (ULONG_MAX), 0, 0, 0, ' ', "", "%p");
#ifdef _RWSTD_LLONG_MAX
# if _RWSTD_LLONG_SIZE <= _RWSTD_PTR_SIZE
TEST (T, PVoid (_RWSTD_LLONG_MAX), 0, 0, 0, ' ', "", "%p");
TEST (T, PVoid (_RWSTD_ULLONG_MAX), 0, 0, 0, ' ', "", "%p");
# endif // LLONG_MAX
#endif // _RWSTD_LLONG_MAX
}
/**************************************************************************/
template <class charT>
void errno_test (charT, const char *cname)
{
const char* const tname = "long";
rw_info (0, 0, 0,
"std::num_put<%s>::put (..., %s) and errno", cname, tname);
// verify that errno doesn't change after, or adversely affect
// successful insertion; and that the insertion doesn't change
// the value of errno
errno = -1;
TEST (T, 12345L, 0, 0, 0, ' ', "", "12345");
rw_assert (-1 == errno, 0, __LINE__,
"errno unexpectedly changed from %d to %{#m} (%m)", -1);
errno = 0;
TEST (T, 12346L, 0, 0, 0, ' ', "", "12346");
rw_assert (0 == errno, 0, __LINE__,
"errno unexpectedly changed from %d to %{#m} (%m)", -0);
errno = 1;
TEST (T, 12347L, 0, 0, 0, ' ', "", "12347");
rw_assert (1 == errno, 0, __LINE__,
"errno unexpectedly changed from %d to %{#m} (%m)", 1);
errno = 2;
TEST (T, 12348L, 0, 0, 0, ' ', "", "12348");
rw_assert (2 == errno, 0, __LINE__,
"errno unexpectedly changed from %d to %{#m} (%m)", 2);
errno = 3;
TEST (T, 12349L, 0, 0, 0, ' ', "", "12349");
rw_assert (3 == errno, 0, __LINE__,
"errno unexpectedly changed from %d to %{#m} (%m)", 3);
errno = 4;
TEST (T, 12350L, 0, 0, 0, ' ', "", "12350");
rw_assert (4 == errno, 0, __LINE__,
"errno unexpectedly changed from %d to %{#m} (%m)", 4);
errno = ERANGE;
TEST (T, 12351L, 0, 0, 0, ' ', "", "12351");
rw_assert (ERANGE == errno, 0, __LINE__,
"errno unexpectedly changed from %{#m} to %{#m} (%m)", ERANGE);
errno = Bad;
TEST (T, 12352L, 0, 0, 0, ' ', "", "12352");
rw_assert (Bad == errno, 0, __LINE__,
"errno unexpectedly changed from %d to %{#m} (%m)", Bad);
errno = Eof;
TEST (T, 12353L, 0, 0, 0, ' ', "", "12353");
rw_assert (Eof == errno, 0, __LINE__,
"errno unexpectedly changed from %d to %{#m} (%m)", Eof);
errno = Fail;
TEST (T, 12354L, 0, 0, 0, ' ', "", "12354");
rw_assert (Fail == errno, 0, __LINE__,
"errno unexpectedly changed from %d to %{#m} (%m)", Fail);
errno = 0;
}
/**************************************************************************/
// verify that std::ctype<>::widen() is called at least once
// for every distinct narow character (not for fill characters)
// note that an implementation is allowed to cache the results
// of facet virtual functions() called with the same arguments
// (including the implicit this pointer), so the numbers here
// are minimum required values but not exact or maximums
void widen_test ()
{
rw_info (0, 0, 0,
"std::num_put<char>::put (..., long) calls ctype<char>::widen()");
static const struct {
long val;
std::streamsize width;
int flags;
int n_widen;
const char *str;
} data[] = {
{ 0, 0, 0, 1, "9" },
{ 1, 0, 0, 1, "8" },
{ 11, 0, 0, 1, "88" },
{ 12, 0, 0, 2, "87" },
{ 123, 0, 0, 3, "876" },
{ 111, 0, 0, 1, "888" },
{ -1234, 0, 0, 5, "-8765" },
{ 12121, 0, 0, 2, "87878" },
{ 12345, 0, showpos, 6, "+87654" },
{ 0123456, 0, oct | showbase, 7, "9876543" },
{ 0x234567, 0, hex | showbase, 8, "9x765432" },
{ 0x2345678, 10, hex | showbase, 9, " 9x7654321" },
{ 9, 5, showpos | internal, 2, "+ 0" }
};
for (unsigned i = 0; i != sizeof data / sizeof *data; ++i) {
const Ctype<char> ctp;
// construct and initialize a basic_ios-derived object
Ios<char> ios;
// construct a num_put-derived facet to exercise
const NumPut<char> np;
// imbue a stream object with a custom locale
// containing the replacement ctype facet
ios.imbue (std::locale (ios.getloc (), (const std::ctype<char>*)&ctp));
ios.flags (std::ios_base::fmtflags (data [i].flags));
ios.width (data [i].width);
char buf [40];
// reset function call counter
Ctype<char>::n_widen_ = 0;
*np.put (buf, ios, ' ', data [i].val) = '\0';
rw_assert (data [i].n_widen <= Ctype<char>::n_widen_, 0, __LINE__,
"%d. num_put<char>::do_put (..., %d) called "
"ctype<char>::do_widen() %d times, %d expected; "
"flags = %{If}, width = %d", i, data [i].val,
Ctype<char>::n_widen_, data [i].n_widen,
data [i].flags, data [i].width);
rw_assert (0 == rw_strncmp (buf, data [i].str), 0, __LINE__,
"%d. num_put<char>::do_put (..., %d) produced %s, "
"expected \"%{#*s}\"; "
"flags = %{If}, width = %d",
i, data [i].val, buf,
int (sizeof data [i].str [0]), data [i].str,
data [i].flags, data [i].width);
}
}
/**************************************************************************/
// verify that std::numpunct<>::grouping() is called and used correctly
void grouping_test ()
{
// construct a "replacement" numpunct-derived facet
const Punct<char> pun (1);
// construct and initialize a basic_ios-derived object
Ios<char> ios;
// construct a num_put-derived facet to exercise
const NumPut<char> np;
// imbue a stream object with a custom locale
// containing the replacement punctuation facet
ios.imbue (std::locale (ios.getloc (), (const std::numpunct<char>*)&pun));
rw_assert (1 == Punct<char>::n_objs_, 0, __LINE__,
"%d facets exist, 1 expected", Punct<char>::n_objs_);
// decimal output, no special formatting
ios.setf (std::ios::fmtflags ());
char buf [40];
// group after every digit
Punct<char>::grouping_ = "\1";
// reset the do_thousands_sep()-call counter
Punct<char>::n_thousands_sep_ = 0;
*np.put (buf, ios, '\0', 123456789L) = '\0';
// verify that the number was formatted correctly
rw_assert (0 == std::strcmp (buf, "1,2,3,4,5,6,7,8,9"), 0, __LINE__,
"num_put<char>::do_put (..., 123456789) produced \"%s\", "
"expected \"%s\"", buf, "1,2,3,4,5,6,7,8,9");
// verify that do_thousands_sep() was called at least once
rw_assert (0 < Punct<char>::n_thousands_sep_, 0, __LINE__,
"num_put<char>::do_put (..., 123456789) failed to call "
"numpunct<char>::do_thousands_sep()");
// repeat test to verify that distinct instances
// of the same facet do not cache each other's data
{
// nested scope works around a SunPro bug (PR #27543)
ios.imbue (std::locale (ios.getloc (),
(const std::numpunct<char>*)new Punct<char>(0)));
}
rw_assert (2 == Punct<char>::n_objs_, 0, __LINE__,
"%d facets exist, 2 expected", Punct<char>::n_objs_);
// now group after every other digit
Punct<char>::grouping_ = "\2";
// reset the do_thousands_sep()-call counter
Punct<char>::n_thousands_sep_ = 0;
*np.put (buf, ios, '\0', 123456790L) = '\0';
// again verify that the number was formatted correctly
rw_assert (0 == std::strcmp (buf, "1,23,45,67,90"), 0, __LINE__,
"num_put<char>::do_put (..., 123456790) produced \"%s\", "
"expected \"%s\"", buf, "1,23,45,67,90");
// verify that do_thousands_sep() was called at least once
// (i.e., that there is no unwarranted caching going on)
rw_assert (0 < Punct<char>::n_thousands_sep_, 0, __LINE__,
"num_put<char>::do_put (..., 123456790) failed to call "
"numpunct<char>::do_thousands_sep()");
// replace imbued locale with a copy of the classic locale
// and remove the previously installed locale containing
// the user-defined facet; this must destroy the dynamically
// created facet leaving only the local facet on the stack
{
// nested scope works around a SunPro bug (PR #27543)
ios.imbue (std::locale::classic ());
}
rw_assert (1 == Punct<char>::n_objs_, 0, __LINE__,
"%d facets exist, 1 expected", Punct<char>::n_objs_);
}
/**************************************************************************/
template <class charT>
void numput_virtuals_test (charT, const char *cname)
{
const NumPut<charT> put (1);
const std::num_put<charT, charT*> &np = put;
Ios<charT> ios;
ios.flags (std::ios_base::fmtflags ());
#define Abs(i) ((i) < 0 ? (-i) : (i))
#define ASSERT(T, N, T2, tname, t2name) \
do { \
/* number of expected calls to the do_put() member */ \
const int expect = N + put.ncalls_ [put.test_ ## T]; \
const int expect_2 = !N + put.ncalls_ [put.test_ ## T2]; \
charT buf [80]; \
const charT* const end = np.put (buf, ios, charT (), (T)0); \
rw_assert (end == buf + 1, 0, __LINE__, \
"line %d: num_put<%s>::put (..., %s = 0) " \
"return value", __LINE__, cname, tname); \
const int ncalls = put.ncalls_ [put.test_ ## T]; \
const int ncalls_2 = put.ncalls_ [put.test_ ## T2]; \
rw_assert (expect == ncalls, 0, __LINE__, \
"line %d: num_put<%s>::put (..., %s) called " \
"do_put(..., %s) %d times, expected %d", \
__LINE__, cname, tname, \
tname, Abs (ncalls - expect - N), N); \
/* make sure extensions, if any, are implemented in */ \
/* terms of and call the standard virtual functions */ \
/* bogus addressof operator prevents warnings about */ \
/* unreachable code when T is the same as T2 */ \
if (put.test_ ## T != put.test_ ## T2) \
rw_assert (expect_2 == ncalls_2, 0, __LINE__, \
"line %d: num_put<%s>::put (..., %s) called " \
"do_put(..., %s) %d times, expected %d", \
__LINE__, cname, tname, \
t2name, Abs (expect_2 - ncalls_2 - !N), !N); \
} while (0)
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
// verify that each public member function calls each corresponding
// implementation do_xxx() member functions exactly once
// in the case of extensions, verify that each extended public member
// function calls the appropriate implementation standard do_xxx()
// member function
#ifndef _RWSTD_NO_BOOL
ASSERT (bool, 1, bool, "bool", "bool");
#endif // _RWSTD_NO_BOOL
ASSERT (long, 1, long, "long", "long");
ASSERT (ulong, 1, ulong, "unsigned long", "unsigned long");
#if defined (_RWSTD_LONG_LONG) && !defined (_RWSTD_NO_EXT_NUM_PUT)
typedef _RWSTD_LONG_LONG llong;
typedef unsigned _RWSTD_LONG_LONG ullong;
ASSERT (llong, 1, llong, "long long", "long long");
ASSERT (ullong, 1, ullong, "unsigned long long", "unsigned long long");
#endif // _RWSTD_LONG_LONG && !_RWSTD_NO_EXT_NUM_PUT
ASSERT (double, 1, double, "double", "double");
#ifndef _RWSTD_NO_LONG_DOUBLE
typedef long double ldouble;
ASSERT (ldouble, 1, ldouble, "long double", "long double");
#endif // _RWSTD_NO_LONG_DOUBLE
typedef const void* pvoid;
ASSERT (pvoid, 1, pvoid, "const void*", "const void*");
}
/**************************************************************************/
template <class charT>
void run_tests (charT, const char *cname)
{
numput_virtuals_test (charT (), cname);
direct_use_test (charT (), cname);
#undef TEST
#define TEST(T, tname) \
if (rw_enabled (#T)) \
T ## _test (charT (), cname); \
else \
rw_note (0, __FILE__, __LINE__, "%s test disabled", \
tname && *tname ? tname : #T)
#ifndef _RWSTD_NO_BOOL
TEST (bool, "");
#endif // _RWSTD_NO_BOOL
// NOTE: there is no num_put::put(..., short)
// TEST (shrt, "short");
// TEST (ushrt, "unsigned short");
// NOTE: there is no num_put::put(..., int)
// TEST (int, "");
// TEST (uint, "unsigned int");
TEST (long, "");
TEST (ulong, "unsigned long");
#ifndef _RWSTD_NO_LONG_LONG
TEST (llong, "long long");
TEST (ullong, "unsigned long long");
#endif // _RWSTD_NO_LONG_LONG
// NOTE: there is no num_put::put(..., float)
// TEST (flt, "float");
TEST (dbl, "dbouble");
#ifndef _RWSTD_NO_LONG_DOUBLE
TEST (ldbl, "long double");
#endif // _RWSTD_NO_LONG_DOUBLE
TEST (pvoid, "void*");
if (rw_opt_no_errno)
rw_note (0, __FILE__, __LINE__, "errno test disabled");
else
errno_test (charT (), cname);
}
/**************************************************************************/
static int
run_test (int, char*[])
{
if (rw_opt_no_widen) {
rw_note (0, 0, 0, "widen test disabled");
}
else {
widen_test ();
}
if (rw_opt_no_grouping) {
rw_note (0, 0, 0, "grouping test disabled");
}
else {
grouping_test ();
}
if (rw_enabled ("char"))
run_tests (char (), "char");
else
rw_note (0, __FILE__, __LINE__, "char test disabled");
#ifndef _RWSTD_NO_WCHAR_T
if (rw_enabled ("wchar_t"))
run_tests (wchar_t (), "wchar_t");
else
rw_note (0, __FILE__, __LINE__, "wchar_t test disabled");
#endif // _RWSTD_NO_WCHAR_T
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.locale.num.put",
0 /* no comment */, run_test,
"|-enable-num_get# "
"|-no-errno# "
"|-no-grouping# "
"|-no-widen# ",
&rw_opt_enable_num_get,
&rw_opt_no_errno,
&rw_opt_no_grouping,
&rw_opt_no_widen);
}