1 // 2001-05-21 Benjamin Kosnik  <bkoz@redhat.com>
2 
3 // Copyright (C) 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 // 27.8.1.4 Overridden virtual functions
22 
23 #include <fstream>
24 #include <unistd.h>
25 #include <signal.h>
26 #include <fcntl.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <locale>
30 #include <testsuite_hooks.h>
31 
32 // @require@ %-*.tst %-*.txt
33 // @diff@ %-*.tst %*.txt
34 
test01()35 void test01()
36 {
37   using namespace std;
38 
39   bool test = true;
40   char buf[512];
41   const char* strlit = "how to tell a story and other essays: mark twain";
42   const size_t strlitsize = std::strlen(strlit);
43   filebuf fbuf01;
44 
45   fbuf01.pubsetbuf(buf, 512);
46   fbuf01.sputn(strlit, strlitsize);
47   VERIFY( std::strncmp(strlit, buf, strlitsize) != 0 );
48 }
49 
test02()50 void test02()
51 {
52   using namespace std;
53 
54   bool test = true;
55   char buf[512];
56   const char* strlit = "how to tell a story and other essays: mark twain";
57   const size_t strlitsize = std::strlen(strlit);
58   filebuf fbuf01;
59   fbuf01.open("tmp", ios_base::out);
60 
61   fbuf01.pubsetbuf(buf, strlitsize);
62   fbuf01.sputn(strlit, strlitsize);
63   VERIFY( std::strncmp(strlit, buf, strlitsize) == 0 );
64 }
65 
66 
67 // NB: This test assumes that _M_buf_size == 40, and not the usual
68 // buffer_size length of BUFSIZ (8192), so that overflow/underflow can be
69 // simulated a bit more readily.
70 // NRB (Nota Really Bene): setting it to 40 breaks the test, as intended.
71 const int buffer_size = 8192;
72 //const int buffer_size = 40;
73 
74 const char carray_01[] = "santa cruz or sandiego?";
75 const char carray_02[] = "memphis, new orleans, and savanah";
76 const char name_01[] = "filebuf_virtuals-1.txt"; // file with data in it
77 const char name_02[] = "filebuf_virtuals-2.txt"; // empty file, need to create
78 const char name_03[] = "filebuf_virtuals-3.txt"; // empty file, need to create
79 const char name_04[] = "filebuf_virtuals-4.txt"; // empty file, need to create
80 const char name_05[] = "filebuf_virtuals-5.txt"; // empty file, need to create
81 const char name_06[] = "filebuf_virtuals-6.txt"; // empty file, need to create
82 const char name_07[] = "filebuf_virtuals-7.txt"; // empty file, need to create
83 
84 class derived_filebuf: public std::filebuf
85 {
86  public:
87   void
set_size(int_type __size)88   set_size(int_type __size) { _M_buf_size_opt = __size; }
89 };
90 
91 derived_filebuf fb_01; // in
92 derived_filebuf fb_02; // out
93 derived_filebuf fb_03; // in | out
94 
95 
96 // Initialize filebufs to be the same size regardless of platform.
test03()97 void test03()
98 {
99   fb_01.set_size(buffer_size);
100   fb_02.set_size(buffer_size);
101   fb_03.set_size(buffer_size);
102 }
103 
104 
105 // Test the filebuf/stringbuf locale settings.
test04()106 void test04()
107 {
108   std::locale loc_tmp;
109   loc_tmp = fb_01.getloc();
110   fb_01.pubimbue(loc_tmp); //This should initialize _M_init to true
111   fb_01.getloc(); //This should just return _M_locale
112 }
113 
114 // Test overloaded virtual functions.
test05()115 void test05()
116 {
117   typedef std::filebuf::int_type 	int_type;
118   typedef std::filebuf::traits_type 	traits_type;
119   typedef std::filebuf::pos_type 	pos_type;
120   typedef std::filebuf::off_type 	off_type;
121   typedef size_t 			size_type;
122 
123   bool 					test = true;
124   std::filebuf 				f_tmp;
125   std::streamsize 			strmsz_1, strmsz_2;
126   std::streamoff  			strmof_1, strmof_2;
127   int 					i = 0, j = 0, k = 0;
128 
129   // GET
130   // int showmanyc()
131   // returns an estimate of the numbers of chars in the seq, or -1.
132   // if __retval > 0, then calls to underflow won't return
133   // traits_type::eof() till at least __retval chars.
134   // if __retval == -1, then calls to underflow or uflow will fail.
135   // NB overriding def if it can determine more chars can be read from
136   // the input sequence.
137 
138   // int in_avail()
139   // if a read position is available, return _M_in_end - _M_in_cur.
140   // else return showmanyc.
141   strmof_1 = fb_01.in_avail();
142   strmof_2 = fb_02.in_avail();
143   VERIFY( strmof_1 == -1 );
144   VERIFY( strmof_1 == strmof_2 ); //fail because not open
145   strmof_1 = fb_03.in_avail();
146   VERIFY( strmof_1 == strmof_2 );
147   fb_01.open(name_01, std::ios_base::in);
148   fb_02.open(name_02, std::ios_base::out | std::ios_base::trunc);
149   fb_03.open(name_03, std::ios_base::out | std::ios_base::in | std::ios_base::trunc);
150   strmof_1 = fb_01.in_avail();
151   strmof_2 = fb_02.in_avail();
152   VERIFY( strmof_1 != strmof_2 );
153   VERIFY( strmof_1 >= 0 );
154   VERIFY( strmof_2 == -1 );  // empty file
155   strmof_1 = fb_03.in_avail();
156   VERIFY( strmof_1  == 0 ); // empty file
157 
158   // int_type sbumpc()
159   // if read_cur not avail returns uflow(), else return *read_cur & increment
160   int_type c1 = fb_01.sbumpc();
161   int_type c2 = fb_02.sbumpc();
162   VERIFY( c1 != c2 );
163   VERIFY( c1 == '/' );
164   VERIFY( c2 == -1 );
165   int_type c3 = fb_01.sbumpc();
166   int_type c4 = fb_02.sbumpc();
167   VERIFY( c3 != c4 );
168   VERIFY( c1 == c3 ); // fluke, both happen to be '/'
169   VERIFY( c2 == c4 );
170   int_type c5 = fb_03.sbumpc();
171   VERIFY( c5 == traits_type::eof() );
172   // XXX should do some kind of test to make sure that internal
173   // buffers point ot the same thing, to check consistancy.
174 
175   // int_type sgetc()
176   // if read_cur not avail, return uflow(), else return *read_cur
177   int_type c6 = fb_01.sgetc();
178   int_type c7 = fb_02.sgetc();
179   VERIFY( c6 != c3 );
180   VERIFY( c7 == c4 ); // both -1
181   int_type c8 = fb_01.sgetc();
182   int_type c9 = fb_02.sgetc();
183   VERIFY( c6 == c8 );
184   VERIFY( c7 == c9 );
185   c5 = fb_03.sgetc();
186   VERIFY( c5 == traits_type::eof() );
187 
188   // int_type snextc()
189   // calls sbumpc and if sbumpc != eof, return sgetc
190   c6 = fb_01.snextc();
191   c7 = fb_02.snextc();
192   VERIFY( c6 != c8 );
193   VERIFY( c7 == c9 ); // -1
194   VERIFY( c6 == '9' );
195   c6 = fb_01.snextc();
196   c7 = fb_02.snextc();
197   VERIFY( c6 != c8 );
198   VERIFY( c7 == c9 ); // -1
199   VERIFY( c6 == '9' );
200   c5 = fb_03.snextc();
201   VERIFY( c5 == traits_type::eof() );
202 
203   // streamsize sgetn(char_type *s, streamsize n)
204   // streamsize xsgetn(char_type *s, streamsize n)
205   // assign up to n chars to s from input sequence, indexing in_cur as
206   // approp and returning the number of chars assigned
207   strmsz_1 = fb_01.in_avail();
208   strmsz_2 = fb_02.in_avail();
209   test = strmsz_1 != strmsz_2;
210   char carray1[13] = "";
211   strmsz_1 = fb_01.sgetn(carray1, 10);
212   char carray2[buffer_size] = "";
213   strmsz_2 = fb_02.sgetn(carray2, 10);
214   VERIFY( strmsz_1 != strmsz_2 );
215   VERIFY( strmsz_1 == 10 );
216   VERIFY( strmsz_2 == 0 );
217   c1 = fb_01.sgetc();
218   c2 = fb_02.sgetc();
219   VERIFY( c1 == '\n' );
220   VERIFY( c7 == c2 ); // n != i
221   strmsz_1 = fb_03.sgetn(carray1, 10);
222   VERIFY( !strmsz_1 ); //zero
223   strmsz_1 = fb_01.in_avail();
224   strmsz_2 = fb_01.sgetn(carray2, strmsz_1 + 5);
225   VERIFY( strmsz_1 == strmsz_2 - 5 );
226   c4 = fb_01.sgetc(); // buffer should have underflowed from above.
227   VERIFY( c4 == 'i' );
228   strmsz_1 = fb_01.in_avail();
229   VERIFY( strmsz_1 > 0 );
230   strmsz_2 = fb_01.sgetn(carray2, strmsz_1 + 5);
231   VERIFY( strmsz_1 == strmsz_2 ); //at the end of the actual file
232   strmsz_1 = fb_02.in_avail();
233   strmsz_2 = fb_02.sgetn(carray2, strmsz_1 + 5);
234   VERIFY( strmsz_1 == -1 );
235   VERIFY( strmsz_2 == 0 );
236   c4 = fb_02.sgetc(); // should be EOF
237   VERIFY( c4 == traits_type::eof() );
238 
239   // PUT
240   // int_type sputc(char_type c)
241   // if out_cur not avail, return overflow(traits_type::to_int_type(c))
242   // else, stores c at out_cur,
243   // increments out_cur, and returns c as int_type
244   // strmsz_1 = fb_03.in_avail();  // XXX valid for in|out??
245   c1 = fb_02.sputc('a');
246   c2 = fb_03.sputc('b');
247   VERIFY( c1 != c2 );
248   c1 = fb_02.sputc('c');
249   c2 = fb_03.sputc('d');
250   VERIFY( c1 != c2 );
251   // strmsz_2 = fb_03.in_avail();
252   // VERIFY( strmsz_1 != strmsz_2 );
253   for (int i = 50; i <= 90; ++i)
254     c2 = fb_02.sputc(char(i));
255   // 27filebuf-2.txt == ac23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX
256   // fb_02._M_out_cur = '2'
257   strmsz_1 = fb_03.in_avail();
258   for (int i = 50; i <= 90; ++i)
259     c2 = fb_03.sputc(char(i));
260   strmsz_2 = fb_03.in_avail();
261   // VERIFY( strmsz_1 != strmsz_2 );
262   // VERIFY( strmsz_1 > 0 );
263   // VERIFY( strmsz_2 > 0 );
264   // 27filebuf-2.txt == bd23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX
265   // fb_02._M_out_cur = '2'
266   c3 = fb_01.sputc('a'); // should be EOF because this is read-only
267   VERIFY( c3 == traits_type::eof() );
268 
269   // streamsize sputn(const char_typs* s, streamsize n)
270   // write up to n chars to out_cur from s, returning number assigned
271   // NB *sputn will happily put '\0' into your stream if you give it a chance*
272   strmsz_1 = fb_03.sputn("racadabras", 10);//"abracadabras or what?"
273   VERIFY( strmsz_1 == 10 );
274   strmsz_2 = fb_03.sputn(", i wanna reach out and", 10);
275   VERIFY( strmsz_2 == 10 );
276   VERIFY( strmsz_1 == strmsz_2 );
277   // fb_03._M_out_beg = "YZracadabras, i wanna FGHIJKLMNOPQRSTUVW"
278   // fb_03._M_out_cur = "FGHIJKLMNOPQRSTUVW"
279   strmsz_1 = fb_02.sputn("racadabras", 10);
280   VERIFY( strmsz_1 == 10 );
281   // fb_02._M_out_beg = "YZracadabras<=>?@ABCDEFGHIJKLMNOPQRSTUVW"
282   // fb_02._M_out_cur = "<=>?@ABCDEFGHIJKLMNOPQRSTUVW"
283   strmsz_1 = fb_01.sputn("racadabra", 10);
284   VERIFY( strmsz_1 == 0 );
285 
286   // PUTBACK
287   // int_type pbfail(int_type c)
288   // called when gptr() null, gptr() == eback(), or traits::eq(*gptr, c) false
289   // "pending sequence" is:
290   //	1) everything as defined in underflow
291   // 	2) + if (traits::eq_int_type(c, traits::eof()), then input
292   // 	sequence is backed up one char before the pending sequence is
293   // 	determined.
294   //	3) + if (not 2) then c is prepended. Left unspecified is
295   //	whether the input sequence is backedup or modified in any way
296   // returns traits::eof() for failure, unspecified other value for success
297 
298   // int_type sputbackc(char_type c)
299   // if in_cur not avail || ! traits::eq(c, gptr() [-1]), return pbfail
300   // otherwise decrements in_cur and returns *gptr()
301   c1 = fb_03.sgetc(); // -1
302   c2 = fb_03.sputbackc('z');
303   strmsz_2 = fb_03.in_avail();
304   c3 = fb_03.sgetc();
305   VERIFY( c3 == c2 );
306   VERIFY( c1 != c3 );
307   VERIFY( 1 == strmsz_2 );
308   //test for _in_cur == _in_beg
309   // fb_03._M_out_beg = "bd23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZracada" etc
310   fb_03.pubseekoff(10, std::ios_base::beg,
311 		   std::ios_base::in | std::ios_base::out);
312   fb_03.sputc('m');
313   strmsz_1 = fb_03.in_avail();
314   c1 = fb_03.sgetc();
315   fb_03.snextc();
316   c2 = fb_03.sputbackc('z');
317   strmsz_2 = fb_03.in_avail();
318   c3 = fb_03.sgetc();
319   VERIFY( c1 != c2 );
320   VERIFY( c3 == c2 );
321   VERIFY( c1 != c3 );
322   VERIFY( c2 == 'z' );
323   //  VERIFY( strmsz_1 == strmsz_2 );
324   // test for replacing char with identical one
325   fb_03.snextc();
326   fb_03.sputc('u');
327   fb_03.sputc('v');
328   fb_03.sputc('a');
329   strmsz_1 = fb_03.in_avail();
330   c2 = fb_03.sputbackc('a');
331   strmsz_2 = fb_03.in_avail();
332   c3 = fb_03.sgetc();
333   VERIFY( c3 == c2 );
334   VERIFY( strmsz_1 + 1 == strmsz_2 );
335   //test for ios_base::out
336   c1 = fb_02.sgetc(); // undefined
337   c2 = fb_02.sputbackc('a');
338   VERIFY( c1 == c2 );
339   VERIFY( c1 == -1 );
340 
341   // int_type sungetc()
342   // if in_cur not avail, return pbackfail(), else decrement and
343   // return to_int_type(*gptr())
344   // fb_03._M_out_beg = "uvaacadabras, i wannaZ[\\]^_`abcdefghijkl"
345   // fb_03._M_out_cur = "aacadabras, i wannaZ[\\]^_`abcdefghijkl"
346   strmsz_1 = fb_03.in_avail();
347   c2 = fb_03.sungetc(); // delete the 'a'
348   strmsz_2 = fb_03.in_avail();
349   VERIFY( c2 == 'v' ); //  VERIFY( c2 != traits_type::eof() );
350   VERIFY( strmsz_1 + 1 == strmsz_2 );
351   //test for _in_cur == _in_beg
352   for (int i = 50; i < 32 + 29; ++i)
353     fb_02.sputc(char(i));
354   fb_02.pubseekoff(0, std::ios_base::beg, std::ios_base::out);
355   c1 = fb_02.sgetc();
356   strmsz_1 = fb_02.in_avail();
357   c2 = fb_02.sungetc();
358   c3 = fb_02.sgetc();
359   strmsz_2 = fb_02.in_avail();
360   VERIFY( c1 == c2 );
361   VERIFY( c2 == c3 );
362   VERIFY( c1 == traits_type::eof() );
363   VERIFY( strmsz_1 == strmsz_2 );
364   //test for _in_cur == _in_end
365   fb_03.pubseekoff(0, std::ios_base::end);
366   strmsz_1 = fb_03.in_avail(); // -1 cuz at the end
367   c1 = fb_03.sgetc();
368   c2 = fb_03.sungetc();
369   strmsz_2 = fb_03.in_avail(); // 1
370   c3 = fb_03.sgetc();
371   VERIFY( c1 != c2 );
372   // VERIFY( c2 == c3 || c2 == traits_type::not_eof(int(c3)) );
373   VERIFY( strmsz_2 != strmsz_1 );
374   VERIFY( strmsz_2 == 1 );
375   //test for ios_base::out
376 
377   // BUFFER MANAGEMENT & POSITIONING
378   // int sync()
379   // if a put area exists, overflow.
380   // if a get area exists, do something undefined. (like, nothing)
381   strmsz_1 = fb_01.in_avail();
382   fb_01.pubsync();
383   strmsz_2 = fb_01.in_avail();
384   VERIFY( strmsz_2 == strmsz_1 );
385   strmsz_1 = fb_02.in_avail();
386   fb_02.pubsync();
387   // 27filebuf-2.txt == 53 bytes after this.
388   strmsz_2 = fb_02.in_avail();
389   VERIFY( strmsz_2 == -1 );
390   VERIFY( strmsz_2 == strmsz_1 );
391   strmsz_1 = fb_03.in_avail();
392   fb_03.pubsync();
393   // 27filebuf-3.txt
394   // bd23456789mzuva?@ABCDEFGHIJKLMNOPQRSTUVWXYZracadabras, i wannaz
395   // 63 bytes.
396   strmsz_2 = fb_03.in_avail();
397   VERIFY( strmsz_1 == 1 );
398   // VERIFY( strmsz_2 == 1 );
399 
400   // setbuf
401   // pubsetbuf(char_type* s, streamsize n)
402   fb_01.pubsetbuf(0,0);
403   fb_02.pubsetbuf(0,0);
404   fb_03.pubsetbuf(0,0);
405   // Need to test unbuffered output, which means calling this on some
406   // things that have just been opened.
407 
408 
409   // seekoff
410   // pubseekoff(off_type off, ios_base::seekdir way, ios_base::openmode which)
411   // alters the stream position to off
412   pos_type pt_1(off_type(-1));
413   pos_type pt_2(off_type(0));
414   off_type off_1 = 0;
415   off_type off_2 = 0;
416   //IN|OUT
417   // 27filebuf-3.txt = bd23456789:;<=>?...
418   //beg
419   strmsz_1 = fb_03.in_avail();
420   pt_1 = fb_03.pubseekoff(2, std::ios_base::beg);
421   strmsz_2 = fb_03.in_avail();
422   off_1 = pt_1;
423   VERIFY( off_1 > 0 );
424   c1 = fb_03.snextc(); //current in pointer +1
425   VERIFY( c1 == '3' );
426   c2 = fb_03.sputc('\n');  //current in pointer +1
427   c3 = fb_03.sgetc();
428   VERIFY( c2 != c3 );
429   VERIFY( c3 == '4' );
430   fb_03.pubsync();
431   c1 = fb_03.sgetc();
432   VERIFY( c1 == c3 );
433   //cur
434   // 27filebuf-3.txt = bd2\n456789:;<=>?...
435   pt_2 = fb_03.pubseekoff(2, std::ios_base::cur);
436   off_2 = pt_2;
437   VERIFY( (off_2 == (off_1 + 2 + 1 + 1)) );
438   c1 = fb_03.snextc(); //current in pointer +1
439   VERIFY( c1 == '7' );
440   c2 = fb_03.sputc('x');  //test current out pointer
441   c3 = fb_03.sputc('\n');
442   c1 = fb_03.sgetc();
443   fb_03.pubsync();
444   c3 = fb_03.sgetc();
445   VERIFY( c1 == c3 );
446   //end
447   // 27filebuf-3.txt = "bd2\n456x\n9"
448   pt_2 = fb_03.pubseekoff(0, std::ios_base::end,
449 			  std::ios_base::in|std::ios_base::out);
450   off_1 = pt_2;
451   VERIFY( off_1 > off_2 ); //weak, but don't know exactly where it ends
452   c3 = fb_03.sputc('\n');
453   strmsz_1 = fb_03.sputn("because because because. . .", 28);
454   VERIFY( strmsz_1 == 28 );
455   c1 = fb_03.sungetc();
456   // Defect?  retval of sungetc is not necessarily the character ungotten.
457   // So re-get it.
458   c1 = fb_03.sgetc();
459   fb_03.pubsync();
460   c3 = fb_03.sgetc();
461   VERIFY( c1 == c3 );
462   // IN
463   // OUT
464 
465 
466   // seekpos
467   // pubseekpos(pos_type sp, ios_base::openmode)
468   // alters the stream position to sp
469   //IN|OUT
470   //beg
471   pt_1 = fb_03.pubseekoff(78, std::ios_base::beg);
472   off_1 = pt_1;
473   VERIFY( off_1 > 0 );
474   c1 = fb_03.snextc(); 		//current in pointer +1
475   VERIFY( c1 == ' ' );
476   c2 = fb_03.sputc('\n');  	//test current out pointer
477   c3 = fb_03.sgetc();
478   fb_03.pubsync(); 		//resets pointers
479   pt_2 = fb_03.pubseekpos(pt_1);
480   off_2 = pt_2;
481   VERIFY( off_1 == off_2 );
482   c3 = fb_03.snextc(); 		//current in pointer +1
483   VERIFY( c2 == c3 );
484   pt_1 = fb_03.pubseekoff(0, std::ios_base::end);
485   off_1 = pt_1;
486   VERIFY( off_1 > off_2 );
487   fb_03.sputn("\nof the wonderful things he does!!\nok", 37);
488   fb_03.pubsync();
489 
490   // IN
491   // OUT
492 
493   // VIRTUALS (indirectly tested)
494   // underflow
495   // if read position avail, returns *gptr()
496 
497   // pbackfail(int_type c)
498   // put c back into input sequence
499 
500   // overflow
501   // appends c to output seq
502 
503   // NB Have to close these suckers. . .
504   // filebuf_type* close()
505   fb_01.close();
506   fb_02.close();
507   fb_03.close();
508   VERIFY( !fb_01.is_open() );
509   VERIFY( !fb_02.is_open() );
510   VERIFY( !fb_03.is_open() );
511 }
512 
test06()513 void test06()
514 {
515   using namespace std;
516   typedef istream::int_type	int_type;
517 
518   bool test = true;
519   ifstream ifs(name_02);
520   char buffer[] = "xxxxxxxxxx";
521   int_type len1 = ifs.rdbuf()->sgetn(buffer, sizeof(buffer));
522   VERIFY( len1 == sizeof(buffer) );
523   VERIFY( buffer[0] == 'a' );
524 }
525 
526 // libstdc++/9322
test07()527 void test07()
528 {
529   using std::locale;
530   bool test = true;
531 
532   locale loc;
533   std::filebuf ob;
534   VERIFY( ob.getloc() == loc );
535 
536   locale::global(locale("en_US"));
537   VERIFY( ob.getloc() == loc );
538 
539   locale loc_de ("de_DE");
540   locale ret = ob.pubimbue(loc_de);
541   VERIFY( ob.getloc() == loc_de );
542   VERIFY( ret == loc );
543 
544   locale::global(loc);
545   VERIFY( ob.getloc() == loc_de );
546 }
547 
548 class MyTraits : public std::char_traits<char>
549 {
550 public:
eq(char c1,char c2)551   static bool eq(char c1, char c2)
552   {
553     VERIFY( c1 != 'X' );
554     VERIFY( c2 != 'X' );
555     return std::char_traits<char>::eq(c1, c2);
556   }
557 };
558 
559 class MyBuf : public std::basic_streambuf<char, MyTraits>
560 {
561   char buffer[8];
562 
563 public:
MyBuf()564   MyBuf()
565   {
566     std::memset(buffer, 'X', sizeof(buffer));
567     std::memset(buffer + 2, 'f', 4);
568     setg(buffer + 2, buffer + 2, buffer + 6);
569   }
570 };
571 
572 // libstdc++/9538
test08()573 void test08()
574 {
575   bool test = true;
576 
577   MyBuf mb;
578   mb.sputbackc('a');
579 }
580 
581 // libstdc++/9439, libstdc++/9425
test09()582 void test09()
583 {
584   using namespace std;
585   bool test = true;
586 
587   filebuf fbuf;
588   fbuf.open(name_01, ios_base::in);
589   filebuf::int_type r = fbuf.sputbackc('a');
590   fbuf.close();
591 
592   VERIFY( r == filebuf::traits_type::eof() );
593 }
594 
595 class Cvt_to_upper : public std::codecvt<char, char, mbstate_t>
596 {
do_always_noconv() const597   bool do_always_noconv() const throw()
598   {
599     return false;
600   }
601 };
602 
603 // libstdc++/9169
test10()604 void test10()
605 {
606   using namespace std;
607   bool test = true;
608 
609   locale c_loc;
610   locale loc(c_loc, new Cvt_to_upper);
611 
612   string str("abcdefghijklmnopqrstuvwxyz");
613   string tmp;
614 
615   {
616     ofstream out;
617     out.imbue(loc);
618     out.open(name_04);
619     copy(str.begin(), str.end(),
620 	 ostreambuf_iterator<char>(out));
621   }
622 
623   {
624     ifstream in;
625     in.open(name_04);
626     copy(istreambuf_iterator<char>(in),
627 	 istreambuf_iterator<char>(),
628 	 back_inserter(tmp));
629   }
630 
631   VERIFY( tmp.size() == str.size() );
632   VERIFY( tmp == str );
633 }
634 
635 // libstdc++/9825
test11()636 void test11()
637 {
638   using namespace std;
639   bool test = true;
640 
641   filebuf fbuf;
642 
643   fbuf.open(name_05, ios_base::in|ios_base::out|ios_base::trunc);
644   fbuf.sputn("crazy bees!", 11);
645   fbuf.pubseekoff(0, ios_base::beg);
646   fbuf.sbumpc();
647   fbuf.sputbackc('x');
648   filebuf::int_type c = fbuf.sbumpc();
649   VERIFY( c == 'x' );
650   c = fbuf.sbumpc();
651   VERIFY( c == 'r' );
652   c = fbuf.sbumpc();
653   VERIFY( c == 'a' );
654   fbuf.close();
655 }
656 
657 class errorcvt : public std::codecvt<char, char, mbstate_t>
658 {
659 protected:
660   std::codecvt_base::result
do_out(mbstate_t &,const char * from,const char *,const char * & from_next,char * to,char *,char * & to_next) const661   do_out(mbstate_t&, const char* from, const char*,
662 	 const char*& from_next, char* to, char*,
663 	 char*& to_next) const
664   {
665     from_next = from;
666     to_next = to;
667     return std::codecvt<char, char, mbstate_t>::error;
668   }
669 
do_always_noconv() const670   virtual bool do_always_noconv() const throw()
671   {
672     return false;
673   }
674 };
675 
676 // libstdc++/9182
test12()677 void test12()
678 {
679   using namespace std;
680   bool test = true;
681 
682   locale loc;
683   loc = locale(loc, new errorcvt);
684 
685   filebuf fbuf1;
686   fbuf1.pubimbue(loc);
687   fbuf1.open(name_06, ios_base::out | ios_base::trunc);
688   fbuf1.sputn("ison", 4);
689   int r = fbuf1.pubsync();
690   VERIFY( r == -1 );
691   fbuf1.close();
692 }
693 
test13()694 void test13()
695 {
696   using namespace std;
697   bool test = true;
698 
699   locale loc;
700   loc = locale(loc, new errorcvt);
701 
702   filebuf fbuf1;
703   fbuf1.pubimbue(loc);
704   fbuf1.pubsetbuf(0, 0);
705   fbuf1.open(name_06, ios_base::out | ios_base::trunc);
706   streamsize n = fbuf1.sputn("onne", 4);
707   VERIFY( n == 0 );
708   fbuf1.close();
709 }
710 
711 class OverBuf : public std::filebuf
712 {
713 public:
pub_overflow(int_type c=traits_type::eof ())714   int_type pub_overflow(int_type c = traits_type::eof())
715   { return std::filebuf::overflow(c); }
716 };
717 
718 // libstdc++/9988
test14()719 void test14()
720 {
721   using namespace std;
722   bool test = true;
723 
724   OverBuf fb;
725   fb.open(name_07, ios_base::out | ios_base::trunc);
726 
727   fb.sputc('a');
728   fb.pub_overflow('b');
729   fb.pub_overflow();
730   fb.sputc('c');
731   fb.close();
732 
733   filebuf fbin;
734   fbin.open(name_07, ios_base::in);
735   filebuf::int_type c;
736   c = fbin.sbumpc();
737   VERIFY( c == 'a' );
738   c = fbin.sbumpc();
739   VERIFY( c == 'b' );
740   c = fbin.sbumpc();
741   VERIFY( c == 'c' );
742   c = fbin.sbumpc();
743   VERIFY( c == filebuf::traits_type::eof() );
744   fbin.close();
745 }
746 
747 class UnderBuf : public std::filebuf
748 {
749 public:
750   int_type
pub_underflow()751   pub_underflow()
752   { return underflow(); }
753 
754   std::streamsize
pub_showmanyc()755   pub_showmanyc()
756   { return showmanyc(); }
757 };
758 
759 // libstdc++/10097
test15()760 void test15()
761 {
762   using namespace std;
763   bool test = true;
764 
765   const char* name = "tmp_fifo1";
766 
767   signal(SIGPIPE, SIG_IGN);
768   unlink(name);
769 
770   if (0 != mkfifo(name, S_IRWXU))
771     {
772       VERIFY( false );
773     }
774 
775   int fval = fork();
776   if (fval == -1)
777     {
778       unlink(name);
779       VERIFY( false );
780     }
781   else if (fval == 0)
782     {
783       filebuf fbout;
784       fbout.open(name, ios_base::out);
785       fbout.sputn("0123456789", 10);
786       fbout.pubsync();
787       sleep(2);
788       fbout.close();
789       exit(0);
790     }
791 
792   UnderBuf fb;
793   fb.open(name, ios_base::in);
794   sleep(1);
795 
796   fb.sgetc();
797   streamsize n = fb.pub_showmanyc();
798 
799   while (n > 0)
800     {
801       --n;
802 
803       UnderBuf::int_type c = fb.pub_underflow();
804       VERIFY( c != UnderBuf::traits_type::eof() );
805 
806       fb.sbumpc();
807     }
808 
809   fb.close();
810 }
811 
main()812 main()
813 {
814   test01();
815   test02();
816 
817   test03();
818   test04();
819   test05();
820   test06();
821 
822   test07();
823   test08();
824   test09();
825   test10();
826   test11();
827   test12();
828   test13();
829   test14();
830   test15();
831   return 0;
832 }
833