/*************************************************************************** * * 22.locale.num.put.cpp - tests exercising the std::num_put facet * * $Id: 22.locale.num.put.cpp 648752 2008-04-16 17:01:56Z faridz $ * *************************************************************************** * * 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 # undef ushort # undef uint # undef ulong #endif // __GNUG__ #include #include #include // for ERANGE, errno #include // for floating limits macros #include // for integral limits macros #include // for LC_NUMERIC, setlocale() #include // for sprintf() #include // for strcmp(), strlen() #include // for TOSTR() #include // for rw_enabled #include // for rw_test #include // for rw_locales #include // 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 struct Ctype: std::ctype { typedef std::ctype 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 int Ctype::n_widen_; /**************************************************************************/ // replacement numpunct facet template struct Punct: std::numpunct { typedef typename std::numpunct::char_type char_type; typedef typename std::numpunct::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(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 const char* Punct::grouping_ = ""; template typename Punct::char_type Punct::decimal_point_ = '.'; template typename Punct::char_type Punct::thousands_sep_ = ','; template const typename Punct::char_type* Punct::truename_; template const typename Punct::char_type* Punct::falsename_; template int Punct::n_thousands_sep_; template int Punct::n_objs_; /**************************************************************************/ template struct Ios: std::basic_ios { Ios () { this->init (0); } }; template struct NumGet: std::num_get { NumGet () { } }; template struct NumPut: std::num_put { typedef std::num_put 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 /* static */ int NumPut::ncalls_ [13] = { 0 }; /**************************************************************************/ template 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 pun (1); Ios ios; NumPut np; ios.imbue (std::locale (ios.getloc (), (const std::numpunct*)&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 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 struct Streambuf: std::basic_streambuf > { }; template 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 ios; const std::num_put np; Streambuf sb; #define DIRECT_USE_TEST(T) \ np.put (std::ostreambuf_iterator(&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 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::decimal_point_ = '*'; Punct::truename_ = boolnames [0]; Punct::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::truename_ = boolnames [2]; Punct::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::truename_ = boolnames [4]; Punct::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::truename_ = boolnames [6]; Punct::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 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 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 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 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 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-464) 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 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::decimal_point_ = '.'; TEST (T, 0.0, 0, 0, 0, ' ', "", "%.0g"); TEST (T, -0.0, 0, 0, 0, ' ', "", "%.0g"); TEST (T, 1.0, 0, 0, 0, ' ', "", "%.0g"); TEST (T, 1.0, 0, 0, 0, ' ', "", "1"); TEST (T, -1.0, 0, 0, 0, ' ', "", "%.0g"); TEST (T, -1.0, 0, 0, 0, ' ', "", "-1"); TEST (T, 1.1, 0, 0, 0, ' ', "", "%.0g"); TEST (T, 1.1, 0, 0, 0, ' ', "", "1"); TEST (T, -1.1, 0, 0, 0, ' ', "", "%.0g"); TEST (T, -1.1, 0, 0, 0, ' ', "", "-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::decimal_point_ = '*'; Punct::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::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 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::decimal_point_ = '.'; TEST (T, 0.0L, 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, 1.0L, 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, 2.1L, 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, -3.2L, 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, -4.3L, 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, 1.0e+10L, 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, 2.0e+20L, 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, 4.0e+30L, 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, 1.0e-10L, 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, 2.0e-20L, 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, 4.0e-30L, 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, LDbl (CHAR_MAX), 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, LDbl (UCHAR_MAX), 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, LDbl (SCHAR_MAX), 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, LDbl (SHRT_MAX), 0, 0, 0, ' ', "", "%.0Lg"); TEST (T, LDbl (USHRT_MAX), 0, 0, 0, ' ', "", "%.0Lg"); // 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 // the precision == 0 should have the same effect as precision == 1 TEST (T, Pi, 0, 0, 0, ' ', "", "%.0Lg", Eof, 3.0L); 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 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 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::put (..., long) calls ctype::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 ctp; // construct and initialize a basic_ios-derived object Ios ios; // construct a num_put-derived facet to exercise const NumPut np; // imbue a stream object with a custom locale // containing the replacement ctype facet ios.imbue (std::locale (ios.getloc (), (const std::ctype*)&ctp)); ios.flags (std::ios_base::fmtflags (data [i].flags)); ios.width (data [i].width); char buf [40]; // reset function call counter Ctype::n_widen_ = 0; *np.put (buf, ios, ' ', data [i].val) = '\0'; rw_assert (data [i].n_widen <= Ctype::n_widen_, 0, __LINE__, "%d. num_put::do_put (..., %d) called " "ctype::do_widen() %d times, %d expected; " "flags = %{If}, width = %d", i, data [i].val, Ctype::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::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 pun (1); // construct and initialize a basic_ios-derived object Ios ios; // construct a num_put-derived facet to exercise const NumPut np; // imbue a stream object with a custom locale // containing the replacement punctuation facet ios.imbue (std::locale (ios.getloc (), (const std::numpunct*)&pun)); rw_assert (1 == Punct::n_objs_, 0, __LINE__, "%d facets exist, 1 expected", Punct::n_objs_); // decimal output, no special formatting ios.setf (std::ios::fmtflags ()); char buf [40]; // group after every digit Punct::grouping_ = "\1"; // reset the do_thousands_sep()-call counter Punct::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::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::n_thousands_sep_, 0, __LINE__, "num_put::do_put (..., 123456789) failed to call " "numpunct::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*)new Punct(0))); } rw_assert (2 == Punct::n_objs_, 0, __LINE__, "%d facets exist, 2 expected", Punct::n_objs_); // now group after every other digit Punct::grouping_ = "\2"; // reset the do_thousands_sep()-call counter Punct::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::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::n_thousands_sep_, 0, __LINE__, "num_put::do_put (..., 123456790) failed to call " "numpunct::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::n_objs_, 0, __LINE__, "%d facets exist, 1 expected", Punct::n_objs_); } /**************************************************************************/ template void numput_virtuals_test (charT, const char *cname) { const NumPut put (1); const std::num_put &np = put; Ios 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 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); }