| 1 | // Stream buffer classes -*- C++ -*-
|
|---|
| 2 |
|
|---|
| 3 | // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
|
|---|
| 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 | bool __testne = _M_in_cur && !traits_type::eq(__c, this->gptr()[-1]);
|
|---|
| 71 | if (!__testpos || __testne)
|
|---|
| 72 | __ret = this->pbackfail(traits_type::to_int_type(__c));
|
|---|
| 73 | else
|
|---|
| 74 | {
|
|---|
| 75 | _M_in_cur_move(-1);
|
|---|
| 76 | __ret = traits_type::to_int_type(*this->gptr());
|
|---|
| 77 | }
|
|---|
| 78 | return __ret;
|
|---|
| 79 | }
|
|---|
| 80 |
|
|---|
| 81 | template<typename _CharT, typename _Traits>
|
|---|
| 82 | typename basic_streambuf<_CharT, _Traits>::int_type
|
|---|
| 83 | basic_streambuf<_CharT, _Traits>::
|
|---|
| 84 | sungetc()
|
|---|
| 85 | {
|
|---|
| 86 | int_type __ret;
|
|---|
| 87 | if (_M_in_cur && _M_in_beg < _M_in_cur)
|
|---|
| 88 | {
|
|---|
| 89 | _M_in_cur_move(-1);
|
|---|
| 90 | __ret = traits_type::to_int_type(*_M_in_cur);
|
|---|
| 91 | }
|
|---|
| 92 | else
|
|---|
| 93 | __ret = this->pbackfail();
|
|---|
| 94 | return __ret;
|
|---|
| 95 | }
|
|---|
| 96 |
|
|---|
| 97 | // Don't test against _M_buf + _M_buf_size, because _M_buf reflects
|
|---|
| 98 | // allocated space, and on certain (rare but entirely legal)
|
|---|
| 99 | // situations, there will be no allocated space yet the internal
|
|---|
| 100 | // buffers will still be valid. (This happens if setp is used to set
|
|---|
| 101 | // the internal buffer to say some externally-allocated sequence.)
|
|---|
| 102 | template<typename _CharT, typename _Traits>
|
|---|
| 103 | typename basic_streambuf<_CharT, _Traits>::int_type
|
|---|
| 104 | basic_streambuf<_CharT, _Traits>::
|
|---|
| 105 | sputc(char_type __c)
|
|---|
| 106 | {
|
|---|
| 107 | int_type __ret;
|
|---|
| 108 | if (_M_out_buf_size())
|
|---|
| 109 | {
|
|---|
| 110 | *_M_out_cur = __c;
|
|---|
| 111 | _M_out_cur_move(1);
|
|---|
| 112 | __ret = traits_type::to_int_type(__c);
|
|---|
| 113 | }
|
|---|
| 114 | else
|
|---|
| 115 | __ret = this->overflow(traits_type::to_int_type(__c));
|
|---|
| 116 | return __ret;
|
|---|
| 117 | }
|
|---|
| 118 |
|
|---|
| 119 | template<typename _CharT, typename _Traits>
|
|---|
| 120 | streamsize
|
|---|
| 121 | basic_streambuf<_CharT, _Traits>::
|
|---|
| 122 | xsgetn(char_type* __s, streamsize __n)
|
|---|
| 123 | {
|
|---|
| 124 | streamsize __ret = 0;
|
|---|
| 125 | while (__ret < __n)
|
|---|
| 126 | {
|
|---|
| 127 | size_t __buf_len = _M_in_end - _M_in_cur;
|
|---|
| 128 | if (__buf_len > 0)
|
|---|
| 129 | {
|
|---|
| 130 | size_t __remaining = __n - __ret;
|
|---|
| 131 | size_t __len = min(__buf_len, __remaining);
|
|---|
| 132 | traits_type::copy(__s, _M_in_cur, __len);
|
|---|
| 133 | __ret += __len;
|
|---|
| 134 | __s += __len;
|
|---|
| 135 | _M_in_cur_move(__len);
|
|---|
| 136 | }
|
|---|
| 137 |
|
|---|
| 138 | if (__ret < __n)
|
|---|
| 139 | {
|
|---|
| 140 | int_type __c = this->uflow();
|
|---|
| 141 | if (!traits_type::eq_int_type(__c, traits_type::eof()))
|
|---|
| 142 | {
|
|---|
| 143 | traits_type::assign(*__s++, traits_type::to_char_type(__c));
|
|---|
| 144 | ++__ret;
|
|---|
| 145 | }
|
|---|
| 146 | else
|
|---|
| 147 | break;
|
|---|
| 148 | }
|
|---|
| 149 | }
|
|---|
| 150 | return __ret;
|
|---|
| 151 | }
|
|---|
| 152 |
|
|---|
| 153 | // Don't test against _M_buf + _M_buf_size, because _M_buf reflects
|
|---|
| 154 | // allocated space, and on certain (rare but entirely legal)
|
|---|
| 155 | // situations, there will be no allocated space yet the internal
|
|---|
| 156 | // buffers will still be valid. (This happens if setp is used to set
|
|---|
| 157 | // the internal buffer to say some externally-allocated sequence.)
|
|---|
| 158 | template<typename _CharT, typename _Traits>
|
|---|
| 159 | streamsize
|
|---|
| 160 | basic_streambuf<_CharT, _Traits>::
|
|---|
| 161 | xsputn(const char_type* __s, streamsize __n)
|
|---|
| 162 | {
|
|---|
| 163 | streamsize __ret = 0;
|
|---|
| 164 | while (__ret < __n)
|
|---|
| 165 | {
|
|---|
| 166 | off_type __buf_len = _M_out_buf_size();
|
|---|
| 167 | if (__buf_len > 0)
|
|---|
| 168 | {
|
|---|
| 169 | off_type __remaining = __n - __ret;
|
|---|
| 170 | off_type __len = min(__buf_len, __remaining);
|
|---|
| 171 | traits_type::copy(_M_out_cur, __s, __len);
|
|---|
| 172 | __ret += __len;
|
|---|
| 173 | __s += __len;
|
|---|
| 174 | _M_out_cur_move(__len);
|
|---|
| 175 | }
|
|---|
| 176 |
|
|---|
| 177 | if (__ret < __n)
|
|---|
| 178 | {
|
|---|
| 179 | int_type __c = this->overflow(traits_type::to_int_type(*__s));
|
|---|
| 180 | if (!traits_type::eq_int_type(__c, traits_type::eof()))
|
|---|
| 181 | {
|
|---|
| 182 | ++__ret;
|
|---|
| 183 | ++__s;
|
|---|
| 184 | }
|
|---|
| 185 | else
|
|---|
| 186 | break;
|
|---|
| 187 | }
|
|---|
| 188 | }
|
|---|
| 189 | return __ret;
|
|---|
| 190 | }
|
|---|
| 191 |
|
|---|
| 192 | // Conceivably, this could be used to implement buffer-to-buffer
|
|---|
| 193 | // copies, if this was ever desired in an un-ambiguous way by the
|
|---|
| 194 | // standard. If so, then checks for __ios being zero would be
|
|---|
| 195 | // necessary.
|
|---|
| 196 | template<typename _CharT, typename _Traits>
|
|---|
| 197 | streamsize
|
|---|
| 198 | __copy_streambufs(basic_ios<_CharT, _Traits>& __ios,
|
|---|
| 199 | basic_streambuf<_CharT, _Traits>* __sbin,
|
|---|
| 200 | basic_streambuf<_CharT, _Traits>* __sbout)
|
|---|
| 201 | {
|
|---|
| 202 | typedef typename _Traits::int_type int_type;
|
|---|
| 203 |
|
|---|
| 204 | streamsize __ret = 0;
|
|---|
| 205 | streamsize __bufsize = __sbin->in_avail();
|
|---|
| 206 | streamsize __xtrct;
|
|---|
| 207 | bool __testput = __sbout->_M_mode & ios_base::out;
|
|---|
| 208 | try
|
|---|
| 209 | {
|
|---|
| 210 | while (__testput && __bufsize != -1)
|
|---|
| 211 | {
|
|---|
| 212 | if (__bufsize != 0 && __sbin->gptr() != NULL
|
|---|
| 213 | && __sbin->gptr() + __bufsize <= __sbin->egptr())
|
|---|
| 214 | {
|
|---|
| 215 | __xtrct = __sbout->sputn(__sbin->gptr(), __bufsize);
|
|---|
| 216 | __ret += __xtrct;
|
|---|
| 217 | __sbin->_M_in_cur_move(__xtrct);
|
|---|
| 218 | if (__xtrct != __bufsize)
|
|---|
| 219 | break;
|
|---|
| 220 | }
|
|---|
| 221 | else
|
|---|
| 222 | {
|
|---|
| 223 | size_t __size =
|
|---|
| 224 | __sbin->_M_buf_size_opt > 0 ? __sbin->_M_buf_size_opt : 1;
|
|---|
| 225 | _CharT* __buf =
|
|---|
| 226 | static_cast<_CharT*>(__builtin_alloca(sizeof(_CharT) * __size));
|
|---|
| 227 | streamsize __charsread = __sbin->sgetn(__buf, __size);
|
|---|
| 228 | __xtrct = __sbout->sputn(__buf, __charsread);
|
|---|
| 229 | __ret += __xtrct;
|
|---|
| 230 | if (__xtrct != __charsread)
|
|---|
| 231 | break;
|
|---|
| 232 | }
|
|---|
| 233 | if (_Traits::eq_int_type(__sbin->sgetc(), _Traits::eof()))
|
|---|
| 234 | break;
|
|---|
| 235 | __bufsize = __sbin->in_avail();
|
|---|
| 236 | }
|
|---|
| 237 | }
|
|---|
| 238 | catch(exception& __fail)
|
|---|
| 239 | {
|
|---|
| 240 | __ios.setstate(ios_base::failbit);
|
|---|
| 241 | if ((__ios.exceptions() & ios_base::failbit) != 0)
|
|---|
| 242 | __throw_exception_again;
|
|---|
| 243 | }
|
|---|
| 244 | return __ret;
|
|---|
| 245 | }
|
|---|
| 246 |
|
|---|
| 247 | // Inhibit implicit instantiations for required instantiations,
|
|---|
| 248 | // which are defined via explicit instantiations elsewhere.
|
|---|
| 249 | // NB: This syntax is a GNU extension.
|
|---|
| 250 | extern template class basic_streambuf<char>;
|
|---|
| 251 | extern template
|
|---|
| 252 | streamsize
|
|---|
| 253 | __copy_streambufs(basic_ios<char>&, basic_streambuf<char>*,
|
|---|
| 254 | basic_streambuf<char>*);
|
|---|
| 255 |
|
|---|
| 256 | #ifdef _GLIBCPP_USE_WCHAR_T
|
|---|
| 257 | extern template class basic_streambuf<wchar_t>;
|
|---|
| 258 | extern template
|
|---|
| 259 | streamsize
|
|---|
| 260 | __copy_streambufs(basic_ios<wchar_t>&, basic_streambuf<wchar_t>*,
|
|---|
| 261 | basic_streambuf<wchar_t>*);
|
|---|
| 262 | #endif
|
|---|
| 263 | } // namespace std
|
|---|
| 264 |
|
|---|
| 265 | #endif
|
|---|