2002-01-11 Phil Edwards <pme@gcc.gnu.org>
[official-gcc.git] / libstdc++-v3 / include / std / std_streambuf.h
blob59f70705361047b52504d9ba16ed621f4aff6c5b
1 // Stream buffer classes -*- C++ -*-
3 // Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
4 //
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)
9 // any later version.
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,
19 // USA.
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>
45 #include <iosfwd>
46 #include <cstdio> // For SEEK_SET, SEEK_CUR, SEEK_END
47 #include <bits/localefwd.h>
48 #include <bits/ios_base.h>
50 namespace std
52 template<typename _CharT, typename _Traits>
53 streamsize
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>
60 class basic_streambuf
62 public:
63 // Types:
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>;
80 friend streamsize
81 __copy_streambufs<>(basic_ios<char_type, traits_type>& __ios,
82 __streambuf_type* __sbin,__streambuf_type* __sbout);
84 protected:
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,
90 // leave it NULL.
91 char_type* _M_buf;
93 // Actual size of allocated internal buffer, in bytes.
94 int_type _M_buf_size;
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.
101 bool _M_buf_unified;
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;
130 char_type* _M_pback;
131 char_type* _M_pback_cur_save;
132 char_type* _M_pback_end_save;
133 bool _M_pback_init;
135 // Initializes pback buffers, and moves normal buffers to safety.
136 // Assumptions:
137 // _M_in_cur has already been moved back
138 void
139 _M_pback_create()
141 if (!_M_pback_init)
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.
154 // Assumptions:
155 // The pback buffer has only moved forward.
156 void
157 _M_pback_destroy()
159 if (_M_pback_init)
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.
181 void
182 _M_in_cur_move(off_type __n) // argument needs to be +-
184 bool __testout = _M_out_cur;
185 _M_in_cur += __n;
186 if (__testout && _M_buf_unified)
187 _M_out_cur += __n;
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.
193 // Invariant:
194 // __n + _M_out_[cur, end] <= _M_buf + _M_buf_size
195 // Assuming all _M_*_[beg, cur, end] pointers are operating on
196 // the same range:
197 // _M_buf <= _M_*_ <= _M_buf + _M_buf_size
198 void
199 _M_out_cur_move(off_type __n) // argument needs to be +-
201 bool __testin = _M_in_cur;
203 _M_out_cur += __n;
204 if (__testin && _M_buf_unified)
205 _M_in_cur += __n;
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...
210 if (__testin)
211 _M_in_end += __n;
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.
218 off_type
219 _M_out_buf_size()
221 off_type __ret = 0;
222 if (_M_out_cur)
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.
228 else
229 __ret = _M_out_end - _M_out_cur;
231 return __ret;
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.
241 void
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);
250 void
251 _M_set_determinate(off_type __off)
253 bool __testin = _M_mode & ios_base::in;
254 bool __testout = _M_mode & ios_base::out;
255 if (__testin)
256 this->setg(_M_buf, _M_buf, _M_buf + __off);
257 if (__testout)
258 this->setp(_M_buf, _M_buf + __off);
261 bool
262 _M_is_indeterminate(void)
264 bool __ret = false;
265 // Don't return true if unbuffered.
266 if (_M_buf)
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;
273 return __ret;
276 public:
277 virtual
278 ~basic_streambuf()
280 _M_buf_unified = false;
281 _M_buf_size = 0;
282 _M_buf_size_opt = 0;
283 _M_mode = ios_base::openmode(0);
284 _M_buf_locale_init = false;
287 // Locales:
288 locale
289 pubimbue(const locale &__loc)
291 locale __tmp(this->getloc());
292 this->imbue(__loc);
293 return __tmp;
296 locale
297 getloc() const
299 if (_M_buf_locale_init)
300 return _M_buf_locale;
301 else
302 return locale();
305 // Buffer and positioning:
306 __streambuf_type*
307 pubsetbuf(char_type* __s, streamsize __n)
308 { return this->setbuf(__s, __n); }
310 pos_type
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); }
315 pos_type
316 pubseekpos(pos_type __sp,
317 ios_base::openmode __mode = ios_base::in | ios_base::out)
318 { return this->seekpos(__sp, __mode); }
320 int
321 pubsync() { return this->sync(); }
323 // Get and put areas:
324 // Get area:
325 streamsize
326 in_avail()
328 streamsize __ret;
329 if (_M_in_cur && _M_in_cur < _M_in_end)
331 if (_M_pback_init)
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;
337 else
338 __ret = this->egptr() - this->gptr();
340 else
341 __ret = this->showmanyc();
342 return __ret;
345 int_type
346 snextc()
348 int_type __eof = traits_type::eof();
349 return (this->sbumpc() == __eof ? __eof : this->sgetc());
352 int_type
353 sbumpc();
355 int_type
356 sgetc()
358 int_type __ret;
359 if (_M_in_cur && _M_in_cur < _M_in_end)
360 __ret = traits_type::to_int_type(*(this->gptr()));
361 else
362 __ret = this->underflow();
363 return __ret;
366 streamsize
367 sgetn(char_type* __s, streamsize __n)
368 { return this->xsgetn(__s, __n); }
370 // Putback:
371 int_type
372 sputbackc(char_type __c);
374 int_type
375 sungetc();
377 // Put area:
378 int_type
379 sputc(char_type __c);
381 streamsize
382 sputn(const char_type* __s, streamsize __n)
383 { return this->xsputn(__s, __n); }
385 protected:
386 basic_streambuf()
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)
395 // Get area:
396 char_type*
397 eback() const { return _M_in_beg; }
399 char_type*
400 gptr() const { return _M_in_cur; }
402 char_type*
403 egptr() const { return _M_in_end; }
405 void
406 gbump(int __n) { _M_in_cur += __n; }
408 void
409 setg(char_type* __gbeg, char_type* __gnext, char_type* __gend)
411 _M_in_beg = __gbeg;
412 _M_in_cur = __gnext;
413 _M_in_end = __gend;
414 if (!(_M_mode & ios_base::in) && __gbeg && __gnext && __gend)
415 _M_mode = _M_mode | ios_base::in;
418 // Put area:
419 char_type*
420 pbase() const { return _M_out_beg; }
422 char_type*
423 pptr() const { return _M_out_cur; }
425 char_type*
426 epptr() const { return _M_out_end; }
428 void
429 pbump(int __n) { _M_out_cur += __n; }
431 void
432 setp(char_type* __pbeg, char_type* __pend)
434 _M_out_beg = _M_out_cur = __pbeg;
435 _M_out_end = __pend;
436 if (!(_M_mode & ios_base::out) && __pbeg && __pend)
437 _M_mode = _M_mode | ios_base::out;
440 // Virtual functions:
441 // Locales:
442 virtual void
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)
453 { return this; }
455 virtual pos_type
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)); }
460 virtual pos_type
461 seekpos(pos_type,
462 ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
463 { return pos_type(off_type(-1)); }
465 virtual int
466 sync() { return 0; }
468 // Get area:
469 virtual streamsize
470 showmanyc() { return 0; }
472 virtual streamsize
473 xsgetn(char_type* __s, streamsize __n);
475 virtual int_type
476 underflow()
477 { return traits_type::eof(); }
479 virtual int_type
480 uflow()
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);
488 ++_M_in_cur;
489 if (_M_buf_unified && _M_mode & ios_base::out)
490 ++_M_out_cur;
492 return __ret;
495 // Putback:
496 virtual int_type
497 pbackfail(int_type /* __c */ = traits_type::eof())
498 { return traits_type::eof(); }
500 // Put area:
501 virtual streamsize
502 xsputn(const char_type* __s, streamsize __n);
504 virtual int_type
505 overflow(int_type /* __c */ = traits_type::eof())
506 { return traits_type::eof(); }
508 #ifdef _GLIBCPP_DEPRECATED
509 public:
510 void
511 stossc()
513 if (_M_in_cur < _M_in_end)
514 ++_M_in_cur;
515 else
516 this->uflow();
518 #endif
520 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
521 // Side effect of DR 50.
522 private:
523 basic_streambuf(const __streambuf_type&);
525 __streambuf_type&
526 operator=(const __streambuf_type&);
527 #endif
530 } // namespace std
532 #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT
533 # define export
534 #ifdef _GLIBCPP_FULLY_COMPLIANT_HEADERS
535 #include <bits/streambuf.tcc>
536 #endif
537 #endif
539 #endif /* _CPP_STREAMBUF */