1// 1999-10-11 bkoz 2 3// Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 4// 5// This file is part of the GNU ISO C++ Library. This library is free 6// software; you can redistribute it and/or modify it under the 7// terms of the GNU General Public License as published by the 8// Free Software Foundation; either version 2, or (at your option) 9// any later version. 10 11// This library is distributed in the hope that it will be useful, 12// but WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14// GNU General Public License for more details. 15 16// You should have received a copy of the GNU General Public License along 17// with this library; see the file COPYING. If not, write to the Free 18// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 19// USA. 20 21// As a special exception, you may use this file as part of a free software 22// library without restriction. Specifically, if other files instantiate 23// templates or use macros or inline functions from this file, or you compile 24// this file and link it with other files to produce an executable, this 25// file does not by itself cause the resulting executable to be covered by 26// the GNU General Public License. This exception does not however 27// invalidate any other reasons why the executable file might be covered by 28// the GNU General Public License. 29 30// 27.5.2 template class basic_streambuf 31 32#include <cstring> // for memset, memcmp 33#include <streambuf> 34#include <sstream> 35#include <ostream> 36#include <testsuite_hooks.h> 37 38class testbuf : public std::streambuf 39{ 40public: 41 42 // Typedefs: 43 typedef std::streambuf::traits_type traits_type; 44 typedef std::streambuf::char_type char_type; 45 46 testbuf(): std::streambuf() 47 { _M_mode = (std::ios_base::in | std::ios_base::out); } 48 49 bool 50 check_pointers() 51 { 52 bool test = true; 53 VERIFY( this->eback() == NULL ); 54 VERIFY( this->gptr() == NULL ); 55 VERIFY( this->egptr() == NULL ); 56 VERIFY( this->pbase() == NULL ); 57 VERIFY( this->pptr() == NULL ); 58 VERIFY( this->epptr() == NULL ); 59 return test; 60 } 61 62 int_type 63 pub_uflow() 64 { return (this->uflow()); } 65 66 int_type 67 pub_overflow(int_type __c = traits_type::eof()) 68 { return (this->overflow(__c)); } 69 70 int_type 71 pub_pbackfail(int_type __c) 72 { return (this->pbackfail(__c)); } 73 74 void 75 pub_setg(char* beg, char* cur, char *end) 76 { this->setg(beg, cur, end); } 77 78 void 79 pub_setp(char* beg, char* end) 80 { this->setp(beg, end); } 81 82protected: 83 int_type 84 underflow() 85 { 86 int_type __retval = traits_type::eof(); 87 if (this->gptr() < this->egptr()) 88 __retval = traits_type::not_eof(0); 89 return __retval; 90 } 91}; 92 93void test01() 94{ 95 typedef testbuf::traits_type traits_type; 96 typedef testbuf::int_type int_type; 97 98 bool test = true; 99 char* lit01 = "chicago underground trio/possible cube on delmark"; 100 testbuf buf01; 101 102 // 27.5.2.1 basic_streambuf ctors 103 // default ctor initializes 104 // - all pointer members to null pointers 105 // - locale to current global locale 106 VERIFY( buf01.check_pointers() ); 107 VERIFY( buf01.getloc() == std::locale() ); 108 109 // 27.5.2.3.1 get area 110 // 27.5.2.2.3 get area 111 // 27.5.2.4.3 get area 112 int i01 = 3; 113 buf01.pub_setg(lit01, lit01, (lit01 + i01)); 114 VERIFY( i01 == buf01.in_avail() ); 115 116 VERIFY( buf01.pub_uflow() == lit01[0] ); 117 VERIFY( buf01.sgetc() == traits_type::to_int_type(lit01[1]) ); 118 VERIFY( buf01.pub_uflow() == lit01[1] ); 119 VERIFY( buf01.sgetc() == traits_type::to_int_type(lit01[2]) ); 120 VERIFY( buf01.pub_uflow() == lit01[2] ); 121 VERIFY( buf01.sgetc() == traits_type::eof() ); 122 123 // pbackfail 124 buf01.pub_setg(lit01, lit01, (lit01 + i01)); 125 VERIFY( i01 == buf01.in_avail() ); 126 int_type intt01 = traits_type::to_int_type('b'); 127 VERIFY( traits_type::eof() == buf01.pub_pbackfail(intt01) ); 128 129 // overflow 130 VERIFY( traits_type::eof() == buf01.pub_overflow(intt01) ); 131 VERIFY( traits_type::eof() == buf01.pub_overflow() ); 132 VERIFY( buf01.sgetc() == traits_type::to_int_type(lit01[0]) ); 133 134 // sputn/xsputn 135 char* lit02 = "isotope 217: the unstable molecule on thrill jockey"; 136 int i02 = std::strlen(lit02); 137 char carray[i02 + 1]; 138 std::memset(carray, 0, i02 + 1); 139 140 buf01.pub_setp(carray, (carray + i02)); 141 buf01.sputn(lit02, 0); 142 VERIFY( carray[0] == 0 ); 143 VERIFY( lit02[0] == 'i' ); 144 buf01.sputn(lit02, 1); 145 VERIFY( lit02[0] == carray[0] ); 146 VERIFY( lit02[1] == 's' ); 147 VERIFY( carray[1] == 0 ); 148 buf01.sputn(lit02 + 1, 10); 149 VERIFY( std::memcmp(lit02, carray, 10) == 0 ); 150 buf01.sputn(lit02 + 11, 20); 151 VERIFY( std::memcmp(lit02, carray, 30) == 0 ); 152 153#ifdef DEBUG_ASSERT 154 assert(test); 155#endif 156} 157 158void test02() 159{ 160 typedef testbuf::traits_type traits_type; 161 typedef testbuf::int_type int_type; 162 163 bool test = true; 164 char* lit01 = "chicago underground trio/possible cube on delmark"; 165 testbuf buf01; 166 167 // 27.5.2.1 basic_streambuf ctors 168 // default ctor initializes 169 // - all pointer members to null pointers 170 // - locale to current global locale 171 VERIFY( buf01.check_pointers() ); 172 VERIFY( buf01.getloc() == std::locale() ); 173 174 // 27.5.2.2.5 Put area 175 size_t i01 = traits_type::length(lit01); 176 char carray01[i01]; 177 std::memset(carray01, 0, i01); 178 179 buf01.pub_setg(lit01, lit01, lit01 + i01); 180 buf01.sgetn(carray01, 0); 181 VERIFY( carray01[0] == 0 ); 182 buf01.sgetn(carray01, 1); 183 VERIFY( carray01[0] == 'c' ); 184 buf01.sgetn(carray01 + 1, i01 - 1); 185 VERIFY( carray01[0] == 'c' ); 186 VERIFY( carray01[1] == 'h' ); 187 VERIFY( carray01[i01 - 1] == 'k' ); 188 189#ifdef DEBUG_ASSERT 190 assert(test); 191#endif 192} 193 194// test03 195// http://gcc.gnu.org/ml/libstdc++/2000-q1/msg00151.html 196template<typename charT, typename traits = std::char_traits<charT> > 197 class basic_nullbuf : public std::basic_streambuf<charT, traits> 198 { 199 protected: 200 typedef typename 201 std::basic_streambuf<charT, traits>::int_type int_type; 202 virtual int_type 203 overflow(int_type c) 204 { return traits::not_eof(c); } 205 }; 206 207typedef basic_nullbuf<char> nullbuf; 208typedef basic_nullbuf<wchar_t> wnullbuf; 209 210template<typename T> 211 char 212 print(const T& x) 213 { 214 nullbuf ob; 215 std::ostream out(&ob); 216 out << x << std::endl; 217 return (!out ? '0' : '1'); 218 } 219 220void test03() 221{ 222 bool test = true; 223 const std::string control01("11111"); 224 std::string test01; 225 226 test01 += print(true); 227 test01 += print(3.14159); 228 test01 += print(10); 229 test01 += print('x'); 230 test01 += print("pipo"); 231 232 VERIFY( test01 == control01 ); 233#ifdef DEBUG_ASSERT 234 assert(test); 235#endif 236} 237 238class setpbuf : public std::streambuf 239{ 240 char buffer[4]; 241 std::string result; 242 243public: 244 245 std::string& 246 get_result() 247 { return result; } 248 249 setpbuf() 250 { 251 char foo [32]; 252 setp(foo, foo + 32); 253 setp(buffer, buffer + 4); 254 } 255 256 ~setpbuf() 257 { sync(); } 258 259 virtual int_type 260 overflow(int_type n) 261 { 262 if (sync() != 0) 263 return traits_type::eof(); 264 265 result += traits_type::to_char_type(n); 266 267 return n; 268 } 269 270 virtual int 271 sync() 272 { 273 result.append(pbase(), pptr()); 274 setp(buffer, buffer + 4); 275 return 0; 276 } 277}; 278 279// libstdc++/1057 280void test04() 281{ 282 bool test = true; 283 std::string text = "abcdefghijklmn"; 284 285 // 01 286 setpbuf sp1; 287 // Here xsputn writes over sp1.result 288 sp1.sputn(text.c_str(), text.length()); 289 290 // This crashes when result is accessed 291 sp1.pubsync(); 292 VERIFY( sp1.get_result() == text ); 293 294 295 // 02 296 setpbuf sp2; 297 for (std::string::size_type i = 0; i < text.length(); ++i) 298 { 299 // sputc also writes over result 300 sp2.sputc(text[i]); 301 } 302 303 // Crash here 304 sp2.pubsync(); 305 VERIFY( sp2.get_result() == text ); 306} 307 308class nullsetpbuf : public std::streambuf 309{ 310 char foo[64]; 311public: 312 nullsetpbuf() 313 { 314 setp(foo, foo + 64); 315 setp(NULL, NULL); 316 } 317}; 318 319// libstdc++/1057 320void test05() 321{ 322 std::string text1 = "abcdefghijklmn"; 323 324 nullsetpbuf nsp; 325 // Immediate crash as xsputn writes to null pointer 326 nsp.sputn(text1.c_str(), text1.length()); 327 // ditto 328 nsp.sputc('a'); 329} 330 331// test06 332namespace gnu 333{ 334 class something_derived; 335} 336 337class gnu::something_derived : std::streambuf { }; 338 339// libstdc++/3599 340class testbuf2 : public std::streambuf 341{ 342public: 343 typedef std::streambuf::traits_type traits_type; 344 345 testbuf2() : std::streambuf() { } 346 347protected: 348 int_type 349 overflow(int_type c = traits_type::eof()) 350 { return traits_type::not_eof(0); } 351}; 352 353void 354test07() 355{ 356 bool test = true; 357 testbuf2 ob; 358 std::ostream out(&ob); 359 360 out << "gasp"; 361 VERIFY(out.good()); 362 363 out << std::endl; 364 VERIFY(out.good()); 365} 366 367// libstdc++/9322 368void test08() 369{ 370 using std::locale; 371 bool test = true; 372 373 locale loc; 374 testbuf2 ob; 375 VERIFY( ob.getloc() == loc ); 376 377 locale::global(locale("en_US")); 378 VERIFY( ob.getloc() == loc ); 379 380 locale loc_de ("de_DE"); 381 locale ret = ob.pubimbue(loc_de); 382 VERIFY( ob.getloc() == loc_de ); 383 VERIFY( ret == loc ); 384 385 locale::global(loc); 386 VERIFY( ob.getloc() == loc_de ); 387} 388 389// libstdc++/9318 390class Outbuf : public std::streambuf 391{ 392public: 393 typedef std::streambuf::traits_type traits_type; 394 395 std::string result() const { return str; } 396 397protected: 398 virtual int_type overflow(int_type c = traits_type::eof()) 399 { 400 if (!traits_type::eq_int_type(c, traits_type::eof())) 401 str.push_back(traits_type::to_char_type(c)); 402 return traits_type::not_eof(c); 403 } 404 405private: 406 std::string str; 407}; 408 409// <1> 410void test09() 411{ 412 bool test = true; 413 414 std::istringstream stream("Bad Moon Rising"); 415 Outbuf buf; 416 stream >> &buf; 417 418 VERIFY( buf.result() == "Bad Moon Rising" ); 419} 420 421// <2> 422void test10() 423{ 424 bool test = true; 425 426 std::stringbuf sbuf("Bad Moon Rising", std::ios::in); 427 Outbuf buf; 428 std::ostream stream(&buf); 429 stream << &sbuf; 430 431 VERIFY( buf.result() == "Bad Moon Rising" ); 432} 433 434// libstdc++/9424 435class Outbuf_2 : public std::streambuf 436{ 437 char buf[1]; 438 439public: 440 Outbuf_2() 441 { 442 setp(buf, buf + 1); 443 } 444 445 int_type overflow(int_type c) 446 { 447 int_type eof = traits_type::eof(); 448 449 if (pptr() < epptr()) 450 { 451 if (traits_type::eq_int_type(c, eof)) 452 return traits_type::not_eof(c); 453 454 *pptr() = traits_type::to_char_type(c); 455 pbump(1); 456 return c; 457 } 458 459 return eof; 460 } 461}; 462 463class Inbuf_2 : public std::streambuf 464{ 465 static const char buf[]; 466 const char* current; 467 int size; 468 469public: 470 Inbuf_2() 471 { 472 current = buf; 473 size = std::strlen(buf); 474 } 475 476 int_type underflow() 477 { 478 if (current < buf + size) 479 return traits_type::to_int_type(*current); 480 return traits_type::eof(); 481 } 482 483 int_type uflow() 484 { 485 if (current < buf + size) 486 return traits_type::to_int_type(*current++); 487 return traits_type::eof(); 488 } 489}; 490 491const char Inbuf_2::buf[] = "Atteivlis"; 492 493// <1> 494void test11() 495{ 496 bool test = true; 497 498 Inbuf_2 inbuf1; 499 std::istream is(&inbuf1); 500 Outbuf_2 outbuf1; 501 is >> &outbuf1; 502 VERIFY( inbuf1.sgetc() == 't' ); 503 VERIFY( is.good() ); 504} 505 506// <2> 507void test12() 508{ 509 bool test = true; 510 511 Outbuf_2 outbuf2; 512 std::ostream os (&outbuf2); 513 Inbuf_2 inbuf2; 514 os << &inbuf2; 515 VERIFY( inbuf2.sgetc() == 't' ); 516 VERIFY( os.good() ); 517} 518 519int main() 520{ 521 test01(); 522 test02(); 523 test03(); 524 525 test04(); 526 test05(); 527 528 test07(); 529 test08(); 530 531 test09(); 532 test10(); 533 test11(); 534 test12(); 535 return 0; 536} 537