d7ae5693d33488d4ff676601beae4b88fbe0381e
[gcc.git] / libstdc++-v3 / testsuite / 27_io / streambuf_members.cc
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
38 class testbuf : public std::streambuf
39 {
40 public:
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
82 protected:
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
93 void 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
158 void 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
196 template<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
207 typedef basic_nullbuf<char> nullbuf;
208 typedef basic_nullbuf<wchar_t> wnullbuf;
209
210 template<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
220 void 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
238 class setpbuf : public std::streambuf
239 {
240 char buffer[4];
241 std::string result;
242
243 public:
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
280 void 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
308 class nullsetpbuf : public std::streambuf
309 {
310 char foo[64];
311 public:
312 nullsetpbuf()
313 {
314 setp(foo, foo + 64);
315 setp(NULL, NULL);
316 }
317 };
318
319 // libstdc++/1057
320 void 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
332 namespace gnu
333 {
334 class something_derived;
335 }
336
337 class gnu::something_derived : std::streambuf { };
338
339 // libstdc++/3599
340 class testbuf2 : public std::streambuf
341 {
342 public:
343 typedef std::streambuf::traits_type traits_type;
344
345 testbuf2() : std::streambuf() { }
346
347 protected:
348 int_type
349 overflow(int_type c = traits_type::eof())
350 { return traits_type::not_eof(0); }
351 };
352
353 void
354 test07()
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
368 void 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
390 class Outbuf : public std::streambuf
391 {
392 public:
393 typedef std::streambuf::traits_type traits_type;
394
395 std::string result() const { return str; }
396
397 protected:
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
405 private:
406 std::string str;
407 };
408
409 // <1>
410 void 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>
422 void 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
435 class Outbuf_2 : public std::streambuf
436 {
437 char buf[1];
438
439 public:
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
463 class Inbuf_2 : public std::streambuf
464 {
465 static const char buf[];
466 const char* current;
467 int size;
468
469 public:
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
491 const char Inbuf_2::buf[] = "Atteivlis";
492
493 // <1>
494 void 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>
507 void 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
519 int 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 }