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

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gnu-src/] [gcc-4.5.1/] [gcc-4.5.1-or32-1.0rc4/] [libstdc++-v3/] [include/] [bits/] [fstream.tcc] - Blame information for rev 519

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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