Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

fstream.tcc

Go to the documentation of this file.
00001 // File based streams -*- C++ -*-
00002 
00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
00004 //
00005 // This file is part of the GNU ISO C++ Library.  This library is free
00006 // software; you can redistribute it and/or modify it under the
00007 // terms of the GNU General Public License as published by the
00008 // Free Software Foundation; either version 2, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // GNU General Public License for more details.
00015 
00016 // You should have received a copy of the GNU General Public License along
00017 // with this library; see the file COPYING.  If not, write to the Free
00018 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00019 // USA.
00020 
00021 // As a special exception, you may use this file as part of a free software
00022 // library without restriction.  Specifically, if other files instantiate
00023 // templates or use macros or inline functions from this file, or you compile
00024 // this file and link it with other files to produce an executable, this
00025 // file does not by itself cause the resulting executable to be covered by
00026 // the GNU General Public License.  This exception does not however
00027 // invalidate any other reasons why the executable file might be covered by
00028 // the GNU General Public License.
00029 
00030 //
00031 // ISO C++ 14882: 27.8  File-based streams
00032 //
00033 
00034 #ifndef _CPP_BITS_FSTREAM_TCC
00035 #define _CPP_BITS_FSTREAM_TCC 1
00036 
00037 namespace std
00038 {
00039   template<typename _CharT, typename _Traits>
00040     void
00041     basic_filebuf<_CharT, _Traits>::
00042     _M_filebuf_init()
00043     {
00044       if (!_M_file)
00045     {
00046       _M_buf_unified = true; // Tie input to output for basic_filebuf.
00047       try 
00048         { _M_file = new __file_type(&_M_lock); }
00049       catch(...) 
00050         {
00051           delete _M_file;
00052           __throw_exception_again;
00053         }
00054     }
00055     }
00056 
00057   template<typename _CharT, typename _Traits>
00058     void
00059     basic_filebuf<_CharT, _Traits>::
00060     _M_allocate_buffers()
00061     {
00062       if (!_M_buf)
00063     {
00064       _M_buf_size = _M_buf_size_opt;
00065       // Allocate internal buffer.
00066       try { _M_buf = new char_type[_M_buf_size]; }
00067       catch(...) 
00068         {
00069           delete [] _M_buf;
00070           __throw_exception_again;
00071         }
00072       
00073       // Allocate pback buffer.
00074       try 
00075         { _M_pback = new char_type[_M_pback_size]; }
00076       catch(...) 
00077         {
00078           delete [] _M_pback;
00079           __throw_exception_again;
00080         }
00081     }
00082     }
00083 
00084   template<typename _CharT, typename _Traits>
00085     basic_filebuf<_CharT, _Traits>::
00086     basic_filebuf() 
00087     : __streambuf_type(), _M_file(NULL), _M_state_cur(__state_type()), 
00088     _M_state_beg(__state_type()), _M_last_overflowed(false)
00089     { }
00090 
00091   template<typename _CharT, typename _Traits>
00092     basic_filebuf<_CharT, _Traits>::
00093     basic_filebuf(__c_file_type* __f, bool __s, ios_base::openmode __mode)
00094     : __streambuf_type(),  _M_file(NULL), _M_state_cur(__state_type()), 
00095     _M_state_beg(__state_type()), _M_last_overflowed(false)
00096     {
00097       _M_filebuf_init();
00098       _M_file->sys_open(__f, __mode);
00099       if (this->is_open())
00100     {
00101       _M_mode = __mode;
00102       if (!__s)
00103         {
00104           _M_allocate_buffers();
00105           _M_set_indeterminate();
00106         }
00107     }
00108     }
00109 
00110   template<typename _CharT, typename _Traits>
00111     basic_filebuf<_CharT, _Traits>::__filebuf_type* 
00112     basic_filebuf<_CharT, _Traits>::
00113     open(const char* __s, ios_base::openmode __mode)
00114     {
00115       __filebuf_type *__ret = NULL;
00116       if (!this->is_open())
00117     {
00118       _M_filebuf_init();
00119       _M_file->open(__s, __mode);
00120       if (this->is_open())
00121         {
00122           _M_allocate_buffers();
00123           _M_mode = __mode;
00124           
00125           // For time being, set both (in/out) sets  of pointers.
00126           _M_set_indeterminate();
00127           if (__mode & ios_base::ate
00128           && this->seekoff(0, ios_base::end, __mode) < 0)
00129         this->close();
00130           __ret = this;
00131         }
00132     }
00133       return __ret;
00134     }
00135 
00136   template<typename _CharT, typename _Traits>
00137     basic_filebuf<_CharT, _Traits>::__filebuf_type* 
00138     basic_filebuf<_CharT, _Traits>::
00139     close()
00140     {
00141       __filebuf_type *__ret = NULL;
00142       if (this->is_open())
00143     {
00144       bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
00145       if (__testput)
00146         _M_really_overflow(traits_type::eof());
00147 
00148       // NB: Do this here so that re-opened filebufs will be cool...
00149       _M_pback_destroy();
00150 
00151 #if 0
00152       // XXX not done
00153       if (_M_last_overflowed)
00154         {
00155           _M_output_unshift();
00156           _M_really_overflow(traits_type::eof());
00157         }
00158 #endif
00159 
00160       _M_mode = ios_base::openmode(0);
00161       if (_M_buf)
00162         {
00163           delete [] _M_buf;
00164           _M_buf = NULL;
00165           delete [] _M_pback;
00166           _M_pback = NULL;
00167           this->setg(NULL, NULL, NULL);
00168           this->setp(NULL, NULL);
00169         }
00170       __ret = this;
00171     }
00172 
00173       // Can actually allocate this file as part of an open and never
00174       // have it be opened.....
00175       if (_M_file)
00176     {
00177       delete _M_file;
00178       _M_file = NULL;
00179     }
00180       _M_last_overflowed = false;   
00181       return __ret;
00182     }
00183 
00184   template<typename _CharT, typename _Traits>
00185     streamsize 
00186     basic_filebuf<_CharT, _Traits>::
00187     showmanyc()
00188     {
00189       streamsize __ret = -1;
00190       bool __testin = _M_mode & ios_base::in;
00191 
00192       if (__testin)
00193     {
00194       bool __testeof = false;
00195       if (_M_in_cur >= _M_in_end)
00196         __testeof = this->underflow() == traits_type::eof();
00197       if (!__testeof)
00198         __ret = _M_in_end - _M_in_cur;
00199     }
00200       _M_last_overflowed = false;   
00201       return __ret;
00202     }
00203 
00204   template<typename _CharT, typename _Traits>
00205     basic_filebuf<_CharT, _Traits>::int_type 
00206     basic_filebuf<_CharT, _Traits>::
00207     underflow()
00208     {
00209       int_type __ret = traits_type::eof();
00210       bool __testin = _M_mode & ios_base::in;
00211       
00212       if (__testin)
00213     {
00214       // Check for pback madness, and if so swich back to the
00215       // normal buffers and jet outta here before expensive
00216       // fileops happen...
00217       if (_M_pback_init)
00218         {
00219           _M_pback_destroy();
00220           if (_M_in_cur < _M_in_end)
00221         return traits_type::to_int_type(*_M_in_cur);
00222         }
00223 
00224       bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
00225       bool __testinit = _M_is_indeterminate();
00226       bool __testout = _M_mode & ios_base::out;
00227 
00228       // Sync internal and external buffers.
00229       // NB: __testget -> __testput as _M_buf_unified here.
00230       if (__testget)
00231         {
00232           if (__testout)
00233         _M_really_overflow();
00234           else 
00235         _M_file->seekoff(_M_in_cur - _M_in_beg, 
00236                  ios_base::cur, ios_base::in);
00237         }
00238 
00239       if (__testinit || __testget)
00240         {
00241 #if 1
00242           streamsize __size = _M_file->xsgetn(_M_in_beg, _M_buf_size);
00243           if (0 < __size)
00244         {
00245           _M_set_determinate(__size);
00246           if (__testout)
00247             _M_out_cur = _M_in_cur;
00248           __ret = traits_type::to_int_type(*_M_in_cur);
00249           streamoff __p = _M_file->seekoff(0 - __size, ios_base::cur, 
00250                            ios_base::in);
00251           if (__p == -1)
00252             {
00253               // XXX Something is wrong, do error checking.
00254             }
00255         }
00256 #else
00257           // 2000-08-04 bkoz disable
00258           // Part one: (Re)fill external buf (_M_file->_IO_*) from
00259           // external byte sequence (whatever physical byte sink or
00260           // FILE actually is.)
00261           char_type* __conv_buf = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * _M_buf_size));
00262           streamsize __size = _M_file->xsgetn(__conv_buf, _M_buf_size);
00263           
00264           // Part two: (Re)fill internal buf contents from external buf.
00265           if (0 < __size)
00266         {
00267           _M_set_determinate(__size);
00268           
00269           char* __conv_cur = __conv_buf;
00270           _M_state_beg = _M_state_cur;
00271           __res_type __r = _M_fcvt->in(_M_state_cur, 
00272                            __conv_buf,
00273                            __conv_buf + __size,
00274                      const_cast<const char*&>(__conv_cur), 
00275                           _M_in_beg, _M_in_end, _M_in_cur);
00276           
00277           if (__r == codecvt_base::partial)
00278             {
00279               // XXX Retry with larger _M_buf size.
00280             }
00281           
00282           // Set pointers to internal and external buffers
00283           // correctly. . .
00284           if (__r != codecvt_base::error)
00285             {
00286               if (__testout)
00287             _M_out_cur = _M_in_cur;
00288               __ret = traits_type::to_int_type(*_M_in_cur);
00289             }
00290 
00291           // Part three: Sync the current internal buffer
00292           // position with the (now overshot) external buffer
00293           // position.  
00294           streamoff __p = _M_file->seekoff(0 - __size, ios_base::cur, 
00295                           ios_base::in);
00296           if (__p == -1)
00297             {
00298               // XXX Something is wrong, do error checking.
00299             }
00300         }
00301 #endif        
00302         }
00303     }
00304       _M_last_overflowed = false;   
00305       return __ret;
00306     }
00307   
00308   template<typename _CharT, typename _Traits>
00309     basic_filebuf<_CharT, _Traits>::int_type 
00310     basic_filebuf<_CharT, _Traits>::
00311     pbackfail(int_type __i)
00312     {
00313       int_type __ret = traits_type::eof();
00314       bool __testin = _M_mode & ios_base::in;
00315 
00316       if (__testin)
00317     {
00318       bool __testpb = _M_in_beg < _M_in_cur;
00319       char_type __c = traits_type::to_char_type(__i);
00320       bool __testeof = traits_type::eq_int_type(__i, __ret);
00321 
00322       if (__testpb)
00323         {
00324           bool __testout = _M_mode & ios_base::out;
00325           bool __testeq = traits_type::eq(__c, this->gptr()[-1]);
00326 
00327           // Try to put back __c into input sequence in one of three ways.
00328           // Order these tests done in is unspecified by the standard.
00329           if (!__testeof && __testeq)
00330         {
00331           --_M_in_cur;
00332           if (__testout)
00333             --_M_out_cur;
00334           __ret = __i;
00335         }
00336           else if (__testeof)
00337         {
00338           --_M_in_cur;
00339           if (__testout)
00340             --_M_out_cur;
00341           __ret = traits_type::not_eof(__i);
00342         }
00343           else if (!__testeof)
00344         {
00345           --_M_in_cur;
00346           if (__testout)
00347             --_M_out_cur;
00348           _M_pback_create();
00349           *_M_in_cur = __c; 
00350           __ret = __i;
00351         }
00352         }
00353       else
00354         {    
00355           // At the beginning of the buffer, need to make a
00356           // putback position available.
00357           this->seekoff(-1, ios_base::cur);
00358           this->underflow();
00359           if (!__testeof)
00360         {
00361           if (!traits_type::eq(__c, *_M_in_cur))
00362             {
00363               _M_pback_create();
00364               *_M_in_cur = __c;
00365             }
00366           __ret = __i;
00367         }
00368           else
00369         __ret = traits_type::not_eof(__i);
00370         }
00371     }
00372       _M_last_overflowed = false;   
00373       return __ret;
00374     }
00375 
00376   template<typename _CharT, typename _Traits>
00377     basic_filebuf<_CharT, _Traits>::int_type 
00378     basic_filebuf<_CharT, _Traits>::
00379     overflow(int_type __c)
00380     {
00381       int_type __ret = traits_type::eof();
00382       bool __testput = _M_out_cur && _M_out_cur < _M_buf + _M_buf_size;
00383       bool __testout = _M_mode & ios_base::out;
00384       
00385       if (__testout)
00386     {
00387       if (__testput)
00388         {
00389           *_M_out_cur = traits_type::to_char_type(__c);
00390           _M_out_cur_move(1);
00391           __ret = traits_type::not_eof(__c);
00392         }
00393       else 
00394         __ret = this->_M_really_overflow(__c);
00395     }
00396 
00397       _M_last_overflowed = false;    // Set in _M_really_overflow, below.
00398       return __ret;
00399     }
00400   
00401   template<typename _CharT, typename _Traits>
00402     basic_filebuf<_CharT, _Traits>::int_type 
00403     basic_filebuf<_CharT, _Traits>::
00404     _M_really_overflow(int_type __c)
00405     {
00406       int_type __ret = traits_type::eof();
00407       bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
00408       bool __testunbuffered = _M_file && !_M_buf_size;
00409 
00410       if (__testput || __testunbuffered)
00411     {
00412 #if 1
00413       int __plen = _M_out_end - _M_out_beg;
00414       streamsize __len = 0;
00415 
00416       if (__plen)
00417         __len = _M_file->xsputn(_M_out_beg, __plen);
00418 
00419       if (__c !=traits_type::eof())
00420         {
00421           char_type __pending = traits_type::to_char_type(__c);
00422           __len += _M_file->xsputn(&__pending, 1);
00423           ++__plen;
00424         }
00425 
00426       // NB: Need this so that external byte sequence reflects
00427       // internal buffer.
00428       _M_file->sync();
00429       if (__len == __plen)
00430         {
00431           _M_set_indeterminate();
00432           __ret = traits_type::not_eof(__c);
00433         }
00434 #else
00435       // Part one: Allocate temporary conversion buffer on
00436       // stack. Convert internal buffer plus __c (ie,
00437       // "pending sequence") to temporary conversion buffer.
00438       int __plen = _M_out_end - _M_out_beg;
00439       char_type* __pbuf = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __plen + 1));
00440       traits_type::copy(__pbuf, this->pbase(), __plen);
00441       if (!__testeof)
00442         {
00443           __pbuf[__plen] = traits_type::to_char_type(__c);
00444           ++__plen;
00445         }
00446 
00447       char_type* __pend;
00448       char* __conv_buf = static_cast<char*>(__builtin_alloca(__plen));
00449       char* __conv_end;
00450       _M_state_beg = _M_state_cur;
00451 
00452       __res_type __r = _M_fcvt->out(_M_state_cur, 
00453                     __pbuf, __pbuf + __plen,
00454                     const_cast<const char_type*&>(__pend),
00455                     __conv_buf, __conv_buf + __plen,
00456                     __conv_end);
00457       
00458       // Part two: (Re)spill converted "pending sequence"
00459       // contents (now in temporary conversion buffer) to
00460       // external buffer (_M_file->_IO_*) using
00461       // _M_file->sys_write(), and do error (minimal) checking.
00462       if (__r != codecvt_base::error)
00463         {
00464           streamsize __len = _M_file->xsputn(__conv_buf, __plen);
00465           // NB: Need this so that external byte sequence reflects
00466           // internal buffer.
00467           _M_file->sync();
00468           if (__len == __plen)
00469         {
00470           _M_set_indeterminate();
00471           __ret = traits_type::not_eof(__c);
00472         }
00473         }
00474 #endif
00475     }         
00476       _M_last_overflowed = true;    
00477       return __ret;
00478     }
00479 
00480   template<typename _CharT, typename _Traits>
00481     basic_filebuf<_CharT, _Traits>::pos_type
00482     basic_filebuf<_CharT, _Traits>::
00483     seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
00484     {
00485       pos_type __ret =  pos_type(off_type(-1)); 
00486       bool __testopen = this->is_open();
00487       bool __testin = __mode & ios_base::in && _M_mode & ios_base::in;
00488       bool __testout = __mode & ios_base::out && _M_mode & ios_base::out;
00489 
00490       // Should probably do has_facet checks here.
00491       int __width = use_facet<__codecvt_type>(_M_buf_locale).encoding();
00492       if (__width < 0)
00493     __width = 0;
00494       bool __testfail = __off != 0  && __width <= 0;
00495       
00496       if (__testopen && !__testfail && (__testin || __testout))
00497     {
00498       // Ditch any pback buffers to avoid confusion.
00499       _M_pback_destroy();
00500 
00501       if (__way != ios_base::cur || __off != 0)
00502         { 
00503           off_type __computed_off = __width * __off;
00504           
00505           bool __testget = _M_in_cur && _M_in_beg < _M_in_end;
00506           bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
00507           // Sync the internal and external streams.
00508           // out
00509           if (__testput || _M_last_overflowed)
00510         {
00511           // Part one: update the output sequence.
00512           this->sync();
00513           // Part two: output unshift sequence.
00514           _M_output_unshift();
00515         }
00516           //in
00517           // NB: underflow() rewinds the external buffer.
00518           else if (__testget && __way == ios_base::cur)
00519         __computed_off += _M_in_cur - _M_in_beg;
00520       
00521           __ret = _M_file->seekoff(__computed_off, __way, __mode);
00522           _M_set_indeterminate();
00523         }
00524       // NB: Need to do this in case _M_file in indeterminate
00525       // state, ie _M_file->_offset == -1
00526       else
00527         {
00528           __ret = _M_file->seekoff(__off, ios_base::cur, __mode);
00529           __ret += max(_M_out_cur, _M_in_cur) - _M_buf;
00530         }
00531     }
00532       _M_last_overflowed = false;   
00533       return __ret;
00534     }
00535 
00536   template<typename _CharT, typename _Traits>
00537     basic_filebuf<_CharT, _Traits>::pos_type
00538     basic_filebuf<_CharT, _Traits>::
00539     seekpos(pos_type __pos, ios_base::openmode __mode)
00540     {
00541       pos_type __ret;
00542       off_type __off = __pos;
00543 
00544       __ret = this->seekoff(__off, ios_base::beg, __mode); 
00545 
00546       _M_last_overflowed = false;   
00547       return __ret;
00548     }
00549 
00550   template<typename _CharT, typename _Traits>
00551     void 
00552     basic_filebuf<_CharT, _Traits>::
00553     _M_output_unshift()
00554     { }
00555 
00556   template<typename _CharT, typename _Traits>
00557     void
00558     basic_filebuf<_CharT, _Traits>::
00559     imbue(const locale& __loc)
00560     {
00561       bool __testbeg = gptr() == eback() && pptr() == pbase();
00562 
00563       if (__testbeg && _M_buf_locale != __loc)
00564     {
00565       _M_buf_locale = __loc;
00566       _M_buf_locale_init = true;
00567     }
00568 
00569       // NB this may require the reconversion of previously
00570       // converted chars. This in turn may cause the reconstruction
00571       // of the original file. YIKES!!
00572       // XXX The part in the above comment is not done.
00573       _M_last_overflowed = false;   
00574     }
00575   
00576 } // namespace std
00577 
00578 #endif // _CPP_BITS_FSTREAM_TCC
00579 
00580 

Generated at Tue May 1 16:28:37 2001 for libstdc++-v3 by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001