OpenCores
URL https://opencores.org/ocsvn/altor32/altor32/trunk

Subversion Repositories altor32

[/] [altor32/] [trunk/] [gcc-x64/] [or1knd-elf/] [or1knd-elf/] [include/] [c++/] [4.8.0/] [bits/] [fstream.tcc] - Blame information for rev 35

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 35 ultra_embe
// 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
// .
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 
42
 
43
namespace std _GLIBCXX_VISIBILITY(default)
44
{
45
_GLIBCXX_BEGIN_NAMESPACE_VERSION
46
 
47
  template
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
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
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
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
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
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
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(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
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
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
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
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(__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(__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(__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
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(__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
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(this->pbase());
662
              __ret = _M_file.xsputn_2(__buf, __buffill,
663
                                       reinterpret_cast(__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
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
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
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
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
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
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
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
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;
969
  extern template class basic_ifstream;
970
  extern template class basic_ofstream;
971
  extern template class basic_fstream;
972
 
973
#ifdef _GLIBCXX_USE_WCHAR_T
974
  extern template class basic_filebuf;
975
  extern template class basic_ifstream;
976
  extern template class basic_ofstream;
977
  extern template class basic_fstream;
978
#endif
979
#endif
980
 
981
_GLIBCXX_END_NAMESPACE_VERSION
982
} // namespace std
983
 
984
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.