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