1 // Stream buffer classes -*- C++ -*-
3 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING. If not, write to the Free
18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
31 // ISO C++ 14882: 27.5 Stream buffers
34 /** @file std_streambuf.h
35 * This is an internal header file, included by other library headers.
36 * You should not attempt to use it directly.
39 #ifndef _CPP_STREAMBUF
40 #define _CPP_STREAMBUF 1
42 #pragma GCC system_header
44 #include <bits/c++config.h>
46 #include <cstdio> // For SEEK_SET, SEEK_CUR, SEEK_END
47 #include <bits/localefwd.h>
48 #include <bits/ios_base.h>
52 template<typename _CharT
, typename _Traits
>
54 __copy_streambufs(basic_ios
<_CharT
, _Traits
>& _ios
,
55 basic_streambuf
<_CharT
, _Traits
>* __sbin
,
56 basic_streambuf
<_CharT
, _Traits
>* __sbout
);
58 // 27.5.2 Template class basic_streambuf<_CharT, _Traits>
59 template<typename _CharT
, typename _Traits
>
64 typedef _CharT char_type
;
65 typedef _Traits traits_type
;
66 typedef typename
traits_type::int_type int_type
;
67 typedef typename
traits_type::pos_type pos_type
;
68 typedef typename
traits_type::off_type off_type
;
70 // Non-standard Types:
71 typedef ctype
<char_type
> __ctype_type
;
72 typedef basic_streambuf
<char_type
, traits_type
> __streambuf_type
;
74 friend class basic_ios
<char_type
, traits_type
>;
75 friend class basic_istream
<char_type
, traits_type
>;
76 friend class basic_ostream
<char_type
, traits_type
>;
77 friend class istreambuf_iterator
<char_type
, traits_type
>;
78 friend class ostreambuf_iterator
<char_type
, traits_type
>;
81 __copy_streambufs
<>(basic_ios
<char_type
, traits_type
>& __ios
,
82 __streambuf_type
* __sbin
,__streambuf_type
* __sbout
);
86 // Pointer to the beginning of internally-allocated
87 // space. Filebuf manually allocates/deallocates this, whereas
88 // stringstreams attempt to use the built-in intelligence of the
89 // string class. If you are managing memory, set this. If not,
93 // Actual size of allocated internal buffer, in bytes.
96 // Optimal or preferred size of internal buffer, in bytes.
97 int_type _M_buf_size_opt
;
99 // True iff _M_in_* and _M_out_* buffers should always point to
100 // the same place. True for fstreams, false for sstreams.
103 // This is based on _IO_FILE, just reordered to be more
104 // consistent, and is intended to be the most minimal abstraction
105 // for an internal buffer.
106 // get == input == read
107 // put == output == write
108 char_type
* _M_in_beg
; // Start of get area.
109 char_type
* _M_in_cur
; // Current read area.
110 char_type
* _M_in_end
; // End of get area.
111 char_type
* _M_out_beg
; // Start of put area.
112 char_type
* _M_out_cur
; // Current put area.
113 char_type
* _M_out_end
; // End of put area.
115 // Place to stash in || out || in | out settings for current streambuf.
116 ios_base::openmode _M_mode
;
118 // Current locale setting.
119 locale _M_buf_locale
;
121 // True iff locale is initialized.
122 bool _M_buf_locale_init
;
124 // Necessary bits for putback buffer management. Only used in
125 // the basic_filebuf class, as necessary for the standard
126 // requirements. The only basic_streambuf member function that
127 // needs access to these data members is in_avail...
128 // NB: pbacks of over one character are not currently supported.
129 int_type _M_pback_size
;
131 char_type
* _M_pback_cur_save
;
132 char_type
* _M_pback_end_save
;
135 // Initializes pback buffers, and moves normal buffers to safety.
137 // _M_in_cur has already been moved back
143 int_type __dist
= _M_in_end
- _M_in_cur
;
144 int_type __len
= min(_M_pback_size
, __dist
);
145 traits_type::copy(_M_pback
, _M_in_cur
, __len
);
146 _M_pback_cur_save
= _M_in_cur
;
147 _M_pback_end_save
= _M_in_end
;
148 this->setg(_M_pback
, _M_pback
, _M_pback
+ __len
);
149 _M_pback_init
= true;
153 // Deactivates pback buffer contents, and restores normal buffer.
155 // The pback buffer has only moved forward.
161 // Length _M_in_cur moved in the pback buffer.
162 int_type __off_cur
= _M_in_cur
- _M_pback
;
164 // For in | out buffers, the end can be pushed back...
165 int_type __off_end
= 0;
166 int_type __pback_len
= _M_in_end
- _M_pback
;
167 int_type __save_len
= _M_pback_end_save
- _M_buf
;
168 if (__pback_len
> __save_len
)
169 __off_end
= __pback_len
- __save_len
;
171 this->setg(_M_buf
, _M_pback_cur_save
+ __off_cur
,
172 _M_pback_end_save
+ __off_end
);
173 _M_pback_cur_save
= NULL
;
174 _M_pback_end_save
= NULL
;
175 _M_pback_init
= false;
179 // Correctly sets the _M_in_cur pointer, and bumps the
180 // _M_out_cur pointer as well if necessary.
182 _M_in_cur_move(off_type __n
) // argument needs to be +-
184 bool __testout
= _M_out_cur
;
186 if (__testout
&& _M_buf_unified
)
190 // Correctly sets the _M_out_cur pointer, and bumps the
191 // appropriate _M_*_end pointers as well. Necessary for the
192 // un-tied stringbufs, in in|out mode.
194 // __n + _M_out_[cur, end] <= _M_buf + _M_buf_size
195 // Assuming all _M_*_[beg, cur, end] pointers are operating on
197 // _M_buf <= _M_*_ <= _M_buf + _M_buf_size
199 _M_out_cur_move(off_type __n
) // argument needs to be +-
201 bool __testin
= _M_in_cur
;
204 if (__testin
&& _M_buf_unified
)
206 if (_M_out_cur
> _M_out_end
)
208 _M_out_end
= _M_out_cur
;
209 // NB: in | out buffers drag the _M_in_end pointer along...
215 // Return the size of the output buffer. This depends on the
216 // buffer in use: allocated buffers have a stored size in
217 // _M_buf_size and setbuf() buffers don't.
224 // Using allocated buffer.
225 if (_M_out_beg
== _M_buf
)
226 __ret
= _M_out_beg
+ _M_buf_size
- _M_out_cur
;
227 // Using non-allocated buffer.
229 __ret
= _M_out_end
- _M_out_cur
;
234 // These three functions are used to clarify internal buffer
235 // maintenance. After an overflow, or after a seekoff call that
236 // started at beg or end, or possibly when the stream becomes
237 // unbuffered, and a myrid other obscure corner cases, the
238 // internal buffer does not truly reflect the contents of the
239 // external buffer. At this point, for whatever reason, it is in
240 // an indeterminate state.
242 _M_set_indeterminate(void)
244 if (_M_mode
& ios_base::in
)
245 this->setg(_M_buf
, _M_buf
, _M_buf
);
246 if (_M_mode
& ios_base::out
)
247 this->setp(_M_buf
, _M_buf
);
251 _M_set_determinate(off_type __off
)
253 bool __testin
= _M_mode
& ios_base::in
;
254 bool __testout
= _M_mode
& ios_base::out
;
256 this->setg(_M_buf
, _M_buf
, _M_buf
+ __off
);
258 this->setp(_M_buf
, _M_buf
+ __off
);
262 _M_is_indeterminate(void)
265 // Don't return true if unbuffered.
268 if (_M_mode
& ios_base::in
)
269 __ret
= _M_in_beg
== _M_in_cur
&& _M_in_cur
== _M_in_end
;
270 if (_M_mode
& ios_base::out
)
271 __ret
= _M_out_beg
== _M_out_cur
&& _M_out_cur
== _M_out_end
;
280 _M_buf_unified
= false;
283 _M_mode
= ios_base::openmode(0);
284 _M_buf_locale_init
= false;
289 pubimbue(const locale
&__loc
)
291 locale
__tmp(this->getloc());
299 if (_M_buf_locale_init
)
300 return _M_buf_locale
;
305 // Buffer and positioning:
307 pubsetbuf(char_type
* __s
, streamsize __n
)
308 { return this->setbuf(__s
, __n
); }
311 pubseekoff(off_type __off
, ios_base::seekdir __way
,
312 ios_base::openmode __mode
= ios_base::in
| ios_base::out
)
313 { return this->seekoff(__off
, __way
, __mode
); }
316 pubseekpos(pos_type __sp
,
317 ios_base::openmode __mode
= ios_base::in
| ios_base::out
)
318 { return this->seekpos(__sp
, __mode
); }
321 pubsync() { return this->sync(); }
323 // Get and put areas:
329 if (_M_in_cur
&& _M_in_cur
< _M_in_end
)
333 int_type __save_len
= _M_pback_end_save
- _M_pback_cur_save
;
334 int_type __pback_len
= _M_in_cur
- _M_pback
;
335 __ret
= __save_len
- __pback_len
;
338 __ret
= this->egptr() - this->gptr();
341 __ret
= this->showmanyc();
348 int_type __eof
= traits_type::eof();
349 return (this->sbumpc() == __eof
? __eof
: this->sgetc());
359 if (_M_in_cur
&& _M_in_cur
< _M_in_end
)
360 __ret
= traits_type::to_int_type(*(this->gptr()));
362 __ret
= this->underflow();
367 sgetn(char_type
* __s
, streamsize __n
)
368 { return this->xsgetn(__s
, __n
); }
372 sputbackc(char_type __c
);
379 sputc(char_type __c
);
382 sputn(const char_type
* __s
, streamsize __n
)
383 { return this->xsputn(__s
, __n
); }
387 : _M_buf(NULL
), _M_buf_size(0),
388 _M_buf_size_opt(static_cast<int_type
>(BUFSIZ
)), _M_buf_unified(false),
389 _M_in_beg(0), _M_in_cur(0), _M_in_end(0), _M_out_beg(0), _M_out_cur(0),
390 _M_out_end(0), _M_mode(ios_base::openmode(0)), _M_buf_locale(locale()),
391 _M_buf_locale_init(false), _M_pback_size(1), _M_pback(NULL
),
392 _M_pback_cur_save(NULL
), _M_pback_end_save(NULL
), _M_pback_init(false)
397 eback() const { return _M_in_beg
; }
400 gptr() const { return _M_in_cur
; }
403 egptr() const { return _M_in_end
; }
406 gbump(int __n
) { _M_in_cur
+= __n
; }
409 setg(char_type
* __gbeg
, char_type
* __gnext
, char_type
* __gend
)
414 if (!(_M_mode
& ios_base::in
) && __gbeg
&& __gnext
&& __gend
)
415 _M_mode
= _M_mode
| ios_base::in
;
420 pbase() const { return _M_out_beg
; }
423 pptr() const { return _M_out_cur
; }
426 epptr() const { return _M_out_end
; }
429 pbump(int __n
) { _M_out_cur
+= __n
; }
432 setp(char_type
* __pbeg
, char_type
* __pend
)
434 _M_out_beg
= _M_out_cur
= __pbeg
;
436 if (!(_M_mode
& ios_base::out
) && __pbeg
&& __pend
)
437 _M_mode
= _M_mode
| ios_base::out
;
440 // Virtual functions:
443 imbue(const locale
& __loc
)
445 _M_buf_locale_init
= true;
446 if (_M_buf_locale
!= __loc
)
447 _M_buf_locale
= __loc
;
450 // Buffer management and positioning:
451 virtual basic_streambuf
<char_type
,_Traits
>*
452 setbuf(char_type
*, streamsize
)
456 seekoff(off_type
, ios_base::seekdir
,
457 ios_base::openmode
/*__mode*/ = ios_base::in
| ios_base::out
)
458 { return pos_type(off_type(-1)); }
462 ios_base::openmode
/*__mode*/ = ios_base::in
| ios_base::out
)
463 { return pos_type(off_type(-1)); }
470 showmanyc() { return 0; }
473 xsgetn(char_type
* __s
, streamsize __n
);
477 { return traits_type::eof(); }
482 int_type __ret
= traits_type::eof();
483 bool __testeof
= this->underflow() == __ret
;
484 bool __testpending
= _M_in_cur
&& _M_in_cur
< _M_in_end
;
485 if (!__testeof
&& __testpending
)
487 __ret
= traits_type::to_int_type(*_M_in_cur
);
489 if (_M_buf_unified
&& _M_mode
& ios_base::out
)
497 pbackfail(int_type
/* __c */ = traits_type::eof())
498 { return traits_type::eof(); }
502 xsputn(const char_type
* __s
, streamsize __n
);
505 overflow(int_type
/* __c */ = traits_type::eof())
506 { return traits_type::eof(); }
508 #ifdef _GLIBCPP_DEPRECATED
513 if (_M_in_cur
< _M_in_end
)
520 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
521 // Side effect of DR 50.
523 basic_streambuf(const __streambuf_type
&);
526 operator=(const __streambuf_type
&);
532 #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT
534 #ifdef _GLIBCPP_FULLY_COMPLIANT_HEADERS
535 #include <bits/streambuf.tcc>
539 #endif /* _CPP_STREAMBUF */