Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
fstream.cc
Go to the documentation of this file.
1// -*- C++ -*-
2
31
32
33template<class _CharT, class _Traits>
34basic_filebuf<_CharT, _Traits>*
35basic_filebuf<_CharT, _Traits>::
36open (const char *__name, ios_base::openmode __mode, long __prot)
37{
38 _RWSTD_ASSERT (this->_C_is_valid ());
39
40 // fail if `mode' has invalid bits set or if the file is already open
41 if ((__mode & ~_RWSTD_IOS_OPENMODE_MASK) || is_open ())
42 return 0;
43
44 _C_file = _RW::__rw_fopen (__name, __mode, __prot);
45
46 if (!_C_file)
47 return 0;
48
49 pos_type __pos = pos_type ();
50
51 if (__mode & ios_base::ate) {
52
53 // the end of a file is assumed to be in the initial shift state
54 // this assumption is safe as long as the file has been properly
55 // closed (or unshifted) after the last write operation on it
56 __pos = _RW::__rw_fseek (_C_file, 0, 0, ios_base::end);
57
58 if (-1L == __pos) {
59 _RW::__rw_fclose (_C_file, 0);
60 _C_file = 0;
61 return 0;
62 }
63 }
64
65 _C_beg_pos = _C_cur_pos = __pos;
66
67 this->_C_state &= ~_RWSTD_IOS_OPENMODE_MASK;
68 this->_C_state |= __mode;
69
70 return this;
71}
72
73
74template<class _CharT, class _Traits>
75basic_filebuf<_CharT, _Traits>*
76basic_filebuf<_CharT, _Traits>::
77close (bool __close_file /* = true */)
78{
79 // close_file is false when close() is called from detach()
80
81 _RWSTD_ASSERT (this->_C_is_valid ());
82
83 if (!is_open ())
84 return 0; // failure
85
86 // close() returns this on success, 0 on failure
87 basic_filebuf *__retval = this;
88
89 _TRY {
90 // avoid expensive call to overflow() unless necessary
91 if (this->pptr () != this->pbase () && this->_C_is_eof (overflow ()))
92 __retval = 0; // failure
93
94 // write out any unshift sequence if necessary
95 // (applies to multibyte, state dependent encodings only)
96 if (__retval && this->_C_out_last () && !_C_unshift ())
97 __retval = 0; // failure
98 }
99 _CATCH (...) {
100 // either overflow() or codecvt::unshift() threw
101
102 if (__close_file) {
103 _RW::__rw_fclose (_C_file, this->_C_state);
104
105 // zero out the file pointer except when detaching fd
106 _C_file = 0;
107 _C_cur_pos = _C_beg_pos = pos_type (off_type (-1));
108
109 // reset input/output sequences to prevent any
110 // subsequent I/O attempts on closed file
111 this->setg (0, 0, 0);
112 this->setp (0, 0);
113 }
114
115 // rethrow the caught exception
116 _RETHROW;
117 }
118
119 if (__close_file) {
120 if (_RW::__rw_fclose (_C_file, this->_C_state))
121 __retval = 0;
122
123 // zero out the file pointer except when detaching fd
124 _C_file = 0;
125 _C_cur_pos = _C_beg_pos = pos_type (off_type (-1));
126
127 // reset input/output sequences to prevent any
128 // subsequent I/O attempts on closed file
129 this->setg (0, 0, 0);
130 this->setp (0, 0);
131 }
132
133 return __retval;
134}
135
136
137template<class _CharT, class _Traits>
138streamsize
139basic_filebuf<_CharT, _Traits>::
140showmanyc ()
141{
142 _RWSTD_ASSERT (this->_C_is_valid ());
143
144 if ( !this->_C_is_in () || !is_open ()
145 || _C_cur_pos == pos_type (off_type (-1)))
146 return -1;
147
148 // start with the number of chars in get area
149 _RWSTD_STREAMSIZE __retval = this->egptr () - this->gptr ();
150
151 // no prob if this fails for non-seekable devices
152 const pos_type __end_pos =
153 _RW::__rw_fseek (_C_file, this->_C_state, 0, ios_base::end);
154
155 if (__end_pos != pos_type (off_type (-1))) {
156
157 // restore position within file only if seek succeeded
158 _RW::__rw_fseek (_C_file, this->_C_state, _C_cur_pos, ios_base::beg);
159
160 typedef typename traits_type::state_type _StateT;
161 typedef codecvt<char_type, char, _StateT> _Codecvt;
162
163 const _Codecvt &__cvt = _USE_FACET (_Codecvt, this->getloc ());
164
165 if (__cvt.always_noconv ())
166 __retval += __end_pos - _C_cur_pos;
167 else
168 // make most pessimistic conversion estimate
169 __retval += (__end_pos - _C_cur_pos) / __cvt.max_length ();
170 }
171
172 return __retval > 0 ? __retval : 0;
173}
174
175
176template<class _CharT, class _Traits>
177typename basic_filebuf<_CharT, _Traits>::int_type
178basic_filebuf<_CharT, _Traits>::
179underflow ()
180{
181 _RWSTD_ASSERT (this->_C_is_valid ());
182
183 this->setp (0, 0); // invalidate put area
184
185 this->_C_out_last (false); // needed by close ()
186
187 if (!this->_C_is_in () || !is_open())
188 return traits_type::eof ();
189
190 char_type* const __to_end = this->_C_buffer + this->_C_bufsize;
191
192 typedef typename traits_type::int_type _IntType;
193
194 _IntType __ret = _IntType ();
195
196 // fill the buffer if it's empty
197
198 if (this->gptr () == this->egptr()) { // N.B.: gptr() could be null here
199
200 // determine the maximum possible size of putback area (if any)
201 // make sure putback area isn't too big - try to honor
202 // _RWSTD_PBACK_SIZE if possible, otherwise shrink
203
204 const _RWSTD_SIZE_T __pbackavail = this->_C_putback_avail ();
205 _C_pbacksize = __pbackavail < _RWSTD_PBACK_SIZE ?
206 __pbackavail : _RWSTD_PBACK_SIZE;
207
208 _RWSTD_ASSERT (0 != this->_C_bufsize);
209
210 if (_C_pbacksize == this->_C_bufsize)
211 _C_pbacksize = this->_C_bufsize - 1;
212
213 traits_type::move (this->eback(), this->gptr () - _C_pbacksize,
214 _C_pbacksize);
215
216 // fill the get area from the file, performing code conversion if
217 // necessary
218
219 _RWSTD_STREAMSIZE __nread = 0; // number of bytes read from file
220
221 _C_beg_pos = _C_cur_pos;
222
223 typedef typename traits_type::state_type _StateT;
224 typedef codecvt<char_type, char, _StateT> _Codecvt;
225
226 const _Codecvt &__cvt = _USE_FACET (_Codecvt, this->getloc ());
227
228 if (__cvt.always_noconv ()) {
229 // no conversion required
230 __nread = (__to_end - this->_C_buffer) - _C_pbacksize;
231 __nread = _RW::__rw_fread (_C_file, this->_C_state,
232 this->_C_buffer + _C_pbacksize,
233 sizeof (char_type) * __nread);
234 if (__nread < 0)
235 return traits_type::eof (); // error while reading
236
237 this->setg (this->_C_buffer,
238 this->_C_buffer + _C_pbacksize,
239 this->_C_buffer + _C_pbacksize + __nread);
240
241 // adjust the current position in the file,
242 // taking into account CR/LF conversion on windows
243 __nread += _C_crlf_intern_count (this->gptr (),
244 this->gptr () + __nread);
245 }
246 else { // conversion required
247
248 char __xbuf [_RWSTD_DEFAULT_BUFSIZE];
249 char* __from_base = __xbuf;
250 const char* __from_next = 0;
251 char_type* __to_base = this->_C_buffer + _C_pbacksize;
252 char_type* __to_next = __to_base;
253
254 _StateT __state = _C_cur_pos.state ();
255
256 codecvt_base::result __res = codecvt_base::ok;
257
258 const ctype<char_type> &__ctp =
259 _USE_FACET (ctype<char_type>, this->getloc ());
260
261 while (__to_next != __to_end && codecvt_base::error != __res) {
262
263 // read only as many characters as we have positions left in
264 // internal buffer - guarantees we won't read more characters
265 // than we can put into the internal buffer after conversion
266 // and ending file position isn't in the middle of a shift
267 // sequence
268 // N.B.: area between __xbuf and __from_base contains partially
269 // converted sequences left from previous read
270 _RWSTD_STREAMSIZE __n = __to_end - __to_next;
271 if (_RWSTD_DEFAULT_BUFSIZE - (__from_base - __xbuf) < __n)
272 __n = _RWSTD_DEFAULT_BUFSIZE - (__from_base - __xbuf);
273
274 __n = _RW::__rw_fread (_C_file, this->_C_state,
275 __from_base, __n);
276
277 if (0 > __n)
278 return traits_type::eof (); // error while reading
279
280 if (0 == __n)
281 break; // reached eof
282
283 // take into account CR/LF conversion on Win32
284 __nread += __n +
285 _C_crlf_extern_count (__from_base, __from_base + __n);
286
287 // adjust 'n' to hold the number of external chars in buffer
288 __n += __from_base - __xbuf;
289
290 // convert any partially converted sequence from the previous
291 // iteration (possibly empty) plus what we just read in
292 __res = __cvt.in (__state, __xbuf, __xbuf + __n, __from_next,
293 __to_base, __to_end, __to_next);
294
295 switch (__res) {
296 case codecvt_base::ok:
297 // there may be yet unconverted elements at the end
298 // of the source sequence, fall through and treat
299 // as partial (`n' below may be 0)
300
301 case codecvt_base::partial:
302 // compute the length of partially converted sequence
303 __n -= __from_next - __xbuf;
304
305 typedef char_traits<char> CharTraits;
306
307 // copy the sequence to beginning of xbuf
308 CharTraits::move (__xbuf, __from_next, __n);
309
310 // will append external chars to end of the sequence
311 __from_base = __xbuf + __n;
312 break;
313
314 case codecvt_base::noconv:
315 // note that according to lwg issue 19, codecvt<wchar_t,
316 // char>::in() may not return noconv since internT and
317 // externT are not the same type
318
319 // since codecvt<char, char>::always_noconv() is required
320 // to return true, this branch only executes for a user-
321 // defined codecvt<T, T> facet with internT and externT
322 // being the same type
323
324 // FIXME: do not widen external buffer just memcpy it
325 // to internal buffer (externT == internT)
326 __ctp.widen (__xbuf, __xbuf + __n, __to_base);
327 __to_next = __to_base + __n;
328 break;
329
330 case codecvt_base::error:
331 // failed to convert part of the buffer
332 // retain the part that has been successfully
333 // converted, and disregard the rest
334 __ret = traits_type::eof ();
335 break;
336
337 default:
338 // bad return value from codecvt
339 return traits_type::eof ();
340 }
341 __to_base = __to_next; // continue at end of converted seq
342 }
343
344 _C_cur_pos.state (__state);
345
346 this->setg (this->_C_buffer, this->_C_buffer + _C_pbacksize,
347 __to_next);
348 } // end conversion block
349
350 if (__nread == 0)
351 return traits_type::eof ();
352
353 _C_cur_pos += __nread;
354 }
355
356 return traits_type::eq_int_type (__ret, _IntType ()) ?
357 traits_type::to_int_type (*this->gptr ()) : __ret;
358}
359
360
361template<class _CharT, class _Traits>
362typename basic_filebuf<_CharT, _Traits>::int_type
363basic_filebuf<_CharT, _Traits>::
364overflow (int_type __c /* = eof () */)
365{
366 _RWSTD_ASSERT (this->_C_is_valid ());
367
368 if (!this->_C_is_out () || !is_open ())
369 return traits_type::eof ();
370
371 this->setg (0, 0, 0); // invalidate the get area
372
373 const bool __unbuf = this->_C_is_unbuffered ();
374
375 const char_type __c_to_char = traits_type::to_char_type (__c);
376
377 if (this->pptr () == 0 && !__unbuf) {
378 // put area not valid yet - just need to initialize it
379 this->setp (this->_C_buffer, this->_C_buf_end ());
380 }
381 else if ( this->pptr () == this->epptr ()
382 || this->_C_is_eof (__c)
383 || __unbuf) {
384
385 const char_type* __buf;
386 _RWSTD_STREAMSIZE __nchars;
387
388 if (__unbuf) {
389 if (this->_C_is_eof (__c)){
390 __buf = 0;
391 __nchars = 0;
392 }
393 else {
394 __buf = &__c_to_char;
395 __nchars = 1;
396 }
397 }
398 else {
399 // call xsputn() with a special value to have it flush
400 // the controlled sequence to the file
401 __buf = _RWSTD_REINTERPRET_CAST (char_type*, this);
402 __nchars = this->pptr () - this->pbase ();
403 }
404
405 // typedef helps HP aCC 3.27
406 typedef basic_filebuf _FileBuf;
407
408 if (__nchars != _FileBuf::xsputn (__buf, __nchars))
409 return traits_type::eof (); // error while writing
410 }
411
412 // now that there's room in the buffer, call sputc() recursively
413 // to actually place the character in the buffer (unless we're
414 // in unbuffered mode because we just wrote it out)
415 if (!this->_C_is_eof (__c) && !__unbuf)
416 this->sputc (__c_to_char);
417
418 this->_C_out_last (true); // needed by close ()
419
420 return traits_type::not_eof (__c);
421}
422
423
424template <class _CharT, class _Traits>
426basic_filebuf<_CharT, _Traits>::
427xsputn (const char_type* __buf, _RWSTD_STREAMSIZE __nchars)
428{
429 _RWSTD_ASSERT (0 != __buf || 0 == __nchars);
430 _RWSTD_ASSERT (this->_C_is_valid ());
431
432 if (0 == __nchars)
433 return 0; // not an error
434
435 if (__nchars < 0 || !this->_C_is_out () || !is_open ())
436 return -1; // error
437
438 if (0 == this->pptr () && !this->_C_is_unbuffered ())
439 // put area not valid yet - just need to initialize it
440 this->setp (this->_C_buffer, this->_C_buf_end ());
441
442 const _RWSTD_STREAMSIZE __navail = this->epptr () - this->pptr ();
443
444 const char_type* const __special =
445 _RWSTD_REINTERPRET_CAST (char_type*, this);
446
447 if (__buf == __special) {
448 __buf = this->pbase ();
449 }
450 else if (__nchars <= __navail) {
451 // the amount of available space is big enough
452
453 // append the contents of the buffer to the controlled sequence
454 traits_type::copy (this->pptr (), __buf, __nchars);
455
456 this->pbump (__nchars);
457
458 return __nchars;
459 }
460 else {
461 // call self recursively to flush the controlled sequence first
462 const _RWSTD_STREAMSIZE __nwrite = this->pptr () - this->pbase ();
463
464 // typedef helps HP aCC 3.27
465 typedef basic_filebuf _FileBuf;
466
467 // return -1 on error to flush the controlled sequence
468 if (__nwrite != _FileBuf::xsputn (__special, __nwrite))
469 return -1;
470 }
471
472 // flush buffer to file, performing code conversion if necessary
473
474 _RWSTD_ASSERT (this->_C_is_valid ());
475 _RWSTD_ASSERT (this->_C_is_out ());
476 _RWSTD_ASSERT (is_open ());
477
478 const char_type* const __end = __buf + __nchars;
479
480 typedef typename traits_type::state_type _StateT;
481
482 _RWSTD_STREAMSIZE __nwrote = 0; // num chars to write
483 _StateT __state = _C_cur_pos.state (); // state of stream
484
485 _C_beg_pos = _C_cur_pos;
486
487 typedef codecvt<char_type, char, _StateT> _Codecvt;
488
489 const _Codecvt &__cvt = _USE_FACET (_Codecvt, this->getloc ());
490
491 if (__cvt.always_noconv ()) {
492
493 // no conversion
494
495 __nwrote = __end - __buf;
496
497 const _RWSTD_STREAMSIZE __nbytes = sizeof (char_type) * __nwrote;
498
499 if (__nbytes != _RW::__rw_fwrite (_C_file, this->_C_state,
500 __buf, __nbytes))
501 return -1; // error while writing
502 }
503 else {
504
505 // perform codeset conversion in chunks to avoid dynamic
506 // memory allocation
507
508 char __xbuf [_RWSTD_DEFAULT_BUFSIZE];
509 char* __xbuf_end = __xbuf + sizeof __xbuf;
510 char* __to_next = 0;
511 const char_type* __from_next = 0;
512
513 for (const char_type* __base = __buf; __from_next != __end;
514 __base = __from_next) {
515
516 // avoid using const codecvt_base::result here
517 // to prevent HP aCC 3.27 errors
518 const int __res =
519 __cvt.out (__state, __base, __end, __from_next,
520 __xbuf, __xbuf_end, __to_next);
521
522 _RWSTD_STREAMSIZE __nbytes =
523 sizeof (char_type) * (__end - __base);
524
525 switch (__res) {
526 case codecvt_base::error:
527 // write out the sequence successfully converted up
528 // to the point of the error in the internal sequence
529 // and fail
530 _RW::__rw_fwrite (_C_file, this->_C_state, __base, __nbytes);
531 return traits_type::eof ();
532
533 case codecvt_base::noconv:
534 // write the entire sequence
535 if (__nbytes != _RW::__rw_fwrite (_C_file, this->_C_state,
536 __base, __nbytes))
537 return traits_type::eof ();
538
539 __nwrote += __end - __base
540 + _C_crlf_intern_count (__base, __end);
541
542 __from_next = __end; // effectively 'break'
543 break;
544
545 default:
546 _RWSTD_ASSERT ( codecvt_base::ok == __res
547 || codecvt_base::partial == __res);
548
549 // partial conversion will result if there isn't enough
550 // space in the conversion buffer to hold the converted
551 // sequence, but we're O.K. since we'll be passing any
552 // remaining unconverted characters (starting at
553 // __from_next) in the next iteration
554
555 __nbytes = __to_next - __xbuf;
556
557 if (__nbytes != _RW::__rw_fwrite (_C_file, this->_C_state,
558 __xbuf, __nbytes))
559 return -1;
560
561 __nwrote += __nbytes
562 + _C_crlf_extern_count (__xbuf, __to_next);
563 }
564 }
565 }
566
567 // adjust the current position in the file
568 _C_cur_pos += __nwrote;
569 _C_cur_pos.state (__state);
570
571 // reset the put area
572 if (!this->_C_is_unbuffered ())
573 this->setp (this->_C_buffer, this->_C_buf_end ());
574
575 this->_C_out_last (true); // needed by close ()
576
577 // return the number of characters (not bytes) in the buffer
578 // successfully written to the file
579 return __nchars;
580}
581
582
583template<class _CharT, class _Traits>
584typename basic_filebuf<_CharT, _Traits>::int_type
585basic_filebuf<_CharT, _Traits>::
586pbackfail (int_type __c)
587{
588 _RWSTD_ASSERT (this->_C_is_valid ());
589
590 if (!is_open ())
591 return traits_type::eof ();
592
593 // we could get here if gptr = eback or if __c != *(gptr-1)
594 if (!this->_C_putback_avail ()) {
595 // try to make a putback area available
596
597 if (this->seekoff (-1, ios_base::cur) == pos_type (off_type (-1)))
598 return traits_type::eof ();
599
600 if (this->_C_is_eof (underflow ()))
601 return traits_type::eof ();
602
603 this->gbump (1);
604 }
605
606 if (traits_type::eq (traits_type::to_char_type (__c), *(this->gptr () - 1))
607 || this->_C_is_eof (__c)) {
608 // "put back" original value
609 this->gbump (-1);
610 return traits_type::not_eof (__c);
611 }
612 else if (this->_C_is_out ()) {
613 // overwrite existing value with new value
614 this->gbump (-1);
615 *this->gptr () = traits_type::to_char_type (__c);
616 return __c;
617 }
618 else
619 return traits_type::eof ();
620}
621
622
623template<class _CharT, class _Traits>
624basic_streambuf<_CharT, _Traits>*
625basic_filebuf<_CharT, _Traits>::
626setbuf (char_type *__buf, streamsize __ssize)
627{
628 _RWSTD_ASSERT (this->_C_is_valid ());
629
630 if (__ssize < 0)
631 return 0;
632
633 const _RWSTD_SIZE_T __bufsize =
634 _RWSTD_STATIC_CAST (_RWSTD_SIZE_T, __ssize);
635
636 // sync the buffer to the external file so it can be deallocated
637 if ((this->gptr () || this->pptr ()) && is_open () && sync () != 0)
638 return 0;
639
640 bool __reset = true;
641
642 if (0 < __bufsize) {
643
644 if (!__buf && (this->_C_bufsize < __bufsize || !this->_C_buffer)) {
645 // if `buf' is 0 and the requested size is greater than
646 // the size of the object's buffer, or of the object's
647 // buffer is 0, try to allocate a new buffer of the
648 // specified size
649 __buf = new char_type [__bufsize];
650
651 // delete old buffer if the object owns it
652 if (this->_C_own_buf ())
653 delete [] this->_C_buffer;
654
655 // take ownership of the newly allocated buffer
656 this->_C_own_buf (true);
657 }
658 else if (!__buf && __bufsize <= this->_C_bufsize) {
659 // if `buf' is 0 and the requested size is less than
660 // the size of the object's buffer, simply reuse the
661 // object's buffer
662
663 __buf = this->_C_buffer;
664 __reset = false;
665 }
666 else if (__buf && __buf != this->_C_buffer) {
667 // if `buf' is non-0 and different from the existing
668 // buffer, use it
669
670 // delete old buffer if the object owns it
671 if (this->_C_own_buf ())
672 delete [] this->_C_buffer;
673
674 // the object does not own of the new buffer
675 this->_C_own_buf (false);
676 }
677
678 this->_C_buffer = __buf;
679 this->_C_bufsize = __bufsize;
680 this->_C_set_unbuffered (false);
681 }
682 else {
683 // unbuffer this stream object
684
685 // character buffer is preserved (used as get area only),
686 // streambuf object unbuffered for writing
687
688 // to put a streambuf object into an unbuffered mode (see 27.8.1.4,
689 // p10) and affect the size of the get area, setbuf() should first
690 // be called with the desired (non-zero) size and then again with
691 // both arguments being 0
692 this->_C_set_unbuffered (true);
693 }
694
695 if (__reset) {
696 this->setg (0, 0, 0);
697 this->setp (0, 0);
698 }
699
700 // a character buffer of nonzero size must exist even in unbuffered mode
701 _RWSTD_ASSERT (0 != this->_C_buffer);
702 _RWSTD_ASSERT (0 != this->_C_bufsize);
703
704 return this;
705}
706
707
708// 27.8.1.4, p 11
709template<class _CharT, class _Traits>
710typename basic_filebuf<_CharT, _Traits>::pos_type
711basic_filebuf<_CharT, _Traits>::
712seekoff (off_type __off, ios_base::seekdir __way, ios_base::openmode)
713{
714 _RWSTD_ASSERT (this->_C_is_valid ());
715
716 if (!is_open ())
717 return pos_type (off_type (-1));
718
719 typedef typename traits_type::state_type _StateT;
720 typedef codecvt<char_type, char, _StateT> _Codecvt;
721
722 const int __width = _USE_FACET (_Codecvt, this->getloc ()).encoding ();
723
724 // offset must be zero with state-dependent encoding
725 if (0 != __off && __width <= 0)
726 return pos_type (off_type (-1));
727
728 // sync the buffer... (this also invalidates the get/put area)
729 if (sync () != 0)
730 return pos_type (off_type (-1));
731
732 // ...and, if last operation was output, append an unshift sequence
733 if (this->_C_out_last ())
734 _C_unshift ();
735
736 if (__width > 1)
737 __off *= __width;
738
739 // perform the seek and save the result
740 pos_type __pos = _RW::__rw_fseek (_C_file, this->_C_state, __off, __way);
741
742 if (__pos != pos_type (off_type (-1))) {
743
744 // preserve the current state if not changing position
745 // (only matters for state-dependent encodings for which
746 // the offset is required and guaranteed to be 0)
747 if (__way == ios_base::cur)
748 __pos.state (_C_cur_pos.state ());
749
750 _C_beg_pos = _C_cur_pos = __pos;
751 }
752
753 this->_C_out_last (false); // needed by close()
754
755 return __pos;
756}
757
758
759template<class _CharT, class _Traits>
760typename basic_filebuf<_CharT, _Traits>::pos_type
761basic_filebuf<_CharT, _Traits>::
762seekpos (pos_type __pos, ios_base::openmode)
763{
764 _RWSTD_ASSERT (this->_C_is_valid ());
765
766 if (!is_open ())
767 return pos_type (off_type (-1));
768
769 // flush the output area if it exists
770 if (this->pptr () != 0) {
771 if (this->_C_is_eof (this->overflow (traits_type::eof ())))
772 return pos_type (off_type (-1));
773 }
774
775 if ( _RW::__rw_fseek (_C_file, this->_C_state, __pos, ios_base::beg)
776 == pos_type (off_type (-1)))
777 return pos_type (off_type (-1));
778
779 _C_cur_pos = _C_beg_pos = __pos;
780
781 this->setg (0, 0, 0);
782 this->setp (0, 0);
783
784 this->_C_out_last (false); // needed by close()
785
786 return __pos;
787}
788
789
790template<class _CharT, class _Traits>
791int
792basic_filebuf<_CharT, _Traits>::
793sync ()
794{
795 _RWSTD_ASSERT (this->_C_is_valid ());
796
797 // put area active
798 if (this->pptr () != 0) {
799 // flush the buffer to the file
800 if (this->_C_is_eof (overflow (traits_type::eof ())))
801 return -1;
802
803 if (this->_C_state & _RWSTD_IOS_STDIO)
804 _RW::__rw_fflush (_C_file, this->_C_state);
805 }
806
807 // get area active
808 if (this->gptr () != 0) {
809
810 // pbacksize may need to be adjusted if it's greater than
811 // the available putback area (e.g., after calling putback()
812 // at the end of the buffer)
813 const _RWSTD_SIZE_T __pbackavail = this->_C_putback_avail ();
814 if (__pbackavail < _C_pbacksize)
815 _C_pbacksize = __pbackavail;
816
817 _RWSTD_ASSERT (0 != this->_C_bufsize);
818
819 if (_C_pbacksize == this->_C_bufsize)
820 _C_pbacksize = this->_C_bufsize - 1;
821
822 typedef typename traits_type::state_type _StateT;
823 typedef codecvt<char_type, char, _StateT> _Codecvt;
824
825 const _Codecvt &__cvt = _USE_FACET (_Codecvt, this->getloc ());
826 int __width = __cvt.encoding ();
827
828 if (__width > 0) {
829 // get the number of chars consumed in the buffer
830 const off_type __consumed =
831 this->gptr () - this->eback () - _C_pbacksize;
832
833 // constant width conversion:
834 // adjust the current position/state in the file,
835 // taking into account CR/LF conversion on Win32
836 _C_cur_pos = _C_beg_pos;
837 _C_cur_pos += (__width * __consumed)
838 + _C_crlf_intern_count (this->eback () + _C_pbacksize,
839 this->gptr());
840 }
841 else {
842 // This gets a bit tricky here because we don't know the external
843 // file position corresponding to the position in the
844 // internal buffer. To figure this out, we'll use the known
845 // file position/state corresponding to the start of the buffer
846 // (which we have carefully saved in _C_beg_pos) and
847 // convert the characters up to the current position in the
848 // buffer, counting how many external chars result. We can
849 // then use the offset from _C_beg_pos and the state
850 // returned from codecvt::out() to construct the current file
851 // position
852
853 off_type __ext_chars = 0; // converted external chars
854
855 char __xbuf [_RWSTD_DEFAULT_BUFSIZE];
856 char* __xbuf_end = __xbuf + sizeof __xbuf;
857 char* __to_next = 0;
858 const char_type* __from_next = 0;
859 const char_type* __from_end = this->gptr ();
860 _StateT __state = _C_beg_pos.state ();
861 const char_type* __base = this->eback () + _C_pbacksize;
862
863 while (__from_next != __from_end) {
864 const int __res =
865 __cvt.out (__state, __base, __from_end, __from_next,
866 __xbuf, __xbuf_end, __to_next);
867
868 switch (__res) {
869 case codecvt_base::error:
870 return -1;
871
872 case codecvt_base::noconv:
873 __ext_chars += __from_end - __base
874 + _C_crlf_intern_count (__base, __from_end);
875 __from_next = __from_end; // break out of the loop
876 break;
877
878 default: // __res = ok or partial
879 // take into account CR/LF conversion on Win32
880 __ext_chars += __to_next - __xbuf
881 + _C_crlf_extern_count (__xbuf, __to_next);
882 }
883 // repeat with next chunk
884 __base = __from_next;
885 }
886
887 _C_cur_pos = _C_beg_pos;
888 _C_cur_pos += __ext_chars;
889 _C_cur_pos.state (__state);
890 }
891
892 // seek within the external file to the position
893 // corresponding to the future beginning of the buffer
894 const off_type __off =
895 _RW::__rw_fseek (_C_file, this->_C_state,
896 _C_cur_pos, ios_base::beg);
897
898 if (-1L == __off)
899 return -1;
900
901 traits_type::move (this->eback (), this->gptr () - _C_pbacksize,
902 _C_pbacksize);
903
904 this->setg (this->eback (), this->eback () + _C_pbacksize,
905 this->eback () + _C_pbacksize);
906 }
907
908 _C_beg_pos = _C_cur_pos;
909
910 this->setp (0, 0);
911
912 return 0;
913}
914
915
916template<class _CharT, class _Traits>
917basic_filebuf<_CharT, _Traits>*
918basic_filebuf<_CharT, _Traits>::
919_C_open (int __fd, void *__file, char_type *__buf, streamsize __n)
920{
921 if (is_open () || !__file && -1 == __fd || !setbuf (__buf, __n))
922 return 0;
923
924 if (__file) {
925 _RWSTD_ASSERT (-1 == __fd);
926
927 _C_file = __file;
928
929 this->_C_state |= this->_C_stdio;
930 }
931 else {
932 _RWSTD_ASSERT (!__file);
933
934 _C_file = _RW::__rw_fdopen (__fd);
935
936 if (!_C_file)
937 return 0;
938
939 this->_C_state &= ~this->_C_stdio;
940 }
941
942 this->_C_state |= _RW::__rw_fmode (_C_file, this->_C_state);
943
944 this->setg (0, 0, 0);
945 this->setp (0, 0);
946
947 _C_cur_pos = _C_beg_pos = pos_type ();
948
949 return this;
950}
951
952
953// write out an unshift sequence if not in initial shift state
954template<class _CharT, class _Traits>
955bool
956basic_filebuf<_CharT, _Traits>::
957_C_unshift ()
958{
959 typedef typename traits_type::state_type _StateT;
960 typedef codecvt<char_type, char, _StateT> _Codecvt;
961
962 const _Codecvt &__cvt = _USE_FACET (_Codecvt, this->getloc ());
963
964 // unshifting isn't necessary if encoding isn't state dependent
965 // or if the state is equivalent to initial state (determined
966 // by codecvt::unshift())
967 if (__cvt.encoding () >= 0)
968 return true;
969
970 // buf to hold unshift sequence - assumes that the shift
971 // sequence will be less than 64 chars (we can't safely
972 // use dynamic allocation because this function could be
973 // called as a result of memory allocation exception)
974
975 char __useq [64];
976 char* __useq_end = 0;
977
978 _StateT __state = _C_cur_pos.state ();
979
980 const int __res =
981 __cvt.unshift (__state, __useq, __useq + sizeof __useq, __useq_end);
982
983 const _RWSTD_STREAMSIZE __nbytes = __useq_end - __useq;
984
985 // in the unlikely event that the buffer isn't big enough, assert
986 _RWSTD_ASSERT (__res != codecvt_base::partial);
987
988 if (__res == codecvt_base::error)
989 return false;
990
991 if (__res == codecvt_base::noconv)
992 return true;
993
994 const off_type __nwrote =
995 _RW::__rw_fwrite (_C_file, this->_C_state, __useq, __nbytes);
996
997 if (__nwrote < 0)
998 return false;
999
1000 _C_cur_pos += __nwrote; // CR/LF conversion not an issue here
1001
1002 return __nwrote == __nbytes;
1003}
1004
1005
1006} // namespace std
#define _RWSTD_PBACK_SIZE
#define _RWSTD_DEFAULT_BUFSIZE
Definition _config.h:406
#define _RETHROW
Definition _defs.h:853
#define _RWSTD_REINTERPRET_CAST(T, x)
Definition _defs.h:535
#define _RWSTD_IOS_STDIO
Definition _defs.h:823
#define _RWSTD_STATIC_CAST(T, x)
Definition _defs.h:534
#define _TRY
Definition _defs.h:850
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
#define _RWSTD_STREAMSIZE
Definition _defs.h:762
#define _USE_FACET(type, arg)
Definition _defs.h:921
#define _RWSTD_IOS_OPENMODE_MASK
Definition _defs.h:826
#define _RWSTD_ASSERT(ignore)
Definition _defs.h:1108
#define _CATCH(ex)
Definition _defs.h:851
Definition json.h:5363