1 // Stream buffer classes -*- C++ -*- 2 3 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003 4 // Free Software Foundation, Inc. 5 // 6 // This file is part of the GNU ISO C++ Library. This library is free 7 // software; you can redistribute it and/or modify it under the 8 // terms of the GNU General Public License as published by the 9 // Free Software Foundation; either version 2, or (at your option) 10 // any later version. 11 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 17 // You should have received a copy of the GNU General Public License along 18 // with this library; see the file COPYING. If not, write to the Free 19 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 20 // USA. 21 22 // As a special exception, you may use this file as part of a free software 23 // library without restriction. Specifically, if other files instantiate 24 // templates or use macros or inline functions from this file, or you compile 25 // this file and link it with other files to produce an executable, this 26 // file does not by itself cause the resulting executable to be covered by 27 // the GNU General Public License. This exception does not however 28 // invalidate any other reasons why the executable file might be covered by 29 // the GNU General Public License. 30 31 // 32 // ISO C++ 14882: 27.5 Stream buffers 33 // 34 35 #ifndef _CPP_BITS_STREAMBUF_TCC 36 #define _CPP_BITS_STREAMBUF_TCC 1 37 38 #pragma GCC system_header 39 40 namespace std 41 { 42 template<typename _CharT, typename _Traits> 43 const size_t 44 basic_streambuf<_CharT, _Traits>::_S_pback_size; 45 46 template<typename _CharT, typename _Traits> 47 typename basic_streambuf<_CharT, _Traits>::int_type 48 basic_streambuf<_CharT, _Traits>:: 49 sbumpc() 50 { 51 int_type __ret; 52 if (_M_in_cur && _M_in_cur < _M_in_end) 53 { 54 char_type __c = *(this->gptr()); 55 _M_in_cur_move(1); 56 __ret = traits_type::to_int_type(__c); 57 } 58 else 59 __ret = this->uflow(); 60 return __ret; 61 } 62 63 template<typename _CharT, typename _Traits> 64 typename basic_streambuf<_CharT, _Traits>::int_type 65 basic_streambuf<_CharT, _Traits>:: 66 sputbackc(char_type __c) 67 { 68 int_type __ret; 69 bool __testpos = _M_in_cur && _M_in_beg < _M_in_cur; 70 if (!__testpos || !traits_type::eq(__c, this->gptr()[-1])) 71 __ret = this->pbackfail(traits_type::to_int_type(__c)); 72 else 73 { 74 _M_in_cur_move(-1); 75 __ret = traits_type::to_int_type(*this->gptr()); 76 } 77 return __ret; 78 } 79 80 template<typename _CharT, typename _Traits> 81 typename basic_streambuf<_CharT, _Traits>::int_type 82 basic_streambuf<_CharT, _Traits>:: 83 sungetc() 84 { 85 int_type __ret; 86 if (_M_in_cur && _M_in_beg < _M_in_cur) 87 { 88 _M_in_cur_move(-1); 89 __ret = traits_type::to_int_type(*_M_in_cur); 90 } 91 else 92 __ret = this->pbackfail(); 93 return __ret; 94 } 95 96 // Don't test against _M_buf + _M_buf_size, because _M_buf reflects 97 // allocated space, and on certain (rare but entirely legal) 98 // situations, there will be no allocated space yet the internal 99 // buffers will still be valid. (This happens if setp is used to set 100 // the internal buffer to say some externally-allocated sequence.) 101 template<typename _CharT, typename _Traits> 102 typename basic_streambuf<_CharT, _Traits>::int_type 103 basic_streambuf<_CharT, _Traits>:: 104 sputc(char_type __c) 105 { 106 int_type __ret; 107 if (_M_out_buf_size()) 108 { 109 *_M_out_cur = __c; 110 _M_out_cur_move(1); 111 __ret = traits_type::to_int_type(__c); 112 } 113 else 114 __ret = this->overflow(traits_type::to_int_type(__c)); 115 return __ret; 116 } 117 118 template<typename _CharT, typename _Traits> 119 streamsize 120 basic_streambuf<_CharT, _Traits>:: 121 xsgetn(char_type* __s, streamsize __n) 122 { 123 streamsize __ret = 0; 124 while (__ret < __n) 125 { 126 size_t __buf_len = _M_in_end - _M_in_cur; 127 if (__buf_len > 0) 128 { 129 size_t __remaining = __n - __ret; 130 size_t __len = min(__buf_len, __remaining); 131 traits_type::copy(__s, _M_in_cur, __len); 132 __ret += __len; 133 __s += __len; 134 _M_in_cur_move(__len); 135 } 136 137 if (__ret < __n) 138 { 139 int_type __c = this->uflow(); 140 if (!traits_type::eq_int_type(__c, traits_type::eof())) 141 { 142 traits_type::assign(*__s++, traits_type::to_char_type(__c)); 143 ++__ret; 144 } 145 else 146 break; 147 } 148 } 149 return __ret; 150 } 151 152 // Don't test against _M_buf + _M_buf_size, because _M_buf reflects 153 // allocated space, and on certain (rare but entirely legal) 154 // situations, there will be no allocated space yet the internal 155 // buffers will still be valid. (This happens if setp is used to set 156 // the internal buffer to say some externally-allocated sequence.) 157 template<typename _CharT, typename _Traits> 158 streamsize 159 basic_streambuf<_CharT, _Traits>:: 160 xsputn(const char_type* __s, streamsize __n) 161 { 162 streamsize __ret = 0; 163 while (__ret < __n) 164 { 165 off_type __buf_len = _M_out_buf_size(); 166 if (__buf_len > 0) 167 { 168 off_type __remaining = __n - __ret; 169 off_type __len = min(__buf_len, __remaining); 170 traits_type::copy(_M_out_cur, __s, __len); 171 __ret += __len; 172 __s += __len; 173 _M_out_cur_move(__len); 174 } 175 176 if (__ret < __n) 177 { 178 int_type __c = this->overflow(traits_type::to_int_type(*__s)); 179 if (!traits_type::eq_int_type(__c, traits_type::eof())) 180 { 181 ++__ret; 182 ++__s; 183 } 184 else 185 break; 186 } 187 } 188 return __ret; 189 } 190 191 // Conceivably, this could be used to implement buffer-to-buffer 192 // copies, if this was ever desired in an un-ambiguous way by the 193 // standard. If so, then checks for __ios being zero would be 194 // necessary. 195 template<typename _CharT, typename _Traits> 196 streamsize 197 __copy_streambufs(basic_ios<_CharT, _Traits>& __ios, 198 basic_streambuf<_CharT, _Traits>* __sbin, 199 basic_streambuf<_CharT, _Traits>* __sbout) 200 { 201 streamsize __ret = 0; 202 try 203 { 204 typename _Traits::int_type __c = __sbin->sgetc(); 205 while (!_Traits::eq_int_type(__c, _Traits::eof())) 206 { 207 const size_t __n = __sbin->_M_in_end - __sbin->_M_in_cur; 208 if (__n > 1) 209 { 210 const size_t __wrote = __sbout->sputn(__sbin->_M_in_cur, 211 __n); 212 __sbin->_M_in_cur_move(__wrote); 213 __ret += __wrote; 214 if (__wrote < __n) 215 break; 216 __c = __sbin->underflow(); 217 } 218 else 219 { 220 __c = __sbout->sputc(_Traits::to_char_type(__c)); 221 if (_Traits::eq_int_type(__c, _Traits::eof())) 222 break; 223 ++__ret; 224 __c = __sbin->snextc(); 225 } 226 } 227 } 228 catch(exception& __fail) 229 { 230 __ios.setstate(ios_base::failbit); 231 if ((__ios.exceptions() & ios_base::failbit) != 0) 232 __throw_exception_again; 233 } 234 return __ret; 235 } 236 237 // Inhibit implicit instantiations for required instantiations, 238 // which are defined via explicit instantiations elsewhere. 239 // NB: This syntax is a GNU extension. 240 #if _GLIBCPP_EXTERN_TEMPLATE 241 extern template class basic_streambuf<char>; 242 extern template 243 streamsize 244 __copy_streambufs(basic_ios<char>&, basic_streambuf<char>*, 245 basic_streambuf<char>*); 246 247 #ifdef _GLIBCPP_USE_WCHAR_T 248 extern template class basic_streambuf<wchar_t>; 249 extern template 250 streamsize 251 __copy_streambufs(basic_ios<wchar_t>&, basic_streambuf<wchar_t>*, 252 basic_streambuf<wchar_t>*); 253 #endif 254 #endif 255 } // namespace std 256 257 #endif 258