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)
16using 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//
35class 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
91CPPUNIT_TEST_SUITE_REGISTRATION(FstreamTest);
92
93//
94// tests implementation
95//
96void 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
105void 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
144void 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
155void 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
190void 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
210void 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
274void 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
344void 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
371void 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
491void 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
508void 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
573void 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)
603struct my_state {
604  char dummy;
605};
606
607struct 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:
615namespace 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)
671template <>
672locale::id codecvt<char, char, my_state>::id;
673#    endif
674#  endif
675#endif
676
677void 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)
723void 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
798void 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
852void 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)
905void 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