1 1.1 mrg // File based streams -*- C++ -*- 2 1.1 mrg 3 1.1.1.13 mrg // Copyright (C) 1997-2024 Free Software Foundation, Inc. 4 1.1 mrg // 5 1.1 mrg // This file is part of the GNU ISO C++ Library. This library is free 6 1.1 mrg // software; you can redistribute it and/or modify it under the 7 1.1 mrg // terms of the GNU General Public License as published by the 8 1.1 mrg // Free Software Foundation; either version 3, or (at your option) 9 1.1 mrg // any later version. 10 1.1 mrg 11 1.1 mrg // This library is distributed in the hope that it will be useful, 12 1.1 mrg // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 mrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 mrg // GNU General Public License for more details. 15 1.1 mrg 16 1.1 mrg // Under Section 7 of GPL version 3, you are granted additional 17 1.1 mrg // permissions described in the GCC Runtime Library Exception, version 18 1.1 mrg // 3.1, as published by the Free Software Foundation. 19 1.1 mrg 20 1.1 mrg // You should have received a copy of the GNU General Public License and 21 1.1 mrg // a copy of the GCC Runtime Library Exception along with this program; 22 1.1 mrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 1.1 mrg // <http://www.gnu.org/licenses/>. 24 1.1 mrg 25 1.1.1.2 mrg /** @file bits/fstream.tcc 26 1.1 mrg * This is an internal header file, included by other library headers. 27 1.1.1.2 mrg * Do not attempt to use it directly. @headername{fstream} 28 1.1 mrg */ 29 1.1 mrg 30 1.1 mrg // 31 1.1 mrg // ISO C++ 14882: 27.8 File-based streams 32 1.1 mrg // 33 1.1 mrg 34 1.1 mrg #ifndef _FSTREAM_TCC 35 1.1 mrg #define _FSTREAM_TCC 1 36 1.1 mrg 37 1.1 mrg #pragma GCC system_header 38 1.1 mrg 39 1.1.1.2 mrg #include <bits/cxxabi_forced.h> 40 1.1.1.3 mrg #include <bits/move.h> // for swap 41 1.1.1.10 mrg #include <cerrno> 42 1.1 mrg 43 1.1.1.2 mrg namespace std _GLIBCXX_VISIBILITY(default) 44 1.1.1.2 mrg { 45 1.1.1.2 mrg _GLIBCXX_BEGIN_NAMESPACE_VERSION 46 1.1 mrg 47 1.1 mrg template<typename _CharT, typename _Traits> 48 1.1 mrg void 49 1.1 mrg basic_filebuf<_CharT, _Traits>:: 50 1.1 mrg _M_allocate_internal_buffer() 51 1.1 mrg { 52 1.1 mrg // Allocate internal buffer only if one doesn't already exist 53 1.1 mrg // (either allocated or provided by the user via setbuf). 54 1.1 mrg if (!_M_buf_allocated && !_M_buf) 55 1.1 mrg { 56 1.1 mrg _M_buf = new char_type[_M_buf_size]; 57 1.1 mrg _M_buf_allocated = true; 58 1.1 mrg } 59 1.1 mrg } 60 1.1 mrg 61 1.1 mrg template<typename _CharT, typename _Traits> 62 1.1 mrg void 63 1.1 mrg basic_filebuf<_CharT, _Traits>:: 64 1.1 mrg _M_destroy_internal_buffer() throw() 65 1.1 mrg { 66 1.1 mrg if (_M_buf_allocated) 67 1.1 mrg { 68 1.1 mrg delete [] _M_buf; 69 1.1.1.2 mrg _M_buf = 0; 70 1.1 mrg _M_buf_allocated = false; 71 1.1 mrg } 72 1.1 mrg delete [] _M_ext_buf; 73 1.1.1.2 mrg _M_ext_buf = 0; 74 1.1 mrg _M_ext_buf_size = 0; 75 1.1.1.2 mrg _M_ext_next = 0; 76 1.1.1.2 mrg _M_ext_end = 0; 77 1.1 mrg } 78 1.1 mrg 79 1.1 mrg template<typename _CharT, typename _Traits> 80 1.1 mrg basic_filebuf<_CharT, _Traits>:: 81 1.1 mrg basic_filebuf() : __streambuf_type(), _M_lock(), _M_file(&_M_lock), 82 1.1 mrg _M_mode(ios_base::openmode(0)), _M_state_beg(), _M_state_cur(), 83 1.1.1.12 mrg _M_state_last(), _M_buf(0), _M_buf_size(_GLIBCXX_BUFSIZ), 84 1.1 mrg _M_buf_allocated(false), _M_reading(false), _M_writing(false), _M_pback(), 85 1.1 mrg _M_pback_cur_save(0), _M_pback_end_save(0), _M_pback_init(false), 86 1.1 mrg _M_codecvt(0), _M_ext_buf(0), _M_ext_buf_size(0), _M_ext_next(0), 87 1.1 mrg _M_ext_end(0) 88 1.1 mrg { 89 1.1.1.13 mrg _M_codecvt = std::__try_use_facet<__codecvt_type>(this->_M_buf_locale); 90 1.1 mrg } 91 1.1 mrg 92 1.1.1.3 mrg #if __cplusplus >= 201103L 93 1.1.1.3 mrg template<typename _CharT, typename _Traits> 94 1.1.1.3 mrg basic_filebuf<_CharT, _Traits>:: 95 1.1.1.3 mrg basic_filebuf(basic_filebuf&& __rhs) 96 1.1.1.3 mrg : __streambuf_type(__rhs), 97 1.1.1.3 mrg _M_lock(), _M_file(std::move(__rhs._M_file), &_M_lock), 98 1.1.1.3 mrg _M_mode(std::__exchange(__rhs._M_mode, ios_base::openmode(0))), 99 1.1.1.3 mrg _M_state_beg(std::move(__rhs._M_state_beg)), 100 1.1.1.3 mrg _M_state_cur(std::move(__rhs._M_state_cur)), 101 1.1.1.3 mrg _M_state_last(std::move(__rhs._M_state_last)), 102 1.1.1.3 mrg _M_buf(std::__exchange(__rhs._M_buf, nullptr)), 103 1.1.1.3 mrg _M_buf_size(std::__exchange(__rhs._M_buf_size, 1)), 104 1.1.1.3 mrg _M_buf_allocated(std::__exchange(__rhs._M_buf_allocated, false)), 105 1.1.1.3 mrg _M_reading(std::__exchange(__rhs._M_reading, false)), 106 1.1.1.3 mrg _M_writing(std::__exchange(__rhs._M_writing, false)), 107 1.1.1.3 mrg _M_pback(__rhs._M_pback), 108 1.1.1.3 mrg _M_pback_cur_save(std::__exchange(__rhs._M_pback_cur_save, nullptr)), 109 1.1.1.3 mrg _M_pback_end_save(std::__exchange(__rhs._M_pback_end_save, nullptr)), 110 1.1.1.3 mrg _M_pback_init(std::__exchange(__rhs._M_pback_init, false)), 111 1.1.1.3 mrg _M_codecvt(__rhs._M_codecvt), 112 1.1.1.3 mrg _M_ext_buf(std::__exchange(__rhs._M_ext_buf, nullptr)), 113 1.1.1.3 mrg _M_ext_buf_size(std::__exchange(__rhs._M_ext_buf_size, 0)), 114 1.1.1.3 mrg _M_ext_next(std::__exchange(__rhs._M_ext_next, nullptr)), 115 1.1.1.3 mrg _M_ext_end(std::__exchange(__rhs._M_ext_end, nullptr)) 116 1.1.1.3 mrg { 117 1.1.1.3 mrg __rhs._M_set_buffer(-1); 118 1.1.1.3 mrg __rhs._M_state_last = __rhs._M_state_cur = __rhs._M_state_beg; 119 1.1.1.3 mrg } 120 1.1.1.3 mrg 121 1.1.1.3 mrg template<typename _CharT, typename _Traits> 122 1.1.1.3 mrg basic_filebuf<_CharT, _Traits>& 123 1.1.1.3 mrg basic_filebuf<_CharT, _Traits>:: 124 1.1.1.3 mrg operator=(basic_filebuf&& __rhs) 125 1.1.1.3 mrg { 126 1.1.1.3 mrg this->close(); 127 1.1.1.3 mrg __streambuf_type::operator=(__rhs); 128 1.1.1.3 mrg _M_file.swap(__rhs._M_file); 129 1.1.1.3 mrg _M_mode = std::__exchange(__rhs._M_mode, ios_base::openmode(0)); 130 1.1.1.3 mrg _M_state_beg = std::move(__rhs._M_state_beg); 131 1.1.1.3 mrg _M_state_cur = std::move(__rhs._M_state_cur); 132 1.1.1.3 mrg _M_state_last = std::move(__rhs._M_state_last); 133 1.1.1.3 mrg _M_buf = std::__exchange(__rhs._M_buf, nullptr); 134 1.1.1.3 mrg _M_buf_size = std::__exchange(__rhs._M_buf_size, 1); 135 1.1.1.3 mrg _M_buf_allocated = std::__exchange(__rhs._M_buf_allocated, false); 136 1.1.1.3 mrg _M_ext_buf = std::__exchange(__rhs._M_ext_buf, nullptr); 137 1.1.1.3 mrg _M_ext_buf_size = std::__exchange(__rhs._M_ext_buf_size, 0); 138 1.1.1.3 mrg _M_ext_next = std::__exchange(__rhs._M_ext_next, nullptr); 139 1.1.1.3 mrg _M_ext_end = std::__exchange(__rhs._M_ext_end, nullptr); 140 1.1.1.3 mrg _M_reading = std::__exchange(__rhs._M_reading, false); 141 1.1.1.3 mrg _M_writing = std::__exchange(__rhs._M_writing, false); 142 1.1.1.3 mrg _M_pback_cur_save = std::__exchange(__rhs._M_pback_cur_save, nullptr); 143 1.1.1.3 mrg _M_pback_end_save = std::__exchange(__rhs._M_pback_end_save, nullptr); 144 1.1.1.3 mrg _M_pback_init = std::__exchange(__rhs._M_pback_init, false); 145 1.1.1.3 mrg __rhs._M_set_buffer(-1); 146 1.1.1.3 mrg __rhs._M_state_last = __rhs._M_state_cur = __rhs._M_state_beg; 147 1.1.1.3 mrg return *this; 148 1.1.1.3 mrg } 149 1.1.1.3 mrg 150 1.1.1.3 mrg template<typename _CharT, typename _Traits> 151 1.1.1.3 mrg void 152 1.1.1.3 mrg basic_filebuf<_CharT, _Traits>:: 153 1.1.1.3 mrg swap(basic_filebuf& __rhs) 154 1.1.1.3 mrg { 155 1.1.1.3 mrg __streambuf_type::swap(__rhs); 156 1.1.1.3 mrg _M_file.swap(__rhs._M_file); 157 1.1.1.3 mrg std::swap(_M_mode, __rhs._M_mode); 158 1.1.1.3 mrg std::swap(_M_state_beg, __rhs._M_state_beg); 159 1.1.1.3 mrg std::swap(_M_state_cur, __rhs._M_state_cur); 160 1.1.1.3 mrg std::swap(_M_state_last, __rhs._M_state_last); 161 1.1.1.3 mrg std::swap(_M_buf, __rhs._M_buf); 162 1.1.1.3 mrg std::swap(_M_buf_size, __rhs._M_buf_size); 163 1.1.1.3 mrg std::swap(_M_buf_allocated, __rhs._M_buf_allocated); 164 1.1.1.3 mrg std::swap(_M_ext_buf, __rhs._M_ext_buf); 165 1.1.1.3 mrg std::swap(_M_ext_buf_size, __rhs._M_ext_buf_size); 166 1.1.1.3 mrg std::swap(_M_ext_next, __rhs._M_ext_next); 167 1.1.1.3 mrg std::swap(_M_ext_end, __rhs._M_ext_end); 168 1.1.1.3 mrg std::swap(_M_reading, __rhs._M_reading); 169 1.1.1.3 mrg std::swap(_M_writing, __rhs._M_writing); 170 1.1.1.3 mrg std::swap(_M_pback_cur_save, __rhs._M_pback_cur_save); 171 1.1.1.3 mrg std::swap(_M_pback_end_save, __rhs._M_pback_end_save); 172 1.1.1.3 mrg std::swap(_M_pback_init, __rhs._M_pback_init); 173 1.1.1.3 mrg } 174 1.1.1.3 mrg #endif 175 1.1.1.3 mrg 176 1.1 mrg template<typename _CharT, typename _Traits> 177 1.1 mrg typename basic_filebuf<_CharT, _Traits>::__filebuf_type* 178 1.1 mrg basic_filebuf<_CharT, _Traits>:: 179 1.1 mrg open(const char* __s, ios_base::openmode __mode) 180 1.1 mrg { 181 1.1.1.2 mrg __filebuf_type *__ret = 0; 182 1.1 mrg if (!this->is_open()) 183 1.1 mrg { 184 1.1 mrg _M_file.open(__s, __mode); 185 1.1 mrg if (this->is_open()) 186 1.1 mrg { 187 1.1 mrg _M_allocate_internal_buffer(); 188 1.1 mrg _M_mode = __mode; 189 1.1 mrg 190 1.1 mrg // Setup initial buffer to 'uncommitted' mode. 191 1.1 mrg _M_reading = false; 192 1.1 mrg _M_writing = false; 193 1.1 mrg _M_set_buffer(-1); 194 1.1 mrg 195 1.1 mrg // Reset to initial state. 196 1.1 mrg _M_state_last = _M_state_cur = _M_state_beg; 197 1.1 mrg 198 1.1 mrg // 27.8.1.3,4 199 1.1 mrg if ((__mode & ios_base::ate) 200 1.1 mrg && this->seekoff(0, ios_base::end, __mode) 201 1.1 mrg == pos_type(off_type(-1))) 202 1.1 mrg this->close(); 203 1.1 mrg else 204 1.1 mrg __ret = this; 205 1.1 mrg } 206 1.1 mrg } 207 1.1 mrg return __ret; 208 1.1 mrg } 209 1.1 mrg 210 1.1.1.10 mrg #if _GLIBCXX_HAVE__WFOPEN && _GLIBCXX_USE_WCHAR_T 211 1.1.1.10 mrg template<typename _CharT, typename _Traits> 212 1.1.1.10 mrg basic_filebuf<_CharT, _Traits>* 213 1.1.1.10 mrg basic_filebuf<_CharT, _Traits>:: 214 1.1.1.10 mrg open(const wchar_t* __s, ios_base::openmode __mode) 215 1.1.1.10 mrg { 216 1.1.1.10 mrg __filebuf_type *__ret = 0; 217 1.1.1.10 mrg if (!this->is_open()) 218 1.1.1.10 mrg { 219 1.1.1.10 mrg _M_file.open(__s, __mode); 220 1.1.1.10 mrg if (this->is_open()) 221 1.1.1.10 mrg { 222 1.1.1.10 mrg _M_allocate_internal_buffer(); 223 1.1.1.10 mrg _M_mode = __mode; 224 1.1.1.10 mrg 225 1.1.1.10 mrg // Setup initial buffer to 'uncommitted' mode. 226 1.1.1.10 mrg _M_reading = false; 227 1.1.1.10 mrg _M_writing = false; 228 1.1.1.10 mrg _M_set_buffer(-1); 229 1.1.1.10 mrg 230 1.1.1.10 mrg // Reset to initial state. 231 1.1.1.10 mrg _M_state_last = _M_state_cur = _M_state_beg; 232 1.1.1.10 mrg 233 1.1.1.10 mrg // 27.8.1.3,4 234 1.1.1.10 mrg if ((__mode & ios_base::ate) 235 1.1.1.10 mrg && this->seekoff(0, ios_base::end, __mode) 236 1.1.1.10 mrg == pos_type(off_type(-1))) 237 1.1.1.10 mrg this->close(); 238 1.1.1.10 mrg else 239 1.1.1.10 mrg __ret = this; 240 1.1.1.10 mrg } 241 1.1.1.10 mrg } 242 1.1.1.10 mrg return __ret; 243 1.1.1.10 mrg } 244 1.1.1.10 mrg #endif // HAVE__WFOPEN && USE_WCHAR_T 245 1.1.1.10 mrg 246 1.1 mrg template<typename _CharT, typename _Traits> 247 1.1 mrg typename basic_filebuf<_CharT, _Traits>::__filebuf_type* 248 1.1 mrg basic_filebuf<_CharT, _Traits>:: 249 1.1 mrg close() 250 1.1 mrg { 251 1.1 mrg if (!this->is_open()) 252 1.1.1.2 mrg return 0; 253 1.1 mrg 254 1.1 mrg bool __testfail = false; 255 1.1 mrg { 256 1.1 mrg // NB: Do this here so that re-opened filebufs will be cool... 257 1.1 mrg struct __close_sentry 258 1.1 mrg { 259 1.1 mrg basic_filebuf *__fb; 260 1.1 mrg __close_sentry (basic_filebuf *__fbi): __fb(__fbi) { } 261 1.1 mrg ~__close_sentry () 262 1.1 mrg { 263 1.1 mrg __fb->_M_mode = ios_base::openmode(0); 264 1.1 mrg __fb->_M_pback_init = false; 265 1.1 mrg __fb->_M_destroy_internal_buffer(); 266 1.1 mrg __fb->_M_reading = false; 267 1.1 mrg __fb->_M_writing = false; 268 1.1 mrg __fb->_M_set_buffer(-1); 269 1.1 mrg __fb->_M_state_last = __fb->_M_state_cur = __fb->_M_state_beg; 270 1.1 mrg } 271 1.1 mrg } __cs (this); 272 1.1 mrg 273 1.1 mrg __try 274 1.1 mrg { 275 1.1 mrg if (!_M_terminate_output()) 276 1.1 mrg __testfail = true; 277 1.1 mrg } 278 1.1.1.10 mrg __catch(...) 279 1.1 mrg { 280 1.1 mrg _M_file.close(); 281 1.1 mrg __throw_exception_again; 282 1.1 mrg } 283 1.1 mrg } 284 1.1 mrg 285 1.1 mrg if (!_M_file.close()) 286 1.1 mrg __testfail = true; 287 1.1 mrg 288 1.1 mrg if (__testfail) 289 1.1.1.2 mrg return 0; 290 1.1 mrg else 291 1.1 mrg return this; 292 1.1 mrg } 293 1.1 mrg 294 1.1 mrg template<typename _CharT, typename _Traits> 295 1.1 mrg streamsize 296 1.1 mrg basic_filebuf<_CharT, _Traits>:: 297 1.1 mrg showmanyc() 298 1.1 mrg { 299 1.1 mrg streamsize __ret = -1; 300 1.1 mrg const bool __testin = _M_mode & ios_base::in; 301 1.1 mrg if (__testin && this->is_open()) 302 1.1 mrg { 303 1.1 mrg // For a stateful encoding (-1) the pending sequence might be just 304 1.1 mrg // shift and unshift prefixes with no actual character. 305 1.1 mrg __ret = this->egptr() - this->gptr(); 306 1.1 mrg 307 1.1 mrg #if _GLIBCXX_HAVE_DOS_BASED_FILESYSTEM 308 1.1 mrg // About this workaround, see libstdc++/20806. 309 1.1 mrg const bool __testbinary = _M_mode & ios_base::binary; 310 1.1 mrg if (__check_facet(_M_codecvt).encoding() >= 0 311 1.1 mrg && __testbinary) 312 1.1 mrg #else 313 1.1 mrg if (__check_facet(_M_codecvt).encoding() >= 0) 314 1.1 mrg #endif 315 1.1 mrg __ret += _M_file.showmanyc() / _M_codecvt->max_length(); 316 1.1 mrg } 317 1.1 mrg return __ret; 318 1.1 mrg } 319 1.1 mrg 320 1.1 mrg template<typename _CharT, typename _Traits> 321 1.1 mrg typename basic_filebuf<_CharT, _Traits>::int_type 322 1.1 mrg basic_filebuf<_CharT, _Traits>:: 323 1.1 mrg underflow() 324 1.1 mrg { 325 1.1 mrg int_type __ret = traits_type::eof(); 326 1.1 mrg const bool __testin = _M_mode & ios_base::in; 327 1.1.1.2 mrg if (__testin) 328 1.1 mrg { 329 1.1.1.2 mrg if (_M_writing) 330 1.1.1.2 mrg { 331 1.1.1.2 mrg if (overflow() == traits_type::eof()) 332 1.1.1.2 mrg return __ret; 333 1.1.1.2 mrg _M_set_buffer(-1); 334 1.1.1.2 mrg _M_writing = false; 335 1.1.1.2 mrg } 336 1.1 mrg // Check for pback madness, and if so switch back to the 337 1.1 mrg // normal buffers and jet outta here before expensive 338 1.1 mrg // fileops happen... 339 1.1 mrg _M_destroy_pback(); 340 1.1 mrg 341 1.1 mrg if (this->gptr() < this->egptr()) 342 1.1 mrg return traits_type::to_int_type(*this->gptr()); 343 1.1 mrg 344 1.1 mrg // Get and convert input sequence. 345 1.1 mrg const size_t __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1; 346 1.1 mrg 347 1.1 mrg // Will be set to true if ::read() returns 0 indicating EOF. 348 1.1 mrg bool __got_eof = false; 349 1.1 mrg // Number of internal characters produced. 350 1.1 mrg streamsize __ilen = 0; 351 1.1 mrg codecvt_base::result __r = codecvt_base::ok; 352 1.1 mrg if (__check_facet(_M_codecvt).always_noconv()) 353 1.1 mrg { 354 1.1 mrg __ilen = _M_file.xsgetn(reinterpret_cast<char*>(this->eback()), 355 1.1 mrg __buflen); 356 1.1 mrg if (__ilen == 0) 357 1.1 mrg __got_eof = true; 358 1.1 mrg } 359 1.1 mrg else 360 1.1 mrg { 361 1.1 mrg // Worst-case number of external bytes. 362 1.1 mrg // XXX Not done encoding() == -1. 363 1.1 mrg const int __enc = _M_codecvt->encoding(); 364 1.1 mrg streamsize __blen; // Minimum buffer size. 365 1.1 mrg streamsize __rlen; // Number of chars to read. 366 1.1 mrg if (__enc > 0) 367 1.1 mrg __blen = __rlen = __buflen * __enc; 368 1.1 mrg else 369 1.1 mrg { 370 1.1 mrg __blen = __buflen + _M_codecvt->max_length() - 1; 371 1.1 mrg __rlen = __buflen; 372 1.1 mrg } 373 1.1 mrg const streamsize __remainder = _M_ext_end - _M_ext_next; 374 1.1 mrg __rlen = __rlen > __remainder ? __rlen - __remainder : 0; 375 1.1 mrg 376 1.1 mrg // An imbue in 'read' mode implies first converting the external 377 1.1 mrg // chars already present. 378 1.1 mrg if (_M_reading && this->egptr() == this->eback() && __remainder) 379 1.1 mrg __rlen = 0; 380 1.1 mrg 381 1.1 mrg // Allocate buffer if necessary and move unconverted 382 1.1 mrg // bytes to front. 383 1.1 mrg if (_M_ext_buf_size < __blen) 384 1.1 mrg { 385 1.1 mrg char* __buf = new char[__blen]; 386 1.1 mrg if (__remainder) 387 1.1 mrg __builtin_memcpy(__buf, _M_ext_next, __remainder); 388 1.1 mrg 389 1.1 mrg delete [] _M_ext_buf; 390 1.1 mrg _M_ext_buf = __buf; 391 1.1 mrg _M_ext_buf_size = __blen; 392 1.1 mrg } 393 1.1 mrg else if (__remainder) 394 1.1 mrg __builtin_memmove(_M_ext_buf, _M_ext_next, __remainder); 395 1.1 mrg 396 1.1 mrg _M_ext_next = _M_ext_buf; 397 1.1 mrg _M_ext_end = _M_ext_buf + __remainder; 398 1.1 mrg _M_state_last = _M_state_cur; 399 1.1 mrg 400 1.1 mrg do 401 1.1 mrg { 402 1.1 mrg if (__rlen > 0) 403 1.1 mrg { 404 1.1 mrg // Sanity check! 405 1.1 mrg // This may fail if the return value of 406 1.1 mrg // codecvt::max_length() is bogus. 407 1.1 mrg if (_M_ext_end - _M_ext_buf + __rlen > _M_ext_buf_size) 408 1.1 mrg { 409 1.1 mrg __throw_ios_failure(__N("basic_filebuf::underflow " 410 1.1 mrg "codecvt::max_length() " 411 1.1 mrg "is not valid")); 412 1.1 mrg } 413 1.1 mrg streamsize __elen = _M_file.xsgetn(_M_ext_end, __rlen); 414 1.1 mrg if (__elen == 0) 415 1.1 mrg __got_eof = true; 416 1.1 mrg else if (__elen == -1) 417 1.1 mrg break; 418 1.1 mrg _M_ext_end += __elen; 419 1.1 mrg } 420 1.1 mrg 421 1.1 mrg char_type* __iend = this->eback(); 422 1.1 mrg if (_M_ext_next < _M_ext_end) 423 1.1 mrg __r = _M_codecvt->in(_M_state_cur, _M_ext_next, 424 1.1 mrg _M_ext_end, _M_ext_next, 425 1.1 mrg this->eback(), 426 1.1 mrg this->eback() + __buflen, __iend); 427 1.1 mrg if (__r == codecvt_base::noconv) 428 1.1 mrg { 429 1.1 mrg size_t __avail = _M_ext_end - _M_ext_buf; 430 1.1 mrg __ilen = std::min(__avail, __buflen); 431 1.1 mrg traits_type::copy(this->eback(), 432 1.1 mrg reinterpret_cast<char_type*> 433 1.1 mrg (_M_ext_buf), __ilen); 434 1.1 mrg _M_ext_next = _M_ext_buf + __ilen; 435 1.1 mrg } 436 1.1 mrg else 437 1.1 mrg __ilen = __iend - this->eback(); 438 1.1 mrg 439 1.1 mrg // _M_codecvt->in may return error while __ilen > 0: this is 440 1.1 mrg // ok, and actually occurs in case of mixed encodings (e.g., 441 1.1 mrg // XML files). 442 1.1 mrg if (__r == codecvt_base::error) 443 1.1 mrg break; 444 1.1 mrg 445 1.1 mrg __rlen = 1; 446 1.1 mrg } 447 1.1 mrg while (__ilen == 0 && !__got_eof); 448 1.1 mrg } 449 1.1 mrg 450 1.1 mrg if (__ilen > 0) 451 1.1 mrg { 452 1.1 mrg _M_set_buffer(__ilen); 453 1.1 mrg _M_reading = true; 454 1.1 mrg __ret = traits_type::to_int_type(*this->gptr()); 455 1.1 mrg } 456 1.1 mrg else if (__got_eof) 457 1.1 mrg { 458 1.1 mrg // If the actual end of file is reached, set 'uncommitted' 459 1.1 mrg // mode, thus allowing an immediate write without an 460 1.1 mrg // intervening seek. 461 1.1 mrg _M_set_buffer(-1); 462 1.1 mrg _M_reading = false; 463 1.1 mrg // However, reaching it while looping on partial means that 464 1.1 mrg // the file has got an incomplete character. 465 1.1 mrg if (__r == codecvt_base::partial) 466 1.1 mrg __throw_ios_failure(__N("basic_filebuf::underflow " 467 1.1 mrg "incomplete character in file")); 468 1.1 mrg } 469 1.1 mrg else if (__r == codecvt_base::error) 470 1.1 mrg __throw_ios_failure(__N("basic_filebuf::underflow " 471 1.1 mrg "invalid byte sequence in file")); 472 1.1 mrg else 473 1.1 mrg __throw_ios_failure(__N("basic_filebuf::underflow " 474 1.1.1.10 mrg "error reading the file"), errno); 475 1.1 mrg } 476 1.1 mrg return __ret; 477 1.1 mrg } 478 1.1 mrg 479 1.1 mrg template<typename _CharT, typename _Traits> 480 1.1 mrg typename basic_filebuf<_CharT, _Traits>::int_type 481 1.1 mrg basic_filebuf<_CharT, _Traits>:: 482 1.1 mrg pbackfail(int_type __i) 483 1.1 mrg { 484 1.1 mrg int_type __ret = traits_type::eof(); 485 1.1 mrg const bool __testin = _M_mode & ios_base::in; 486 1.1.1.2 mrg if (__testin) 487 1.1 mrg { 488 1.1.1.2 mrg if (_M_writing) 489 1.1.1.2 mrg { 490 1.1.1.2 mrg if (overflow() == traits_type::eof()) 491 1.1.1.2 mrg return __ret; 492 1.1.1.2 mrg _M_set_buffer(-1); 493 1.1.1.2 mrg _M_writing = false; 494 1.1.1.2 mrg } 495 1.1 mrg // Remember whether the pback buffer is active, otherwise below 496 1.1 mrg // we may try to store in it a second char (libstdc++/9761). 497 1.1 mrg const bool __testpb = _M_pback_init; 498 1.1 mrg const bool __testeof = traits_type::eq_int_type(__i, __ret); 499 1.1 mrg int_type __tmp; 500 1.1 mrg if (this->eback() < this->gptr()) 501 1.1 mrg { 502 1.1 mrg this->gbump(-1); 503 1.1 mrg __tmp = traits_type::to_int_type(*this->gptr()); 504 1.1 mrg } 505 1.1 mrg else if (this->seekoff(-1, ios_base::cur) != pos_type(off_type(-1))) 506 1.1 mrg { 507 1.1 mrg __tmp = this->underflow(); 508 1.1 mrg if (traits_type::eq_int_type(__tmp, __ret)) 509 1.1 mrg return __ret; 510 1.1 mrg } 511 1.1 mrg else 512 1.1 mrg { 513 1.1 mrg // At the beginning of the buffer, need to make a 514 1.1 mrg // putback position available. But the seek may fail 515 1.1 mrg // (f.i., at the beginning of a file, see 516 1.1 mrg // libstdc++/9439) and in that case we return 517 1.1 mrg // traits_type::eof(). 518 1.1 mrg return __ret; 519 1.1 mrg } 520 1.1 mrg 521 1.1 mrg // Try to put back __i into input sequence in one of three ways. 522 1.1 mrg // Order these tests done in is unspecified by the standard. 523 1.1 mrg if (!__testeof && traits_type::eq_int_type(__i, __tmp)) 524 1.1 mrg __ret = __i; 525 1.1 mrg else if (__testeof) 526 1.1 mrg __ret = traits_type::not_eof(__i); 527 1.1 mrg else if (!__testpb) 528 1.1 mrg { 529 1.1 mrg _M_create_pback(); 530 1.1 mrg _M_reading = true; 531 1.1 mrg *this->gptr() = traits_type::to_char_type(__i); 532 1.1 mrg __ret = __i; 533 1.1 mrg } 534 1.1 mrg } 535 1.1 mrg return __ret; 536 1.1 mrg } 537 1.1 mrg 538 1.1 mrg template<typename _CharT, typename _Traits> 539 1.1 mrg typename basic_filebuf<_CharT, _Traits>::int_type 540 1.1 mrg basic_filebuf<_CharT, _Traits>:: 541 1.1 mrg overflow(int_type __c) 542 1.1 mrg { 543 1.1 mrg int_type __ret = traits_type::eof(); 544 1.1 mrg const bool __testeof = traits_type::eq_int_type(__c, __ret); 545 1.1.1.3 mrg const bool __testout = (_M_mode & ios_base::out 546 1.1.1.3 mrg || _M_mode & ios_base::app); 547 1.1.1.2 mrg if (__testout) 548 1.1 mrg { 549 1.1.1.2 mrg if (_M_reading) 550 1.1.1.2 mrg { 551 1.1.1.2 mrg _M_destroy_pback(); 552 1.1.1.2 mrg const int __gptr_off = _M_get_ext_pos(_M_state_last); 553 1.1.1.2 mrg if (_M_seek(__gptr_off, ios_base::cur, _M_state_last) 554 1.1.1.2 mrg == pos_type(off_type(-1))) 555 1.1.1.2 mrg return __ret; 556 1.1.1.2 mrg } 557 1.1 mrg if (this->pbase() < this->pptr()) 558 1.1 mrg { 559 1.1 mrg // If appropriate, append the overflow char. 560 1.1 mrg if (!__testeof) 561 1.1 mrg { 562 1.1 mrg *this->pptr() = traits_type::to_char_type(__c); 563 1.1 mrg this->pbump(1); 564 1.1 mrg } 565 1.1 mrg 566 1.1 mrg // Convert pending sequence to external representation, 567 1.1 mrg // and output. 568 1.1 mrg if (_M_convert_to_external(this->pbase(), 569 1.1 mrg this->pptr() - this->pbase())) 570 1.1 mrg { 571 1.1 mrg _M_set_buffer(0); 572 1.1 mrg __ret = traits_type::not_eof(__c); 573 1.1 mrg } 574 1.1 mrg } 575 1.1 mrg else if (_M_buf_size > 1) 576 1.1 mrg { 577 1.1 mrg // Overflow in 'uncommitted' mode: set _M_writing, set 578 1.1 mrg // the buffer to the initial 'write' mode, and put __c 579 1.1 mrg // into the buffer. 580 1.1 mrg _M_set_buffer(0); 581 1.1 mrg _M_writing = true; 582 1.1 mrg if (!__testeof) 583 1.1 mrg { 584 1.1 mrg *this->pptr() = traits_type::to_char_type(__c); 585 1.1 mrg this->pbump(1); 586 1.1 mrg } 587 1.1 mrg __ret = traits_type::not_eof(__c); 588 1.1 mrg } 589 1.1 mrg else 590 1.1 mrg { 591 1.1 mrg // Unbuffered. 592 1.1 mrg char_type __conv = traits_type::to_char_type(__c); 593 1.1 mrg if (__testeof || _M_convert_to_external(&__conv, 1)) 594 1.1 mrg { 595 1.1 mrg _M_writing = true; 596 1.1 mrg __ret = traits_type::not_eof(__c); 597 1.1 mrg } 598 1.1 mrg } 599 1.1 mrg } 600 1.1 mrg return __ret; 601 1.1 mrg } 602 1.1 mrg 603 1.1 mrg template<typename _CharT, typename _Traits> 604 1.1 mrg bool 605 1.1 mrg basic_filebuf<_CharT, _Traits>:: 606 1.1 mrg _M_convert_to_external(_CharT* __ibuf, streamsize __ilen) 607 1.1 mrg { 608 1.1 mrg // Sizes of external and pending output. 609 1.1 mrg streamsize __elen; 610 1.1 mrg streamsize __plen; 611 1.1 mrg if (__check_facet(_M_codecvt).always_noconv()) 612 1.1 mrg { 613 1.1 mrg __elen = _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen); 614 1.1 mrg __plen = __ilen; 615 1.1 mrg } 616 1.1 mrg else 617 1.1 mrg { 618 1.1 mrg // Worst-case number of external bytes needed. 619 1.1 mrg // XXX Not done encoding() == -1. 620 1.1 mrg streamsize __blen = __ilen * _M_codecvt->max_length(); 621 1.1 mrg char* __buf = static_cast<char*>(__builtin_alloca(__blen)); 622 1.1 mrg 623 1.1 mrg char* __bend; 624 1.1 mrg const char_type* __iend; 625 1.1 mrg codecvt_base::result __r; 626 1.1 mrg __r = _M_codecvt->out(_M_state_cur, __ibuf, __ibuf + __ilen, 627 1.1 mrg __iend, __buf, __buf + __blen, __bend); 628 1.1 mrg 629 1.1 mrg if (__r == codecvt_base::ok || __r == codecvt_base::partial) 630 1.1 mrg __blen = __bend - __buf; 631 1.1 mrg else if (__r == codecvt_base::noconv) 632 1.1 mrg { 633 1.1 mrg // Same as the always_noconv case above. 634 1.1 mrg __buf = reinterpret_cast<char*>(__ibuf); 635 1.1 mrg __blen = __ilen; 636 1.1 mrg } 637 1.1 mrg else 638 1.1 mrg __throw_ios_failure(__N("basic_filebuf::_M_convert_to_external " 639 1.1 mrg "conversion error")); 640 1.1 mrg 641 1.1 mrg __elen = _M_file.xsputn(__buf, __blen); 642 1.1 mrg __plen = __blen; 643 1.1 mrg 644 1.1 mrg // Try once more for partial conversions. 645 1.1 mrg if (__r == codecvt_base::partial && __elen == __plen) 646 1.1 mrg { 647 1.1 mrg const char_type* __iresume = __iend; 648 1.1 mrg streamsize __rlen = this->pptr() - __iend; 649 1.1 mrg __r = _M_codecvt->out(_M_state_cur, __iresume, 650 1.1 mrg __iresume + __rlen, __iend, __buf, 651 1.1 mrg __buf + __blen, __bend); 652 1.1 mrg if (__r != codecvt_base::error) 653 1.1 mrg { 654 1.1 mrg __rlen = __bend - __buf; 655 1.1 mrg __elen = _M_file.xsputn(__buf, __rlen); 656 1.1 mrg __plen = __rlen; 657 1.1 mrg } 658 1.1 mrg else 659 1.1 mrg __throw_ios_failure(__N("basic_filebuf::_M_convert_to_external " 660 1.1 mrg "conversion error")); 661 1.1 mrg } 662 1.1 mrg } 663 1.1 mrg return __elen == __plen; 664 1.1 mrg } 665 1.1 mrg 666 1.1.1.2 mrg template<typename _CharT, typename _Traits> 667 1.1.1.2 mrg streamsize 668 1.1.1.2 mrg basic_filebuf<_CharT, _Traits>:: 669 1.1.1.2 mrg xsgetn(_CharT* __s, streamsize __n) 670 1.1.1.2 mrg { 671 1.1.1.2 mrg // Clear out pback buffer before going on to the real deal... 672 1.1.1.2 mrg streamsize __ret = 0; 673 1.1.1.2 mrg if (_M_pback_init) 674 1.1.1.2 mrg { 675 1.1.1.2 mrg if (__n > 0 && this->gptr() == this->eback()) 676 1.1.1.2 mrg { 677 1.1.1.2 mrg *__s++ = *this->gptr(); // emulate non-underflowing sbumpc 678 1.1.1.2 mrg this->gbump(1); 679 1.1.1.2 mrg __ret = 1; 680 1.1.1.2 mrg --__n; 681 1.1.1.2 mrg } 682 1.1.1.2 mrg _M_destroy_pback(); 683 1.1.1.2 mrg } 684 1.1.1.2 mrg else if (_M_writing) 685 1.1.1.2 mrg { 686 1.1.1.9 mrg if (overflow() == traits_type::eof()) 687 1.1.1.9 mrg return __ret; 688 1.1.1.9 mrg _M_set_buffer(-1); 689 1.1.1.9 mrg _M_writing = false; 690 1.1.1.9 mrg } 691 1.1.1.2 mrg 692 1.1.1.2 mrg // Optimization in the always_noconv() case, to be generalized in the 693 1.1.1.2 mrg // future: when __n > __buflen we read directly instead of using the 694 1.1.1.2 mrg // buffer repeatedly. 695 1.1.1.2 mrg const bool __testin = _M_mode & ios_base::in; 696 1.1.1.2 mrg const streamsize __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1; 697 1.1.1.2 mrg 698 1.1.1.2 mrg if (__n > __buflen && __check_facet(_M_codecvt).always_noconv() 699 1.1.1.9 mrg && __testin) 700 1.1.1.9 mrg { 701 1.1.1.9 mrg // First, copy the chars already present in the buffer. 702 1.1.1.9 mrg const streamsize __avail = this->egptr() - this->gptr(); 703 1.1.1.9 mrg if (__avail != 0) 704 1.1.1.9 mrg { 705 1.1.1.9 mrg traits_type::copy(__s, this->gptr(), __avail); 706 1.1.1.9 mrg __s += __avail; 707 1.1.1.9 mrg this->setg(this->eback(), this->gptr() + __avail, this->egptr()); 708 1.1.1.9 mrg __ret += __avail; 709 1.1.1.9 mrg __n -= __avail; 710 1.1.1.9 mrg } 711 1.1.1.8 mrg 712 1.1.1.9 mrg // Need to loop in case of short reads (relatively common 713 1.1.1.9 mrg // with pipes). 714 1.1.1.9 mrg streamsize __len; 715 1.1.1.9 mrg for (;;) 716 1.1.1.9 mrg { 717 1.1.1.9 mrg __len = _M_file.xsgetn(reinterpret_cast<char*>(__s), __n); 718 1.1.1.9 mrg if (__len == -1) 719 1.1.1.9 mrg __throw_ios_failure(__N("basic_filebuf::xsgetn " 720 1.1.1.10 mrg "error reading the file"), errno); 721 1.1.1.9 mrg if (__len == 0) 722 1.1.1.9 mrg break; 723 1.1.1.8 mrg 724 1.1.1.9 mrg __n -= __len; 725 1.1.1.9 mrg __ret += __len; 726 1.1.1.9 mrg if (__n == 0) 727 1.1.1.9 mrg break; 728 1.1.1.9 mrg 729 1.1.1.9 mrg __s += __len; 730 1.1.1.9 mrg } 731 1.1.1.9 mrg 732 1.1.1.9 mrg if (__n == 0) 733 1.1.1.9 mrg { 734 1.1.1.9 mrg // Set _M_reading. Buffer is already in initial 'read' mode. 735 1.1.1.9 mrg _M_reading = true; 736 1.1.1.9 mrg } 737 1.1.1.9 mrg else if (__len == 0) 738 1.1.1.9 mrg { 739 1.1.1.9 mrg // If end of file is reached, set 'uncommitted' 740 1.1.1.9 mrg // mode, thus allowing an immediate write without 741 1.1.1.9 mrg // an intervening seek. 742 1.1.1.9 mrg _M_set_buffer(-1); 743 1.1.1.9 mrg _M_reading = false; 744 1.1.1.9 mrg } 745 1.1.1.9 mrg } 746 1.1.1.2 mrg else 747 1.1.1.9 mrg __ret += __streambuf_type::xsgetn(__s, __n); 748 1.1.1.2 mrg 749 1.1.1.2 mrg return __ret; 750 1.1.1.2 mrg } 751 1.1 mrg 752 1.1.1.2 mrg template<typename _CharT, typename _Traits> 753 1.1.1.2 mrg streamsize 754 1.1.1.2 mrg basic_filebuf<_CharT, _Traits>:: 755 1.1.1.2 mrg xsputn(const _CharT* __s, streamsize __n) 756 1.1.1.2 mrg { 757 1.1.1.2 mrg streamsize __ret = 0; 758 1.1.1.2 mrg // Optimization in the always_noconv() case, to be generalized in the 759 1.1.1.13 mrg // future: when __n is larger than the available capacity we write 760 1.1.1.13 mrg // directly instead of using the buffer. 761 1.1.1.3 mrg const bool __testout = (_M_mode & ios_base::out 762 1.1.1.3 mrg || _M_mode & ios_base::app); 763 1.1.1.2 mrg if (__check_facet(_M_codecvt).always_noconv() 764 1.1.1.9 mrg && __testout && !_M_reading) 765 1.1 mrg { 766 1.1 mrg streamsize __bufavail = this->epptr() - this->pptr(); 767 1.1 mrg 768 1.1 mrg // Don't mistake 'uncommitted' mode buffered with unbuffered. 769 1.1 mrg if (!_M_writing && _M_buf_size > 1) 770 1.1 mrg __bufavail = _M_buf_size - 1; 771 1.1 mrg 772 1.1.1.13 mrg if (__n >= __bufavail) 773 1.1 mrg { 774 1.1 mrg const streamsize __buffill = this->pptr() - this->pbase(); 775 1.1 mrg const char* __buf = reinterpret_cast<const char*>(this->pbase()); 776 1.1 mrg __ret = _M_file.xsputn_2(__buf, __buffill, 777 1.1 mrg reinterpret_cast<const char*>(__s), 778 1.1 mrg __n); 779 1.1 mrg if (__ret == __buffill + __n) 780 1.1 mrg { 781 1.1 mrg _M_set_buffer(0); 782 1.1 mrg _M_writing = true; 783 1.1 mrg } 784 1.1 mrg if (__ret > __buffill) 785 1.1 mrg __ret -= __buffill; 786 1.1 mrg else 787 1.1 mrg __ret = 0; 788 1.1 mrg } 789 1.1 mrg else 790 1.1 mrg __ret = __streambuf_type::xsputn(__s, __n); 791 1.1 mrg } 792 1.1 mrg else 793 1.1 mrg __ret = __streambuf_type::xsputn(__s, __n); 794 1.1 mrg return __ret; 795 1.1 mrg } 796 1.1 mrg 797 1.1 mrg template<typename _CharT, typename _Traits> 798 1.1 mrg typename basic_filebuf<_CharT, _Traits>::__streambuf_type* 799 1.1 mrg basic_filebuf<_CharT, _Traits>:: 800 1.1 mrg setbuf(char_type* __s, streamsize __n) 801 1.1 mrg { 802 1.1 mrg if (!this->is_open()) 803 1.1 mrg { 804 1.1 mrg if (__s == 0 && __n == 0) 805 1.1 mrg _M_buf_size = 1; 806 1.1 mrg else if (__s && __n > 0) 807 1.1 mrg { 808 1.1 mrg // This is implementation-defined behavior, and assumes that 809 1.1 mrg // an external char_type array of length __n exists and has 810 1.1 mrg // been pre-allocated. If this is not the case, things will 811 1.1 mrg // quickly blow up. When __n > 1, __n - 1 positions will be 812 1.1 mrg // used for the get area, __n - 1 for the put area and 1 813 1.1 mrg // position to host the overflow char of a full put area. 814 1.1 mrg // When __n == 1, 1 position will be used for the get area 815 1.1 mrg // and 0 for the put area, as in the unbuffered case above. 816 1.1 mrg _M_buf = __s; 817 1.1 mrg _M_buf_size = __n; 818 1.1 mrg } 819 1.1 mrg } 820 1.1 mrg return this; 821 1.1 mrg } 822 1.1 mrg 823 1.1 mrg 824 1.1 mrg // According to 27.8.1.4 p11 - 13, seekoff should ignore the last 825 1.1 mrg // argument (of type openmode). 826 1.1 mrg template<typename _CharT, typename _Traits> 827 1.1 mrg typename basic_filebuf<_CharT, _Traits>::pos_type 828 1.1 mrg basic_filebuf<_CharT, _Traits>:: 829 1.1 mrg seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode) 830 1.1 mrg { 831 1.1 mrg int __width = 0; 832 1.1 mrg if (_M_codecvt) 833 1.1 mrg __width = _M_codecvt->encoding(); 834 1.1 mrg if (__width < 0) 835 1.1 mrg __width = 0; 836 1.1 mrg 837 1.1.1.2 mrg pos_type __ret = pos_type(off_type(-1)); 838 1.1 mrg const bool __testfail = __off != 0 && __width <= 0; 839 1.1 mrg if (this->is_open() && !__testfail) 840 1.1 mrg { 841 1.1.1.2 mrg // tellg and tellp queries do not affect any state, unless 842 1.1.1.2 mrg // ! always_noconv and the put sequence is not empty. 843 1.1.1.2 mrg // In that case, determining the position requires converting the 844 1.1.1.2 mrg // put sequence. That doesn't use ext_buf, so requires a flush. 845 1.1.1.2 mrg bool __no_movement = __way == ios_base::cur && __off == 0 846 1.1.1.2 mrg && (!_M_writing || _M_codecvt->always_noconv()); 847 1.1.1.2 mrg 848 1.1 mrg // Ditch any pback buffers to avoid confusion. 849 1.1.1.2 mrg if (!__no_movement) 850 1.1.1.2 mrg _M_destroy_pback(); 851 1.1 mrg 852 1.1 mrg // Correct state at destination. Note that this is the correct 853 1.1 mrg // state for the current position during output, because 854 1.1 mrg // codecvt::unshift() returns the state to the initial state. 855 1.1 mrg // This is also the correct state at the end of the file because 856 1.1 mrg // an unshift sequence should have been written at the end. 857 1.1 mrg __state_type __state = _M_state_beg; 858 1.1 mrg off_type __computed_off = __off * __width; 859 1.1 mrg if (_M_reading && __way == ios_base::cur) 860 1.1 mrg { 861 1.1.1.2 mrg __state = _M_state_last; 862 1.1.1.2 mrg __computed_off += _M_get_ext_pos(__state); 863 1.1.1.2 mrg } 864 1.1.1.2 mrg if (!__no_movement) 865 1.1.1.2 mrg __ret = _M_seek(__computed_off, __way, __state); 866 1.1.1.2 mrg else 867 1.1.1.2 mrg { 868 1.1.1.2 mrg if (_M_writing) 869 1.1.1.2 mrg __computed_off = this->pptr() - this->pbase(); 870 1.1.1.2 mrg 871 1.1.1.9 mrg off_type __file_off = _M_file.seekoff(0, ios_base::cur); 872 1.1.1.9 mrg if (__file_off != off_type(-1)) 873 1.1 mrg { 874 1.1.1.2 mrg __ret = __file_off + __computed_off; 875 1.1.1.2 mrg __ret.state(__state); 876 1.1 mrg } 877 1.1 mrg } 878 1.1 mrg } 879 1.1 mrg return __ret; 880 1.1 mrg } 881 1.1 mrg 882 1.1 mrg // _GLIBCXX_RESOLVE_LIB_DEFECTS 883 1.1 mrg // 171. Strange seekpos() semantics due to joint position 884 1.1 mrg // According to the resolution of DR 171, seekpos should ignore the last 885 1.1 mrg // argument (of type openmode). 886 1.1 mrg template<typename _CharT, typename _Traits> 887 1.1 mrg typename basic_filebuf<_CharT, _Traits>::pos_type 888 1.1 mrg basic_filebuf<_CharT, _Traits>:: 889 1.1 mrg seekpos(pos_type __pos, ios_base::openmode) 890 1.1 mrg { 891 1.1 mrg pos_type __ret = pos_type(off_type(-1)); 892 1.1 mrg if (this->is_open()) 893 1.1 mrg { 894 1.1 mrg // Ditch any pback buffers to avoid confusion. 895 1.1 mrg _M_destroy_pback(); 896 1.1 mrg __ret = _M_seek(off_type(__pos), ios_base::beg, __pos.state()); 897 1.1 mrg } 898 1.1 mrg return __ret; 899 1.1 mrg } 900 1.1 mrg 901 1.1 mrg template<typename _CharT, typename _Traits> 902 1.1 mrg typename basic_filebuf<_CharT, _Traits>::pos_type 903 1.1 mrg basic_filebuf<_CharT, _Traits>:: 904 1.1 mrg _M_seek(off_type __off, ios_base::seekdir __way, __state_type __state) 905 1.1 mrg { 906 1.1 mrg pos_type __ret = pos_type(off_type(-1)); 907 1.1 mrg if (_M_terminate_output()) 908 1.1 mrg { 909 1.1.1.2 mrg off_type __file_off = _M_file.seekoff(__off, __way); 910 1.1.1.2 mrg if (__file_off != off_type(-1)) 911 1.1 mrg { 912 1.1 mrg _M_reading = false; 913 1.1 mrg _M_writing = false; 914 1.1 mrg _M_ext_next = _M_ext_end = _M_ext_buf; 915 1.1 mrg _M_set_buffer(-1); 916 1.1 mrg _M_state_cur = __state; 917 1.1.1.2 mrg __ret = __file_off; 918 1.1 mrg __ret.state(_M_state_cur); 919 1.1 mrg } 920 1.1 mrg } 921 1.1 mrg return __ret; 922 1.1 mrg } 923 1.1 mrg 924 1.1.1.2 mrg // Returns the distance from the end of the ext buffer to the point 925 1.1.1.2 mrg // corresponding to gptr(). This is a negative value. Updates __state 926 1.1.1.2 mrg // from eback() correspondence to gptr(). 927 1.1.1.2 mrg template<typename _CharT, typename _Traits> 928 1.1.1.2 mrg int basic_filebuf<_CharT, _Traits>:: 929 1.1.1.2 mrg _M_get_ext_pos(__state_type& __state) 930 1.1.1.2 mrg { 931 1.1.1.2 mrg if (_M_codecvt->always_noconv()) 932 1.1.1.2 mrg return this->gptr() - this->egptr(); 933 1.1.1.2 mrg else 934 1.1.1.2 mrg { 935 1.1.1.2 mrg // Calculate offset from _M_ext_buf that corresponds to 936 1.1.1.2 mrg // gptr(). Precondition: __state == _M_state_last, which 937 1.1.1.2 mrg // corresponds to eback(). 938 1.1.1.2 mrg const int __gptr_off = 939 1.1.1.2 mrg _M_codecvt->length(__state, _M_ext_buf, _M_ext_next, 940 1.1.1.2 mrg this->gptr() - this->eback()); 941 1.1.1.2 mrg return _M_ext_buf + __gptr_off - _M_ext_end; 942 1.1.1.2 mrg } 943 1.1.1.2 mrg } 944 1.1.1.2 mrg 945 1.1 mrg template<typename _CharT, typename _Traits> 946 1.1 mrg bool 947 1.1 mrg basic_filebuf<_CharT, _Traits>:: 948 1.1 mrg _M_terminate_output() 949 1.1 mrg { 950 1.1 mrg // Part one: update the output sequence. 951 1.1 mrg bool __testvalid = true; 952 1.1 mrg if (this->pbase() < this->pptr()) 953 1.1 mrg { 954 1.1 mrg const int_type __tmp = this->overflow(); 955 1.1 mrg if (traits_type::eq_int_type(__tmp, traits_type::eof())) 956 1.1 mrg __testvalid = false; 957 1.1 mrg } 958 1.1 mrg 959 1.1 mrg // Part two: output unshift sequence. 960 1.1 mrg if (_M_writing && !__check_facet(_M_codecvt).always_noconv() 961 1.1 mrg && __testvalid) 962 1.1 mrg { 963 1.1 mrg // Note: this value is arbitrary, since there is no way to 964 1.1 mrg // get the length of the unshift sequence from codecvt, 965 1.1 mrg // without calling unshift. 966 1.1 mrg const size_t __blen = 128; 967 1.1 mrg char __buf[__blen]; 968 1.1 mrg codecvt_base::result __r; 969 1.1 mrg streamsize __ilen = 0; 970 1.1 mrg 971 1.1 mrg do 972 1.1 mrg { 973 1.1 mrg char* __next; 974 1.1 mrg __r = _M_codecvt->unshift(_M_state_cur, __buf, 975 1.1 mrg __buf + __blen, __next); 976 1.1 mrg if (__r == codecvt_base::error) 977 1.1 mrg __testvalid = false; 978 1.1 mrg else if (__r == codecvt_base::ok || 979 1.1 mrg __r == codecvt_base::partial) 980 1.1 mrg { 981 1.1 mrg __ilen = __next - __buf; 982 1.1 mrg if (__ilen > 0) 983 1.1 mrg { 984 1.1 mrg const streamsize __elen = _M_file.xsputn(__buf, __ilen); 985 1.1 mrg if (__elen != __ilen) 986 1.1 mrg __testvalid = false; 987 1.1 mrg } 988 1.1 mrg } 989 1.1 mrg } 990 1.1 mrg while (__r == codecvt_base::partial && __ilen > 0 && __testvalid); 991 1.1 mrg 992 1.1 mrg if (__testvalid) 993 1.1 mrg { 994 1.1 mrg // This second call to overflow() is required by the standard, 995 1.1 mrg // but it's not clear why it's needed, since the output buffer 996 1.1 mrg // should be empty by this point (it should have been emptied 997 1.1 mrg // in the first call to overflow()). 998 1.1 mrg const int_type __tmp = this->overflow(); 999 1.1 mrg if (traits_type::eq_int_type(__tmp, traits_type::eof())) 1000 1.1 mrg __testvalid = false; 1001 1.1 mrg } 1002 1.1 mrg } 1003 1.1 mrg return __testvalid; 1004 1.1 mrg } 1005 1.1 mrg 1006 1.1 mrg template<typename _CharT, typename _Traits> 1007 1.1 mrg int 1008 1.1 mrg basic_filebuf<_CharT, _Traits>:: 1009 1.1 mrg sync() 1010 1.1 mrg { 1011 1.1 mrg // Make sure that the internal buffer resyncs its idea of 1012 1.1 mrg // the file position with the external file. 1013 1.1 mrg int __ret = 0; 1014 1.1 mrg if (this->pbase() < this->pptr()) 1015 1.1 mrg { 1016 1.1 mrg const int_type __tmp = this->overflow(); 1017 1.1 mrg if (traits_type::eq_int_type(__tmp, traits_type::eof())) 1018 1.1 mrg __ret = -1; 1019 1.1 mrg } 1020 1.1 mrg return __ret; 1021 1.1 mrg } 1022 1.1 mrg 1023 1.1 mrg template<typename _CharT, typename _Traits> 1024 1.1 mrg void 1025 1.1 mrg basic_filebuf<_CharT, _Traits>:: 1026 1.1 mrg imbue(const locale& __loc) 1027 1.1 mrg { 1028 1.1 mrg bool __testvalid = true; 1029 1.1 mrg 1030 1.1.1.13 mrg const __codecvt_type* const _M_codecvt_tmp 1031 1.1.1.13 mrg = __try_use_facet<__codecvt_type>(__loc); 1032 1.1 mrg 1033 1.1 mrg if (this->is_open()) 1034 1.1 mrg { 1035 1.1 mrg // encoding() == -1 is ok only at the beginning. 1036 1.1 mrg if ((_M_reading || _M_writing) 1037 1.1 mrg && __check_facet(_M_codecvt).encoding() == -1) 1038 1.1 mrg __testvalid = false; 1039 1.1 mrg else 1040 1.1 mrg { 1041 1.1 mrg if (_M_reading) 1042 1.1 mrg { 1043 1.1 mrg if (__check_facet(_M_codecvt).always_noconv()) 1044 1.1 mrg { 1045 1.1 mrg if (_M_codecvt_tmp 1046 1.1 mrg && !__check_facet(_M_codecvt_tmp).always_noconv()) 1047 1.1 mrg __testvalid = this->seekoff(0, ios_base::cur, _M_mode) 1048 1.1 mrg != pos_type(off_type(-1)); 1049 1.1 mrg } 1050 1.1 mrg else 1051 1.1 mrg { 1052 1.1 mrg // External position corresponding to gptr(). 1053 1.1 mrg _M_ext_next = _M_ext_buf 1054 1.1.1.2 mrg + _M_codecvt->length(_M_state_last, _M_ext_buf, 1055 1.1.1.2 mrg _M_ext_next, 1056 1.1 mrg this->gptr() - this->eback()); 1057 1.1 mrg const streamsize __remainder = _M_ext_end - _M_ext_next; 1058 1.1 mrg if (__remainder) 1059 1.1 mrg __builtin_memmove(_M_ext_buf, _M_ext_next, __remainder); 1060 1.1 mrg 1061 1.1 mrg _M_ext_next = _M_ext_buf; 1062 1.1 mrg _M_ext_end = _M_ext_buf + __remainder; 1063 1.1 mrg _M_set_buffer(-1); 1064 1.1 mrg _M_state_last = _M_state_cur = _M_state_beg; 1065 1.1 mrg } 1066 1.1 mrg } 1067 1.1 mrg else if (_M_writing && (__testvalid = _M_terminate_output())) 1068 1.1 mrg _M_set_buffer(-1); 1069 1.1 mrg } 1070 1.1 mrg } 1071 1.1 mrg 1072 1.1 mrg if (__testvalid) 1073 1.1 mrg _M_codecvt = _M_codecvt_tmp; 1074 1.1 mrg else 1075 1.1 mrg _M_codecvt = 0; 1076 1.1 mrg } 1077 1.1 mrg 1078 1.1 mrg // Inhibit implicit instantiations for required instantiations, 1079 1.1 mrg // which are defined via explicit instantiations elsewhere. 1080 1.1 mrg #if _GLIBCXX_EXTERN_TEMPLATE 1081 1.1 mrg extern template class basic_filebuf<char>; 1082 1.1 mrg extern template class basic_ifstream<char>; 1083 1.1 mrg extern template class basic_ofstream<char>; 1084 1.1 mrg extern template class basic_fstream<char>; 1085 1.1 mrg 1086 1.1 mrg #ifdef _GLIBCXX_USE_WCHAR_T 1087 1.1 mrg extern template class basic_filebuf<wchar_t>; 1088 1.1 mrg extern template class basic_ifstream<wchar_t>; 1089 1.1 mrg extern template class basic_ofstream<wchar_t>; 1090 1.1 mrg extern template class basic_fstream<wchar_t>; 1091 1.1 mrg #endif 1092 1.1 mrg #endif 1093 1.1 mrg 1094 1.1.1.2 mrg _GLIBCXX_END_NAMESPACE_VERSION 1095 1.1.1.2 mrg } // namespace std 1096 1.1 mrg 1097 1.1 mrg #endif 1098