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 //
output()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
input()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
input_char()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
io()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
err()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
tellg()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
tellp()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
buf()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
seek()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
rdbuf()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
streambuf_output()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
win32_file_format()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
codecvt(size_t __refs=0)624 explicit codecvt(size_t __refs = 0) : locale::facet(__refs) {}
out(state_type &,const intern_type * __from,const intern_type *,const intern_type * & __from_next,extern_type * __to,extern_type *,extern_type * & __to_next) const625 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
in(state_type &,const extern_type * __from,const extern_type *,const extern_type * & __from_next,intern_type * __to,intern_type *,intern_type * & __to_next) const634 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
unshift(state_type &,extern_type * __to,extern_type *,extern_type * & __to_next) const643 result unshift(state_type&,
644 extern_type* __to,
645 extern_type*,
646 extern_type*& __to_next) const
647 { __to_next = __to; return noconv; }
648
encoding() const649 int encoding() const throw()
650 { return 1; }
651
always_noconv() const652 bool always_noconv() const throw()
653 { return true; }
654
length(const state_type &,const extern_type * __from,const extern_type * __end,size_t __max) const655 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
max_length() const661 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
custom_facet()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)
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
null_stream()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
null_buf()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)
offset()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