streambuf.tcc revision 97403
197403Sobrien// Stream buffer classes -*- C++ -*-
297403Sobrien
397403Sobrien// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
497403Sobrien// Free Software Foundation, Inc.
597403Sobrien//
697403Sobrien// This file is part of the GNU ISO C++ Library.  This library is free
797403Sobrien// software; you can redistribute it and/or modify it under the
897403Sobrien// terms of the GNU General Public License as published by the
997403Sobrien// Free Software Foundation; either version 2, or (at your option)
1097403Sobrien// any later version.
1197403Sobrien
1297403Sobrien// This library is distributed in the hope that it will be useful,
1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1597403Sobrien// GNU General Public License for more details.
1697403Sobrien
1797403Sobrien// You should have received a copy of the GNU General Public License along
1897403Sobrien// with this library; see the file COPYING.  If not, write to the Free
1997403Sobrien// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
2097403Sobrien// USA.
2197403Sobrien
2297403Sobrien// As a special exception, you may use this file as part of a free software
2397403Sobrien// library without restriction.  Specifically, if other files instantiate
2497403Sobrien// templates or use macros or inline functions from this file, or you compile
2597403Sobrien// this file and link it with other files to produce an executable, this
2697403Sobrien// file does not by itself cause the resulting executable to be covered by
2797403Sobrien// the GNU General Public License.  This exception does not however
2897403Sobrien// invalidate any other reasons why the executable file might be covered by
2997403Sobrien// the GNU General Public License.
3097403Sobrien
3197403Sobrien//
3297403Sobrien// ISO C++ 14882: 27.5  Stream buffers
3397403Sobrien//
3497403Sobrien
3597403Sobrien#ifndef _CPP_BITS_STREAMBUF_TCC
3697403Sobrien#define _CPP_BITS_STREAMBUF_TCC 1
3797403Sobrien
3897403Sobrien#pragma GCC system_header
3997403Sobrien
4097403Sobriennamespace std 
4197403Sobrien{
4297403Sobrien  template<typename _CharT, typename _Traits>
4397403Sobrien    const typename basic_streambuf<_CharT, _Traits>::int_type
4497403Sobrien    basic_streambuf<_CharT, _Traits>::_S_pback_size;
4597403Sobrien
4697403Sobrien  template<typename _CharT, typename _Traits>
4797403Sobrien    typename basic_streambuf<_CharT, _Traits>::int_type
4897403Sobrien    basic_streambuf<_CharT, _Traits>::
4997403Sobrien    sbumpc()
5097403Sobrien    {
5197403Sobrien      int_type __ret;
5297403Sobrien      if (_M_in_cur && _M_in_cur < _M_in_end)
5397403Sobrien	{
5497403Sobrien	  char_type __c = *(this->gptr());
5597403Sobrien	  _M_in_cur_move(1);
5697403Sobrien	  __ret = traits_type::to_int_type(__c);
5797403Sobrien	}
5897403Sobrien      else 
5997403Sobrien	__ret = this->uflow();
6097403Sobrien      return __ret;
6197403Sobrien    }
6297403Sobrien
6397403Sobrien  template<typename _CharT, typename _Traits>
6497403Sobrien    typename basic_streambuf<_CharT, _Traits>::int_type
6597403Sobrien    basic_streambuf<_CharT, _Traits>::
6697403Sobrien    sputbackc(char_type __c) 
6797403Sobrien    {
6897403Sobrien      int_type __ret;
6997403Sobrien      bool __testpos = _M_in_cur && _M_in_beg < _M_in_cur;
7097403Sobrien      bool __testne = _M_in_cur && !traits_type::eq(__c, this->gptr()[-1]);
7197403Sobrien      if (!__testpos || __testne)
7297403Sobrien	__ret = pbackfail(traits_type::to_int_type(__c));
7397403Sobrien      else 
7497403Sobrien	{
7597403Sobrien	  _M_in_cur_move(-1);
7697403Sobrien	  __ret = traits_type::to_int_type(*this->gptr());
7797403Sobrien	}
7897403Sobrien      return __ret;
7997403Sobrien    }
8097403Sobrien  
8197403Sobrien  template<typename _CharT, typename _Traits>
8297403Sobrien    typename basic_streambuf<_CharT, _Traits>::int_type
8397403Sobrien    basic_streambuf<_CharT, _Traits>::
8497403Sobrien    sungetc()
8597403Sobrien    {
8697403Sobrien      int_type __ret;
8797403Sobrien      if (_M_in_cur && _M_in_beg < _M_in_cur)
8897403Sobrien	{
8997403Sobrien	  _M_in_cur_move(-1);
9097403Sobrien	  __ret = traits_type::to_int_type(*_M_in_cur);
9197403Sobrien	}
9297403Sobrien      else 
9397403Sobrien	__ret = this->pbackfail();
9497403Sobrien      return __ret;
9597403Sobrien    }
9697403Sobrien
9797403Sobrien  // Don't test against _M_buf + _M_buf_size, because _M_buf reflects
9897403Sobrien  // allocated space, and on certain (rare but entirely legal)
9997403Sobrien  // situations, there will be no allocated space yet the internal
10097403Sobrien  // buffers will still be valid. (This happens if setp is used to set
10197403Sobrien  // the internal buffer to say some externally-allocated sequence.)
10297403Sobrien  template<typename _CharT, typename _Traits>
10397403Sobrien    typename basic_streambuf<_CharT, _Traits>::int_type
10497403Sobrien    basic_streambuf<_CharT, _Traits>::
10597403Sobrien    sputc(char_type __c)
10697403Sobrien    {
10797403Sobrien      int_type __ret;
10897403Sobrien      if (_M_out_buf_size())
10997403Sobrien	{
11097403Sobrien	  *_M_out_cur = __c;
11197403Sobrien	  _M_out_cur_move(1);
11297403Sobrien	  __ret = traits_type::to_int_type(__c);
11397403Sobrien	}
11497403Sobrien      else
11597403Sobrien	__ret = this->overflow(traits_type::to_int_type(__c));
11697403Sobrien      return __ret;
11797403Sobrien    }
11897403Sobrien
11997403Sobrien  template<typename _CharT, typename _Traits>
12097403Sobrien    streamsize
12197403Sobrien    basic_streambuf<_CharT, _Traits>::
12297403Sobrien    xsgetn(char_type* __s, streamsize __n)
12397403Sobrien    {
12497403Sobrien      streamsize __ret = 0;
12597403Sobrien      while (__ret < __n)
12697403Sobrien	{
12797403Sobrien	  size_t __buf_len = _M_in_end - _M_in_cur;
12897403Sobrien	  if (__buf_len > 0)
12997403Sobrien	    {
13097403Sobrien	      size_t __remaining = __n - __ret;
13197403Sobrien	      size_t __len = min(__buf_len, __remaining);
13297403Sobrien	      traits_type::copy(__s, _M_in_cur, __len);
13397403Sobrien	      __ret += __len;
13497403Sobrien	      __s += __len;
13597403Sobrien	      _M_in_cur_move(__len);
13697403Sobrien	    }
13797403Sobrien	  
13897403Sobrien	  if (__ret < __n)
13997403Sobrien	    {
14097403Sobrien	      int_type __c = this->uflow();  
14197403Sobrien	      if (__c != traits_type::eof())
14297403Sobrien		{
14397403Sobrien		  traits_type::assign(*__s++, traits_type::to_char_type(__c));
14497403Sobrien		  ++__ret;
14597403Sobrien		}
14697403Sobrien	      else
14797403Sobrien		break;
14897403Sobrien	    }
14997403Sobrien	}
15097403Sobrien      return __ret;
15197403Sobrien    }
15297403Sobrien
15397403Sobrien  // Don't test against _M_buf + _M_buf_size, because _M_buf reflects
15497403Sobrien  // allocated space, and on certain (rare but entirely legal)
15597403Sobrien  // situations, there will be no allocated space yet the internal
15697403Sobrien  // buffers will still be valid. (This happens if setp is used to set
15797403Sobrien  // the internal buffer to say some externally-allocated sequence.)
15897403Sobrien  template<typename _CharT, typename _Traits>
15997403Sobrien    streamsize
16097403Sobrien    basic_streambuf<_CharT, _Traits>::
16197403Sobrien    xsputn(const char_type* __s, streamsize __n)
16297403Sobrien    {
16397403Sobrien      streamsize __ret = 0;
16497403Sobrien      while (__ret < __n)
16597403Sobrien	{
16697403Sobrien	  off_type __buf_len = _M_out_buf_size();
16797403Sobrien	  if (__buf_len > 0)
16897403Sobrien	    {
16997403Sobrien	      off_type __remaining = __n - __ret;
17097403Sobrien	      off_type __len = min(__buf_len, __remaining);
17197403Sobrien	      traits_type::copy(_M_out_cur, __s, __len);
17297403Sobrien	      __ret += __len;
17397403Sobrien	      __s += __len;
17497403Sobrien	      _M_out_cur_move(__len);
17597403Sobrien	    }
17697403Sobrien
17797403Sobrien	  if (__ret < __n)
17897403Sobrien	    {
17997403Sobrien	      int_type __c = this->overflow(traits_type::to_int_type(*__s));
18097403Sobrien	      if (__c != traits_type::eof())
18197403Sobrien		{
18297403Sobrien		  ++__ret;
18397403Sobrien		  ++__s;
18497403Sobrien		}
18597403Sobrien	      else
18697403Sobrien		break;
18797403Sobrien	    }
18897403Sobrien	}
18997403Sobrien      return __ret;
19097403Sobrien    }
19197403Sobrien
19297403Sobrien  // Conceivably, this could be used to implement buffer-to-buffer
19397403Sobrien  // copies, if this was ever desired in an un-ambiguous way by the
19497403Sobrien  // standard. If so, then checks for __ios being zero would be
19597403Sobrien  // necessary.
19697403Sobrien  template<typename _CharT, typename _Traits>
19797403Sobrien    streamsize
19897403Sobrien    __copy_streambufs(basic_ios<_CharT, _Traits>& __ios,
19997403Sobrien		      basic_streambuf<_CharT, _Traits>* __sbin,
20097403Sobrien		      basic_streambuf<_CharT, _Traits>* __sbout) 
20197403Sobrien  {
20297403Sobrien      typedef typename _Traits::int_type	int_type;
20397403Sobrien
20497403Sobrien      streamsize __ret = 0;
20597403Sobrien      streamsize __bufsize = __sbin->in_avail();
20697403Sobrien      streamsize __xtrct;
20797403Sobrien      bool __testput = __sbout->_M_mode & ios_base::out;
20897403Sobrien      try 
20997403Sobrien	{
21097403Sobrien	  while (__testput && __bufsize != -1)
21197403Sobrien	    {
21297403Sobrien	      __xtrct = __sbout->sputn(__sbin->gptr(), __bufsize);
21397403Sobrien	      __ret += __xtrct;
21497403Sobrien	      __sbin->_M_in_cur_move(__xtrct);
21597403Sobrien	      if (__xtrct == __bufsize)
21697403Sobrien		{
21797403Sobrien		  if (__sbin->sgetc() == _Traits::eof())
21897403Sobrien		    break;
21997403Sobrien		  __bufsize = __sbin->in_avail();
22097403Sobrien		}
22197403Sobrien	      else
22297403Sobrien		break;
22397403Sobrien	    }
22497403Sobrien	}
22597403Sobrien      catch(exception& __fail) 
22697403Sobrien	{
22797403Sobrien	  __ios.setstate(ios_base::failbit);
22897403Sobrien	  if ((__ios.exceptions() & ios_base::failbit) != 0)
22997403Sobrien	    __throw_exception_again;
23097403Sobrien	}
23197403Sobrien      return __ret;
23297403Sobrien    }
23397403Sobrien
23497403Sobrien  // Inhibit implicit instantiations for required instantiations,
23597403Sobrien  // which are defined via explicit instantiations elsewhere.  
23697403Sobrien  // NB:  This syntax is a GNU extension.
23797403Sobrien  extern template class basic_streambuf<char>;
23897403Sobrien  extern template
23997403Sobrien    streamsize
24097403Sobrien    __copy_streambufs(basic_ios<char>&, basic_streambuf<char>*,
24197403Sobrien		      basic_streambuf<char>*); 
24297403Sobrien
24397403Sobrien  extern template class basic_streambuf<wchar_t>;
24497403Sobrien  extern template
24597403Sobrien    streamsize
24697403Sobrien    __copy_streambufs(basic_ios<wchar_t>&, basic_streambuf<wchar_t>*,
24797403Sobrien		      basic_streambuf<wchar_t>*); 
24897403Sobrien} // namespace std
24997403Sobrien
25097403Sobrien#endif 
251