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 Sat Apr 19 07:14:21 2003 for libstdc++-v3 Source by doxygen1.2.15