# fstream.cc

    00001 // File based streams -*- C++ -*-
    00002
    00003 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
    00004 // Free Software Foundation, Inc.
    00005 //
    00006 // This file is part of the GNU ISO C++ Library.  This library is free
    00007 // software; you can redistribute it and/or modify it under the
    00008 // terms of the GNU General Public License as published by the
    00009 // Free Software Foundation; either version 2, or (at your option)
    00010 // any later version.
    00011
    00012 // This library is distributed in the hope that it will be useful,
    00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00015 // GNU General Public License for more details.
    00016
    00017 // You should have received a copy of the GNU General Public License along
    00018 // with this library; see the file COPYING.  If not, write to the Free
    00019 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
    00020 // USA.
    00021
    00022 // As a special exception, you may use this file as part of a free software
    00023 // library without restriction.  Specifically, if other files instantiate
    00024 // templates or use macros or inline functions from this file, or you compile
    00025 // this file and link it with other files to produce an executable, this
    00026 // file does not by itself cause the resulting executable to be covered by
    00027 // the GNU General Public License.  This exception does not however
    00028 // invalidate any other reasons why the executable file might be covered by
    00029 // the GNU General Public License.
    00030
    00031 //
    00032 // ISO C++ 14882: 27.8  File-based streams
    00033 //
    00034
    00035 #include <fstream>
    00036
    00037 namespace std
    00038 {
    00039   template<>
    00040     basic_filebuf<char>::int_type
    00041     basic_filebuf<char>::_M_underflow_common(bool __bump)
    00042     {
    00043       int_type __ret = traits_type::eof();
    00044       bool __testin = _M_mode & ios_base::in;
    00045       bool __testout = _M_mode & ios_base::out;
    00046
    00047       if (__testin)
    00048     {
    00049       // Check for pback madness, and if so swich back to the
    00050       // normal buffers and jet outta here before expensive
    00051       // fileops happen...
    00052       if (_M_pback_init)
    00053         _M_pback_destroy();
    00054
    00055       if (_M_in_cur && _M_in_cur < _M_in_end)
    00056         {
    00057           __ret = traits_type::to_int_type(*_M_in_cur);
    00058           if (__bump)
    00059         _M_in_cur_move(1);
    00060           return __ret;
    00061         }
    00062
    00063       // Sync internal and external buffers.
    00064       // NB: __testget -> __testput as _M_buf_unified here.
    00065       bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
    00066       bool __testinit = _M_is_indeterminate();
    00067       if (__testget)
    00068         {
    00069           if (__testout)
    00070         _M_really_overflow();
    00071           else if (_M_in_cur != _M_filepos)
    00072         _M_file.seekoff(_M_in_cur - _M_filepos,
    00073                 ios_base::cur, ios_base::in);
    00074         }
    00075
    00076       if (__testinit || __testget)
    00077         {
    00078           streamsize __elen = 0;
    00079           streamsize __ilen = 0;
    00080           __elen = _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg),
    00081                       _M_buf_size);
    00082           __ilen = __elen;
    00083
    00084           if (0 < __ilen)
    00085         {
    00086           _M_set_determinate(__ilen);
    00087           if (__testout)
    00088             _M_out_cur = _M_in_cur;
    00089           __ret = traits_type::to_int_type(*_M_in_cur);
    00090           if (__bump)
    00091             _M_in_cur_move(1);
    00092           else if (_M_buf_size == 1)
    00093             {
    00094               // If we are synced with stdio, we have to unget the
    00095               // character we just read so that the file pointer
    00096               // doesn't move.
    00097               _M_file.sys_ungetc(traits_type::to_int_type(*_M_in_cur));
    00098               _M_set_indeterminate();
    00099             }
    00100         }
    00101         }
    00102     }
    00103       _M_last_overflowed = false;
    00104       return __ret;
    00105     }
    00106
    00107 #ifdef _GLIBCPP_USE_WCHAR_T
    00108   template<>
    00109     basic_filebuf<wchar_t>::int_type
    00110     basic_filebuf<wchar_t>::_M_underflow_common(bool __bump)
    00111     {
    00112       int_type __ret = traits_type::eof();
    00113       bool __testin = _M_mode & ios_base::in;
    00114       bool __testout = _M_mode & ios_base::out;
    00115
    00116       if (__testin)
    00117     {
    00118       // Check for pback madness, and if so swich back to the
    00119       // normal buffers and jet outta here before expensive
    00120       // fileops happen...
    00121       if (_M_pback_init)
    00122         _M_pback_destroy();
    00123
    00124       if (_M_in_cur && _M_in_cur < _M_in_end)
    00125         {
    00126           __ret = traits_type::to_int_type(*_M_in_cur);
    00127           if (__bump)
    00128         _M_in_cur_move(1);
    00129           return __ret;
    00130         }
    00131
    00132       // Sync internal and external buffers.
    00133       // NB: __testget -> __testput as _M_buf_unified here.
    00134       bool __testget = _M_in_cur && _M_in_beg < _M_in_cur;
    00135       bool __testinit = _M_is_indeterminate();
    00136       if (__testget)
    00137         {
    00138           if (__testout)
    00139         _M_really_overflow();
    00140           else if (_M_in_cur != _M_filepos)
    00141         _M_file.seekoff(_M_in_cur - _M_filepos,
    00142                 ios_base::cur, ios_base::in);
    00143         }
    00144
    00145       if (__testinit || __testget)
    00146         {
    00147           const locale __loc = this->getloc();
    00148           const __codecvt_type& __cvt = use_facet<__codecvt_type>(__loc);
    00149
    00150           streamsize __elen = 0;
    00151           streamsize __ilen = 0;
    00152           if (__cvt.always_noconv())
    00153         {
    00154           __elen = _M_file.xsgetn(reinterpret_cast<char*>(_M_in_beg),
    00155                       _M_buf_size);
    00156           __ilen = __elen;
    00157         }
    00158           else
    00159         {
    00160           char* __buf = static_cast<char*>(__builtin_alloca(_M_buf_size));
    00161           __elen = _M_file.xsgetn(__buf, _M_buf_size);
    00162
    00163           const char* __eend;
    00164           char_type* __iend;
    00165           codecvt_base::result __r;
    00166           __r = __cvt.in(_M_state_cur, __buf,
    00167                  __buf + __elen, __eend, _M_in_beg,
    00168                  _M_in_beg + _M_buf_size, __iend);
    00169           if (__r == codecvt_base::ok)
    00170             __ilen = __iend - _M_in_beg;
    00171           else
    00172             {
    00173               // Unwind.
    00174               __ilen = 0;
    00175               _M_file.seekoff(-__elen, ios_base::cur, ios_base::in);
    00176             }
    00177         }
    00178
    00179           if (0 < __ilen)
    00180         {
    00181           _M_set_determinate(__ilen);
    00182           if (__testout)
    00183             _M_out_cur = _M_in_cur;
    00184           __ret = traits_type::to_int_type(*_M_in_cur);
    00185           if (__bump)
    00186             _M_in_cur_move(1);
    00187           else if (_M_buf_size == 1)
    00188             {
    00189               // If we are synced with stdio, we have to unget the
    00190               // character we just read so that the file pointer
    00191               // doesn't move.
    00192               _M_file.sys_ungetc(traits_type::to_int_type(*_M_in_cur));
    00193               _M_set_indeterminate();
    00194             }
    00195         }
    00196         }
    00197     }
    00198       _M_last_overflowed = false;
    00199       return __ret;
    00200     }
    00201 #endif
    00202 } // namespace std