source: svn/newcon3bcm2_21bu/toolchain/include/c++/3.4.2/bits/fstream.tcc @ 22

Last change on this file since 22 was 22, checked in by phkim, 11 years ago
  1. phkim
  2. newcon3sk 를 kctv 로 브랜치 함
  • Property svn:executable set to *
File size: 24.2 KB
Line 
1// File based streams -*- C++ -*-
2
3// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
4// Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library.  This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16
17// You should have received a copy of the GNU General Public License along
18// with this library; see the file COPYING.  If not, write to the Free
19// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20// USA.
21
22// As a special exception, you may use this file as part of a free software
23// library without restriction.  Specifically, if other files instantiate
24// templates or use macros or inline functions from this file, or you compile
25// this file and link it with other files to produce an executable, this
26// file does not by itself cause the resulting executable to be covered by
27// the GNU General Public License.  This exception does not however
28// invalidate any other reasons why the executable file might be covered by
29// the GNU General Public License.
30
31//
32// ISO C++ 14882: 27.8  File-based streams
33//
34
35#ifndef _FSTREAM_TCC
36#define _FSTREAM_TCC 1
37
38#pragma GCC system_header
39
40namespace std
41{
42  template<typename _CharT, typename _Traits>
43    void
44    basic_filebuf<_CharT, _Traits>::
45    _M_allocate_internal_buffer()
46    {
47      // Allocate internal buffer only if one doesn't already exist
48      // (either allocated or provided by the user via setbuf).
49      if (!_M_buf_allocated && !this->_M_buf)
50        {
51          this->_M_buf = new char_type[this->_M_buf_size];
52          _M_buf_allocated = true;
53        }
54    }
55
56  template<typename _CharT, typename _Traits>
57    void
58    basic_filebuf<_CharT, _Traits>::
59    _M_destroy_internal_buffer() throw()
60    {
61      if (_M_buf_allocated)
62        {
63          delete [] this->_M_buf;
64          this->_M_buf = NULL;
65          _M_buf_allocated = false;
66        }
67      delete [] _M_ext_buf;
68      _M_ext_buf = NULL;
69      _M_ext_buf_size = 0;
70      _M_ext_next = NULL;
71      _M_ext_end = NULL;
72    }
73
74  template<typename _CharT, typename _Traits>
75    basic_filebuf<_CharT, _Traits>::
76    basic_filebuf() : __streambuf_type(), _M_lock(), _M_file(&_M_lock),
77    _M_mode(ios_base::openmode(0)), _M_state_beg(), _M_state_cur(),
78    _M_state_last(), _M_buf(NULL), _M_buf_size(BUFSIZ),
79    _M_buf_allocated(false), _M_reading(false), _M_writing(false), _M_pback(), 
80    _M_pback_cur_save(0), _M_pback_end_save(0), _M_pback_init(false),
81    _M_codecvt(0), _M_ext_buf(0), _M_ext_buf_size(0), _M_ext_next(0),
82    _M_ext_end(0)
83    {
84      if (has_facet<__codecvt_type>(this->_M_buf_locale))
85        _M_codecvt = &use_facet<__codecvt_type>(this->_M_buf_locale);
86    }
87
88  template<typename _CharT, typename _Traits>
89    typename basic_filebuf<_CharT, _Traits>::__filebuf_type*
90    basic_filebuf<_CharT, _Traits>::
91    open(const char* __s, ios_base::openmode __mode)
92    {
93      __filebuf_type *__ret = NULL;
94      if (!this->is_open())
95        {
96          _M_file.open(__s, __mode);
97          if (this->is_open())
98            {
99              _M_allocate_internal_buffer();
100              this->_M_mode = __mode;
101
102              // Setup initial buffer to 'uncommitted' mode.
103              _M_reading = false;
104              _M_writing = false;
105              _M_set_buffer(-1);
106
107              // Reset to initial state.
108              _M_state_last = _M_state_cur = _M_state_beg;
109
110              // 27.8.1.3,4
111              if ((__mode & ios_base::ate)
112                  && this->seekoff(0, ios_base::end, __mode)
113                  == pos_type(off_type(-1)))
114                this->close();
115              else
116                __ret = this;
117            }
118        }
119      return __ret;
120    }
121
122  template<typename _CharT, typename _Traits>
123    typename basic_filebuf<_CharT, _Traits>::__filebuf_type*
124    basic_filebuf<_CharT, _Traits>::
125    close() throw()
126    {
127      __filebuf_type* __ret = NULL;
128      if (this->is_open())
129        {
130          bool __testfail = false;
131          try
132            {
133              if (!_M_terminate_output())
134                __testfail = true;
135            }
136          catch(...)
137            { __testfail = true; }
138
139          // NB: Do this here so that re-opened filebufs will be cool...
140          this->_M_mode = ios_base::openmode(0);
141          this->_M_pback_init = false;
142          _M_destroy_internal_buffer();
143          _M_reading = false;
144          _M_writing = false;
145          _M_set_buffer(-1);
146          _M_state_last = _M_state_cur = _M_state_beg;
147
148          if (!_M_file.close())
149            __testfail = true;
150
151          if (!__testfail)
152            __ret = this;
153        }
154      return __ret;
155    }
156
157  template<typename _CharT, typename _Traits>
158    streamsize
159    basic_filebuf<_CharT, _Traits>::
160    showmanyc()
161    {
162      streamsize __ret = -1;
163      const bool __testin = this->_M_mode & ios_base::in;
164      if (__testin && this->is_open())
165        {
166          // For a stateful encoding (-1) the pending sequence might be just
167          // shift and unshift prefixes with no actual character.
168          __ret = this->egptr() - this->gptr();
169          if (__check_facet(_M_codecvt).encoding() >= 0)
170            __ret += _M_file.showmanyc() / _M_codecvt->max_length();
171        }
172      return __ret;
173    }
174
175  template<typename _CharT, typename _Traits>
176    typename basic_filebuf<_CharT, _Traits>::int_type
177    basic_filebuf<_CharT, _Traits>::
178    underflow()
179    {
180      int_type __ret = traits_type::eof();
181      const bool __testin = this->_M_mode & ios_base::in;
182      if (__testin && !_M_writing)
183        {
184          // Check for pback madness, and if so swich back to the
185          // normal buffers and jet outta here before expensive
186          // fileops happen...
187          _M_destroy_pback();
188
189          if (this->gptr() < this->egptr())
190            return traits_type::to_int_type(*this->gptr());
191
192          // Get and convert input sequence.
193          const size_t __buflen = this->_M_buf_size > 1
194                                  ? this->_M_buf_size - 1 : 1;
195
196          // Will be set to true if ::read() returns 0 indicating EOF.
197          bool __got_eof = false;
198          // Number of internal characters produced.
199          streamsize __ilen = 0;
200          codecvt_base::result __r = codecvt_base::ok;
201          if (__check_facet(_M_codecvt).always_noconv())
202            {
203              __ilen = _M_file.xsgetn(reinterpret_cast<char*>(this->eback()),
204                                      __buflen);
205              if (__ilen == 0)
206                __got_eof = true;
207            }
208          else
209            {
210              // Worst-case number of external bytes.
211              // XXX Not done encoding() == -1.
212              const int __enc = _M_codecvt->encoding();
213              streamsize __blen; // Minimum buffer size.
214              streamsize __rlen; // Number of chars to read.
215              if (__enc > 0)
216                __blen = __rlen = __buflen * __enc;
217              else
218                {
219                  __blen = __buflen + _M_codecvt->max_length() - 1;
220                  __rlen = __buflen;
221                }
222              const streamsize __remainder = _M_ext_end - _M_ext_next;
223              __rlen = __rlen > __remainder ? __rlen - __remainder : 0;
224
225              // An imbue in 'read' mode implies first converting the external
226              // chars already present.
227              if (_M_reading && this->egptr() == this->eback() && __remainder)
228                __rlen = 0;
229
230              // Allocate buffer if necessary and move unconverted
231              // bytes to front.
232              if (_M_ext_buf_size < __blen)
233                {
234                  char* __buf = new char[__blen];
235                  if (__remainder)
236                    std::memcpy(__buf, _M_ext_next, __remainder);
237
238                  delete [] _M_ext_buf;
239                  _M_ext_buf = __buf;
240                  _M_ext_buf_size = __blen;
241                }
242              else if (__remainder)
243                std::memmove(_M_ext_buf, _M_ext_next, __remainder);
244
245              _M_ext_next = _M_ext_buf;
246              _M_ext_end = _M_ext_buf + __remainder;
247              _M_state_last = _M_state_cur;
248
249              do
250                {
251                  if (__rlen > 0)
252                    {
253                      // Sanity check!
254                      // This may fail if the return value of
255                      // codecvt::max_length() is bogus.
256                      if (_M_ext_end - _M_ext_buf + __rlen > _M_ext_buf_size)
257                        {
258                          __throw_ios_failure(__N("basic_filebuf::underflow "
259                                              "codecvt::max_length() "
260                                              "is not valid"));
261                        }
262                      streamsize __elen = _M_file.xsgetn(_M_ext_end, __rlen);
263                      if (__elen == 0)
264                        __got_eof = true;
265                      else if (__elen == -1)
266                        break;
267                      _M_ext_end += __elen;
268                    }
269
270                  char_type* __iend;
271                  __r = _M_codecvt->in(_M_state_cur, _M_ext_next,
272                                       _M_ext_end, _M_ext_next, this->eback(),
273                                       this->eback() + __buflen, __iend);
274                  if (__r == codecvt_base::noconv)
275                    {
276                      size_t __avail = _M_ext_end - _M_ext_buf;
277                      __ilen = std::min(__avail, __buflen);
278                      traits_type::copy(this->eback(),
279                                        reinterpret_cast<char_type*>(_M_ext_buf), __ilen);
280                      _M_ext_next = _M_ext_buf + __ilen;
281                    }
282                  else
283                    __ilen = __iend - this->eback();
284
285                  // _M_codecvt->in may return error while __ilen > 0: this is
286                  // ok, and actually occurs in case of mixed encodings (e.g.,
287                  // XML files).
288                  if (__r == codecvt_base::error)
289                    break;
290
291                  __rlen = 1;
292                }
293              while (__ilen == 0 && !__got_eof);
294            }
295
296          if (__ilen > 0)
297            {
298              _M_set_buffer(__ilen);
299              _M_reading = true;
300              __ret = traits_type::to_int_type(*this->gptr());
301            }
302          else if (__got_eof)
303            {
304              // If the actual end of file is reached, set 'uncommitted'
305              // mode, thus allowing an immediate write without an
306              // intervening seek.
307              _M_set_buffer(-1);
308              _M_reading = false;
309              // However, reaching it while looping on partial means that
310              // the file has got an incomplete character.
311              if (__r == codecvt_base::partial)
312                __throw_ios_failure(__N("basic_filebuf::underflow "
313                                    "incomplete character in file"));
314            }
315          else if (__r == codecvt_base::error)
316            __throw_ios_failure(__N("basic_filebuf::underflow "
317                                "invalid byte sequence in file"));
318          else
319            __throw_ios_failure(__N("basic_filebuf::underflow "
320                                "error reading the file"));
321        }
322      return __ret;
323    }
324
325  template<typename _CharT, typename _Traits>
326    typename basic_filebuf<_CharT, _Traits>::int_type
327    basic_filebuf<_CharT, _Traits>::
328    pbackfail(int_type __i)
329    {
330      int_type __ret = traits_type::eof();
331      const bool __testin = this->_M_mode & ios_base::in;
332      if (__testin && !_M_writing)
333        {
334          // Remember whether the pback buffer is active, otherwise below
335          // we may try to store in it a second char (libstdc++/9761).
336          const bool __testpb = this->_M_pback_init;
337          const bool __testeof = traits_type::eq_int_type(__i, __ret);
338          int_type __tmp;
339          if (this->eback() < this->gptr())
340            {
341              this->gbump(-1);
342              __tmp = traits_type::to_int_type(*this->gptr());
343            }
344          else if (this->seekoff(-1, ios_base::cur) != pos_type(off_type(-1)))
345            {
346              __tmp = this->underflow();
347              if (traits_type::eq_int_type(__tmp, __ret))
348                return __ret;
349            }
350          else
351            {
352              // At the beginning of the buffer, need to make a
353              // putback position available.  But the seek may fail
354              // (f.i., at the beginning of a file, see
355              // libstdc++/9439) and in that case we return
356              // traits_type::eof().
357              return __ret;
358            }
359
360          // Try to put back __i into input sequence in one of three ways.
361          // Order these tests done in is unspecified by the standard.
362          if (!__testeof && traits_type::eq_int_type(__i, __tmp))
363            __ret = __i;
364          else if (__testeof)
365            __ret = traits_type::not_eof(__i);
366          else if (!__testpb)
367            {
368              _M_create_pback();
369              _M_reading = true;
370              *this->gptr() = traits_type::to_char_type(__i);
371              __ret = __i;
372            }
373        }
374      return __ret;
375    }
376
377  template<typename _CharT, typename _Traits>
378    typename basic_filebuf<_CharT, _Traits>::int_type
379    basic_filebuf<_CharT, _Traits>::
380    overflow(int_type __c)
381    {
382      int_type __ret = traits_type::eof();
383      const bool __testeof = traits_type::eq_int_type(__c, __ret);
384      const bool __testout = this->_M_mode & ios_base::out;
385      if (__testout && !_M_reading)
386        {
387          if (this->pbase() < this->pptr())
388            {
389              // If appropriate, append the overflow char.
390              if (!__testeof)
391                {
392                  *this->pptr() = traits_type::to_char_type(__c);
393                  this->pbump(1);
394                }
395
396              // Convert pending sequence to external representation,
397              // and output.
398              if (_M_convert_to_external(this->pbase(),
399                                         this->pptr() - this->pbase())
400                  && (!__testeof || !_M_file.sync()))
401                {
402                  _M_set_buffer(0);
403                  __ret = traits_type::not_eof(__c);
404                }
405            }
406          else if (this->_M_buf_size > 1)
407            {
408              // Overflow in 'uncommitted' mode: set _M_writing, set
409              // the buffer to the initial 'write' mode, and put __c
410              // into the buffer.
411              _M_set_buffer(0);
412              _M_writing = true;
413              if (!__testeof)
414                {
415                  *this->pptr() = traits_type::to_char_type(__c);
416                  this->pbump(1);
417                }
418              __ret = traits_type::not_eof(__c);
419            }
420          else
421            {
422              // Unbuffered.
423              char_type __conv = traits_type::to_char_type(__c);
424              if (__testeof || _M_convert_to_external(&__conv, 1))
425                {
426                  _M_writing = true;
427                  __ret = traits_type::not_eof(__c);
428                }
429            }
430        }
431      return __ret;
432    }
433
434  template<typename _CharT, typename _Traits>
435    bool
436    basic_filebuf<_CharT, _Traits>::
437    _M_convert_to_external(_CharT* __ibuf, streamsize __ilen)
438    {
439      // Sizes of external and pending output.
440      streamsize __elen;
441      streamsize __plen;
442      if (__check_facet(_M_codecvt).always_noconv())
443        {
444          __elen = _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen);
445          __plen = __ilen;
446        }
447      else
448        {
449          // Worst-case number of external bytes needed.
450          // XXX Not done encoding() == -1.
451          streamsize __blen = __ilen * _M_codecvt->max_length();
452          char* __buf = static_cast<char*>(__builtin_alloca(__blen));
453
454          char* __bend;
455          const char_type* __iend;
456          codecvt_base::result __r;
457          __r = _M_codecvt->out(_M_state_cur, __ibuf, __ibuf + __ilen,
458                                __iend, __buf, __buf + __blen, __bend);
459
460          if (__r == codecvt_base::ok || __r == codecvt_base::partial)
461            __blen = __bend - __buf;
462          else if (__r == codecvt_base::noconv)
463            {
464              // Same as the always_noconv case above.
465              __buf = reinterpret_cast<char*>(__ibuf);
466              __blen = __ilen;
467            }
468          else
469            __throw_ios_failure(__N("basic_filebuf::_M_convert_to_external "
470                                    "conversion error"));
471 
472          __elen = _M_file.xsputn(__buf, __blen);
473          __plen = __blen;
474
475          // Try once more for partial conversions.
476          if (__r == codecvt_base::partial && __elen == __plen)
477            {
478              const char_type* __iresume = __iend;
479              streamsize __rlen = this->pptr() - __iend;
480              __r = _M_codecvt->out(_M_state_cur, __iresume,
481                                    __iresume + __rlen, __iend, __buf,
482                                    __buf + __blen, __bend);
483              if (__r != codecvt_base::error)
484                {
485                  __rlen = __bend - __buf;
486                  __elen = _M_file.xsputn(__buf, __rlen);
487                  __plen = __rlen;
488                }
489              else
490                __throw_ios_failure(__N("basic_filebuf::_M_convert_to_external "
491                                        "conversion error"));
492            }
493        }
494      return __elen == __plen;
495    }
496
497   template<typename _CharT, typename _Traits>
498     streamsize
499     basic_filebuf<_CharT, _Traits>::
500     xsputn(const _CharT* __s, streamsize __n)
501     {
502       // Optimization in the always_noconv() case, to be generalized in the
503       // future: when __n is sufficiently large we write directly instead of
504       // using the buffer.
505       streamsize __ret = 0;
506       const bool __testout = this->_M_mode & ios_base::out;
507       if (__testout && !_M_reading
508           && __check_facet(_M_codecvt).always_noconv())
509        {
510          // Measurement would reveal the best choice.
511          const streamsize __chunk = 1ul << 10;
512          streamsize __bufavail = this->epptr() - this->pptr();
513
514          // Don't mistake 'uncommitted' mode buffered with unbuffered.
515          if (!_M_writing && this->_M_buf_size > 1)
516            __bufavail = this->_M_buf_size - 1;
517
518          const streamsize __limit = std::min(__chunk, __bufavail);
519          if (__n >= __limit)
520            {
521              const streamsize __buffill = this->pptr() - this->pbase();
522              const char* __buf = reinterpret_cast<const char*>(this->pbase());
523              __ret = _M_file.xsputn_2(__buf, __buffill,
524                                       reinterpret_cast<const char*>(__s),
525                                       __n);
526              if (__ret == __buffill + __n)
527                {
528                  _M_set_buffer(0);
529                  _M_writing = true;
530                }
531              if (__ret > __buffill)
532                __ret -= __buffill;
533              else
534                __ret = 0;
535            }
536          else
537            __ret = __streambuf_type::xsputn(__s, __n);
538        }
539       else
540         __ret = __streambuf_type::xsputn(__s, __n);
541       return __ret;
542    }
543
544  template<typename _CharT, typename _Traits>
545    typename basic_filebuf<_CharT, _Traits>::__streambuf_type*
546    basic_filebuf<_CharT, _Traits>::
547    setbuf(char_type* __s, streamsize __n)
548    {
549      if (!this->is_open())
550        if (__s == 0 && __n == 0)
551          this->_M_buf_size = 1;
552        else if (__s && __n > 0)
553          {
554            // This is implementation-defined behavior, and assumes that
555            // an external char_type array of length __n exists and has
556            // been pre-allocated. If this is not the case, things will
557            // quickly blow up. When __n > 1, __n - 1 positions will be
558            // used for the get area, __n - 1 for the put area and 1
559            // position to host the overflow char of a full put area.
560            // When __n == 1, 1 position will be used for the get area
561            // and 0 for the put area, as in the unbuffered case above.
562            this->_M_buf = __s;
563            this->_M_buf_size = __n;
564          }
565      return this;
566    }
567
568
569  // According to 27.8.1.4 p11 - 13, seekoff should ignore the last
570  // argument (of type openmode).
571  template<typename _CharT, typename _Traits>
572    typename basic_filebuf<_CharT, _Traits>::pos_type
573    basic_filebuf<_CharT, _Traits>::
574    seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode)
575    {
576      int __width = 0;
577      if (_M_codecvt)
578        __width = _M_codecvt->encoding();
579      if (__width < 0)
580        __width = 0;
581
582      pos_type __ret =  pos_type(off_type(-1));
583      const bool __testfail = __off != 0 && __width <= 0;
584      if (this->is_open() && !__testfail)
585        {
586          // Ditch any pback buffers to avoid confusion.
587          _M_destroy_pback();
588
589          // Correct state at destination. Note that this is the correct
590          // state for the current position during output, because
591          // codecvt::unshift() returns the state to the initial state.
592          // This is also the correct state at the end of the file because
593          // an unshift sequence should have been written at the end.
594          __state_type __state = _M_state_beg;
595          off_type __computed_off = __off * __width;
596          if (_M_reading && __way == ios_base::cur)
597            {
598              if (_M_codecvt->always_noconv())
599                __computed_off += this->gptr() - this->egptr();
600              else
601                {
602                  // Calculate offset from _M_ext_buf that corresponds
603                  // to gptr(). Note: uses _M_state_last, which
604                  // corresponds to eback().
605                  const int __gptr_off =
606                    _M_codecvt->length(_M_state_last, _M_ext_buf, _M_ext_next,
607                                       this->gptr() - this->eback());
608                  __computed_off += _M_ext_buf + __gptr_off - _M_ext_end;
609
610                  // _M_state_last is modified by codecvt::length() so
611                  // it now corresponds to gptr().
612                  __state = _M_state_last;
613                }
614            }
615          __ret = _M_seek(__computed_off, __way, __state);
616        }
617      return __ret;
618    }
619
620  // _GLIBCXX_RESOLVE_LIB_DEFECTS
621  // 171. Strange seekpos() semantics due to joint position
622  // According to the resolution of DR 171, seekpos should ignore the last
623  // argument (of type openmode).
624  template<typename _CharT, typename _Traits>
625    typename basic_filebuf<_CharT, _Traits>::pos_type
626    basic_filebuf<_CharT, _Traits>::
627    seekpos(pos_type __pos, ios_base::openmode)
628    {
629      pos_type __ret =  pos_type(off_type(-1));
630      if (this->is_open())
631        {
632          // Ditch any pback buffers to avoid confusion.
633          _M_destroy_pback();
634          __ret = _M_seek(off_type(__pos), ios_base::beg, __pos.state());
635        }
636      return __ret;
637    }
638
639  template<typename _CharT, typename _Traits>
640    typename basic_filebuf<_CharT, _Traits>::pos_type
641    basic_filebuf<_CharT, _Traits>::
642    _M_seek(off_type __off, ios_base::seekdir __way, __state_type __state)
643    {
644      pos_type __ret = pos_type(off_type(-1));
645      if (_M_terminate_output())
646        {
647          // Returns pos_type(off_type(-1)) in case of failure.
648          __ret = pos_type(_M_file.seekoff(__off, __way));
649          _M_reading = false;
650          _M_writing = false;
651          _M_ext_next = _M_ext_end = _M_ext_buf;
652          _M_set_buffer(-1);
653          _M_state_cur = __state;
654          __ret.state(_M_state_cur);
655        }
656      return __ret;
657    }
658
659  template<typename _CharT, typename _Traits>
660    bool
661    basic_filebuf<_CharT, _Traits>::
662    _M_terminate_output()
663    {
664      // Part one: update the output sequence.
665      bool __testvalid = true;
666      if (this->pbase() < this->pptr())
667        {
668          const int_type __tmp = this->overflow();
669          if (traits_type::eq_int_type(__tmp, traits_type::eof()))
670            __testvalid = false;
671        }
672
673      // Part two: output unshift sequence.
674      if (_M_writing && !__check_facet(_M_codecvt).always_noconv()
675          && __testvalid)
676        {
677          // Note: this value is arbitrary, since there is no way to
678          // get the length of the unshift sequence from codecvt,
679          // without calling unshift.
680          const size_t __blen = 128;
681          char __buf[__blen];
682          codecvt_base::result __r;
683          streamsize __ilen = 0;
684
685          do
686            {
687              char* __next;
688              __r = _M_codecvt->unshift(_M_state_cur, __buf,
689                                        __buf + __blen, __next);
690              if (__r == codecvt_base::error)
691                __testvalid = false;
692              else if (__r == codecvt_base::ok ||
693                       __r == codecvt_base::partial)
694                {
695                  __ilen = __next - __buf;
696                  if (__ilen > 0)
697                    {
698                      const streamsize __elen = _M_file.xsputn(__buf, __ilen);
699                      if (__elen != __ilen)
700                        __testvalid = false;
701                    }
702                }
703            }
704          while (__r == codecvt_base::partial && __ilen > 0 && __testvalid);
705
706          if (__testvalid)
707            {
708              // This second call to overflow() is required by the standard,
709              // but it's not clear why it's needed, since the output buffer
710              // should be empty by this point (it should have been emptied
711              // in the first call to overflow()).
712              const int_type __tmp = this->overflow();
713              if (traits_type::eq_int_type(__tmp, traits_type::eof()))
714                __testvalid = false;
715            }
716        }
717      return __testvalid;
718    }
719
720  template<typename _CharT, typename _Traits>
721    int
722    basic_filebuf<_CharT, _Traits>::
723    sync()
724    {
725      // Make sure that the internal buffer resyncs its idea of
726      // the file position with the external file.
727      // NB: _M_file.sync() will be called within.
728      int __ret = 0;
729      if (this->pbase() < this->pptr())
730        {
731          const int_type __tmp = this->overflow();
732          if (traits_type::eq_int_type(__tmp, traits_type::eof()))
733            __ret = -1;
734        }
735      return __ret;
736    }
737
738  template<typename _CharT, typename _Traits>
739    void
740    basic_filebuf<_CharT, _Traits>::
741    imbue(const locale& __loc)
742    {
743      bool __testvalid = true;
744
745      const __codecvt_type* _M_codecvt_tmp = 0;
746      if (__builtin_expect(has_facet<__codecvt_type>(__loc), true))
747        _M_codecvt_tmp = &use_facet<__codecvt_type>(__loc);
748
749      if (this->is_open())
750        {
751          // encoding() == -1 is ok only at the beginning.
752          if ((_M_reading || _M_writing)
753              && __check_facet(_M_codecvt).encoding() == -1)
754            __testvalid = false;
755          else
756            {
757              if (_M_reading)
758                {
759                  if (__check_facet(_M_codecvt).always_noconv())
760                    {
761                      if (_M_codecvt_tmp
762                          && !__check_facet(_M_codecvt_tmp).always_noconv())
763                        __testvalid = this->seekoff(0, ios_base::cur, this->_M_mode)
764                                      != pos_type(off_type(-1));
765                    }
766                  else
767                    {
768                      // External position corresponding to gptr().
769                      _M_ext_next = _M_ext_buf
770                        + _M_codecvt->length(_M_state_last, _M_ext_buf, _M_ext_next,
771                                             this->gptr() - this->eback());
772                      const streamsize __remainder = _M_ext_end - _M_ext_next;
773                      if (__remainder)
774                        std::memmove(_M_ext_buf, _M_ext_next, __remainder);
775
776                      _M_ext_next = _M_ext_buf;
777                      _M_ext_end = _M_ext_buf + __remainder;
778                      _M_set_buffer(-1);
779                      _M_state_last = _M_state_cur = _M_state_beg;
780                    }
781                }
782              else if (_M_writing && (__testvalid = _M_terminate_output()))
783                _M_set_buffer(-1);
784            }
785        }
786
787      if (__testvalid)
788        _M_codecvt = _M_codecvt_tmp;
789      else
790        _M_codecvt = 0;
791    }
792
793  // Inhibit implicit instantiations for required instantiations,
794  // which are defined via explicit instantiations elsewhere.
795  // NB:  This syntax is a GNU extension.
796#if _GLIBCXX_EXTERN_TEMPLATE
797  extern template class basic_filebuf<char>;
798  extern template class basic_ifstream<char>;
799  extern template class basic_ofstream<char>;
800  extern template class basic_fstream<char>;
801
802#ifdef _GLIBCXX_USE_WCHAR_T
803  extern template class basic_filebuf<wchar_t>;
804  extern template class basic_ifstream<wchar_t>;
805  extern template class basic_ofstream<wchar_t>;
806  extern template class basic_fstream<wchar_t>;
807#endif
808#endif
809} // namespace std
810
811#endif
Note: See TracBrowser for help on using the repository browser.