68456432b73387674e2262c97052abfb820797d3
[gcc.git] / libstdc++-v3 / testsuite / 27_io / streambuf.cc
1 // 1999-10-11 bkoz
2
3 // Copyright (C) 1999, 2000, 2001 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 <string>
35 #include <ostream>
36 #include <debug_assert.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 virtual int_type
201 overflow(int_type c)
202 { return traits::not_eof(c); }
203 };
204
205 typedef basic_nullbuf<char> nullbuf;
206 typedef basic_nullbuf<wchar_t> wnullbuf;
207
208 template<typename T>
209 char
210 print(const T& x)
211 {
212 nullbuf ob;
213 std::ostream out(&ob);
214 out << x << std::endl;
215 return (!out ? '0' : '1');
216 }
217
218 void test03()
219 {
220 bool test = true;
221 const std::string control01("11111");
222 std::string test01;
223
224 test01 += print(true);
225 test01 += print(3.14159);
226 test01 += print(10);
227 test01 += print('x');
228 test01 += print("pipo");
229
230 VERIFY( test01 == control01 );
231 #ifdef DEBUG_ASSERT
232 assert(test);
233 #endif
234 }
235
236 class setpbuf : public std::streambuf
237 {
238 char buffer[4];
239 std::string result;
240
241 public:
242
243 std::string&
244 get_result()
245 { return result; }
246
247 setpbuf()
248 {
249 char foo [32];
250 setp(foo, foo + 32);
251 setp(buffer, buffer + 4);
252 }
253
254 ~setpbuf()
255 { sync(); }
256
257 virtual int_type
258 overflow(int_type n)
259 {
260 if (sync() != 0)
261 return traits_type::eof();
262
263 result += traits_type::to_char_type(n);
264
265 return n;
266 }
267
268 virtual int
269 sync()
270 {
271 result.append(pbase(), pptr());
272 setp(buffer, buffer + 4);
273 return 0;
274 }
275 };
276
277 // libstdc++/1057
278 void test04()
279 {
280 bool test = true;
281 std::string text = "abcdefghijklmn";
282
283 // 01
284 setpbuf sp1;
285 // Here xsputn writes over sp1.result
286 sp1.sputn(text.c_str(), text.length());
287
288 // This crashes when result is accessed
289 sp1.pubsync();
290 VERIFY( sp1.get_result() == text );
291
292
293 // 02
294 setpbuf sp2;
295 for (std::string::size_type i = 0; i < text.length(); ++i)
296 {
297 // sputc also writes over result
298 sp2.sputc(text[i]);
299 }
300
301 // Crash here
302 sp2.pubsync();
303 VERIFY( sp2.get_result() == text );
304 }
305
306 class nullsetpbuf : public std::streambuf
307 {
308 char foo[64];
309 public:
310 nullsetpbuf()
311 {
312 setp(foo, foo + 64);
313 setp(NULL, NULL);
314 }
315 };
316
317 // libstdc++/1057
318 void test05()
319 {
320 std::string text1 = "abcdefghijklmn";
321
322 nullsetpbuf nsp;
323 // Immediate crash as xsputn writes to null pointer
324 nsp.sputn(text1.c_str(), text1.length());
325 // ditto
326 nsp.sputc('a');
327 }
328
329 // test06
330 // XXX this should work, doesn't due to compiler limitations.
331 #if 0
332 namespace gnu
333 {
334 class something_derived;
335 }
336
337 class gnu::something_derived : std::streambuf { };
338 #endif
339
340 // libstdc++/3599
341 class testbuf2 : public std::streambuf
342 {
343 public:
344 typedef std::streambuf::traits_type traits_type;
345
346 testbuf2() : std::streambuf() { }
347
348 protected:
349 int_type
350 overflow(int_type c = traits_type::eof())
351 { return traits_type::not_eof(0); }
352 };
353
354 void
355 test07()
356 {
357 testbuf2 ob;
358 std::ostream out(&ob);
359
360 VERIFY(out << "gasp");
361 VERIFY(out << std::endl);
362 }
363
364 int main()
365 {
366 test01();
367 test02();
368 test03();
369
370 test04();
371 test05();
372
373 test07();
374 return 0;
375 }