#include <limits> #if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS) # include <iomanip> # include <string> # include <sstream> # include <cstdio> /* # include <iostream> # include <ieee754.h> */ # include "complete_digits.h" # include "cppunit/cppunit_proxy.h" # if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES) using namespace std; # endif // // TestCase class // class NumPutGetTest : public CPPUNIT_NS::TestCase { CPPUNIT_TEST_SUITE(NumPutGetTest); # if defined (__BORLANDC__) /* Ignore FPU exceptions, set FPU precision to 64 bits */ unsigned int _float_control_word = _control87(0, 0); _control87(PC_64|MCW_EM|IC_AFFINE, MCW_PC|MCW_EM|MCW_IC); # endif CPPUNIT_TEST(num_put_float); CPPUNIT_TEST(num_put_integer); CPPUNIT_TEST(num_get_float); CPPUNIT_TEST(num_get_integer); CPPUNIT_TEST(inhex); CPPUNIT_TEST(pointer); CPPUNIT_TEST(fix_float_long); CPPUNIT_TEST(custom_numpunct); # if defined (__BORLANDC__) /* Reset floating point control word */ _clear87(); _control87(_float_control_word, MCW_PC|MCW_EM|MCW_IC); # endif CPPUNIT_TEST_SUITE_END(); private: void num_put_float(); void num_put_integer(); void num_get_float(); void num_get_integer(); void inhex(); void pointer(); void fix_float_long(); void custom_numpunct(); static bool check_float(float val, float ref) { float epsilon = numeric_limits<float>::epsilon(); return val <= ref + epsilon && val >= ref - epsilon; } static bool check_double(double val, double ref) { double epsilon = numeric_limits<double>::epsilon(); return val <= ref + epsilon && val >= ref - epsilon; } static string reset_stream(ostringstream &ostr) { string tmp = ostr.str(); ostr.str(""); return tmp; } #if !defined (STLPORT) || !defined (_STLP_NO_MEMBER_TEMPLATES) template <class F> void check_get_float( F v ) { F in_val_d = v; typedef numeric_limits<F> limits; { stringstream str; str << "1E+" << limits::max_exponent10; str >> in_val_d; CPPUNIT_ASSERT(!str.fail()); CPPUNIT_ASSERT(str.eof()); CPPUNIT_CHECK( in_val_d == in_val_d ); CPPUNIT_CHECK( in_val_d != limits::infinity() ); } { stringstream str; str << "-1E+" << limits::max_exponent10; str >> in_val_d; CPPUNIT_ASSERT(!str.fail()); CPPUNIT_ASSERT(str.eof()); CPPUNIT_CHECK( in_val_d == in_val_d ); CPPUNIT_CHECK( in_val_d != -limits::infinity() ); } { stringstream str; str << "1E" << limits::min_exponent10; str >> in_val_d; CPPUNIT_ASSERT(!str.fail()); CPPUNIT_ASSERT(str.eof()); CPPUNIT_CHECK( in_val_d == in_val_d ); CPPUNIT_CHECK( in_val_d != F(0.0) ); } { stringstream str; str << "1E+" << (limits::max_exponent10 + 1); str >> in_val_d; CPPUNIT_ASSERT(!str.fail()); CPPUNIT_ASSERT(str.eof()); CPPUNIT_CHECK( in_val_d == in_val_d ); CPPUNIT_CHECK( in_val_d == limits::infinity() ); } { stringstream str; str << "-1E+" << (limits::max_exponent10 + 1); str >> in_val_d; CPPUNIT_ASSERT(!str.fail()); CPPUNIT_ASSERT(str.eof()); CPPUNIT_CHECK( in_val_d == in_val_d ); CPPUNIT_CHECK( in_val_d == -limits::infinity() ); } { stringstream str; str << "1E" << (limits::min_exponent10 - 1); str >> in_val_d; CPPUNIT_ASSERT(!str.fail()); CPPUNIT_ASSERT(str.eof()); CPPUNIT_CHECK( in_val_d == in_val_d ); CPPUNIT_CHECK( in_val_d >= F(0.0) && in_val_d <= limits::min() ); } #if !defined (__MINGW32__) { stringstream str; str << limits::max(); CPPUNIT_ASSERT(!str.fail()); CPPUNIT_CHECK( str.str() != "inf" && str.str() != "Inf" ); CPPUNIT_CHECK( str.str() != "-inf" && str.str() != "-Inf" ); CPPUNIT_CHECK( str.str() != "nan" && str.str() != "NaN" ); CPPUNIT_CHECK( str.str() != "-nan" && str.str() != "-NaN" ); //CPPUNIT_MESSAGE( str.str().c_str() ); //str.str(""); //str << limits::max_exponent10; //CPPUNIT_MESSAGE( str.str().c_str() ); str >> in_val_d; CPPUNIT_ASSERT(!str.fail()); CPPUNIT_ASSERT(str.eof()); CPPUNIT_CHECK( in_val_d == in_val_d ); CPPUNIT_CHECK( in_val_d != limits::infinity() ); } { stringstream str; str << fixed << limits::max(); CPPUNIT_ASSERT(!str.fail()); CPPUNIT_CHECK( str.str() != "inf" && str.str() != "Inf" ); CPPUNIT_CHECK( str.str() != "-inf" && str.str() != "-Inf" ); CPPUNIT_CHECK( str.str() != "nan" && str.str() != "NaN" ); CPPUNIT_CHECK( str.str() != "-nan" && str.str() != "-NaN" ); //CPPUNIT_MESSAGE( str.str().c_str() ); //str.str(""); //str << limits::max_exponent10; //CPPUNIT_MESSAGE( str.str().c_str() ); str >> in_val_d; CPPUNIT_ASSERT(!str.fail()); CPPUNIT_ASSERT(str.eof()); CPPUNIT_CHECK( in_val_d == in_val_d ); CPPUNIT_CHECK( in_val_d != limits::infinity() ); } { stringstream str; str << scientific << setprecision(50) << limits::max(); CPPUNIT_ASSERT(!str.fail()); CPPUNIT_CHECK( str.str() != "inf" && str.str() != "Inf" ); CPPUNIT_CHECK( str.str() != "-inf" && str.str() != "-Inf" ); CPPUNIT_CHECK( str.str() != "nan" && str.str() != "NaN" ); CPPUNIT_CHECK( str.str() != "-nan" && str.str() != "-NaN" ); //CPPUNIT_MESSAGE( str.str().c_str() ); //str.str(""); //str << limits::max_exponent10; //CPPUNIT_MESSAGE( str.str().c_str() ); str >> in_val_d; CPPUNIT_ASSERT(!str.fail()); CPPUNIT_ASSERT(str.eof()); CPPUNIT_CHECK( in_val_d == in_val_d ); CPPUNIT_CHECK( in_val_d != limits::infinity() ); } #endif { stringstream str; str << limits::infinity(); CPPUNIT_ASSERT( !str.fail() ); CPPUNIT_ASSERT( !limits::has_infinity || str.str() == "inf" || str.str() == "Inf" ); } { stringstream str; str << -limits::infinity(); CPPUNIT_ASSERT( !str.fail() ); CPPUNIT_ASSERT( !limits::has_infinity || str.str() == "-inf" || str.str() == "-Inf" ); } { stringstream str; str << limits::quiet_NaN(); CPPUNIT_ASSERT( !str.fail() ); CPPUNIT_ASSERT( !limits::has_quiet_NaN || str.str() == "nan" || str.str() == "NaN" ); } { stringstream str; str << "0." << string(limits::max_exponent10, '0') << "1e" << (limits::max_exponent10 + 1); CPPUNIT_ASSERT( !str.fail() ); str >> in_val_d; CPPUNIT_ASSERT( !str.fail() ); CPPUNIT_ASSERT( str.eof() ); CPPUNIT_CHECK( in_val_d == 1 ); } { stringstream str; str << "1" << string(-(limits::min_exponent10 - 1), '0') << "e" << (limits::min_exponent10 - 1); CPPUNIT_ASSERT( !str.fail() ); str >> in_val_d; CPPUNIT_ASSERT( !str.fail() ); CPPUNIT_ASSERT( str.eof() ); CPPUNIT_CHECK( in_val_d == 1 ); } # if defined (_STLPORT_VERSION) && (_STLPORT_VERSION >= 0x530) // The following tests are showing that simply changing stream // precision lead to different result. Do not seems to be a real // problem, simply rounding approximation but additional study should // be done after 5.2 release. { stringstream str; str << setprecision(limits::digits10 + 2) << limits::max(); CPPUNIT_MESSAGE(str.str().c_str()); CPPUNIT_ASSERT( !str.fail() ); F val; str >> val; CPPUNIT_ASSERT( !str.fail() ); CPPUNIT_ASSERT( limits::infinity() > val ); } { stringstream str; str << setprecision(limits::digits10 + 1) << limits::max(); CPPUNIT_MESSAGE(str.str().c_str()); CPPUNIT_ASSERT( !str.fail() ); F val; str >> val; CPPUNIT_ASSERT( !str.fail() ); CPPUNIT_ASSERT( limits::infinity() > val ); } # endif } #else # define __check_get_float( F ) \ void check_get_float( F v ) \ { \ F in_val_d = v; \ { \ stringstream str; \ \ str << "1E+" << numeric_limits<F>::max_exponent10; \ \ str >> in_val_d; \ CPPUNIT_ASSERT(!str.fail()); \ CPPUNIT_ASSERT(str.eof()); \ CPPUNIT_CHECK( in_val_d == in_val_d ); \ CPPUNIT_CHECK( in_val_d != numeric_limits<F>::infinity() ); \ } \ { \ stringstream str; \ \ str << "-1E+" << numeric_limits<F>::max_exponent10; \ \ str >> in_val_d; \ CPPUNIT_ASSERT(!str.fail()); \ CPPUNIT_ASSERT(str.eof()); \ CPPUNIT_CHECK( in_val_d == in_val_d ); \ CPPUNIT_CHECK( in_val_d != -numeric_limits<F>::infinity() ); \ } \ { \ stringstream str; \ \ str << "1E" << numeric_limits<F>::min_exponent10; \ \ str >> in_val_d; \ CPPUNIT_ASSERT(!str.fail()); \ CPPUNIT_ASSERT(str.eof()); \ CPPUNIT_CHECK( in_val_d == in_val_d ); \ CPPUNIT_CHECK( in_val_d != F(0.0) ); \ } \ { \ stringstream str; \ \ str << "1E+" << (numeric_limits<F>::max_exponent10 + 1); \ \ str >> in_val_d; \ CPPUNIT_ASSERT(!str.fail()); \ CPPUNIT_ASSERT(str.eof()); \ CPPUNIT_CHECK( in_val_d == in_val_d ); \ CPPUNIT_CHECK( in_val_d == numeric_limits<F>::infinity() ); \ } \ { \ stringstream str; \ \ str << "-1E+" << (numeric_limits<F>::max_exponent10 + 1); \ \ str >> in_val_d; \ CPPUNIT_ASSERT(!str.fail()); \ CPPUNIT_ASSERT(str.eof()); \ CPPUNIT_CHECK( in_val_d == in_val_d ); \ CPPUNIT_CHECK( in_val_d == -numeric_limits<F>::infinity() ); \ } \ { \ stringstream str; \ \ str << "1E" << (numeric_limits<F>::min_exponent10 - 1); \ \ str >> in_val_d; \ CPPUNIT_ASSERT(!str.fail()); \ CPPUNIT_ASSERT(str.eof()); \ CPPUNIT_CHECK( in_val_d == in_val_d ); \ CPPUNIT_CHECK( in_val_d >= F(0.0) && in_val_d <= numeric_limits<F>::min() ); \ } \ } __check_get_float( float ) __check_get_float( double ) # if !defined (STLPORT) || !defined (_STLP_NO_LONG_DOUBLE) __check_get_float( long double ) # endif # undef __check_get_float #endif // _STLP_NO_MEMBER_TEMPLATES }; CPPUNIT_TEST_SUITE_REGISTRATION(NumPutGetTest); #if defined (_MSC_VER) # pragma warning (disable : 4056) # pragma warning (disable : 4756) #endif // // tests implementation // void NumPutGetTest::num_put_float() { { string output, digits; { ostringstream ostr; ostr << 1.23457e+17f; CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); digits = "17"; complete_digits(digits); CPPUNIT_CHECK(output == string("1.23457e+") + digits ); } { ostringstream ostr; ostr << setprecision(200) << 1.23457e+17f; CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); CPPUNIT_CHECK( output.size() < 200 ); } { ostringstream ostr; ostr << setprecision(200) << numeric_limits<float>::min(); CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); CPPUNIT_CHECK( output.size() < 200 ); } { ostringstream ostr; ostr << fixed << 1.23457e+17f; CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); CPPUNIT_CHECK(output.size() == 25); CPPUNIT_CHECK(output.substr(0, 5) == "12345"); CPPUNIT_CHECK(output.substr(18) == ".000000"); } { ostringstream ostr; ostr << fixed << showpos << 1.23457e+17f; CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); CPPUNIT_CHECK(output.size() == 26); CPPUNIT_CHECK(output.substr(0, 6) == "+12345"); CPPUNIT_CHECK(output.substr(19) == ".000000"); } { ostringstream ostr; ostr << fixed << showpos << setprecision(100) << 1.23457e+17f; CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); CPPUNIT_CHECK(output.size() == 120); CPPUNIT_CHECK(output.substr(0, 6) == "+12345"); CPPUNIT_CHECK(output.substr(19) == ".0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ); } { ostringstream ostr; ostr << scientific << setprecision(8) << 0.12345678; // float doesn't have enough precision, 0.12345678f ended up 0.1234567836.. CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); digits = "1"; complete_digits(digits); CPPUNIT_CHECK(output == string("1.23456780e-") + digits ); } { ostringstream ostr; ostr << fixed << setprecision(8) << setw(30) << setfill('0') << 0.12345678f; CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); CPPUNIT_CHECK(output == "000000000000000000000.12345678"); } { ostringstream ostr; ostr << fixed << showpos << setprecision(8) << setw(30) << setfill('0') << 0.12345678f; CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); CPPUNIT_CHECK(output == "0000000000000000000+0.12345678"); } { ostringstream ostr; ostr << fixed << showpos << setprecision(8) << setw(30) << left << setfill('0') << 0.12345678f; CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); CPPUNIT_CHECK(output == "+0.123456780000000000000000000"); } { ostringstream ostr; ostr << fixed << showpos << setprecision(8) << setw(30) << internal << setfill('0') << 0.12345678f; CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); CPPUNIT_CHECK(output == "+00000000000000000000.12345678"); } { ostringstream ostr; ostr << fixed << showpos << setprecision(100) << 1.234567e+17; CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); CPPUNIT_CHECK(output.size() == 120); CPPUNIT_CHECK(output.substr(0, 6) == "+12345"); CPPUNIT_CHECK(output.substr(19) == ".0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ); } #if !defined (STLPORT) || !defined (_STLP_NO_LONG_DOUBLE) { ostringstream ostr; ostr << fixed << showpos << setprecision(100) << 1.234567e+17l; CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); CPPUNIT_CHECK(output.size() == 120); CPPUNIT_CHECK(output.substr(0, 6) == "+12345"); CPPUNIT_CHECK(output.substr(19) == ".0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ); } #endif { ostringstream ostr; ostr << scientific << setprecision(50) << 0.0; CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); CPPUNIT_CHECK( output == "0.00000000000000000000000000000000000000000000000000e+00" ); } { ostringstream ostr; ostr << fixed << setprecision(100) << numeric_limits<float>::max(); CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); //CPPUNIT_MESSAGE( output.c_str() ); } { ostringstream ostr; ostr << setprecision(100) << numeric_limits<double>::max(); CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); //CPPUNIT_MESSAGE( output.c_str() ); } #if !defined (STLPORT) || !defined (_STLP_NO_LONG_DOUBLE) { ostringstream ostr; ostr << setprecision(100) << numeric_limits<long double>::max(); CPPUNIT_ASSERT(ostr.good()); output = reset_stream(ostr); //CPPUNIT_MESSAGE( output.c_str() ); } #endif //{ // ostringstream ostr; // ostr << setprecision(-numeric_limits<float>::min_exponent10 + numeric_limits<float>::digits10 + 9) << numeric_limits<float>::min(); // CPPUNIT_ASSERT(ostr.good()); // output = reset_stream(ostr); // //CPPUNIT_MESSAGE( output.c_str() ); //} //{ // ostringstream ostr; // ostr << setprecision(-numeric_limits<double>::min_exponent10 + numeric_limits<double>::digits10) << numeric_limits<double>::min(); // CPPUNIT_ASSERT(ostr.good()); // output = reset_stream(ostr); // //CPPUNIT_MESSAGE( output.c_str() ); //} //#if !defined (STLPORT) || !defined (_STLP_NO_LONG_DOUBLE) // { // ostringstream ostr; // ostr << setprecision(-numeric_limits<long double>::min_exponent10 + numeric_limits<long double>::digits10) << numeric_limits<long double>::min(); // CPPUNIT_ASSERT(ostr.good()); // output = reset_stream(ostr); // CPPUNIT_MESSAGE( output.c_str() ); // } //#endif } { ostringstream str; str.setf(ios::fixed, ios::floatfield); str << 1.0e+5; // cerr << str.str() << endl; CPPUNIT_CHECK( str.str() == "100000.000000" ); reset_stream(str); str.precision(0); str << 1.0e+5; CPPUNIT_CHECK( str.str() == "100000" ); reset_stream(str); str.precision(4); str << 1.0e+5; CPPUNIT_CHECK( str.str() == "100000.0000" ); reset_stream(str); str.precision(0); str << 1.0e+83; CPPUNIT_CHECK( str.str().size() == 84 ); //printf("\nC result: %.0f\n", 1.0e+83); //CPPUNIT_MESSAGE( str.str().c_str() ); //CPPUNIT_CHECK( str.str() == "100000000000000000000000000000000000000000000000000000000000000000000000000000000000" ); // cerr.setf(ios::fixed, ios::floatfield); // cerr << DBL_MAX << endl; // cerr << 1.0e+37 << endl; } } #define CHECK_COMPLETE(type, val, base, showbase, showpos, casing, width, adjust, expected) \ { \ type tmp = val; \ ostringstream ostr; \ ostr << base << showbase << showpos << casing << setw(width) << adjust << tmp; \ CPPUNIT_CHECK( ostr.str() == expected ); \ } #define CHECK(type, val, base, expected) \ CHECK_COMPLETE(type, val, base, noshowbase, noshowpos, nouppercase, 0, right, expected) void NumPutGetTest::num_put_integer() { //octal outputs { CHECK(short, 0, oct, "0") CHECK(short, 1, oct, "1") CHECK(short, 12345, oct, "30071") if (sizeof(short) == 2) { CHECK(short, -1, oct, "177777") CHECK(short, -12345, oct, "147707") } CHECK(unsigned short, 0, oct, "0") CHECK(unsigned short, 12345, oct, "30071") CHECK(int, 0, oct, "0") CHECK(int, 12345678, oct, "57060516") if (sizeof(int) == 4) { CHECK(int, -1, oct, "37777777777") CHECK(int, -12345678, oct, "37720717262") } CHECK(unsigned int, 0, oct, "0") CHECK(unsigned int, 12345678, oct, "57060516") CHECK(long, 0, oct, "0") CHECK(long, 12345678, oct, "57060516") if (sizeof(long) == 4) { CHECK(long, -1, oct, "37777777777") CHECK(long, -12345678, oct, "37720717262") } CHECK(unsigned long, 0, oct, "0") CHECK(unsigned long, 12345678, oct, "57060516") #if defined (STLPORT) && defined (_STLP_LONG_LONG) CHECK(_STLP_LONG_LONG, 0, oct, "0") CHECK(_STLP_LONG_LONG, 12345678, oct, "57060516") if (sizeof(_STLP_LONG_LONG) == 8) { CHECK(_STLP_LONG_LONG, -1, oct, "1777777777777777777777") CHECK(_STLP_LONG_LONG, -12345678, oct, "1777777777777720717262") } CHECK(unsigned _STLP_LONG_LONG, 0, oct, "0") CHECK(unsigned _STLP_LONG_LONG, 12345678, oct, "57060516") #endif //Even with showbase, 0 value gives "0" (see printf documentation) CHECK_COMPLETE(short, 0, oct, showbase, noshowpos, nouppercase, 0, right, "0") CHECK_COMPLETE(short, 0, oct, showbase, showpos, nouppercase, 6, right, " 0") CHECK_COMPLETE(short, 1, oct, showbase, noshowpos, nouppercase, 6, right, " 01") CHECK_COMPLETE(short, 1, oct, showbase, noshowpos, nouppercase, 6, left, "01 ") CHECK_COMPLETE(short, 1, oct, showbase, showpos, nouppercase, 6, internal, " 01") } //decimal outputs { CHECK(short, 0, dec, "0") CHECK(short, -1, dec, "-1") CHECK(short, 12345, dec, "12345") CHECK(short, -12345, dec, "-12345") CHECK(unsigned short, 0, dec, "0") CHECK(unsigned short, 12345, dec, "12345") CHECK(int, 0, dec, "0") CHECK(int, -1, dec, "-1") CHECK(int, 12345678, dec, "12345678") CHECK(int, -12345678, dec, "-12345678") CHECK(unsigned int, 0, dec, "0") CHECK(unsigned int, 12345678, dec, "12345678") CHECK(long, 0, dec, "0") CHECK(long, -1, dec, "-1") CHECK(long, 12345678, dec, "12345678") CHECK(long, -12345678, dec, "-12345678") CHECK(unsigned long, 0, dec, "0") CHECK(unsigned long, 12345678, dec, "12345678") #if defined (STLPORT) && defined (_STLP_LONG_LONG) CHECK(_STLP_LONG_LONG, 0, dec, "0") CHECK(_STLP_LONG_LONG, -1, dec, "-1") CHECK(_STLP_LONG_LONG, 12345678, dec, "12345678") CHECK(_STLP_LONG_LONG, -12345678, dec, "-12345678") CHECK(unsigned _STLP_LONG_LONG, 0, dec, "0") CHECK(unsigned _STLP_LONG_LONG, 12345678, dec, "12345678") #endif CHECK_COMPLETE(short, 0, dec, showbase, showpos, nouppercase, 0, right, "+0") CHECK_COMPLETE(short, 0, dec, showbase, showpos, nouppercase, 6, right, " +0") CHECK_COMPLETE(short, 1, dec, showbase, showpos, nouppercase, 6, right, " +1") CHECK_COMPLETE(short, 1, dec, showbase, showpos, nouppercase, 6, left, "+1 ") CHECK_COMPLETE(short, 1, dec, showbase, showpos, nouppercase, 6, internal, "+ 1") } //hexadecimal outputs { CHECK(short, 0, hex, "0") CHECK(short, 12345, hex, "3039") if (sizeof(short) == 2) { CHECK(short, -1, hex, "ffff") CHECK(short, -12345, hex, "cfc7") } CHECK(unsigned short, 0, hex, "0") CHECK(unsigned short, 12345, hex, "3039") CHECK(int, 0, hex, "0") CHECK(int, 12345678, hex, "bc614e") if (sizeof(int) == 4) { CHECK(int, -1, hex, "ffffffff") CHECK(int, -12345678, hex, "ff439eb2") } CHECK(unsigned int, 0, hex, "0") CHECK(unsigned int, 12345678, hex, "bc614e") CHECK(long, 0, hex, "0") CHECK(long, 12345678, hex, "bc614e") if (sizeof(long) == 4) { CHECK(long, -1, hex, "ffffffff") CHECK(long, -12345678, hex, "ff439eb2") } CHECK(unsigned long, 0, hex, "0") CHECK(unsigned long, 12345678, hex, "bc614e") #if defined (STLPORT) && defined (_STLP_LONG_LONG) CHECK(_STLP_LONG_LONG, 0, hex, "0") CHECK(_STLP_LONG_LONG, 12345678, hex, "bc614e") if (sizeof(_STLP_LONG_LONG) == 8) { CHECK(_STLP_LONG_LONG, -1, hex, "ffffffffffffffff") CHECK(_STLP_LONG_LONG, -12345678, hex, "ffffffffff439eb2") } CHECK(unsigned _STLP_LONG_LONG, 0, hex, "0") CHECK(unsigned _STLP_LONG_LONG, 12345678, hex, "bc614e") #endif //Even with showbase, 0 value gives "0" output (see printf documentation) CHECK_COMPLETE(short, 0, hex, showbase, showpos, nouppercase, 0, right, "0") CHECK_COMPLETE(short, 0, hex, showbase, noshowpos, nouppercase, 6, right, " 0") CHECK_COMPLETE(short, 0, hex, showbase, noshowpos, nouppercase, 6, internal, " 0") CHECK_COMPLETE(short, 1, hex, showbase, noshowpos, nouppercase, 6, right, " 0x1") CHECK_COMPLETE(short, 1, hex, showbase, noshowpos, nouppercase, 6, left, "0x1 ") CHECK_COMPLETE(short, 1, hex, showbase, noshowpos, nouppercase, 6, internal, "0x 1") CHECK_COMPLETE(short, 1, hex, showbase, noshowpos, uppercase, 6, left, "0X1 ") CHECK_COMPLETE(short, 1, hex, showbase, showpos, uppercase, 6, internal, "0X 1") } } void NumPutGetTest::num_get_float() { float in_val; istringstream istr; istr.str("1.2345"); istr >> in_val; CPPUNIT_ASSERT(!istr.fail()); CPPUNIT_ASSERT(istr.eof()); CPPUNIT_ASSERT(check_float(in_val, 1.2345f)); istr.clear(); istr.str("-1.2345"); istr >> in_val; CPPUNIT_ASSERT(!istr.fail()); CPPUNIT_ASSERT(istr.eof()); CPPUNIT_ASSERT(check_float(in_val, -1.2345f)); istr.clear(); istr.str("+1.2345"); istr >> in_val; CPPUNIT_ASSERT(!istr.fail()); CPPUNIT_ASSERT(check_float(in_val, 1.2345f)); istr.clear(); istr.str("000000000000001.234500000000"); istr >> in_val; CPPUNIT_ASSERT(!istr.fail()); CPPUNIT_ASSERT(istr.eof()); CPPUNIT_ASSERT(check_float(in_val, 1.2345f)); istr.clear(); istr.str("1.2345e+04"); istr >> in_val; CPPUNIT_ASSERT(!istr.fail()); CPPUNIT_ASSERT(istr.eof()); CPPUNIT_ASSERT(check_float(in_val, 12345.0f)); istr.clear(); CPPUNIT_MESSAGE( "float" ); check_get_float( 0.0F ); CPPUNIT_MESSAGE( "double" ); check_get_float( 0.0 ); #if (!defined (STLPORT) || !defined (_STLP_NO_LONG_DOUBLE)) && !defined(__ANDROID__) CPPUNIT_MESSAGE( "long double" ); check_get_float( 0.0L ); #endif { stringstream str; str << "1e" << numeric_limits<double>::max_exponent10; CPPUNIT_ASSERT(!str.fail()); float val; str >> val; CPPUNIT_ASSERT(!str.fail()); CPPUNIT_ASSERT(str.eof()); CPPUNIT_ASSERT( numeric_limits<double>::max_exponent10 <= numeric_limits<float>::max_exponent10 || val == numeric_limits<float>::infinity() ); } { stringstream str; str << "1e" << numeric_limits<double>::min_exponent10; CPPUNIT_ASSERT(!str.fail()); float val; str >> val; CPPUNIT_ASSERT(!str.fail()); CPPUNIT_ASSERT(str.eof()); CPPUNIT_ASSERT( numeric_limits<double>::min_exponent10 >= numeric_limits<float>::min_exponent10 || val == 0.0f ); } #if !defined (STLPORT) || !defined (_STLP_NO_LONG_DOUBLE) { stringstream str; str << "1e" << numeric_limits<long double>::max_exponent10; CPPUNIT_ASSERT(!str.fail()); double val; str >> val; CPPUNIT_ASSERT(!str.fail()); CPPUNIT_ASSERT(str.eof()); CPPUNIT_ASSERT( numeric_limits<long double>::max_exponent10 <= numeric_limits<double>::max_exponent10 || val == numeric_limits<double>::infinity() ); } { stringstream str; str << "1e" << numeric_limits<long double>::min_exponent10; CPPUNIT_ASSERT(!str.fail()); double val; str >> val; CPPUNIT_ASSERT(!str.fail()); CPPUNIT_ASSERT(str.eof()); CPPUNIT_ASSERT( numeric_limits<long double>::min_exponent10 >= numeric_limits<double>::min_exponent10 || val == 0.0 ); } #if !defined(__ANDROID__) // "long double" in Android is still a distinct type but size is the same as "double" { const char* p = "2.718281828459045235360287471352662497757247093e0"; std::stringstream s; s << p; long double x; s >> x; CPPUNIT_ASSERT( x > 2.70l && x < 2.72l ); } #endif #endif } void NumPutGetTest::num_get_integer() { //octal input { istringstream istr; istr.str("30071"); short val; istr >> oct >> val; CPPUNIT_ASSERT( !istr.fail() ); CPPUNIT_ASSERT( istr.eof() ); CPPUNIT_ASSERT( val == 12345 ); istr.clear(); if (sizeof(short) == 2) { istr.str("177777"); istr >> oct >> val; CPPUNIT_ASSERT( !istr.fail() ); CPPUNIT_ASSERT( istr.eof() ); CPPUNIT_ASSERT( val == -1 ); istr.clear(); } } //decimal input { istringstream istr; istr.str("10000"); short val = -1; istr >> val; CPPUNIT_ASSERT( !istr.fail() ); CPPUNIT_ASSERT( istr.eof() ); CPPUNIT_ASSERT( val == 10000 ); istr.clear(); istr.str("+10000"); val = -1; istr >> val; CPPUNIT_ASSERT( !istr.fail() ); CPPUNIT_ASSERT( istr.eof() ); CPPUNIT_ASSERT( val == 10000 ); istr.clear(); if (sizeof(short) == 2) { val = -1; istr.str("10000000"); istr >> val; CPPUNIT_ASSERT( istr.fail() ); CPPUNIT_ASSERT( istr.eof() ); CPPUNIT_ASSERT( val == -1 ); istr.clear(); } val = -1; istr.str("0x0"); istr >> val; CPPUNIT_ASSERT( !istr.fail() ); CPPUNIT_ASSERT( !istr.eof() ); CPPUNIT_ASSERT( val == 0 ); istr.clear(); val = -1; istr.str("000001"); istr >> val; CPPUNIT_ASSERT( !istr.fail() ); CPPUNIT_ASSERT( istr.eof() ); CPPUNIT_ASSERT( val == 1 ); istr.clear(); } //hexadecimal input { istringstream istr; istr.str("3039"); short val = -1; istr >> hex >> val; CPPUNIT_ASSERT( !istr.fail() ); CPPUNIT_ASSERT( istr.eof() ); CPPUNIT_ASSERT( val == 12345 ); istr.clear(); istr.str("x3039"); val = -1; istr >> hex >> val; CPPUNIT_ASSERT( istr.fail() ); CPPUNIT_ASSERT( !istr.eof() ); CPPUNIT_ASSERT( val == -1 ); istr.clear(); istr.str("03039"); val = -1; istr >> hex >> val; CPPUNIT_ASSERT( !istr.fail() ); CPPUNIT_ASSERT( istr.eof() ); CPPUNIT_ASSERT( val == 12345 ); istr.clear(); istr.str("0x3039"); istr >> hex >> val; CPPUNIT_ASSERT( !istr.fail() ); CPPUNIT_ASSERT( istr.eof() ); CPPUNIT_ASSERT( val == 12345 ); istr.clear(); if (sizeof(short) == 2) { val = -1; istr.str("cfc7"); istr >> hex >> val; CPPUNIT_ASSERT( !istr.fail() ); CPPUNIT_ASSERT( istr.eof() ); CPPUNIT_ASSERT( val == -12345 ); istr.clear(); } } } void NumPutGetTest::inhex() { { ostringstream s; s << hex << 0; CPPUNIT_CHECK( s.str() == "0" ); } { ostringstream s; s << hex << 0xff; CPPUNIT_CHECK( s.str() == "ff" ); } { ostringstream s; s << hex << setw( 4 ) << 0xff; CPPUNIT_CHECK( s.str() == " ff" ); } { ostringstream s; s << hex << setw( 4 ) << 0; CPPUNIT_CHECK( s.str() == " 0" ); } { ostringstream s; s << hex << showbase << 0; CPPUNIT_CHECK( s.str() == "0" ); } { ostringstream s; s << hex << showbase << 0xff; CPPUNIT_CHECK( s.str() == "0xff" ); } { ostringstream s; s << hex << showbase << setw( 4 ) << 0xff; CPPUNIT_CHECK( s.str() == "0xff" ); } { // special case for regression (partially duplicate CHECK_COMPLETE above): ostringstream s; s.setf( ios_base::internal, ios_base::adjustfield ); s << hex << showbase << setw(8+2) << 0; CPPUNIT_CHECK( s.str() == " 0" ); } } void NumPutGetTest::pointer() { // Problem with printing pointer to null /* * Really C's formatting not help here, due to: * * p The argument shall be a pointer to void. The value of * the pointer is converted to a sequence of printable characters, * in an implementation-defined manner. */ { /* char buf[128]; void *p = (void *)0xff00; sprintf( buf, "%p", p ); // cerr << buf << endl; // Hmmm, I see 0xff00 on box with 32-bits address; pointer like 'unsigned hex'? if ( sizeof( p ) == 2 ) { CPPUNIT_ASSERT( strcmp( buf, "0xff00" ) == 0 ); } else if ( sizeof( p ) == 4 ) { CPPUNIT_ASSERT( strcmp( buf, "0x0000ff00" ) == 0 ); } else if ( sizeof( p ) == 8 ) { CPPUNIT_ASSERT( strcmp( buf, "0x000000000000ff00" ) == 0 ); } else { CPPUNIT_CHECK( sizeof( p ) == 2 || sizeof( p ) == 4 || sizeof( p ) == 8 ); } */ } { /* char buf[128]; void *p = 0; */ // sprintf( buf, "%p", p ); /* Cool. "%p" print '(nil)'; "%#x" print '0' */ // sprintf( buf, "%#x", (unsigned)p ); // cerr << buf << endl; } { ostringstream s; void *p = (void *)0xff00; s << p; CPPUNIT_ASSERT( s.good() ); if ( sizeof( p ) == 2 ) { CPPUNIT_ASSERT( s.str() == "0xff00" ); } else if ( sizeof( p ) == 4 ) { CPPUNIT_ASSERT( s.str() == "0x0000ff00" ); // this pass } else if ( sizeof( p ) == 8 ) { CPPUNIT_ASSERT( s.str() == "0x000000000000ff00" ); } else { CPPUNIT_CHECK( sizeof( p ) == 2 || sizeof( p ) == 4 || sizeof( p ) == 8 ); } } { ostringstream s; void *p = 0; s << p; CPPUNIT_ASSERT( s.good() ); if ( sizeof( p ) == 2 ) { CPPUNIT_ASSERT( s.str() == "0x0000" ); } else if ( sizeof( p ) == 4 ) { CPPUNIT_ASSERT( s.str() == "0x00000000" ); // but this will fail, if follow %p } else if ( sizeof( p ) == 8 ) { CPPUNIT_ASSERT( s.str() == "0x0000000000000000" ); } else { CPPUNIT_CHECK( sizeof( p ) == 2 || sizeof( p ) == 4 || sizeof( p ) == 8 ); } } } void NumPutGetTest::fix_float_long() { ostringstream str; str.setf(ios::fixed, ios::floatfield); str << 1.0e+5; CPPUNIT_CHECK( str.str() == "100000.000000" ); reset_stream(str); str.precision(0); str << 1.0e+5; CPPUNIT_CHECK( str.str() == "100000" ); reset_stream(str); str.precision(4); str << 1.0e+5; CPPUNIT_CHECK( str.str() == "100000.0000" ); reset_stream(str); str.precision(0); str << 1.0e+83; { istringstream istr( str.str() ); double f; istr >> f; CPPUNIT_CHECK( !istr.fail() ); if ( int(numeric_limits<double>::digits10) < 83 ) { double delta = 1.0; for ( int ee = 83 - int(numeric_limits<double>::digits10); ee > 0; --ee ) { delta *= 10.0; } // we may loss some digits here, but not more than mantissa: CPPUNIT_CHECK( (f > (1.0e+83 - delta)) && (f < (1.0e+83 + delta)) ); } else { CPPUNIT_CHECK( check_double(f, 1.0e+83) ); } } #if 0 // #ifndef _STLP_NO_LONG_DOUBLE reset_stream(str); str.precision(0); str << 1.0e+83l; { istringstream istr( str.str() ); long double f; istr >> f; CPPUNIT_CHECK( !istr.fail() ); if ( int(numeric_limits<long double>::digits10) < 83 ) { long double delta = 1.0l; for ( int ee = 83 - int(numeric_limits<long double>::digits10); ee > 0; --ee ) { delta *= 10.0l; } // we may loss some digits here, but not more than mantissa: cerr << "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789" << endl; cerr << str.str() << endl; cerr << delta << endl; cerr << f << endl; CPPUNIT_CHECK( (f > (1.0e+83l - delta)) && (f < (1.0e+83l + delta)) ); } else { CPPUNIT_CHECK( check_double(f, 1.0e+83l) ); } } #endif reset_stream(str); str.precision(0); str << numeric_limits<double>::max(); { istringstream istr( str.str() ); double f; istr >> f; CPPUNIT_CHECK( !istr.fail() ); if ( int(numeric_limits<double>::digits10) < int(numeric_limits<double>::max_exponent10) ) { double delta = 9.0; for ( int ee = int(numeric_limits<double>::max_exponent10) - int(numeric_limits<double>::digits10); ee > 0; --ee ) { delta *= 10.0; } // we may loss some digits here, but not more than mantissa: CPPUNIT_CHECK( (f > (numeric_limits<double>::max() - delta)) ); } } #if 0 // #ifndef _STLP_NO_LONG_DOUBLE reset_stream(str); str.precision(0); str << numeric_limits<long double>::max(); { istringstream istr( str.str() ); long double f; istr >> f; CPPUNIT_CHECK( !istr.fail() ); if ( int(numeric_limits<long double>::digits10) < int(numeric_limits<long double>::max_exponent10) ) { long double delta = 1.0l; for ( int ee = int(numeric_limits<long double>::max_exponent10) - int(numeric_limits<long double>::digits10); ee > 0; --ee ) { delta *= 10.0l; } // we may loss some digits here, but not more than mantissa: CPPUNIT_CHECK( (f > (numeric_limits<long double>::max() - delta)) ); } } #endif } class CommaSepNumPunct : public numpunct<char> { char do_thousands_sep() const { return ','; } string do_grouping() const { return string("\1\2\3") + (char)CHAR_MAX; } }; #define CHECK2(val, expected) \ os.str(""); os << fixed << setprecision(3) << showpos << val; \ CPPUNIT_ASSERT( os.str() == expected ) // Use unadulterated os2 when expecting inf #define CHECKINF(val, expected, expected2) \ os2.str(""); os2 << fixed << setprecision(4) << showpos << val; \ CPPUNIT_ASSERT( os2.str() == expected || os2.str() == expected2 ) void NumPutGetTest::custom_numpunct() { ostringstream os, os2; locale loc(os.getloc(), new CommaSepNumPunct()); os.imbue(loc); CHECK2(1, "+1"); CHECK2(10, "+1,0"); CHECK2(100, "+10,0"); CHECK2(1000, "+1,00,0"); CHECK2(1.234, "+1.234"); CHECK2(123.456, "+12,3.456"); CHECK2(1234.567, "+1,23,4.567"); CHECK2(12345.678, "+12,34,5.678"); CHECK2(123456.789, "+123,45,6.789"); CHECK2(1234567.891, "+1,234,56,7.891"); CHECK2(123456789.123, "+123,456,78,9.123"); //CHECK2(100000000000000000000000000000.0, "+100000000000000000000000,000,00,0.000"); CHECKINF(numeric_limits<double>::infinity(), "+inf", "+Inf"); CHECK2(-1.234, "-1.234"); CHECK2(-123.456, "-12,3.456"); CHECK2(-1234.567, "-1,23,4.567"); CHECK2(-12345.678, "-12,34,5.678"); CHECK2(-123456.789, "-123,45,6.789"); CHECK2(-1234567.891, "-1,234,56,7.891"); CHECK2(-123456789.123, "-123,456,78,9.123"); //CHECK2(-100000000000000000000000000000.0, "-100000000000000000000000,000,00,0.000"); CHECKINF(-numeric_limits<double>::infinity(), "-inf", "-Inf"); } #endif