1 #include <string>
2 #if !defined (STLPORT) || !defined (_STLP_USE_NO_IOSTREAMS)
3 #  include <fstream>
4 #  include <iostream>
5 #  include <iomanip>
6 #  include <sstream>
7 #  include <vector>
8 #  include <stdexcept>
9 
10 #include <stdio.h>
11 
12 #  include "full_streambuf.h"
13 #  include "cppunit/cppunit_proxy.h"
14 
15 #  if !defined (STLPORT) || defined(_STLP_USE_NAMESPACES)
16 using namespace std;
17 #  endif
18 
19 //The macro value gives approximately the generated file
20 //size in Go
21 //#define CHECK_BIG_FILE 4
22 
23 #  if (!defined(STLPORT) && (defined (__GNUC__) && (__GNUC__ > 3))) || \
24       (defined (STLPORT) && !defined (_STLP_NO_CUSTOM_IO) && !defined (_STLP_NO_MEMBER_TEMPLATES) && \
25                             !((defined (_STLP_MSVC) && (_STLP_MSVC < 1300)) || \
26                               (defined (__GNUC__) && (__GNUC__ < 3)) || \
27                               (defined (__SUNPRO_CC)) || \
28                               (defined (__DMC__) && defined (_DLL))))
29 #    define DO_CUSTOM_FACET_TEST
30 #  endif
31 
32 //
33 // TestCase class
34 //
35 class FstreamTest : public CPPUNIT_NS::TestCase
36 {
37   CPPUNIT_TEST_SUITE(FstreamTest);
38   CPPUNIT_TEST(output);
39   CPPUNIT_TEST(input);
40   CPPUNIT_TEST(input_char);
41   CPPUNIT_TEST(io);
42   CPPUNIT_TEST(err);
43   CPPUNIT_TEST(tellg);
44   CPPUNIT_TEST(tellp);
45   CPPUNIT_TEST(seek);
46   CPPUNIT_TEST(buf);
47   CPPUNIT_TEST(rdbuf);
48   CPPUNIT_TEST(streambuf_output);
49   CPPUNIT_TEST(win32_file_format);
50   CPPUNIT_TEST(null_stream);
51 #  if defined (STLPORT) && (defined (_STLP_NO_WCHAR_T) || !defined (_STLP_USE_EXCEPTIONS))
52   CPPUNIT_IGNORE;
53 #  endif
54   CPPUNIT_TEST(null_buf);
55 #  if !defined (STLPORT) || !defined (_STLP_WIN32)
56   CPPUNIT_TEST(offset);
57 #  endif
58 #  if defined (CHECK_BIG_FILE)
59   CPPUNIT_TEST(big_file);
60 #  endif
61 #  if !defined (DO_CUSTOM_FACET_TEST)
62   CPPUNIT_IGNORE;
63 #  endif
64   CPPUNIT_TEST(custom_facet);
65   CPPUNIT_TEST_SUITE_END();
66 
67   protected:
68     void output();
69     void input();
70     void input_char();
71     void io();
72     void err();
73     void tellg();
74     void tellp();
75     void seek();
76     void buf();
77     void rdbuf();
78     void streambuf_output();
79     void win32_file_format();
80     void null_stream();
81     void null_buf();
82 #  if !defined (STLPORT) || !defined (_STLP_WIN32)
83     void offset();
84 #  endif
85     void custom_facet();
86 #  if defined (CHECK_BIG_FILE)
87     void big_file();
88 #  endif
89 };
90 
91 CPPUNIT_TEST_SUITE_REGISTRATION(FstreamTest);
92 
93 //
94 // tests implementation
95 //
96 void FstreamTest::output()
97 {
98   ofstream f( "test_file.txt" );
99 
100   f << 1 << '\n' << 2.0 << '\n' << "abcd\n" << "ghk lm\n" << "abcd ef";
101   CPPUNIT_ASSERT (f.good());
102   // CPPUNIT_ASSERT( s.str() == "1\n2\nabcd\nghk lm\nabcd ef" );
103 }
104 
105 void FstreamTest::input()
106 {
107   {
108     ifstream f( "test_file.txt" );
109     int i = 0;
110     f >> i;
111     CPPUNIT_ASSERT( f.good() );
112     CPPUNIT_ASSERT( i == 1 );
113     double d = 0.0;
114     f >> d;
115     CPPUNIT_ASSERT( f.good() );
116     CPPUNIT_ASSERT( d == 2.0 );
117     string str;
118     f >> str;
119     CPPUNIT_ASSERT( f.good() );
120     CPPUNIT_ASSERT( str == "abcd" );
121     char c;
122     f.get(c); // extract newline, that not extracted by operator >>
123     CPPUNIT_ASSERT( f.good() );
124     CPPUNIT_ASSERT( c == '\n' );
125     getline( f, str );
126     CPPUNIT_ASSERT( f.good() );
127     CPPUNIT_ASSERT( str == "ghk lm" );
128     getline( f, str );
129     CPPUNIT_ASSERT( f.eof() );
130     CPPUNIT_ASSERT( str == "abcd ef" );
131   }
132 #if defined (STLPORT) && !defined (_STLP_USE_WIN32_IO)
133   {
134     ifstream in("/tmp");
135     if (in.good()) {
136       string s;
137       getline(in, s);
138       CPPUNIT_ASSERT( in.fail() );
139     }
140   }
141 #endif
142 }
143 
144 void FstreamTest::input_char()
145 {
146   char buf[16] = { 0, '1', '2', '3' };
147   ifstream s( "test_file.txt" );
148   s >> buf;
149 
150   CPPUNIT_ASSERT( buf[0] == '1' );
151   CPPUNIT_ASSERT( buf[1] == 0 );
152   CPPUNIT_ASSERT( buf[2] == '2' );
153 }
154 
155 void FstreamTest::io()
156 {
157   basic_fstream<char,char_traits<char> > f( "test_file.txt", ios_base::in | ios_base::out | ios_base::trunc );
158 
159   CPPUNIT_ASSERT( f.is_open() );
160 
161   f << 1 << '\n' << 2.0 << '\n' << "abcd\n" << "ghk lm\n" << "abcd ef";
162 
163   // f.flush();
164   f.seekg( 0, ios_base::beg );
165 
166   int i = 0;
167   f >> i;
168   CPPUNIT_ASSERT( f.good() );
169   CPPUNIT_ASSERT( i == 1 );
170   double d = 0.0;
171   f >> d;
172   CPPUNIT_ASSERT( d == 2.0 );
173   string s;
174   f >> s;
175   CPPUNIT_ASSERT( f.good() );
176   CPPUNIT_ASSERT( s == "abcd" );
177   char c;
178   f.get(c); // extract newline, that not extracted by operator >>
179   CPPUNIT_ASSERT( f.good() );
180   CPPUNIT_ASSERT( c == '\n' );
181   getline( f, s );
182   CPPUNIT_ASSERT( f.good() );
183   CPPUNIT_ASSERT( s == "ghk lm" );
184   getline( f, s );
185   CPPUNIT_ASSERT( !f.fail() );
186   CPPUNIT_ASSERT( s == "abcd ef" );
187   CPPUNIT_ASSERT( f.eof() );
188 }
189 
190 void FstreamTest::err()
191 {
192   basic_fstream<char,char_traits<char> > f( "test_file.txt", ios_base::in | ios_base::out | ios_base::trunc );
193 
194   CPPUNIT_ASSERT( f.is_open() );
195 
196   int i = 9;
197   f << i;
198   CPPUNIT_ASSERT( f.good() );
199   i = 0;
200   f.seekg( 0, ios_base::beg );
201   f >> i;
202   CPPUNIT_ASSERT( !f.fail() );
203   CPPUNIT_ASSERT( i == 9 );
204   f >> i;
205   CPPUNIT_ASSERT( f.fail() );
206   CPPUNIT_ASSERT( f.eof() );
207   CPPUNIT_ASSERT( i == 9 );
208 }
209 
210 void FstreamTest::tellg()
211 {
212   {
213     // bogus ios_base::binary is for Wins
214     ofstream of("test_file.txt", ios_base::out | ios_base::binary | ios_base::trunc);
215     CPPUNIT_ASSERT( of.is_open() );
216 
217     for (int i = 0; i < 50; ++i) {
218       of << "line " << setiosflags(ios_base::right) << setfill('0') << setw(2) << i << "\n";
219       CPPUNIT_ASSERT( !of.fail() );
220     }
221     of.close();
222   }
223 
224   {
225     // bogus ios_base::binary is for Wins
226     ifstream is("test_file.txt", ios_base::in | ios_base::binary);
227     CPPUNIT_ASSERT( is.is_open() );
228     char buf[64];
229 
230     // CPPUNIT_ASSERT( is.tellg() == 0 );
231     streampos p = 0;
232     for (int i = 0; i < 50; ++i) {
233       is.read(buf, 0);
234       CPPUNIT_ASSERT( is.gcount() == 0 );
235       CPPUNIT_ASSERT( is.tellg() == p );
236       is.read( buf, 8 );
237       CPPUNIT_ASSERT( !is.fail() );
238       CPPUNIT_ASSERT( is.gcount() == 8 );
239       p += 8;
240     }
241   }
242 
243   {
244     // bogus ios_base::binary is for Wins
245     ifstream is("test_file.txt", ios_base::in | ios_base::binary);
246     CPPUNIT_ASSERT( is.is_open() );
247 
248     streampos p = 0;
249     for (int i = 0; i < 50; ++i) {
250       CPPUNIT_ASSERT( !is.fail() );
251       is.tellg();
252       CPPUNIT_ASSERT( is.tellg() == p );
253       p += 8;
254       is.seekg( p, ios_base::beg  );
255       CPPUNIT_ASSERT( !is.fail() );
256     }
257   }
258 
259   {
260     // bogus ios_base::binary is for Wins
261     ifstream is("test_file.txt", ios_base::in | ios_base::binary);
262     CPPUNIT_ASSERT( is.is_open() );
263 
264     streampos p = 0;
265     for (int i = 0; i < 50; ++i) {
266       CPPUNIT_ASSERT( is.tellg() == p );
267       p += 8;
268       is.seekg( 8, ios_base::cur );
269       CPPUNIT_ASSERT( !is.fail() );
270     }
271   }
272 }
273 
274 void FstreamTest::tellp()
275 {
276   {
277     ofstream o( "test_file.txt" );
278 
279     o << "123456";
280 
281     CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == ofstream::pos_type(6) );
282     CPPUNIT_CHECK( o.tellp() == ofstream::pos_type(6) );
283   }
284   {
285     ofstream o( "test_file.txt" );
286 
287     o << "123456789";
288 
289     CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == ofstream::pos_type(9) );
290     CPPUNIT_CHECK( o.tellp() == ofstream::pos_type(9) );
291   }
292   /* According to the standard
293      ofstream o( "test_file.txt", ios_base::app | ios_base::out )
294      should give the same effect as fopen( "test_file.txt", "a" ).
295      Problem is fopen( "test_file.txt", "a" ) has a bit different behaviour
296      on different platforms, and this difference is not covered by specification.
297      After fopen( "test_file.txt", "a" ) in this context ftell( f ) == 9 for
298      Linux and Mac OS X (I expect the same for others POSIX-like platforms too);
299      on Windows (independently from version?) ftell( f ) == 0, i.e. write pointer not
300      shifted to EOF (but shifted to EOF just before write, as described in the specs).
301 
302      It isn't specifications violation, neither for Linux and Mac OS X nor for Windows.
303 
304      The code below is intended to demonstrate ambiguity (dependance from fopen implementation).
305    */
306   {
307     #ifdef WIN32
308     //In Windows, stlport and fopen use kernel32.CreateFile for open.
309     //File position is at BOF after open, unless we open with ios_base::ate
310     long expected_pos = 0;
311     #else
312     //On UNIX flavours, stlport and fopen use unix's open
313     //File position is at EOF after open
314     //
315     //3rd possible scenario, "other platforms" - _STLP_USE_STDIO_IO
316     //stlport uses fopen here. This case may fail this test, since the file position after
317     //fopen is implementation-dependent
318     long expected_pos = 9;
319     #endif
320     ofstream o( "test_file.txt", ios_base::app | ios_base::out );
321     CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == ofstream::pos_type(expected_pos) );
322     CPPUNIT_CHECK( o.tellp() == ofstream::pos_type(expected_pos) );
323   }
324   { // for reference, to test fopen/ftell behaviour in append mode:
325     #ifdef WIN32
326     long expected_pos = 0;
327     #else
328     long expected_pos = 9;
329     #endif
330     FILE* f = fopen( "test_file.txt", "a" );
331     CPPUNIT_CHECK( ftell( f ) == expected_pos );
332     fclose( f );
333   }
334   {
335     //In append mode, file is positioned at EOF just before a write.
336     // After a write, file is at EOF. This is implementation-independent.
337     ofstream o( "test_file.txt", ios_base::app | ios_base::out );
338     o << "X";
339     CPPUNIT_CHECK( o.rdbuf()->pubseekoff( 0, ios_base::cur, ios_base::out ) == ofstream::pos_type(10) );
340     CPPUNIT_CHECK( o.tellp() == ofstream::pos_type(10) );
341   }
342 }
343 
344 void FstreamTest::buf()
345 {
346   fstream ss( "test_file.txt", ios_base::in | ios_base::out | ios_base::binary | ios_base::trunc );
347 
348   ss << "1234567\n89\n";
349   ss.seekg( 0, ios_base::beg );
350   char buf[10];
351   buf[7] = 'x';
352   ss.get( buf, 10 );
353   CPPUNIT_ASSERT( !ss.fail() );
354   CPPUNIT_ASSERT( buf[0] == '1' );
355   CPPUNIT_ASSERT( buf[1] == '2' );
356   CPPUNIT_ASSERT( buf[2] == '3' );
357   CPPUNIT_ASSERT( buf[3] == '4' );
358   CPPUNIT_ASSERT( buf[4] == '5' );
359   CPPUNIT_ASSERT( buf[5] == '6' );
360   CPPUNIT_ASSERT( buf[6] == '7' ); // 27.6.1.3 paragraph 10, paragraph 7
361   CPPUNIT_ASSERT( buf[7] == 0 ); // 27.6.1.3 paragraph 8
362   char c;
363   ss.get(c);
364   CPPUNIT_ASSERT( !ss.fail() );
365   CPPUNIT_ASSERT( c == '\n' ); // 27.6.1.3 paragraph 10, paragraph 7
366   ss.get(c);
367   CPPUNIT_ASSERT( !ss.fail() );
368   CPPUNIT_ASSERT( c == '8' );
369 }
370 
371 void FstreamTest::seek()
372 {
373   {
374     // Test in binary mode:
375     {
376       fstream s( "test_file.txt", ios_base::in | ios_base::out | ios_base::binary | ios_base::trunc );
377       CPPUNIT_ASSERT( s );
378 
379       s << "1234567890\n";
380       CPPUNIT_ASSERT( s );
381     }
382 
383     char b1[] = { 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x' };
384     fstream s( "test_file.txt", ios_base::in | ios_base::out | ios_base::binary );
385     CPPUNIT_ASSERT( s );
386 
387     int chars_read = (int)s.rdbuf()->sgetn( b1, sizeof(b1) );
388     CPPUNIT_CHECK( chars_read == 11 );
389     CPPUNIT_CHECK( b1[9] == '0' );
390     CPPUNIT_ASSERT( s.rdbuf()->pubseekoff( 0, ios_base::cur ) == fstream::pos_type(chars_read) );
391     CPPUNIT_ASSERT( s.rdbuf()->pubseekoff( -chars_read, ios_base::cur ) == fstream::pos_type(0) );
392 
393     char b2[10] = { 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y' };
394 
395     CPPUNIT_ASSERT( s.rdbuf()->sgetn( b2, 10 ) == 10 );
396     CPPUNIT_CHECK( b2[9] == '0' );
397   }
398 
399   {
400     // Test in text mode:
401     {
402       fstream s( "test_file.txt", ios_base::in | ios_base::out | ios_base::trunc );
403       CPPUNIT_ASSERT( s );
404 
405       s << "1234567890\n";
406       CPPUNIT_ASSERT( s );
407     }
408 
409     char b1[] = { 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x' };
410     fstream s( "test_file.txt", ios_base::in | ios_base::out );
411     CPPUNIT_ASSERT( s );
412 
413     int chars_read = (int)s.rdbuf()->sgetn( b1, sizeof(b1) );
414     CPPUNIT_CHECK( chars_read == 11 );
415     CPPUNIT_CHECK( b1[9] == '0' );
416 
417     fstream::pos_type pos = s.rdbuf()->pubseekoff(0, ios_base::cur);
418     // Depending on how '\n' is written in file, file position can be greater or equal to the number of chars_read read.
419     streamoff offset = pos;
420     CPPUNIT_ASSERT( offset >= chars_read );
421     offset = s.rdbuf()->pubseekoff( -offset, ios_base::cur );
422     CPPUNIT_ASSERT( offset == 0 );
423 
424     char b2[10] = { 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y' };
425 
426     CPPUNIT_ASSERT( s.rdbuf()->sgetn( b2, 5 ) == 5 );
427     CPPUNIT_CHECK( b2[4] == '5' );
428 
429     pos = s.rdbuf()->pubseekoff(0, ios_base::cur);
430     CPPUNIT_ASSERT( pos == fstream::pos_type(5) );
431     CPPUNIT_ASSERT( s.rdbuf()->pubseekoff(-5, ios_base::cur) == fstream::pos_type(0) );
432   }
433 
434 #if !defined (STLPORT) || \
435     (!defined (_STLP_NO_WCHAR_T) && defined (_STLP_USE_EXCEPTIONS))
436   {
437     // Test with a wariable encoding:
438     locale loc;
439     try
440     {
441       locale tmp(locale::classic(), new codecvt_byname<wchar_t, char, mbstate_t>(".UTF8"));
442       loc = tmp;
443     }
444     catch (const runtime_error&)
445     {
446       // Localization no supported so no test:
447       return;
448     }
449 
450     {
451       wfstream s( "test_file.txt", ios_base::in | ios_base::out | ios_base::trunc );
452       CPPUNIT_ASSERT( s );
453       s.imbue(loc);
454       CPPUNIT_ASSERT( s );
455 
456       s << L"1234567890\n";
457       CPPUNIT_ASSERT( s );
458     }
459 
460     wchar_t b1[] = { L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x', L'x' };
461     wfstream s( "test_file.txt", ios_base::in | ios_base::out );
462     CPPUNIT_ASSERT( s );
463     s.imbue(loc);
464     CPPUNIT_ASSERT( s );
465 
466     int chars_read = (int)s.rdbuf()->sgetn( b1, sizeof(b1) / sizeof(wchar_t) );
467     CPPUNIT_CHECK( chars_read == 11 );
468     CPPUNIT_CHECK( b1[9] == L'0' );
469 
470     fstream::pos_type pos = s.rdbuf()->pubseekoff(0, ios_base::cur);
471     // Depending on how '\n' is written in file, file position can be greater or equal to the number of chars_read read.
472     streamoff off = pos;
473     CPPUNIT_ASSERT( off >= chars_read );
474     off = s.rdbuf()->pubseekoff(-off, ios_base::cur);
475     CPPUNIT_ASSERT( off == -1 );
476     off = s.rdbuf()->pubseekoff(0, ios_base::beg);
477     CPPUNIT_ASSERT( off == 0 );
478 
479     wchar_t b2[10] = { L'y', L'y', L'y', L'y', L'y', L'y', L'y', L'y', L'y', L'y' };
480 
481     CPPUNIT_ASSERT( s.rdbuf()->sgetn( b2, 5 ) == 5 );
482     CPPUNIT_CHECK( b2[4] == L'5' );
483 
484     pos = s.rdbuf()->pubseekoff(0, ios_base::cur);
485     CPPUNIT_ASSERT( pos == fstream::pos_type(5) );
486     //CPPUNIT_ASSERT( s.rdbuf()->pubseekoff(-5, ios_base::cur) == fstream::pos_type(0) );
487   }
488 #endif
489 }
490 
491 void FstreamTest::rdbuf()
492 {
493   fstream ss( "test_file.txt", ios_base::in | ios_base::out | ios_base::binary | ios_base::trunc );
494 
495   ss << "1234567\n89\n";
496   ss.seekg( 0, ios_base::beg );
497 
498   ostringstream os;
499   ss.get( *os.rdbuf(), '\n' );
500   CPPUNIT_ASSERT( !ss.fail() );
501   char c;
502   ss.get(c);
503   CPPUNIT_ASSERT( !ss.fail() );
504   CPPUNIT_ASSERT( c == '\n' ); // 27.6.1.3 paragraph 12
505   CPPUNIT_ASSERT( os.str() == "1234567" );
506 }
507 
508 void FstreamTest::streambuf_output()
509 {
510   {
511     ofstream ofstr("test_file.txt", ios_base::binary);
512     if (!ofstr)
513       //No test if we cannot create the file
514       return;
515     ofstr << "01234567890123456789";
516     CPPUNIT_ASSERT( ofstr );
517   }
518 
519   {
520     ifstream in("test_file.txt", ios_base::binary);
521     CPPUNIT_ASSERT( in );
522 
523     full_streambuf full_buf(10);
524     ostream out(&full_buf);
525     CPPUNIT_ASSERT( out );
526 
527     out << in.rdbuf();
528     CPPUNIT_ASSERT( out );
529     CPPUNIT_ASSERT( in );
530     CPPUNIT_ASSERT( full_buf.str() == "0123456789" );
531 
532     out << in.rdbuf();
533     CPPUNIT_ASSERT( out.fail() );
534     CPPUNIT_ASSERT( in );
535 
536     ostringstream ostr;
537     ostr << in.rdbuf();
538     CPPUNIT_ASSERT( ostr );
539     CPPUNIT_ASSERT( in );
540     CPPUNIT_ASSERT( ostr.str() == "0123456789" );
541   }
542 
543 #  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
544   {
545     //If the output stream buffer throws:
546     ifstream in("test_file.txt", ios_base::binary);
547     CPPUNIT_ASSERT( in );
548 
549     full_streambuf full_buf(10, true);
550     ostream out(&full_buf);
551     CPPUNIT_ASSERT( out );
552 
553     out << in.rdbuf();
554     CPPUNIT_ASSERT( out.bad() );
555     CPPUNIT_ASSERT( in );
556     //out is bad we have no guaranty on what has been extracted:
557     //CPPUNIT_ASSERT( full_buf.str() == "0123456789" );
558 
559     out.clear();
560     out << in.rdbuf();
561     CPPUNIT_ASSERT( out.fail() && out.bad() );
562     CPPUNIT_ASSERT( in );
563 
564     ostringstream ostr;
565     ostr << in.rdbuf();
566     CPPUNIT_ASSERT( ostr );
567     CPPUNIT_ASSERT( in );
568     CPPUNIT_ASSERT( ostr.str() == "0123456789" );
569   }
570 #  endif
571 }
572 
573 void FstreamTest::win32_file_format()
574 {
575   const char* file_name = "win32_file_format.tmp";
576   const size_t nb_lines = 2049;
577   {
578     ofstream out(file_name);
579     CPPUNIT_ASSERT( out.good() );
580     out << 'a';
581     for (size_t i = 0; i < nb_lines - 1; ++i) {
582       out << '\n';
583     }
584     out << '\r';
585     CPPUNIT_ASSERT( out.good() );
586   }
587   {
588     ifstream in(file_name);
589     CPPUNIT_ASSERT( in.good() );
590     string line, last_line;
591     size_t nb_read_lines = 0;
592     while (getline(in, line)) {
593       ++nb_read_lines;
594       last_line = line;
595     }
596     CPPUNIT_ASSERT( in.eof() );
597     CPPUNIT_ASSERT( nb_read_lines == nb_lines );
598     CPPUNIT_ASSERT( !last_line.empty() && (last_line[0] == '\r') );
599   }
600 }
601 
602 #if defined (DO_CUSTOM_FACET_TEST)
603 struct my_state {
604   char dummy;
605 };
606 
607 struct my_traits : public char_traits<char> {
608   typedef my_state state_type;
609   typedef fpos<state_type> pos_type;
610 };
611 
612 #if !defined (STLPORT)
613 //STLport grant a default implementation, other Standard libs implementation
614 //do not necessarily do the same:
615 namespace std {
616   template <>
617   class codecvt<char, char, my_state>
618     : public locale::facet, public codecvt_base {
619   public:
620     typedef char intern_type;
621     typedef char extern_type;
622     typedef my_state state_type;
623 
624     explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {}
625     result out(state_type&,
626                const intern_type*  __from,
627                const intern_type*,
628                const intern_type*& __from_next,
629                extern_type*        __to,
630                extern_type*,
631                extern_type*&       __to_next) const
632     { __from_next = __from; __to_next   = __to; return noconv; }
633 
634     result in (state_type&,
635                const extern_type*  __from,
636                const extern_type*,
637                const extern_type*& __from_next,
638                intern_type*        __to,
639                intern_type*,
640                intern_type*&       __to_next) const
641     { __from_next = __from; __to_next = __to; return noconv; }
642 
643     result unshift(state_type&,
644                    extern_type* __to,
645                    extern_type*,
646                    extern_type*& __to_next) const
647     { __to_next = __to; return noconv; }
648 
649     int encoding() const throw()
650     { return 1; }
651 
652     bool always_noconv() const throw()
653     { return true; }
654 
655     int length(const state_type&,
656                const extern_type* __from,
657                const extern_type* __end,
658                size_t __max) const
659     { return (int)min(static_cast<size_t>(__end - __from), __max); }
660 
661     int max_length() const throw()
662     { return 1; }
663 
664     static locale::id id;
665   };
666 
667   locale::id codecvt<char, char, my_state>::id;
668 }
669 #  else
670 #    if defined (__BORLANDC__) && (__BORLANDC__ < 0x590)
671 template <>
672 locale::id codecvt<char, char, my_state>::id;
673 #    endif
674 #  endif
675 #endif
676 
677 void FstreamTest::custom_facet()
678 {
679 #if defined (DO_CUSTOM_FACET_TEST)
680   const char* fileName = "test_file.txt";
681   //File preparation:
682   {
683     ofstream ofstr(fileName, ios_base::binary);
684     ofstr << "0123456789";
685     CPPUNIT_ASSERT( ofstr );
686   }
687 
688   {
689     typedef basic_ifstream<char, my_traits> my_ifstream;
690     typedef basic_string<char, my_traits> my_string;
691 
692     my_ifstream ifstr(fileName);
693     CPPUNIT_ASSERT( ifstr );
694 
695 #  if !defined (STLPORT) || defined (_STLP_USE_EXCEPTIONS)
696     ifstr.imbue(locale::classic());
697     CPPUNIT_ASSERT( ifstr.fail() && !ifstr.bad() );
698     ifstr.clear();
699 #  endif
700     typedef codecvt<char, char, my_state> my_codecvt;
701     locale my_loc(locale::classic(), new my_codecvt());
702     // Check that my_codecvt has not replace default codecvt:
703     CPPUNIT_ASSERT( (has_facet<my_codecvt>(my_loc)) );
704     CPPUNIT_ASSERT( (has_facet<codecvt<char, char, mbstate_t> >(my_loc)) );
705 #  if !defined (STLPORT) || !defined (_STLP_NO_WCHAR_T)
706     CPPUNIT_ASSERT( (has_facet<codecvt<wchar_t, char, mbstate_t> >(my_loc)) );
707 #  endif
708     ifstr.imbue(my_loc);
709     CPPUNIT_ASSERT( ifstr.good() );
710     /*
711     my_string res;
712     ifstr >> res;
713     CPPUNIT_ASSERT( !ifstr.fail() );
714     CPPUNIT_ASSERT( !ifstr.bad() );
715     CPPUNIT_ASSERT( ifstr.eof() );
716     CPPUNIT_ASSERT( res == "0123456789" );
717     */
718   }
719 #endif
720 }
721 
722 #  if defined (CHECK_BIG_FILE)
723 void FstreamTest::big_file()
724 {
725   vector<pair<streamsize, streamoff> > file_pos;
726 
727   //Big file creation:
728   {
729     ofstream out("big_file.txt");
730     CPPUNIT_ASSERT( out );
731 
732     //We are going to generate a file with the following schema for the content:
733     //0(1019 times)0000  //1023 characters + 1 charater for \n (for some platforms it will be a 1 ko line)
734     //0(1019 times)0001
735     //...
736     //0(1019 times)1234
737     //...
738 
739     //Generation of the number of loop:
740     streamoff nb = 1;
741     for (int i = 0; i < 20; ++i) {
742       //This assertion check that the streamoff can at least represent the necessary integers values
743       //for this test:
744       CPPUNIT_ASSERT( (nb << 1) > nb );
745       nb <<= 1;
746     }
747     CPPUNIT_ASSERT( nb * CHECK_BIG_FILE >= nb );
748     nb *= CHECK_BIG_FILE;
749 
750     //Preparation of the ouput stream state:
751     out << setiosflags(ios_base::right) << setfill('*');
752     for (streamoff index = 0; index < nb; ++index) {
753       if (index % 1024 == 0) {
754         file_pos.push_back(make_pair(out.tellp(), index));
755         CPPUNIT_ASSERT( file_pos.back().first != streamsize(-1) );
756         if (file_pos.size() > 1) {
757           CPPUNIT_ASSERT( file_pos[file_pos.size() - 1].first > file_pos[file_pos.size() - 2].first );
758         }
759       }
760       out << setw(1023) << index << '\n';
761     }
762   }
763 
764   {
765     ifstream in("big_file.txt");
766     CPPUNIT_ASSERT( in );
767 
768     string line;
769     vector<pair<streamsize, streamsize> >::const_iterator pit(file_pos.begin()),
770                                                           pitEnd(file_pos.end());
771     for (; pit != pitEnd; ++pit) {
772       in.seekg((*pit).first);
773       CPPUNIT_ASSERT( in );
774       in >> line;
775       size_t lastStarPos = line.rfind('*');
776       CPPUNIT_ASSERT( atoi(line.substr(lastStarPos + 1).c_str()) == (*pit).second );
777     }
778   }
779 
780   /*
781   The following test has been used to check that STLport do not generate
782   an infinite loop when the file size is larger than the streamsize and
783   streamoff representation (32 bits or 64 bits).
784   {
785     ifstream in("big_file.txt");
786     CPPUNIT_ASSERT( in );
787     char tmp[4096];
788     streamsize nb_reads = 0;
789     while ((!in.eof()) && in.good()){
790       in.read(tmp, 4096);
791       nb_reads += in.gcount();
792     }
793   }
794   */
795 }
796 #  endif
797 
798 void FstreamTest::null_stream()
799 {
800 #  if (defined (STLPORT) && defined (_STLP_USE_WIN32_IO)) || \
801       (!defined (STLPORT) && (defined (WIN32) || defined (_WIN32)))
802   const char* nullStreamName = "NUL";
803 #  else
804   const char* nullStreamName = "/dev/null";
805 #  endif
806   {
807     ofstream nullStream(nullStreamName);
808     CPPUNIT_CHECK( nullStream );
809   }
810 
811   {
812     ofstream nullStream(nullStreamName, ios_base::ate);
813     CPPUNIT_CHECK( nullStream );
814   }
815 
816   {
817     ofstream nullStream(nullStreamName, ios_base::trunc);
818     CPPUNIT_CHECK( nullStream );
819   }
820 
821   {
822     ofstream nullStream(nullStreamName, ios_base::app);
823     CPPUNIT_CHECK( nullStream );
824   }
825 
826   {
827     ifstream nullStream(nullStreamName);
828     CPPUNIT_CHECK( nullStream );
829   }
830 
831   {
832     ifstream nullStream(nullStreamName, ios_base::ate);
833     CPPUNIT_CHECK( nullStream );
834   }
835 
836   {
837     fstream nullStream(nullStreamName);
838     CPPUNIT_CHECK( nullStream );
839   }
840 
841   {
842     fstream nullStream(nullStreamName, ios_base::in | ios_base::out | ios_base::ate);
843     CPPUNIT_CHECK( nullStream );
844   }
845 
846   {
847     fstream nullStream(nullStreamName, ios_base::in | ios_base::out | ios_base::trunc);
848     CPPUNIT_CHECK( nullStream );
849   }
850 }
851 
852 void FstreamTest::null_buf()
853 {
854   /* **********************************************************************************
855 
856   testcase for bug #1830513:
857   in _istream.c
858 
859   template < class _CharT, class _Traits, class _Is_Delim>
860   streamsize _STLP_CALL __read_unbuffered(basic_istream<_CharT, _Traits>* __that,
861                                           basic_streambuf<_CharT, _Traits>* __buf,
862                                           streamsize _Num, _CharT* __s,
863                                           _Is_Delim __is_delim,
864                                           bool __extract_delim, bool __append_null,
865                                           bool __is_getline)
866 
867   can't accept _Num == 0; this is legal case, and may happen from
868 
869   template <class _CharT, class _Traits>
870   basic_istream<_CharT, _Traits>&
871   basic_istream<_CharT, _Traits>::getline(_CharT* __s, streamsize __n, _CharT __delim)
872 
873   *********************************************************************************** */
874 
875   fstream f( "test.txt", ios_base::in | ios_base::out | ios_base::trunc );
876   // string line;
877 
878   for ( int i = 0; i < 0x200; ++i ) {
879     f.put( ' ' );
880   }
881 
882   // const streambuf *b = f.rdbuf();
883 
884   // string s;
885   char buf[1024];
886   buf[0] = 'a';
887   buf[1] = 'b';
888   buf[2] = 'c';
889 
890   // getline( f, s );
891   // cerr << f.good() << endl;
892   f.seekg( 0, ios_base::beg );
893   // f.seekg( 0, ios_base::end );
894   // buf[0] = f.get();
895 
896   // cerr << (void *)(b->_M_gptr()) << " " << (void *)(b->_M_egptr()) << endl;
897   // cerr << f.good() << endl;
898   // getline( f, s );
899   f.getline( buf, 1 ); // <-- key line
900   CPPUNIT_CHECK( buf[0] == 0 );
901   CPPUNIT_CHECK( f.fail() ); // due to delimiter not found while buffer was exhausted
902 }
903 
904 #  if !defined (STLPORT) || !defined (_STLP_WIN32)
905 void FstreamTest::offset()
906 {
907 #    if (defined(_LARGEFILE_SOURCE) || defined(_LARGEFILE64_SOURCE)) && !defined(_STLP_USE_DEFAULT_FILE_OFFSET)
908   CPPUNIT_CHECK( sizeof(streamoff) == 8 );
909 #    else
910   CPPUNIT_CHECK( sizeof(streamoff) == sizeof(off_t) );
911 #    endif
912 }
913 #  endif
914 
915 #endif
916