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