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 */