xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/include/bits/fstream.tcc (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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