# streambuf.tcc

    00001 // Stream buffer classes -*- 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.5  Stream buffers
    00033 //
    00034
    00035 #ifndef _CPP_BITS_STREAMBUF_TCC
    00036 #define _CPP_BITS_STREAMBUF_TCC 1
    00037
    00038 #pragma GCC system_header
    00039
    00040 namespace std
    00041 {
    00042   template<typename _CharT, typename _Traits>
    00043     const size_t
    00044     basic_streambuf<_CharT, _Traits>::_S_pback_size;
    00045
    00046   template<typename _CharT, typename _Traits>
    00047     typename basic_streambuf<_CharT, _Traits>::int_type
    00048     basic_streambuf<_CharT, _Traits>::
    00049     sbumpc()
    00050     {
    00051       int_type __ret;
    00052       if (_M_in_cur && _M_in_cur < _M_in_end)
    00053     {
    00054       char_type __c = *(this->gptr());
    00055       _M_in_cur_move(1);
    00056       __ret = traits_type::to_int_type(__c);
    00057     }
    00058       else
    00059     __ret = this->uflow();
    00060       return __ret;
    00061     }
    00062
    00063   template<typename _CharT, typename _Traits>
    00064     typename basic_streambuf<_CharT, _Traits>::int_type
    00065     basic_streambuf<_CharT, _Traits>::
    00066     sputbackc(char_type __c)
    00067     {
    00068       int_type __ret;
    00069       bool __testpos = _M_in_cur && _M_in_beg < _M_in_cur;
    00070       if (!__testpos || !traits_type::eq(__c, this->gptr()[-1]))
    00071     __ret = this->pbackfail(traits_type::to_int_type(__c));
    00072       else
    00073     {
    00074       _M_in_cur_move(-1);
    00075       __ret = traits_type::to_int_type(*this->gptr());
    00076     }
    00077       return __ret;
    00078     }
    00079
    00080   template<typename _CharT, typename _Traits>
    00081     typename basic_streambuf<_CharT, _Traits>::int_type
    00082     basic_streambuf<_CharT, _Traits>::
    00083     sungetc()
    00084     {
    00085       int_type __ret;
    00086       if (_M_in_cur && _M_in_beg < _M_in_cur)
    00087     {
    00088       _M_in_cur_move(-1);
    00089       __ret = traits_type::to_int_type(*_M_in_cur);
    00090     }
    00091       else
    00092     __ret = this->pbackfail();
    00093       return __ret;
    00094     }
    00095
    00096   // Don't test against _M_buf + _M_buf_size, because _M_buf reflects
    00097   // allocated space, and on certain (rare but entirely legal)
    00098   // situations, there will be no allocated space yet the internal
    00099   // buffers will still be valid. (This happens if setp is used to set
    00100   // the internal buffer to say some externally-allocated sequence.)
    00101   template<typename _CharT, typename _Traits>
    00102     typename basic_streambuf<_CharT, _Traits>::int_type
    00103     basic_streambuf<_CharT, _Traits>::
    00104     sputc(char_type __c)
    00105     {
    00106       int_type __ret;
    00107       if (_M_out_buf_size())
    00108     {
    00109       *_M_out_cur = __c;
    00110       _M_out_cur_move(1);
    00111       __ret = traits_type::to_int_type(__c);
    00112     }
    00113       else
    00114     __ret = this->overflow(traits_type::to_int_type(__c));
    00115       return __ret;
    00116     }
    00117
    00118   template<typename _CharT, typename _Traits>
    00119     streamsize
    00120     basic_streambuf<_CharT, _Traits>::
    00121     xsgetn(char_type* __s, streamsize __n)
    00122     {
    00123       streamsize __ret = 0;
    00124       while (__ret < __n)
    00125     {
    00126       size_t __buf_len = _M_in_end - _M_in_cur;
    00127       if (__buf_len > 0)
    00128         {
    00129           size_t __remaining = __n - __ret;
    00130           size_t __len = min(__buf_len, __remaining);
    00131           traits_type::copy(__s, _M_in_cur, __len);
    00132           __ret += __len;
    00133           __s += __len;
    00134           _M_in_cur_move(__len);
    00135         }
    00136
    00137       if (__ret < __n)
    00138         {
    00139           int_type __c = this->uflow();
    00140           if (!traits_type::eq_int_type(__c, traits_type::eof()))
    00141         {
    00142           traits_type::assign(*__s++, traits_type::to_char_type(__c));
    00143           ++__ret;
    00144         }
    00145           else
    00146         break;
    00147         }
    00148     }
    00149       return __ret;
    00150     }
    00151
    00152   // Don't test against _M_buf + _M_buf_size, because _M_buf reflects
    00153   // allocated space, and on certain (rare but entirely legal)
    00154   // situations, there will be no allocated space yet the internal
    00155   // buffers will still be valid. (This happens if setp is used to set
    00156   // the internal buffer to say some externally-allocated sequence.)
    00157   template<typename _CharT, typename _Traits>
    00158     streamsize
    00159     basic_streambuf<_CharT, _Traits>::
    00160     xsputn(const char_type* __s, streamsize __n)
    00161     {
    00162       streamsize __ret = 0;
    00163       while (__ret < __n)
    00164     {
    00165       off_type __buf_len = _M_out_buf_size();
    00166       if (__buf_len > 0)
    00167         {
    00168           off_type __remaining = __n - __ret;
    00169           off_type __len = min(__buf_len, __remaining);
    00170           traits_type::copy(_M_out_cur, __s, __len);
    00171           __ret += __len;
    00172           __s += __len;
    00173           _M_out_cur_move(__len);
    00174         }
    00175
    00176       if (__ret < __n)
    00177         {
    00178           int_type __c = this->overflow(traits_type::to_int_type(*__s));
    00179           if (!traits_type::eq_int_type(__c, traits_type::eof()))
    00180         {
    00181           ++__ret;
    00182           ++__s;
    00183         }
    00184           else
    00185         break;
    00186         }
    00187     }
    00188       return __ret;
    00189     }
    00190
    00191   // Conceivably, this could be used to implement buffer-to-buffer
    00192   // copies, if this was ever desired in an un-ambiguous way by the
    00193   // standard. If so, then checks for __ios being zero would be
    00194   // necessary.
    00195   template<typename _CharT, typename _Traits>
    00196     streamsize
    00197     __copy_streambufs(basic_ios<_CharT, _Traits>& __ios,
    00198               basic_streambuf<_CharT, _Traits>* __sbin,
    00199               basic_streambuf<_CharT, _Traits>* __sbout)
    00200   {
    00201       typedef typename _Traits::int_type    int_type;
    00202
    00203       streamsize __ret = 0;
    00204       streamsize __bufsize = __sbin->in_avail();
    00205       streamsize __xtrct;
    00206       const typename _Traits::off_type __size_opt =
    00207     __sbin->_M_buf_size_opt > 0 ? __sbin->_M_buf_size_opt : 1;
    00208
    00209       try
    00210     {
    00211       while (__bufsize != -1)
    00212         {
    00213           if (__bufsize != 0 && __sbin->gptr() != NULL
    00214           && __sbin->gptr() + __bufsize <= __sbin->egptr())
    00215         {
    00216           __xtrct = __sbout->sputn(__sbin->gptr(), __bufsize);
    00217           __ret += __xtrct;
    00218           __sbin->_M_in_cur_move(__xtrct);
    00219           if (__xtrct != __bufsize)
    00220             break;
    00221         }
    00222           else
    00223         {
    00224           streamsize __charsread;
    00225           const streamsize __size =
    00226             min(__size_opt, __sbout->_M_out_buf_size());
    00227           if (__size > 1)
    00228             {
    00229               _CharT* __buf =
    00230             static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT)
    00231                                   * __size));
    00232               // Since the next sputn cannot fail sgetn can be
    00233               // safely used.
    00234               __charsread = __sbin->sgetn(__buf, __size);
    00235               __xtrct = __sbout->sputn(__buf, __charsread);
    00236             }
    00237           else
    00238             {
    00239               __xtrct = __charsread = 0;
    00240               int_type __c = __sbin->sgetc();
    00241               while (!_Traits::eq_int_type(__c, _Traits::eof()))
    00242             {
    00243               ++__charsread;
    00244               if (_Traits::eq_int_type(__sbout->sputc(_Traits::to_char_type(__c)),
    00245                            _Traits::eof()))
    00246                 break;
    00247               ++__xtrct;
    00248               __c = __sbin->snextc();
    00249             }
    00250             }
    00251           __ret += __xtrct;
    00252           if (__xtrct != __charsread)
    00253             break;
    00254         }
    00255           if (_Traits::eq_int_type(__sbin->sgetc(), _Traits::eof()))
    00256         break;
    00257           __bufsize = __sbin->in_avail();
    00258         }
    00259     }
    00260       catch(exception& __fail)
    00261     {
    00262       __ios.setstate(ios_base::failbit);
    00263       if ((__ios.exceptions() & ios_base::failbit) != 0)
    00264         __throw_exception_again;
    00265     }
    00266       return __ret;
    00267     }
    00268
    00269   // Inhibit implicit instantiations for required instantiations,
    00270   // which are defined via explicit instantiations elsewhere.
    00271   // NB:  This syntax is a GNU extension.
    00272 #if _GLIBCPP_EXTERN_TEMPLATE
    00273   extern template class basic_streambuf<char>;
    00274   extern template
    00275     streamsize
    00276     __copy_streambufs(basic_ios<char>&, basic_streambuf<char>*,
    00277               basic_streambuf<char>*);
    00278
    00279 #ifdef _GLIBCPP_USE_WCHAR_T
    00280   extern template class basic_streambuf<wchar_t>;
    00281   extern template
    00282     streamsize
    00283     __copy_streambufs(basic_ios<wchar_t>&, basic_streambuf<wchar_t>*,
    00284               basic_streambuf<wchar_t>*);
    00285 #endif
    00286 #endif
    00287 } // namespace std
    00288
    00289 #endif