1
/* Copyright (C) 2004 Garrett A. Kajmowicz
3
This file is part of the uClibc++ Library.
4
This library is free software; you can redistribute it and/or
5
modify it under the terms of the GNU Lesser General Public
6
License as published by the Free Software Foundation; either
7
version 2.1 of the License, or (at your option) any later version.
9
This library is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
Lesser General Public License for more details.
14
You should have received a copy of the GNU Lesser General Public
15
License along with this library; if not, write to the Free Software
16
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
#ifndef __STD_HEADER_FSTREAM
20
#define __STD_HEADER_FSTREAM 1
23
#include<basic_definitions>
30
#include <char_traits>
36
#ifdef __UCLIBCXX_HAS_WCHAR__
39
#endif //__UCLIBCXX_HAS_WCHAR__
41
#pragma GCC visibility push(default)
45
template <class C, class T> class basic_filebuf;
47
typedef basic_filebuf<char> filebuf;
48
#ifdef __UCLIBCXX_HAS_WCHAR__
49
typedef basic_filebuf<wchar_t> wfilebuf;
53
template <class charT, class traits> class _UCXXEXPORT basic_filebuf
54
: public basic_streambuf<charT,traits>
56
#ifdef __UCLIBCXX_SUPPORT_CDIR__
57
friend ios_base::Init::Init(); //Needed for cout/cin stuff
60
// Types (inherited from basic_streambuf:
61
typedef typename basic_streambuf<charT, traits>::char_type char_type;
62
typedef typename basic_streambuf<charT, traits>::int_type int_type;
63
typedef typename basic_streambuf<charT, traits>::pos_type pos_type;
64
typedef typename basic_streambuf<charT, traits>::off_type off_type;
65
typedef traits traits_type;
67
//Constructors/destructor:
69
_UCXXEXPORT basic_filebuf() : basic_streambuf<charT, traits>(), fp(0), pbuffer(0), gbuffer(0)
72
pbuffer = new char_type[__UCLIBCXX_IOSTREAM_BUFSIZE__];
73
gbuffer = new char_type[__UCLIBCXX_IOSTREAM_BUFSIZE__];
75
setp(pbuffer, pbuffer + __UCLIBCXX_IOSTREAM_BUFSIZE__);
76
//Position get buffer so that there is no data available
77
setg(gbuffer, gbuffer + __UCLIBCXX_IOSTREAM_BUFSIZE__,
78
gbuffer + __UCLIBCXX_IOSTREAM_BUFSIZE__);
82
_UCXXEXPORT virtual ~basic_filebuf(){
94
_UCXXEXPORT bool is_open() const{
101
_UCXXEXPORT basic_filebuf<charT,traits>* open(const char* s, ios_base::openmode mode){
102
bool move_end = (mode & ios_base::ate) != 0;
103
if(is_open() !=false){ //Must call close() first
106
basic_streambuf<charT,traits>::openedFor = mode;
107
mode = mode & ~ios_base::ate;
109
if(mode == ios_base::out || mode == (ios_base::out | ios_base::trunc)){
111
}else if((mode & ios_base::app) && ! (mode & ios_base::trunc)){
112
if(mode & ios_base::binary){
113
if(mode & ios_base::in){
114
fp = fopen(s, "a+b");
119
if(mode & ios_base::in){
125
}else if(mode == ios_base::in){
127
}else if(mode == (ios_base::in | ios_base::out)){
129
}else if(mode == (ios_base::in | ios_base::out | ios_base::trunc)){
131
}else if(mode == (ios_base::binary | ios_base::out)){
133
}else if(mode == (ios_base::in | ios_base::binary)){
135
}else if(mode == (ios_base::in | ios_base::binary | ios_base::out)){
136
fp = fopen(s, "r+b");
137
}else if(mode==(ios_base::binary | ios_base::out | ios_base::trunc)){
138
fp = fopen(s, "w+b");
139
}else if(mode == (ios_base::in | ios_base::binary | ios_base::out | ios_base::trunc)){
140
fp = fopen(s, "w+b");
153
//Check to make sure the stream is good
154
if(move_end == true){
155
retval = fseek(fp, 0, SEEK_END);
157
retval = fseek(fp, 0, SEEK_SET);
159
if(retval!=0){ //Seek error
165
basic_streambuf<charT,traits>::mgnext = basic_streambuf<charT,traits>::mgend;
169
_UCXXEXPORT basic_filebuf<charT,traits>* close(){
170
if(fp != 0 && fp != stdin && fp != stdout && fp !=stderr ){
173
int retval = fclose(fp);
174
if(retval !=0){ //Error of some sort
182
_UCXXEXPORT basic_filebuf(const basic_filebuf<charT,traits> &){ }
183
_UCXXEXPORT basic_filebuf<charT,traits> & operator=(const basic_filebuf<charT,traits> &){ return *this; }
185
//Overridden virtual functions:
187
virtual _UCXXEXPORT int showmanyc(){
188
return basic_streambuf<charT,traits>::egptr() - basic_streambuf<charT,traits>::gptr();
190
virtual _UCXXEXPORT int_type underflow(){
191
/* Some variables used internally:
197
eback() returns mgbeg
198
gptr() returns mgnext
199
egptr() returns mgend
201
gbump(int n) mgnext+=n
206
return traits::eof();
209
if(basic_streambuf<charT,traits>::eback() == 0){
213
retval = fread(&c, sizeof(charT), 1, fp);
215
if(retval == 0 || feof(fp) || ferror(fp) ){
216
return traits::eof();
218
return traits::to_int_type(c);
221
if(basic_streambuf<charT,traits>::eback() == basic_streambuf<charT,traits>::gptr()){ //Buffer is full
222
return traits::to_int_type(*basic_streambuf<charT,traits>::gptr());
224
//Shift entire buffer back to the begining
225
size_t offset = basic_streambuf<charT,traits>::gptr() - basic_streambuf<charT,traits>::eback();
226
size_t amountData = basic_streambuf<charT,traits>::egptr() - basic_streambuf<charT,traits>::gptr();
228
for(charT * i = basic_streambuf<charT,traits>::gptr(); i < basic_streambuf<charT,traits>::egptr(); ++i){
233
//Save operating flags from file descriptor
234
int fcntl_flags = fcntl(fileno(fp), F_GETFL);
237
//Set to non_blocking mode
238
fcntl(fileno(fp), F_SETFL, fcntl_flags | O_NONBLOCK);
240
//Fill rest of buffer
241
retval = fread(basic_streambuf<charT,traits>::egptr() -
242
basic_streambuf<charT,traits>::gptr() + basic_streambuf<charT,traits>::eback(),
248
//Clear problems where we didn't read in enough characters
253
//Restore file descriptor clase
254
fcntl(fileno(fp), F_SETFL, fcntl_flags);
256
//Now we are going to make sure that we read in at least one character. The hard way.
258
fcntl_flags = fcntl(fileno(fp), F_GETFL);
259
//Set to blocking mode
260
fcntl(fileno(fp), F_SETFL, fcntl_flags & ~O_NONBLOCK);
262
retval = fread(basic_streambuf<charT,traits>::egptr() -
263
basic_streambuf<charT,traits>::gptr() + basic_streambuf<charT,traits>::eback(),
269
//Restore file descriptor clase
270
fcntl(fileno(fp), F_SETFL, fcntl_flags);
274
if(retval !=offset){ //Slide buffer forward again
275
for(size_t i = 0; i < amountData + retval; ++i){
276
*(basic_streambuf<charT,traits>::egptr() - i - 1) =
277
*(basic_streambuf<charT,traits>::eback() + amountData + retval - i - 1);
281
basic_streambuf<charT,traits>::mgnext -= retval;
283
if( (retval <= 0 && feof(fp)) || ferror(fp) ){
284
return traits::eof();
287
return traits::to_int_type(*basic_streambuf<charT,traits>::gptr());
289
virtual _UCXXEXPORT int_type uflow(){
290
bool dobump = (basic_streambuf<charT,traits>::gptr() != 0);
291
int_type retval = underflow();
293
basic_streambuf<charT,traits>::gbump(1);
297
virtual _UCXXEXPORT int_type pbackfail(int_type c = traits::eof()){
298
if(is_open() == false ||
299
basic_streambuf<charT,traits>::gptr() == basic_streambuf<charT,traits>::eback())
301
return traits::eof();
303
if(traits::eq_int_type(c,traits::eof()) == false){
304
if(traits::eq(traits::to_char_type(c), basic_streambuf<charT,traits>::gptr()[-1]) == true){
305
basic_streambuf<charT,traits>::gbump(-1);
307
basic_streambuf<charT,traits>::gbump(-1);
308
basic_streambuf<charT,traits>::gptr()[0] = c;
312
basic_streambuf<charT,traits>::gbump(-1);
313
return traits::not_eof(c);
317
virtual _UCXXEXPORT int_type overflow(int_type c = traits::eof()){
318
if(is_open() == false){
320
return traits::eof();
322
if(basic_streambuf<charT,traits>::pbase() == 0){ //Unbuffered - elliminate dupe code below
323
if(fputc(c, fp) == EOF){
324
return traits::eof();
328
if(basic_streambuf<charT,traits>::pbase() == 0 && traits::eq_int_type(c,traits::eof()) ){
330
return traits::not_eof(c);
332
size_t r = basic_streambuf<charT,traits>::pptr() - basic_streambuf<charT,traits>::pbase();
334
if( r == 0 && traits::eq_int_type(c,traits::eof()) ){
335
return traits::not_eof(c);
337
if(fputc(c, fp) == EOF){
338
return traits::eof();
343
size_t totalChars = r;
345
char_type *buffer = 0;
346
if(traits::eq_int_type(c,traits::eof())){
347
buffer = new char_type[r];
349
buffer = new char_type[r+1];
354
traits::copy(buffer, basic_streambuf<charT,traits>::pbase(), r);
355
// memcpy(buffer, basic_streambuf<charT,traits>::pbase(), r);
357
size_t retval = fwrite(buffer, sizeof(charT), totalChars, fp);
358
if(retval !=totalChars){
361
return traits::eof();
363
basic_streambuf<charT,traits>::pbump(-retval);
364
fprintf(stderr, "***** Did not write the full buffer out. Should be: %d, actually: %d\n",
367
basic_streambuf<charT,traits>::pbump(-r);
371
return traits::not_eof(c);
374
virtual _UCXXEXPORT basic_streambuf<charT,traits>* setbuf(char_type* s, streamsize n){
375
if(s == 0 && n == 0){ //Unbuffered
384
}else if(basic_streambuf<charT,traits>::gptr() !=0 &&
385
basic_streambuf<charT,traits>::gptr()==basic_streambuf<charT,traits>::egptr())
392
virtual _UCXXEXPORT pos_type seekoff(off_type off, ios_base::seekdir way,
393
ios_base::openmode = ios_base::in | ios_base::out)
395
if(is_open() == false){
398
int whence = SEEK_SET; // if(way == basic_ios<charT>::beg)
399
off_type position = off;
401
if(way == basic_ios<charT>::cur){
403
position -= (basic_streambuf<charT,traits>::egptr() - basic_streambuf<charT,traits>::gptr());
404
}else if(way == basic_ios<charT>::end){
412
sizeof(charT)*(position),
416
//Invalidate read buffer
417
basic_streambuf<charT,traits>::gbump(
418
basic_streambuf<charT,traits>::egptr() - basic_streambuf<charT,traits>::gptr()
427
virtual _UCXXEXPORT pos_type seekpos(pos_type sp, ios_base::openmode = ios_base::in | ios_base::out){
428
if(is_open() == false){
433
int retval = fseek(fp,sizeof(charT)* sp, SEEK_SET);
435
//Invalidate read buffer
436
basic_streambuf<charT,traits>::gbump(basic_streambuf<charT,traits>::egptr() - basic_streambuf<charT,traits>::gptr());
442
virtual _UCXXEXPORT int sync(){
444
if(overflow() == traits::eof()){
448
if(0 != fp && 0 != fflush(fp)){
453
virtual _UCXXEXPORT void imbue(const locale&){
458
virtual _UCXXEXPORT streamsize xsputn(const char_type* s, streamsize n){
459
if(is_open() == false){
462
//Check to see if buffered
464
//Check to see if we can buffer the data
465
streamsize buffer_avail = basic_streambuf<charT,traits>::epptr() - basic_streambuf<charT,traits>::pptr();
467
if(n > buffer_avail){ //Flush buffer and write directly
468
overflow(); //Flush the buffer
469
return fwrite(s, sizeof(charT), n, fp);
472
//Add to buffer to be written later
474
traits::copy(basic_streambuf<charT,traits>::pptr(), s, n);
475
basic_streambuf<charT,traits>::pbump(n);
487
#ifdef __UCLIBCXX_HAS_WCHAR__
489
template <> _UCXXEXPORT basic_filebuf<wchar_t, char_traits<wchar_t> >::int_type
490
basic_filebuf<wchar_t, char_traits<wchar_t> >::overflow(int_type c);
492
template <> _UCXXEXPORT basic_filebuf<wchar_t, char_traits<wchar_t> >::int_type
493
basic_filebuf<wchar_t, char_traits<wchar_t> >::underflow();
495
#endif //__UCLIBCXX_HAS_WCHAR__
499
#ifdef __UCLIBCXX_EXPAND_FSTREAM_CHAR__
500
#ifndef __UCLIBCXX_COMPILE_FSTREAM__
502
#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__
504
template <> _UCXXEXPORT filebuf::basic_filebuf();
505
template <> _UCXXEXPORT filebuf::~basic_filebuf();
507
#endif // __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__
509
template <> _UCXXEXPORT filebuf::int_type filebuf::pbackfail(filebuf::int_type c);
510
template <> _UCXXEXPORT filebuf * filebuf::open(const char* s, ios_base::openmode mode);
511
template <> _UCXXEXPORT filebuf * filebuf::close();
512
template <> _UCXXEXPORT filebuf::int_type filebuf::overflow(filebuf::int_type c);
513
template <> _UCXXEXPORT filebuf::int_type filebuf::underflow ();
515
template <> _UCXXEXPORT basic_streambuf<char, char_traits<char> > * filebuf::setbuf(char * s, streamsize n);
516
template <> _UCXXEXPORT streamsize filebuf::xsputn(const char* s, streamsize n);
522
template <class charT, class traits> class _UCXXEXPORT basic_ifstream
523
: public basic_istream<charT,traits>
526
typedef charT char_type;
527
typedef typename traits::int_type int_type;
528
typedef typename traits::pos_type pos_type;
529
typedef typename traits::off_type off_type;
531
_UCXXEXPORT basic_ifstream(): basic_ios<charT, traits>(&sb), basic_istream<charT,traits>(&sb){
532
//Passing the address of sb
534
explicit _UCXXEXPORT basic_ifstream(const char* s, ios_base::openmode mode = ios_base::in)
535
: basic_ios<charT, traits>(&sb), basic_istream<charT,traits>(&sb)
537
if(sb.open(s, mode) == 0){
538
basic_ios<charT,traits>::setstate(ios_base::failbit);
542
virtual _UCXXEXPORT ~basic_ifstream(){
546
_UCXXEXPORT basic_filebuf<charT,traits>* rdbuf() const{
547
return (basic_filebuf<charT,traits>*)&sb;
549
_UCXXEXPORT bool is_open() const{
552
_UCXXEXPORT void open(const char* s, ios_base::openmode mode = ios_base::in){
553
if(sb.open(s, mode) == 0){
554
basic_ios<charT,traits>::setstate(ios_base::failbit);
557
_UCXXEXPORT void close(){
561
basic_filebuf<charT,traits> sb;
565
template <class charT, class traits> class _UCXXEXPORT basic_ofstream
566
: public basic_ostream<charT,traits>
569
typedef charT char_type;
570
typedef typename traits::int_type int_type;
571
typedef typename traits::pos_type pos_type;
572
typedef typename traits::off_type off_type;
574
_UCXXEXPORT basic_ofstream() : basic_ios<charT, traits>(&sb), basic_ostream<charT,traits>(&sb){
578
virtual _UCXXEXPORT ~basic_ofstream();
580
explicit _UCXXEXPORT basic_ofstream(const char* s, ios_base::openmode mode = ios_base::out | ios_base::trunc) :
581
basic_ios<charT, traits>(&sb), basic_ostream<charT,traits>(&sb)
583
if(sb.open(s, mode | ios_base::out ) == 0){
584
basic_ios<charT,traits>::setstate(ios_base::failbit);
588
_UCXXEXPORT basic_filebuf<charT,traits>* rdbuf() const{
589
return (basic_filebuf<charT,traits>*)&sb;
592
_UCXXEXPORT bool is_open() const{
595
_UCXXEXPORT void open(const char* s, ios_base::openmode mode = ios_base::out | ios_base::trunc){
596
if(sb.open(s, mode) == 0){
597
basic_ios<charT,traits>::setstate(ios_base::failbit);
600
_UCXXEXPORT void close(){
604
basic_filebuf<charT,traits> sb;
607
template <class charT, class traits> _UCXXEXPORT basic_ofstream<charT, traits>::~basic_ofstream(){
608
basic_ostream<charT, traits>::flush();
612
template <class charT, class traits> class _UCXXEXPORT basic_fstream
613
: public basic_iostream<charT,traits>
616
typedef charT char_type;
617
typedef typename traits::int_type ins_type;
618
typedef typename traits::pos_type pos_type;
619
typedef typename traits::off_type off_type;
621
_UCXXEXPORT basic_fstream(): basic_ios<charT, traits>(&sb), basic_iostream<charT,traits>(&sb){ }
623
explicit _UCXXEXPORT basic_fstream(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out):
624
basic_ios<charT, traits>(&sb), basic_iostream<charT,traits>(&sb)
626
if(sb.open(s, mode) == 0){
627
basic_ios<charT,traits>::setstate(ios_base::failbit);
631
_UCXXEXPORT basic_filebuf<charT,traits>* rdbuf() const{
632
return (basic_filebuf<charT,traits>*)&sb;
634
_UCXXEXPORT bool is_open() const{
637
_UCXXEXPORT void open(const char* s, ios_base::openmode mode = ios_base::in|ios_base::out){
638
if(sb.open(s, mode) == 0){
639
basic_ios<charT,traits>::setstate(ios_base::failbit);
642
_UCXXEXPORT void close(){
646
basic_filebuf<charT,traits> sb;
651
#ifdef __UCLIBCXX_EXPAND_FSTREAM_CHAR__
652
#ifndef __UCLIBCXX_COMPILE_FSTREAM__
654
#ifdef __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__
656
template <> _UCXXEXPORT basic_ofstream<char, char_traits<char> >::basic_ofstream();
657
template <> _UCXXEXPORT basic_ofstream<char, char_traits<char> >::basic_ofstream(const char* s, ios_base::openmode mode);
658
template <> _UCXXEXPORT basic_ofstream<char, char_traits<char> >::~basic_ofstream();
660
template <> _UCXXEXPORT basic_ifstream<char, char_traits<char> >::basic_ifstream();
661
template <> _UCXXEXPORT basic_ifstream<char, char_traits<char> >::basic_ifstream(const char* s, ios_base::openmode mode);
662
template <> _UCXXEXPORT basic_ifstream<char, char_traits<char> >::~basic_ifstream();
664
#endif // __UCLIBCXX_EXPAND_CONSTRUCTORS_DESTRUCTORS__
675
#pragma GCC visibility pop