#include <string> #include "math_aux.h" #if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS) # include <sstream> # include <memory> # include "full_streambuf.h" # include "cppunit/cppunit_proxy.h" # if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES) using namespace std; # endif // // TestCase class // class SstreamTest : public CPPUNIT_NS::TestCase { CPPUNIT_TEST_SUITE(SstreamTest); CPPUNIT_TEST(output); CPPUNIT_TEST(input); CPPUNIT_TEST(input_char); CPPUNIT_TEST(io); CPPUNIT_TEST(err); CPPUNIT_TEST(err_long); CPPUNIT_TEST(maxint); CPPUNIT_TEST(init_in); CPPUNIT_TEST(init_out); CPPUNIT_TEST(buf); CPPUNIT_TEST(rdbuf); CPPUNIT_TEST(streambuf_output); CPPUNIT_TEST(seek); CPPUNIT_TEST(seekp); CPPUNIT_TEST(seek_gp); CPPUNIT_TEST(tellp); CPPUNIT_TEST(negative); CPPUNIT_TEST_SUITE_END(); protected: void output(); void input(); void input_char(); void io(); void err(); void err_long(); void maxint(); void init_in(); void init_out(); void buf(); void rdbuf(); void streambuf_output(); void seek(); void seekp(); void seek_gp(); void tellp(); void negative(); }; CPPUNIT_TEST_SUITE_REGISTRATION(SstreamTest); // // tests implementation // void SstreamTest::output() { { ostringstream s; s << 1 << '\n' << 2.0 << '\n' << "abcd\n" << "ghk lm\n" << "abcd ef"; CPPUNIT_ASSERT( s.good() ); CPPUNIT_ASSERT( s.str() == "1\n2\nabcd\nghk lm\nabcd ef" ); } //Following tests are mostly used to reveal problem with the MSVC /Wp64 option //used to track 64 bits portability issue: { ostringstream s; size_t i = 0; s << i; CPPUNIT_ASSERT( s.good() ); CPPUNIT_ASSERT( s.str() == "0" ); } { ostringstream s; ptrdiff_t i = 0; s << i; CPPUNIT_ASSERT( s.good() ); CPPUNIT_ASSERT( s.str() == "0" ); } } void SstreamTest::input() { { istringstream s( "1\n2\nabcd\nghk lm\nabcd ef" ); int i = 0; s >> i; CPPUNIT_ASSERT( s.good() ); CPPUNIT_ASSERT( i == 1 ); double d = 0.0; s >> d; CPPUNIT_ASSERT( s.good() ); CPPUNIT_ASSERT( d == 2.0 ); string str; s >> str; CPPUNIT_ASSERT( s.good() ); CPPUNIT_ASSERT( str == "abcd" ); char c; s.get(c); // extract newline, that not extracted by operator >> CPPUNIT_ASSERT( s.good() ); CPPUNIT_ASSERT( c == '\n' ); getline( s, str ); CPPUNIT_ASSERT( s.good() ); CPPUNIT_ASSERT( str == "ghk lm" ); getline( s, str ); CPPUNIT_ASSERT( s.eof() ); CPPUNIT_ASSERT( str == "abcd ef" ); } { istringstream s("0"); size_t i = 1; s >> i; CPPUNIT_ASSERT( !s.fail() ); CPPUNIT_ASSERT( s.eof() ); CPPUNIT_ASSERT( i == 0 ); } } void SstreamTest::input_char() { char buf[16] = { 0, '1', '2', '3' }; istringstream s( "0" ); s >> buf; CPPUNIT_ASSERT( buf[0] == '0' ); CPPUNIT_ASSERT( buf[1] == 0 ); CPPUNIT_ASSERT( buf[2] == '2' ); } void SstreamTest::io() { stringstream s; s << 1 << '\n' << 2.0 << '\n' << "abcd\n" << "ghk lm\n" << "abcd ef"; CPPUNIT_ASSERT( s.good() ); int i = 0; s >> i; CPPUNIT_ASSERT( i == 1 ); CPPUNIT_ASSERT( s.good() ); double d = 0.0; s >> d; CPPUNIT_ASSERT( d == 2.0 ); CPPUNIT_ASSERT( s.good() ); string str; s >> str; CPPUNIT_ASSERT( str == "abcd" ); CPPUNIT_ASSERT( s.good() ); char c; s.get(c); // extract newline, that not extracted by operator >> CPPUNIT_ASSERT( s.good() ); CPPUNIT_ASSERT( c == '\n' ); getline( s, str ); CPPUNIT_ASSERT( s.good() ); CPPUNIT_ASSERT( str == "ghk lm" ); getline( s, str ); CPPUNIT_ASSERT( str == "abcd ef" ); CPPUNIT_ASSERT( s.eof() ); } void SstreamTest::err() { stringstream s( "9" ); int i = 0; s >> i; CPPUNIT_ASSERT( !s.fail() ); CPPUNIT_ASSERT( i == 9 ); s >> i; CPPUNIT_ASSERT( s.fail() ); CPPUNIT_ASSERT( s.eof() ); CPPUNIT_ASSERT( i == 9 ); } void SstreamTest::err_long() { stringstream s( "9" ); long i = 0; s >> i; CPPUNIT_ASSERT( !s.fail() ); CPPUNIT_ASSERT( i == 9 ); s >> i; CPPUNIT_ASSERT( s.fail() ); CPPUNIT_ASSERT( s.eof() ); CPPUNIT_ASSERT( i == 9 ); } void SstreamTest::maxint() { stringstream s; s << INT_MAX << " " << UINT_MAX << " " << LONG_MAX << " " << ULONG_MAX << " " << INT_MIN << " " << LONG_MIN; CPPUNIT_ASSERT( s.good() ); int i = 0; unsigned int u = 0; long l = 0; unsigned long ul = 0; s >> i >> u >> l >> ul; CPPUNIT_ASSERT( s.good() ); CPPUNIT_ASSERT( i == INT_MAX ); CPPUNIT_ASSERT( u == UINT_MAX ); CPPUNIT_ASSERT( l == LONG_MAX ); CPPUNIT_ASSERT( ul == ULONG_MAX ); s >> i >> l; CPPUNIT_ASSERT( !s.fail() ); CPPUNIT_ASSERT( i == INT_MIN ); CPPUNIT_ASSERT( l == LONG_MIN ); } void SstreamTest::init_in() { istringstream is( "12345" ); int n; is >> n; CPPUNIT_ASSERT( !is.fail() ); CPPUNIT_ASSERT( n == 12345 ); istringstream dis( "1.2345" ); double d; dis >> d; CPPUNIT_ASSERT( !dis.fail() ); CPPUNIT_ASSERT( are_equals(d, 1.2345) ); istringstream fis( "1.2345" ); float f; fis >> f; CPPUNIT_ASSERT( !fis.fail() ); CPPUNIT_ASSERT( are_equals(f, 1.2345f) ); } void SstreamTest::init_out() { ostringstream os( "12345" ); CPPUNIT_ASSERT( os.str() == "12345" ); os << 67; CPPUNIT_ASSERT( os.good() ); // This satisfy to the Standard: // CPPUNIT_ASSERT( os.str() == "67345" ); // But we don't know the reason, why standard state that. /* * 27.7.1.1: ... then copies the content of str into the basic_sringbuf * underlying character sequence and initializes the input and output * sequences according to which. If which & ios_base::out is true, initializes * the output sequence with underlying sequence. ... * * I can treat this as 'like output was performed', and then I should bump * put pointer... Looks like more useful then my previous treatment. * * - ptr */ CPPUNIT_ASSERT( os.str() == "1234567" ); os.str( "89ab" ); CPPUNIT_ASSERT( os.str() == "89ab" ); os << 10; CPPUNIT_ASSERT( os.good() ); // CPPUNIT_ASSERT( os.str() == "10ab" ); CPPUNIT_ASSERT( os.str() == "89ab10" ); } void SstreamTest::buf() { stringstream ss; ss << "1234567\n89\n"; char buf[10]; buf[7] = 'x'; ss.get( buf, 10 ); CPPUNIT_ASSERT( !ss.fail() ); CPPUNIT_ASSERT( buf[0] == '1' ); CPPUNIT_ASSERT( buf[1] == '2' ); CPPUNIT_ASSERT( buf[2] == '3' ); CPPUNIT_ASSERT( buf[3] == '4' ); CPPUNIT_ASSERT( buf[4] == '5' ); CPPUNIT_ASSERT( buf[5] == '6' ); CPPUNIT_ASSERT( buf[6] == '7' ); // 27.6.1.3 paragraph 10, paragraph 7 CPPUNIT_ASSERT( buf[7] == 0 ); // 27.6.1.3 paragraph 8 char c; ss.get(c); CPPUNIT_ASSERT( !ss.fail() ); CPPUNIT_ASSERT( c == '\n' ); // 27.6.1.3 paragraph 10, paragraph 7 ss.get(c); CPPUNIT_ASSERT( !ss.fail() ); CPPUNIT_ASSERT( c == '8' ); } void SstreamTest::rdbuf() { stringstream ss; ss << "1234567\n89\n"; ostringstream os; ss.get( *os.rdbuf(), '\n' ); CPPUNIT_ASSERT( !ss.fail() ); char c; ss.get(c); CPPUNIT_ASSERT( !ss.fail() ); CPPUNIT_ASSERT( c == '\n' ); // 27.6.1.3 paragraph 12 CPPUNIT_ASSERT( os.str() == "1234567" ); } void SstreamTest::streambuf_output() { { istringstream in("01234567890123456789"); CPPUNIT_ASSERT( in ); full_streambuf full_buf(10); ostream out(&full_buf); CPPUNIT_ASSERT( out ); out << in.rdbuf(); CPPUNIT_ASSERT( out ); CPPUNIT_ASSERT( in ); //out is good we can check what has been extracted: CPPUNIT_ASSERT( full_buf.str() == "0123456789" ); out << in.rdbuf(); CPPUNIT_ASSERT( out.fail() ); CPPUNIT_ASSERT( in ); ostringstream ostr; ostr << in.rdbuf(); CPPUNIT_ASSERT( ostr ); CPPUNIT_ASSERT( in ); CPPUNIT_ASSERT( ostr.str() == "0123456789" ); } # if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS) { //If the output stream buffer throws: istringstream in("01234567890123456789"); CPPUNIT_ASSERT( in ); full_streambuf full_buf(10, true); ostream out(&full_buf); CPPUNIT_ASSERT( out ); out << in.rdbuf(); CPPUNIT_ASSERT( out.bad() ); CPPUNIT_ASSERT( in ); //out is bad we have no guaranty on what has been extracted: //CPPUNIT_ASSERT( full_buf.str() == "0123456789" ); out.clear(); out << in.rdbuf(); CPPUNIT_ASSERT( out.fail() && out.bad() ); CPPUNIT_ASSERT( in ); ostringstream ostr; ostr << in.rdbuf(); CPPUNIT_ASSERT( ostr ); CPPUNIT_ASSERT( in ); CPPUNIT_ASSERT( ostr.str() == "01234567890123456789" ); } # endif } void SstreamTest::seek() { stringstream s( "0123456789" ); CPPUNIT_ASSERT( s.tellg() == stringstream::pos_type(0) ); s.seekg( 6, ios::beg ); CPPUNIT_ASSERT( s.tellg() == stringstream::pos_type(6) ); s.seekg( -3, ios::cur ); CPPUNIT_ASSERT( s.tellg() == stringstream::pos_type(3) ); istringstream is( "0123456789" ); CPPUNIT_ASSERT( is.tellg() == stringstream::pos_type(0) ); is.seekg( 6, ios::beg ); CPPUNIT_ASSERT( is.tellg() == stringstream::pos_type(6) ); is.seekg( -3, ios::cur ); CPPUNIT_ASSERT( is.tellg() == stringstream::pos_type(3) ); } void SstreamTest::seekp() { ostringstream s; s << "1234567"; CPPUNIT_CHECK( s.tellp() == stringstream::pos_type(7) ); CPPUNIT_CHECK( s.str() == "1234567" ); s.seekp( 0 ); s << "X"; CPPUNIT_CHECK( s.str() == "X234567" ); s.seekp( 0, ios::beg ); s << "Y"; CPPUNIT_CHECK( s.str() == "Y234567" ); } void SstreamTest::seek_gp() { stringstream ss( "1" ); /* ISO/IEC 14882 2003 (and 1998 too) assume change as get as put positions with seekg and seekp (27.6.1.3, par 38; 27.6.2.4 par 2), but this contradict to common practice and proposed draft N2588 (27.6.1.3, par 41; 27.6.2.5, par 4) Now STLport implement (i.e. change behaviour ) the draft's point of view. */ ss.seekg( 0, ios::beg ); ss.seekp( 0, ios::end ); ss << "2"; string str; ss >> str; /* CPPUNIT_CHECK( str == "2" ); --- according ISO/IEC 14882 2003 */ CPPUNIT_CHECK( str == "12" ); } void SstreamTest::tellp() { { ostringstream o( "1" ); o << "23456"; CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == stringstream::pos_type(6) ); CPPUNIT_CHECK( o.tellp() == stringstream::pos_type(6) ); } { ostringstream o; o << "123456"; CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == stringstream::pos_type(6) ); CPPUNIT_CHECK( o.tellp() == stringstream::pos_type(6) ); } { ostringstream o( "1" ); o << "23456789"; CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == stringstream::pos_type(9) ); CPPUNIT_CHECK( o.tellp() == stringstream::pos_type(9) ); } } template < class T > string to_string( const T& v ) { ostringstream oss; oss << v; return oss.str(); } void SstreamTest::negative() { CPPUNIT_CHECK( to_string<int>(-1) == "-1" ); CPPUNIT_CHECK( to_string<long>(-1) == "-1" ); } #endif