streambuf.tcc revision 132720
197403Sobrien// Stream buffer classes -*- C++ -*-
297403Sobrien
3117397Skan// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
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
35132720Skan#ifndef _STREAMBUF_TCC
36132720Skan#define _STREAMBUF_TCC 1
3797403Sobrien
3897403Sobrien#pragma GCC system_header
3997403Sobrien
40132720Skannamespace std
4197403Sobrien{
4297403Sobrien  template<typename _CharT, typename _Traits>
4397403Sobrien    streamsize
4497403Sobrien    basic_streambuf<_CharT, _Traits>::
4597403Sobrien    xsgetn(char_type* __s, streamsize __n)
4697403Sobrien    {
4797403Sobrien      streamsize __ret = 0;
4897403Sobrien      while (__ret < __n)
4997403Sobrien	{
50132720Skan	  const size_t __buf_len = this->egptr() - this->gptr();
51132720Skan	  if (__buf_len)
5297403Sobrien	    {
53132720Skan	      const size_t __remaining = __n - __ret;
54132720Skan	      const size_t __len = std::min(__buf_len, __remaining);
55132720Skan	      traits_type::copy(__s, this->gptr(), __len);
5697403Sobrien	      __ret += __len;
5797403Sobrien	      __s += __len;
58132720Skan	      this->gbump(__len);
5997403Sobrien	    }
60132720Skan
6197403Sobrien	  if (__ret < __n)
6297403Sobrien	    {
63132720Skan	      const int_type __c = this->uflow();
64102782Skan	      if (!traits_type::eq_int_type(__c, traits_type::eof()))
6597403Sobrien		{
6697403Sobrien		  traits_type::assign(*__s++, traits_type::to_char_type(__c));
6797403Sobrien		  ++__ret;
6897403Sobrien		}
6997403Sobrien	      else
7097403Sobrien		break;
7197403Sobrien	    }
7297403Sobrien	}
7397403Sobrien      return __ret;
7497403Sobrien    }
7597403Sobrien
7697403Sobrien  template<typename _CharT, typename _Traits>
7797403Sobrien    streamsize
7897403Sobrien    basic_streambuf<_CharT, _Traits>::
7997403Sobrien    xsputn(const char_type* __s, streamsize __n)
8097403Sobrien    {
8197403Sobrien      streamsize __ret = 0;
8297403Sobrien      while (__ret < __n)
8397403Sobrien	{
84132720Skan	  const size_t __buf_len = this->epptr() - this->pptr();
85132720Skan	  if (__buf_len)
8697403Sobrien	    {
87132720Skan	      const size_t __remaining = __n - __ret;
88132720Skan	      const size_t __len = std::min(__buf_len, __remaining);
89132720Skan	      traits_type::copy(this->pptr(), __s, __len);
9097403Sobrien	      __ret += __len;
9197403Sobrien	      __s += __len;
92132720Skan	      this->pbump(__len);
9397403Sobrien	    }
9497403Sobrien
9597403Sobrien	  if (__ret < __n)
9697403Sobrien	    {
9797403Sobrien	      int_type __c = this->overflow(traits_type::to_int_type(*__s));
98102782Skan	      if (!traits_type::eq_int_type(__c, traits_type::eof()))
9997403Sobrien		{
10097403Sobrien		  ++__ret;
10197403Sobrien		  ++__s;
10297403Sobrien		}
10397403Sobrien	      else
10497403Sobrien		break;
10597403Sobrien	    }
10697403Sobrien	}
10797403Sobrien      return __ret;
10897403Sobrien    }
10997403Sobrien
11097403Sobrien  // Conceivably, this could be used to implement buffer-to-buffer
11197403Sobrien  // copies, if this was ever desired in an un-ambiguous way by the
11297403Sobrien  // standard. If so, then checks for __ios being zero would be
11397403Sobrien  // necessary.
11497403Sobrien  template<typename _CharT, typename _Traits>
11597403Sobrien    streamsize
116132720Skan    __copy_streambufs(basic_streambuf<_CharT, _Traits>* __sbin,
117132720Skan		      basic_streambuf<_CharT, _Traits>* __sbout)
118132720Skan    {
119132720Skan      streamsize __ret = 0;
120132720Skan      typename _Traits::int_type __c = __sbin->sgetc();
121132720Skan      while (!_Traits::eq_int_type(__c, _Traits::eof()))
122132720Skan	{
123132720Skan	  const size_t __n = __sbin->egptr() - __sbin->gptr();
124132720Skan	  if (__n > 1)
125132720Skan	    {
126132720Skan	      const size_t __wrote = __sbout->sputn(__sbin->gptr(), __n);
127132720Skan	      __sbin->gbump(__wrote);
128132720Skan	      __ret += __wrote;
129132720Skan	      if (__wrote < __n)
130132720Skan		break;
131132720Skan	      __c = __sbin->underflow();
132132720Skan	    }
133132720Skan	  else
134132720Skan	    {
135132720Skan	      __c = __sbout->sputc(_Traits::to_char_type(__c));
136132720Skan	      if (_Traits::eq_int_type(__c, _Traits::eof()))
137132720Skan		break;
138132720Skan	      ++__ret;
139132720Skan	      __c = __sbin->snextc();
140132720Skan	    }
141132720Skan	}
142132720Skan      return __ret;
143132720Skan    }
14497403Sobrien
14597403Sobrien  // Inhibit implicit instantiations for required instantiations,
146132720Skan  // which are defined via explicit instantiations elsewhere.
14797403Sobrien  // NB:  This syntax is a GNU extension.
148132720Skan#if _GLIBCXX_EXTERN_TEMPLATE
14997403Sobrien  extern template class basic_streambuf<char>;
15097403Sobrien  extern template
15197403Sobrien    streamsize
152132720Skan    __copy_streambufs(basic_streambuf<char>*, basic_streambuf<char>*);
15397403Sobrien
154132720Skan#ifdef _GLIBCXX_USE_WCHAR_T
15597403Sobrien  extern template class basic_streambuf<wchar_t>;
15697403Sobrien  extern template
15797403Sobrien    streamsize
158132720Skan    __copy_streambufs(basic_streambuf<wchar_t>*, basic_streambuf<wchar_t>*);
159107606Sobrien#endif
160117397Skan#endif
16197403Sobrien} // namespace std
16297403Sobrien
163132720Skan#endif
164