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