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