Whole document tree
    

Whole document tree

fstream.tcc Source File
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_allocate_file()
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_internal_buffer()
00061     {
00062       if (!_M_buf && _M_buf_size_opt)
00063     {
00064       _M_buf_size = _M_buf_size_opt;
00065 
00066       // Allocate internal buffer.
00067       try { _M_buf = new char_type[_M_buf_size]; }
00068       catch(...) 
00069         {
00070           delete [] _M_buf;
00071           __throw_exception_again;
00072         }
00073       _M_buf_allocated = true;
00074     }
00075     }
00076 
00077   // Both close and setbuf need to deallocate internal buffers, if it exists.
00078   template<typename _CharT, typename _Traits>
00079     void
00080     basic_filebuf<_CharT, _Traits>::
00081     _M_destroy_internal_buffer()
00082     {
00083       if (_M_buf_allocated)
00084     {
00085       delete [] _M_buf;
00086       _M_buf = NULL;
00087       _M_buf_allocated = false;
00088       this->setg(NULL, NULL, NULL);
00089       this->setp(NULL, NULL);
00090     }
00091     }
00092 
00093  template<typename _CharT, typename _Traits>
00094     void
00095     basic_filebuf<_CharT, _Traits>::
00096     _M_allocate_pback_buffer()
00097     {
00098       if (!_M_pback && _M_pback_size)
00099     {
00100       // Allocate pback buffer.
00101       try 
00102         { _M_pback = new char_type[_M_pback_size]; }
00103       catch(...) 
00104         {
00105           delete [] _M_pback;
00106           __throw_exception_again;
00107         }
00108     }
00109     }
00110 
00111   template<typename _CharT, typename _Traits>
00112     basic_filebuf<_CharT, _Traits>::
00113     basic_filebuf() 
00114     : __streambuf_type(), _M_file(NULL), _M_state_cur(__state_type()), 
00115     _M_state_beg(__state_type()), _M_buf_allocated(false), 
00116     _M_last_overflowed(false)
00117     { }
00118 
00119   template<typename _CharT, typename _Traits>
00120     basic_filebuf<_CharT, _Traits>::
00121     basic_filebuf(__c_file_type* __f, ios_base::openmode __mode, int_type __s)
00122     : __streambuf_type(),  _M_file(NULL), _M_state_cur(__state_type()), 
00123     _M_state_beg(__state_type()), _M_buf_allocated(false), 
00124     _M_last_overflowed(false)
00125     {
00126       _M_allocate_file();
00127       _M_file->sys_open(__f, __mode);
00128       if (this->is_open())
00129     {
00130       _M_mode = __mode;
00131       if (__s)
00132         {
00133           _M_buf_size_opt = __s;
00134           _M_allocate_internal_buffer();
00135           _M_set_indeterminate();
00136         }
00137       _M_allocate_pback_buffer();
00138     }
00139     }
00140 
00141   template<typename _CharT, typename _Traits>
00142     typename basic_filebuf<_CharT, _Traits>::__filebuf_type* 
00143     basic_filebuf<_CharT, _Traits>::
00144     open(const char* __s, ios_base::openmode __mode)
00145     {
00146       __filebuf_type *__ret = NULL;
00147       if (!this->is_open())
00148     {
00149       _M_allocate_file();
00150       _M_file->open(__s, __mode);
00151       if (this->is_open())
00152         {
00153           _M_allocate_internal_buffer();
00154           _M_allocate_pback_buffer();
00155           _M_mode = __mode;
00156           
00157           // For time being, set both (in/out) sets  of pointers.
00158           _M_set_indeterminate();
00159           if (__mode & ios_base::ate
00160           && this->seekoff(0, ios_base::end, __mode) < 0)
00161         this->close();
00162           __ret = this;
00163         }
00164     }
00165       return __ret;
00166     }
00167 
00168   template<typename _CharT, typename _Traits>
00169     typename basic_filebuf<_CharT, _Traits>::__filebuf_type* 
00170     basic_filebuf<_CharT, _Traits>::
00171     close()
00172     {
00173       __filebuf_type *__ret = NULL;
00174       if (this->is_open())
00175     {
00176       bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
00177       if (__testput)
00178         _M_really_overflow(traits_type::eof());
00179 
00180       // NB: Do this here so that re-opened filebufs will be cool...
00181       _M_pback_destroy();
00182 
00183 #if 0
00184       // XXX not done
00185       if (_M_last_overflowed)
00186         {
00187           _M_output_unshift();
00188           _M_really_overflow(traits_type::eof());
00189         }
00190 #endif
00191 
00192       _M_mode = ios_base::openmode(0);
00193       _M_destroy_internal_buffer();
00194 
00195       if (_M_pback)
00196         {
00197           delete [] _M_pback;
00198           _M_pback = NULL;
00199         }
00200       __ret = this;
00201     }
00202 
00203       // Can actually allocate this file as part of an open and never
00204       // have it be opened.....
00205       if (_M_file)
00206     {
00207       delete _M_file;
00208       _M_file = NULL;
00209     }
00210       _M_last_overflowed = false;   
00211       return __ret;
00212     }
00213 
00214   template<typename _CharT, typename _Traits>
00215     streamsize 
00216     basic_filebuf<_CharT, _Traits>::
00217     showmanyc()
00218     {
00219       streamsize __ret = -1;
00220       bool __testin = _M_mode & ios_base::in;
00221 
00222       if (__testin)
00223     {
00224       bool __testeof = false;
00225       if (_M_in_cur >= _M_in_end)
00226         __testeof = this->underflow() == traits_type::eof();
00227       if (!__testeof)
00228         __ret = _M_in_end - _M_in_cur;
00229     }
00230       _M_last_overflowed = false;   
00231       return __ret;
00232     }
00233 
00234   template<typename _CharT, typename _Traits>
00235     typename basic_filebuf<_CharT, _Traits>::int_type 
00236     basic_filebuf<_CharT, _Traits>::
00237     underflow()
00238     {
00239       int_type __ret = traits_type::eof();
00240       bool __testin = _M_mode & ios_base::in;
00241       bool __testout = _M_mode & ios_base::out;
00242 
00243       // XXX Should re-enable codecvt bits disabled after 2.90.8.
00244       if (__testin)
00245     {
00246       // Check for pback madness, and if so swich back to the
00247       // normal buffers and jet outta here before expensive
00248       // fileops happen...
00249       if (_M_pback_init)
00250         {
00251           _M_pback_destroy();
00252           if (_M_in_cur < _M_in_end)
00253         return traits_type::to_int_type(*_M_in_cur);
00254         }
00255 
00256       bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
00257       bool __testinit = _M_is_indeterminate();
00258       // Sync internal and external buffers.
00259       // NB: __testget -> __testput as _M_buf_unified here.
00260       if (__testget)
00261         {
00262           if (__testout)
00263         _M_really_overflow();
00264 #if _GLIBCPP_AVOID_FSEEK
00265           else if ((_M_in_cur - _M_in_beg) == 1)
00266         _M_file->sys_getc();
00267 #endif
00268           else 
00269         _M_file->seekoff(_M_in_cur - _M_in_beg, 
00270                  ios_base::cur, ios_base::in);
00271         }
00272 
00273       if (__testinit || __testget)
00274         {
00275           // Assume buffered case, need to refill internal buffers.
00276           streamsize __size = _M_file->xsgetn(_M_in_beg, _M_buf_size);
00277           if (0 < __size)
00278         {
00279           _M_set_determinate(__size);
00280           if (__testout)
00281             _M_out_cur = _M_in_cur;
00282           __ret = traits_type::to_int_type(*_M_in_cur);
00283 #if _GLIBCPP_AVOID_FSEEK
00284           if (__size == 1)
00285             _M_file->sys_ungetc(*_M_in_cur);
00286           else
00287             {
00288 #endif
00289           streamoff __p = _M_file->seekoff(0 - __size, ios_base::cur, 
00290                            ios_base::in);
00291           if (__p == -1)
00292             {
00293               // XXX Something is wrong, do error checking.
00294             }
00295 #if _GLIBCPP_AVOID_FSEEK
00296             }
00297 #endif
00298         }      
00299         }
00300     }
00301       _M_last_overflowed = false;   
00302       return __ret;
00303     }
00304   
00305   template<typename _CharT, typename _Traits>
00306     typename basic_filebuf<_CharT, _Traits>::int_type 
00307     basic_filebuf<_CharT, _Traits>::
00308     pbackfail(int_type __i)
00309     {
00310       int_type __ret = traits_type::eof();
00311       bool __testin = _M_mode & ios_base::in;
00312 
00313       if (__testin)
00314     {
00315       bool __testpb = _M_in_beg < _M_in_cur;
00316       char_type __c = traits_type::to_char_type(__i);
00317       bool __testeof = traits_type::eq_int_type(__i, __ret);
00318 
00319       if (__testpb)
00320         {
00321           bool __testout = _M_mode & ios_base::out;
00322           bool __testeq = traits_type::eq(__c, this->gptr()[-1]);
00323 
00324           // Try to put back __c into input sequence in one of three ways.
00325           // Order these tests done in is unspecified by the standard.
00326           if (!__testeof && __testeq)
00327         {
00328           --_M_in_cur;
00329           if (__testout)
00330             --_M_out_cur;
00331           __ret = __i;
00332         }
00333           else if (__testeof)
00334         {
00335           --_M_in_cur;
00336           if (__testout)
00337             --_M_out_cur;
00338           __ret = traits_type::not_eof(__i);
00339         }
00340           else if (!__testeof)
00341         {
00342           --_M_in_cur;
00343           if (__testout)
00344             --_M_out_cur;
00345           _M_pback_create();
00346           *_M_in_cur = __c; 
00347           __ret = __i;
00348         }
00349         }
00350       else
00351         {    
00352           // At the beginning of the buffer, need to make a
00353           // putback position available.
00354           this->seekoff(-1, ios_base::cur);
00355           this->underflow();
00356           if (!__testeof)
00357         {
00358           if (!traits_type::eq(__c, *_M_in_cur))
00359             {
00360               _M_pback_create();
00361               *_M_in_cur = __c;
00362             }
00363           __ret = __i;
00364         }
00365           else
00366         __ret = traits_type::not_eof(__i);
00367         }
00368     }
00369       _M_last_overflowed = false;   
00370       return __ret;
00371     }
00372 
00373   template<typename _CharT, typename _Traits>
00374     typename basic_filebuf<_CharT, _Traits>::int_type 
00375     basic_filebuf<_CharT, _Traits>::
00376     overflow(int_type __c)
00377     {
00378       int_type __ret = traits_type::eof();
00379       bool __testput = _M_out_cur && _M_out_cur < _M_buf + _M_buf_size;
00380       bool __testout = _M_mode & ios_base::out;
00381       
00382       if (__testout)
00383     {
00384       if (__testput)
00385         {
00386           *_M_out_cur = traits_type::to_char_type(__c);
00387           _M_out_cur_move(1);
00388           __ret = traits_type::not_eof(__c);
00389         }
00390       else 
00391         __ret = this->_M_really_overflow(__c);
00392     }
00393 
00394       _M_last_overflowed = false;    // Set in _M_really_overflow, below.
00395       return __ret;
00396     }
00397   
00398   template<typename _CharT, typename _Traits>
00399     typename basic_filebuf<_CharT, _Traits>::int_type 
00400     basic_filebuf<_CharT, _Traits>::
00401     _M_really_overflow(int_type __c)
00402     {
00403       int_type __ret = traits_type::eof();
00404       bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
00405       bool __testunbuffered = _M_file && !_M_buf_size;
00406 
00407       if (__testput || __testunbuffered)
00408     {
00409 #if 1
00410       int __plen = _M_out_end - _M_out_beg;
00411       streamsize __len = 0;
00412 
00413       if (__plen)
00414         __len = _M_file->xsputn(_M_out_beg, __plen);
00415 
00416       if (__c !=traits_type::eof())
00417         {
00418           char_type __pending = traits_type::to_char_type(__c);
00419           __len += _M_file->xsputn(&__pending, 1);
00420           ++__plen;
00421         }
00422 
00423       // NB: Need this so that external byte sequence reflects
00424       // internal buffer.
00425       _M_file->sync();
00426       if (__len == __plen)
00427         {
00428           _M_set_indeterminate();
00429           __ret = traits_type::not_eof(__c);
00430         }
00431 #else
00432       // Part one: Allocate temporary conversion buffer on
00433       // stack. Convert internal buffer plus __c (ie,
00434       // "pending sequence") to temporary conversion buffer.
00435       int __plen = _M_out_end - _M_out_beg;
00436       char_type* __pbuf = static_cast<char_type*>(__builtin_alloca(sizeof(char_type) * __plen + 1));
00437       traits_type::copy(__pbuf, this->pbase(), __plen);
00438       if (!__testeof)
00439         {
00440           __pbuf[__plen] = traits_type::to_char_type(__c);
00441           ++__plen;
00442         }
00443 
00444       char_type* __pend;
00445       char* __conv_buf = static_cast<char*>(__builtin_alloca(__plen));
00446       char* __conv_end;
00447       _M_state_beg = _M_state_cur;
00448 
00449       __res_type __r = _M_fcvt->out(_M_state_cur, 
00450                     __pbuf, __pbuf + __plen,
00451                     const_cast<const char_type*&>(__pend),
00452                     __conv_buf, __conv_buf + __plen,
00453                     __conv_end);
00454       
00455       // Part two: (Re)spill converted "pending sequence"
00456       // contents (now in temporary conversion buffer) to
00457       // external buffer (_M_file->_IO_*) using
00458       // _M_file->sys_write(), and do error (minimal) checking.
00459       if (__r != codecvt_base::error)
00460         {
00461           streamsize __len = _M_file->xsputn(__conv_buf, __plen);
00462           // NB: Need this so that external byte sequence reflects
00463           // internal buffer.
00464           _M_file->sync();
00465           if (__len == __plen)
00466         {
00467           _M_set_indeterminate();
00468           __ret = traits_type::not_eof(__c);
00469         }
00470         }
00471 #endif
00472     }         
00473       _M_last_overflowed = true;    
00474       return __ret;
00475     }
00476 
00477   template<typename _CharT, typename _Traits>
00478     typename basic_filebuf<_CharT, _Traits>::__streambuf_type* 
00479     basic_filebuf<_CharT, _Traits>::
00480     setbuf(char_type* __s, streamsize __n)
00481     {
00482       if (!this->is_open() && __s == 0 && __n == 0)
00483     _M_buf_size_opt = 0;
00484       else if (__s && __n)
00485     {
00486       // This is implementation-defined behavior, and assumes
00487       // that an external char_type array of length (__s + __n)
00488       // exists and has been pre-allocated. If this is not the
00489       // case, things will quickly blow up.
00490       // Step 1: Destroy the current internal array.
00491       _M_destroy_internal_buffer();
00492       
00493       // Step 2: Use the external array.
00494       _M_buf = __s;
00495       _M_buf_size_opt = _M_buf_size = __n;
00496       _M_set_indeterminate();
00497       
00498     // Step 3: Make sure a pback buffer is allocated.
00499       _M_allocate_pback_buffer();
00500     }
00501       _M_last_overflowed = false;   
00502       return this; 
00503     }
00504   
00505   template<typename _CharT, typename _Traits>
00506     typename basic_filebuf<_CharT, _Traits>::pos_type
00507     basic_filebuf<_CharT, _Traits>::
00508     seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode)
00509     {
00510       pos_type __ret =  pos_type(off_type(-1)); 
00511       bool __testopen = this->is_open();
00512       bool __testin = __mode & ios_base::in && _M_mode & ios_base::in;
00513       bool __testout = __mode & ios_base::out && _M_mode & ios_base::out;
00514 
00515       // Should probably do has_facet checks here.
00516       int __width = use_facet<__codecvt_type>(_M_buf_locale).encoding();
00517       if (__width < 0)
00518     __width = 0;
00519       bool __testfail = __off != 0  && __width <= 0;
00520       
00521       if (__testopen && !__testfail && (__testin || __testout))
00522     {
00523       // Ditch any pback buffers to avoid confusion.
00524       _M_pback_destroy();
00525 
00526       if (__way != ios_base::cur || __off != 0)
00527         { 
00528           off_type __computed_off = __width * __off;
00529           
00530           bool __testget = _M_in_cur && _M_in_beg < _M_in_end;
00531           bool __testput = _M_out_cur && _M_out_beg < _M_out_end;
00532           // Sync the internal and external streams.
00533           // out
00534           if (__testput || _M_last_overflowed)
00535         {
00536           // Part one: update the output sequence.
00537           this->sync();
00538           // Part two: output unshift sequence.
00539           _M_output_unshift();
00540         }
00541           //in
00542           // NB: underflow() rewinds the external buffer.
00543           else if (__testget && __way == ios_base::cur)
00544         __computed_off += _M_in_cur - _M_in_beg;
00545       
00546           __ret = _M_file->seekoff(__computed_off, __way, __mode);
00547           _M_set_indeterminate();
00548         }
00549       // NB: Need to do this in case _M_file in indeterminate
00550       // state, ie _M_file->_offset == -1
00551       else
00552         {
00553           __ret = _M_file->seekoff(__off, ios_base::cur, __mode);
00554           __ret += max(_M_out_cur, _M_in_cur) - _M_buf;
00555         }
00556     }
00557       _M_last_overflowed = false;   
00558       return __ret;
00559     }
00560 
00561   template<typename _CharT, typename _Traits>
00562     typename basic_filebuf<_CharT, _Traits>::pos_type
00563     basic_filebuf<_CharT, _Traits>::
00564     seekpos(pos_type __pos, ios_base::openmode __mode)
00565     {
00566       pos_type __ret;
00567       off_type __off = __pos;
00568 
00569       __ret = this->seekoff(__off, ios_base::beg, __mode); 
00570 
00571       _M_last_overflowed = false;   
00572       return __ret;
00573     }
00574 
00575   template<typename _CharT, typename _Traits>
00576     void 
00577     basic_filebuf<_CharT, _Traits>::
00578     _M_output_unshift()
00579     { }
00580 
00581   template<typename _CharT, typename _Traits>
00582     void
00583     basic_filebuf<_CharT, _Traits>::
00584     imbue(const locale& __loc)
00585     {
00586       bool __testbeg = gptr() == eback() && pptr() == pbase();
00587 
00588       if (__testbeg && _M_buf_locale != __loc)
00589     {
00590       _M_buf_locale = __loc;
00591       _M_buf_locale_init = true;
00592     }
00593 
00594       // NB this may require the reconversion of previously
00595       // converted chars. This in turn may cause the reconstruction
00596       // of the original file. YIKES!!
00597       // XXX The part in the above comment is not done.
00598       _M_last_overflowed = false;   
00599     }
00600   
00601 } // namespace std
00602 
00603 #endif // _CPP_BITS_FSTREAM_TCC
00604 
00605 

Generated on Mon Apr 8 03:11:25 2002 for libstdc++-v3 Source by doxygen1.2.15