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