1 #include <string> 2 #include "math_aux.h" 3 4 #if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS) 5 # include <sstream> 6 # include <memory> 7 8 # include "full_streambuf.h" 9 10 # include "cppunit/cppunit_proxy.h" 11 12 # if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES) 13 using namespace std; 14 # endif 15 16 // 17 // TestCase class 18 // 19 class SstreamTest : public CPPUNIT_NS::TestCase 20 { 21 CPPUNIT_TEST_SUITE(SstreamTest); 22 CPPUNIT_TEST(output); 23 CPPUNIT_TEST(input); 24 CPPUNIT_TEST(input_char); 25 CPPUNIT_TEST(io); 26 CPPUNIT_TEST(err); 27 CPPUNIT_TEST(err_long); 28 CPPUNIT_TEST(maxint); 29 CPPUNIT_TEST(init_in); 30 CPPUNIT_TEST(init_out); 31 CPPUNIT_TEST(buf); 32 CPPUNIT_TEST(rdbuf); 33 CPPUNIT_TEST(streambuf_output); 34 CPPUNIT_TEST(seek); 35 CPPUNIT_TEST(seekp); 36 CPPUNIT_TEST(seek_gp); 37 CPPUNIT_TEST(tellp); 38 CPPUNIT_TEST(negative); 39 CPPUNIT_TEST_SUITE_END(); 40 41 protected: 42 void output(); 43 void input(); 44 void input_char(); 45 void io(); 46 void err(); 47 void err_long(); 48 void maxint(); 49 void init_in(); 50 void init_out(); 51 void buf(); 52 void rdbuf(); 53 void streambuf_output(); 54 void seek(); 55 void seekp(); 56 void seek_gp(); 57 void tellp(); 58 void negative(); 59 }; 60 61 CPPUNIT_TEST_SUITE_REGISTRATION(SstreamTest); 62 63 // 64 // tests implementation 65 // 66 void SstreamTest::output() 67 { 68 { 69 ostringstream s; 70 71 s << 1 << '\n' << 2.0 << '\n' << "abcd\n" << "ghk lm\n" << "abcd ef"; 72 CPPUNIT_ASSERT( s.good() ); 73 CPPUNIT_ASSERT( s.str() == "1\n2\nabcd\nghk lm\nabcd ef" ); 74 } 75 76 //Following tests are mostly used to reveal problem with the MSVC /Wp64 option 77 //used to track 64 bits portability issue: 78 { 79 ostringstream s; 80 size_t i = 0; 81 s << i; 82 CPPUNIT_ASSERT( s.good() ); 83 CPPUNIT_ASSERT( s.str() == "0" ); 84 } 85 { 86 ostringstream s; 87 ptrdiff_t i = 0; 88 s << i; 89 CPPUNIT_ASSERT( s.good() ); 90 CPPUNIT_ASSERT( s.str() == "0" ); 91 } 92 } 93 94 void SstreamTest::input() 95 { 96 { 97 istringstream s( "1\n2\nabcd\nghk lm\nabcd ef" ); 98 int i = 0; 99 s >> i; 100 CPPUNIT_ASSERT( s.good() ); 101 CPPUNIT_ASSERT( i == 1 ); 102 double d = 0.0; 103 s >> d; 104 CPPUNIT_ASSERT( s.good() ); 105 CPPUNIT_ASSERT( d == 2.0 ); 106 string str; 107 s >> str; 108 CPPUNIT_ASSERT( s.good() ); 109 CPPUNIT_ASSERT( str == "abcd" ); 110 char c; 111 s.get(c); // extract newline, that not extracted by operator >> 112 CPPUNIT_ASSERT( s.good() ); 113 CPPUNIT_ASSERT( c == '\n' ); 114 getline( s, str ); 115 CPPUNIT_ASSERT( s.good() ); 116 CPPUNIT_ASSERT( str == "ghk lm" ); 117 getline( s, str ); 118 CPPUNIT_ASSERT( s.eof() ); 119 CPPUNIT_ASSERT( str == "abcd ef" ); 120 } 121 { 122 istringstream s("0"); 123 size_t i = 1; 124 s >> i; 125 CPPUNIT_ASSERT( !s.fail() ); 126 CPPUNIT_ASSERT( s.eof() ); 127 CPPUNIT_ASSERT( i == 0 ); 128 } 129 } 130 131 void SstreamTest::input_char() 132 { 133 char buf[16] = { 0, '1', '2', '3' }; 134 istringstream s( "0" ); 135 s >> buf; 136 137 CPPUNIT_ASSERT( buf[0] == '0' ); 138 CPPUNIT_ASSERT( buf[1] == 0 ); 139 CPPUNIT_ASSERT( buf[2] == '2' ); 140 } 141 142 143 void SstreamTest::io() 144 { 145 stringstream s; 146 s << 1 << '\n' << 2.0 << '\n' << "abcd\n" << "ghk lm\n" << "abcd ef"; 147 CPPUNIT_ASSERT( s.good() ); 148 149 int i = 0; 150 s >> i; 151 CPPUNIT_ASSERT( i == 1 ); 152 CPPUNIT_ASSERT( s.good() ); 153 double d = 0.0; 154 s >> d; 155 CPPUNIT_ASSERT( d == 2.0 ); 156 CPPUNIT_ASSERT( s.good() ); 157 string str; 158 s >> str; 159 CPPUNIT_ASSERT( str == "abcd" ); 160 CPPUNIT_ASSERT( s.good() ); 161 char c; 162 s.get(c); // extract newline, that not extracted by operator >> 163 CPPUNIT_ASSERT( s.good() ); 164 CPPUNIT_ASSERT( c == '\n' ); 165 getline( s, str ); 166 CPPUNIT_ASSERT( s.good() ); 167 CPPUNIT_ASSERT( str == "ghk lm" ); 168 getline( s, str ); 169 CPPUNIT_ASSERT( str == "abcd ef" ); 170 CPPUNIT_ASSERT( s.eof() ); 171 } 172 173 void SstreamTest::err() 174 { 175 stringstream s( "9" ); 176 177 int i = 0; 178 s >> i; 179 CPPUNIT_ASSERT( !s.fail() ); 180 CPPUNIT_ASSERT( i == 9 ); 181 s >> i; 182 CPPUNIT_ASSERT( s.fail() ); 183 CPPUNIT_ASSERT( s.eof() ); 184 CPPUNIT_ASSERT( i == 9 ); 185 } 186 187 void SstreamTest::err_long() 188 { 189 stringstream s( "9" ); 190 191 long i = 0; 192 s >> i; 193 CPPUNIT_ASSERT( !s.fail() ); 194 CPPUNIT_ASSERT( i == 9 ); 195 s >> i; 196 CPPUNIT_ASSERT( s.fail() ); 197 CPPUNIT_ASSERT( s.eof() ); 198 CPPUNIT_ASSERT( i == 9 ); 199 } 200 201 void SstreamTest::maxint() 202 { 203 stringstream s; 204 205 s << INT_MAX << " " << UINT_MAX << " " << LONG_MAX << " " << ULONG_MAX << " " 206 << INT_MIN << " " << LONG_MIN; 207 CPPUNIT_ASSERT( s.good() ); 208 209 int i = 0; 210 unsigned int u = 0; 211 long l = 0; 212 unsigned long ul = 0; 213 214 s >> i >> u >> l >> ul; 215 CPPUNIT_ASSERT( s.good() ); 216 CPPUNIT_ASSERT( i == INT_MAX ); 217 CPPUNIT_ASSERT( u == UINT_MAX ); 218 CPPUNIT_ASSERT( l == LONG_MAX ); 219 CPPUNIT_ASSERT( ul == ULONG_MAX ); 220 221 s >> i >> l; 222 CPPUNIT_ASSERT( !s.fail() ); 223 CPPUNIT_ASSERT( i == INT_MIN ); 224 CPPUNIT_ASSERT( l == LONG_MIN ); 225 } 226 227 void SstreamTest::init_in() 228 { 229 istringstream is( "12345" ); 230 int n; 231 232 is >> n; 233 CPPUNIT_ASSERT( !is.fail() ); 234 CPPUNIT_ASSERT( n == 12345 ); 235 236 istringstream dis( "1.2345" ); 237 double d; 238 239 dis >> d; 240 CPPUNIT_ASSERT( !dis.fail() ); 241 CPPUNIT_ASSERT( are_equals(d, 1.2345) ); 242 243 istringstream fis( "1.2345" ); 244 float f; 245 246 fis >> f; 247 CPPUNIT_ASSERT( !fis.fail() ); 248 CPPUNIT_ASSERT( are_equals(f, 1.2345f) ); 249 } 250 251 void SstreamTest::init_out() 252 { 253 ostringstream os( "12345" ); 254 CPPUNIT_ASSERT( os.str() == "12345" ); 255 256 os << 67; 257 CPPUNIT_ASSERT( os.good() ); 258 259 // This satisfy to the Standard: 260 // CPPUNIT_ASSERT( os.str() == "67345" ); 261 // But we don't know the reason, why standard state that. 262 263 /* 264 * 27.7.1.1: ... then copies the content of str into the basic_sringbuf 265 * underlying character sequence and initializes the input and output 266 * sequences according to which. If which & ios_base::out is true, initializes 267 * the output sequence with underlying sequence. ... 268 * 269 * I can treat this as 'like output was performed', and then I should bump 270 * put pointer... Looks like more useful then my previous treatment. 271 * 272 * - ptr 273 */ 274 275 CPPUNIT_ASSERT( os.str() == "1234567" ); 276 277 278 os.str( "89ab" ); 279 CPPUNIT_ASSERT( os.str() == "89ab" ); 280 281 os << 10; 282 CPPUNIT_ASSERT( os.good() ); 283 // CPPUNIT_ASSERT( os.str() == "10ab" ); 284 CPPUNIT_ASSERT( os.str() == "89ab10" ); 285 } 286 287 void SstreamTest::buf() 288 { 289 stringstream ss; 290 291 ss << "1234567\n89\n"; 292 char buf[10]; 293 buf[7] = 'x'; 294 ss.get( buf, 10 ); 295 CPPUNIT_ASSERT( !ss.fail() ); 296 CPPUNIT_ASSERT( buf[0] == '1' ); 297 CPPUNIT_ASSERT( buf[1] == '2' ); 298 CPPUNIT_ASSERT( buf[2] == '3' ); 299 CPPUNIT_ASSERT( buf[3] == '4' ); 300 CPPUNIT_ASSERT( buf[4] == '5' ); 301 CPPUNIT_ASSERT( buf[5] == '6' ); 302 CPPUNIT_ASSERT( buf[6] == '7' ); // 27.6.1.3 paragraph 10, paragraph 7 303 CPPUNIT_ASSERT( buf[7] == 0 ); // 27.6.1.3 paragraph 8 304 char c; 305 ss.get(c); 306 CPPUNIT_ASSERT( !ss.fail() ); 307 CPPUNIT_ASSERT( c == '\n' ); // 27.6.1.3 paragraph 10, paragraph 7 308 ss.get(c); 309 CPPUNIT_ASSERT( !ss.fail() ); 310 CPPUNIT_ASSERT( c == '8' ); 311 } 312 313 void SstreamTest::rdbuf() 314 { 315 stringstream ss; 316 317 ss << "1234567\n89\n"; 318 319 ostringstream os; 320 ss.get( *os.rdbuf(), '\n' ); 321 CPPUNIT_ASSERT( !ss.fail() ); 322 char c; 323 ss.get(c); 324 CPPUNIT_ASSERT( !ss.fail() ); 325 CPPUNIT_ASSERT( c == '\n' ); // 27.6.1.3 paragraph 12 326 CPPUNIT_ASSERT( os.str() == "1234567" ); 327 } 328 329 void SstreamTest::streambuf_output() 330 { 331 { 332 istringstream in("01234567890123456789"); 333 CPPUNIT_ASSERT( in ); 334 335 full_streambuf full_buf(10); 336 ostream out(&full_buf); 337 CPPUNIT_ASSERT( out ); 338 339 out << in.rdbuf(); 340 CPPUNIT_ASSERT( out ); 341 CPPUNIT_ASSERT( in ); 342 //out is good we can check what has been extracted: 343 CPPUNIT_ASSERT( full_buf.str() == "0123456789" ); 344 345 out << in.rdbuf(); 346 CPPUNIT_ASSERT( out.fail() ); 347 CPPUNIT_ASSERT( in ); 348 349 ostringstream ostr; 350 ostr << in.rdbuf(); 351 CPPUNIT_ASSERT( ostr ); 352 CPPUNIT_ASSERT( in ); 353 CPPUNIT_ASSERT( ostr.str() == "0123456789" ); 354 } 355 356 # if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS) 357 { 358 //If the output stream buffer throws: 359 istringstream in("01234567890123456789"); 360 CPPUNIT_ASSERT( in ); 361 362 full_streambuf full_buf(10, true); 363 ostream out(&full_buf); 364 CPPUNIT_ASSERT( out ); 365 366 out << in.rdbuf(); 367 CPPUNIT_ASSERT( out.bad() ); 368 CPPUNIT_ASSERT( in ); 369 //out is bad we have no guaranty on what has been extracted: 370 //CPPUNIT_ASSERT( full_buf.str() == "0123456789" ); 371 372 out.clear(); 373 out << in.rdbuf(); 374 CPPUNIT_ASSERT( out.fail() && out.bad() ); 375 CPPUNIT_ASSERT( in ); 376 377 ostringstream ostr; 378 ostr << in.rdbuf(); 379 CPPUNIT_ASSERT( ostr ); 380 CPPUNIT_ASSERT( in ); 381 CPPUNIT_ASSERT( ostr.str() == "01234567890123456789" ); 382 } 383 # endif 384 } 385 386 void SstreamTest::seek() 387 { 388 stringstream s( "0123456789" ); 389 390 CPPUNIT_ASSERT( s.tellg() == stringstream::pos_type(0) ); 391 s.seekg( 6, ios::beg ); 392 CPPUNIT_ASSERT( s.tellg() == stringstream::pos_type(6) ); 393 s.seekg( -3, ios::cur ); 394 CPPUNIT_ASSERT( s.tellg() == stringstream::pos_type(3) ); 395 396 istringstream is( "0123456789" ); 397 CPPUNIT_ASSERT( is.tellg() == stringstream::pos_type(0) ); 398 is.seekg( 6, ios::beg ); 399 CPPUNIT_ASSERT( is.tellg() == stringstream::pos_type(6) ); 400 is.seekg( -3, ios::cur ); 401 CPPUNIT_ASSERT( is.tellg() == stringstream::pos_type(3) ); 402 } 403 404 void SstreamTest::seekp() 405 { 406 ostringstream s; 407 408 s << "1234567"; 409 CPPUNIT_CHECK( s.tellp() == stringstream::pos_type(7) ); 410 CPPUNIT_CHECK( s.str() == "1234567" ); 411 s.seekp( 0 ); 412 s << "X"; 413 CPPUNIT_CHECK( s.str() == "X234567" ); 414 s.seekp( 0, ios::beg ); 415 s << "Y"; 416 CPPUNIT_CHECK( s.str() == "Y234567" ); 417 } 418 419 void SstreamTest::seek_gp() 420 { 421 stringstream ss( "1" ); 422 423 /* ISO/IEC 14882 2003 (and 1998 too) assume change as get as put positions 424 with seekg and seekp (27.6.1.3, par 38; 27.6.2.4 par 2), 425 but this contradict to common practice and proposed draft N2588 426 (27.6.1.3, par 41; 27.6.2.5, par 4) 427 428 Now STLport implement (i.e. change behaviour ) the draft's point of view. 429 */ 430 431 ss.seekg( 0, ios::beg ); 432 ss.seekp( 0, ios::end ); 433 434 ss << "2"; 435 436 string str; 437 438 ss >> str; 439 440 /* CPPUNIT_CHECK( str == "2" ); --- according ISO/IEC 14882 2003 */ 441 CPPUNIT_CHECK( str == "12" ); 442 } 443 444 void SstreamTest::tellp() 445 { 446 { 447 ostringstream o( "1" ); 448 449 o << "23456"; 450 451 CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == stringstream::pos_type(6) ); 452 CPPUNIT_CHECK( o.tellp() == stringstream::pos_type(6) ); 453 } 454 { 455 ostringstream o; 456 457 o << "123456"; 458 459 CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == stringstream::pos_type(6) ); 460 CPPUNIT_CHECK( o.tellp() == stringstream::pos_type(6) ); 461 } 462 { 463 ostringstream o( "1" ); 464 465 o << "23456789"; 466 467 CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == stringstream::pos_type(9) ); 468 CPPUNIT_CHECK( o.tellp() == stringstream::pos_type(9) ); 469 } 470 } 471 472 473 template < class T > 474 string to_string( const T& v ) 475 { 476 ostringstream oss; 477 oss << v; 478 return oss.str(); 479 } 480 481 void SstreamTest::negative() 482 { 483 CPPUNIT_CHECK( to_string<int>(-1) == "-1" ); 484 CPPUNIT_CHECK( to_string<long>(-1) == "-1" ); 485 } 486 487 #endif 488