source: trunk/src/gcc/libstdc++-v3/include/std/std_streambuf.h@ 2

Last change on this file since 2 was 2, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 13.8 KB
Line 
1// Stream buffer classes -*- C++ -*-
2
3// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
4// Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library. This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16
17// You should have received a copy of the GNU General Public License along
18// with this library; see the file COPYING. If not, write to the Free
19// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20// USA.
21
22// As a special exception, you may use this file as part of a free software
23// library without restriction. Specifically, if other files instantiate
24// templates or use macros or inline functions from this file, or you compile
25// this file and link it with other files to produce an executable, this
26// file does not by itself cause the resulting executable to be covered by
27// the GNU General Public License. This exception does not however
28// invalidate any other reasons why the executable file might be covered by
29// the GNU General Public License.
30
31//
32// ISO C++ 14882: 27.5 Stream buffers
33//
34
35/** @file streambuf
36 * This is a Standard C++ Library header. You should @c #include this header
37 * in your programs, rather than any of the "st[dl]_*.h" implementation files.
38 */
39
40#ifndef _CPP_STREAMBUF
41#define _CPP_STREAMBUF 1
42
43#pragma GCC system_header
44
45#include <bits/c++config.h>
46#include <iosfwd>
47#include <cstdio> // For SEEK_SET, SEEK_CUR, SEEK_END
48#include <bits/localefwd.h>
49#include <bits/ios_base.h>
50
51namespace std
52{
53 template<typename _CharT, typename _Traits>
54 streamsize
55 __copy_streambufs(basic_ios<_CharT, _Traits>& _ios,
56 basic_streambuf<_CharT, _Traits>* __sbin,
57 basic_streambuf<_CharT, _Traits>* __sbout);
58
59 // 27.5.2 Template class basic_streambuf<_CharT, _Traits>
60 template<typename _CharT, typename _Traits>
61 class basic_streambuf
62 {
63 public:
64 // Types:
65 typedef _CharT char_type;
66 typedef _Traits traits_type;
67 typedef typename traits_type::int_type int_type;
68 typedef typename traits_type::pos_type pos_type;
69 typedef typename traits_type::off_type off_type;
70
71 // Non-standard Types:
72 typedef ctype<char_type> __ctype_type;
73 typedef basic_streambuf<char_type, traits_type> __streambuf_type;
74 typedef typename traits_type::state_type __state_type;
75
76 friend class basic_ios<char_type, traits_type>;
77 friend class basic_istream<char_type, traits_type>;
78 friend class basic_ostream<char_type, traits_type>;
79 friend class istreambuf_iterator<char_type, traits_type>;
80 friend class ostreambuf_iterator<char_type, traits_type>;
81
82 friend streamsize
83 __copy_streambufs<>(basic_ios<char_type, traits_type>& __ios,
84 __streambuf_type* __sbin,__streambuf_type* __sbout);
85
86 protected:
87 // Pointer to the beginning of internally-allocated
88 // space. Filebuf manually allocates/deallocates this, whereas
89 // stringstreams attempt to use the built-in intelligence of the
90 // string class. If you are managing memory, set this. If not,
91 // leave it NULL.
92 char_type* _M_buf;
93
94 // Actual size of allocated internal buffer, in bytes.
95 size_t _M_buf_size;
96
97 // Optimal or preferred size of internal buffer, in bytes.
98 size_t _M_buf_size_opt;
99
100 // True iff _M_in_* and _M_out_* buffers should always point to
101 // the same place. True for fstreams, false for sstreams.
102 bool _M_buf_unified;
103
104 // This is based on _IO_FILE, just reordered to be more
105 // consistent, and is intended to be the most minimal abstraction
106 // for an internal buffer.
107 // get == input == read
108 // put == output == write
109 char_type* _M_in_beg; // Start of get area.
110 char_type* _M_in_cur; // Current read area.
111 char_type* _M_in_end; // End of get area.
112 char_type* _M_out_beg; // Start of put area.
113 char_type* _M_out_cur; // Current put area.
114 char_type* _M_out_end; // End of put area.
115
116 // Place to stash in || out || in | out settings for current streambuf.
117 ios_base::openmode _M_mode;
118
119 // Current locale setting.
120 locale _M_buf_locale;
121
122 // True iff locale is initialized.
123 bool _M_buf_locale_init;
124
125 // Necessary bits for putback buffer management. Only used in
126 // the basic_filebuf class, as necessary for the standard
127 // requirements. The only basic_streambuf member function that
128 // needs access to these data members is in_avail...
129 // NB: pbacks of over one character are not currently supported.
130 static const size_t _S_pback_size = 1;
131 char_type _M_pback[_S_pback_size];
132 char_type* _M_pback_cur_save;
133 char_type* _M_pback_end_save;
134 bool _M_pback_init;
135
136 // Yet unused.
137 fpos<__state_type> _M_pos;
138
139 // Initializes pback buffers, and moves normal buffers to safety.
140 // Assumptions:
141 // _M_in_cur has already been moved back
142 void
143 _M_pback_create()
144 {
145 if (!_M_pback_init)
146 {
147 size_t __dist = _M_in_end - _M_in_cur;
148 size_t __len = min(_S_pback_size, __dist);
149 traits_type::copy(_M_pback, _M_in_cur, __len);
150 _M_pback_cur_save = _M_in_cur;
151 _M_pback_end_save = _M_in_end;
152 this->setg(_M_pback, _M_pback, _M_pback + __len);
153 _M_pback_init = true;
154 }
155 }
156
157 // Deactivates pback buffer contents, and restores normal buffer.
158 // Assumptions:
159 // The pback buffer has only moved forward.
160 void
161 _M_pback_destroy()
162 {
163 if (_M_pback_init)
164 {
165 // Length _M_in_cur moved in the pback buffer.
166 size_t __off_cur = _M_in_cur - _M_pback;
167
168 // For in | out buffers, the end can be pushed back...
169 size_t __off_end = 0;
170 size_t __pback_len = _M_in_end - _M_pback;
171 size_t __save_len = _M_pback_end_save - _M_buf;
172 if (__pback_len > __save_len)
173 __off_end = __pback_len - __save_len;
174
175 this->setg(_M_buf, _M_pback_cur_save + __off_cur,
176 _M_pback_end_save + __off_end);
177 _M_pback_cur_save = NULL;
178 _M_pback_end_save = NULL;
179 _M_pback_init = false;
180 }
181 }
182
183 // Correctly sets the _M_in_cur pointer, and bumps the
184 // _M_out_cur pointer as well if necessary.
185 void
186 _M_in_cur_move(off_type __n) // argument needs to be +-
187 {
188 bool __testout = _M_out_cur;
189 _M_in_cur += __n;
190 if (__testout && _M_buf_unified)
191 _M_out_cur += __n;
192 }
193
194 // Correctly sets the _M_out_cur pointer, and bumps the
195 // appropriate _M_*_end pointers as well. Necessary for the
196 // un-tied stringbufs, in in|out mode.
197 // Invariant:
198 // __n + _M_out_[cur, end] <= _M_buf + _M_buf_size
199 // Assuming all _M_*_[beg, cur, end] pointers are operating on
200 // the same range:
201 // _M_buf <= _M_*_ <= _M_buf + _M_buf_size
202 void
203 _M_out_cur_move(off_type __n) // argument needs to be +-
204 {
205 bool __testin = _M_in_cur;
206
207 _M_out_cur += __n;
208 if (__testin && _M_buf_unified)
209 _M_in_cur += __n;
210 if (_M_out_cur > _M_out_end)
211 {
212 _M_out_end = _M_out_cur;
213 // NB: in | out buffers drag the _M_in_end pointer along...
214 if (__testin)
215 _M_in_end += __n;
216 }
217 }
218
219 // Return the size of the output buffer. This depends on the
220 // buffer in use: allocated buffers have a stored size in
221 // _M_buf_size and setbuf() buffers don't.
222 off_type
223 _M_out_buf_size()
224 {
225 off_type __ret = 0;
226 if (_M_out_cur)
227 {
228 // Using allocated buffer.
229 if (_M_out_beg == _M_buf)
230 __ret = _M_out_beg + _M_buf_size - _M_out_cur;
231 // Using non-allocated buffer.
232 else
233 __ret = _M_out_end - _M_out_cur;
234 }
235 return __ret;
236 }
237
238 public:
239 virtual
240 ~basic_streambuf()
241 {
242 _M_buf_unified = false;
243 _M_buf_size = 0;
244 _M_buf_size_opt = 0;
245 _M_mode = ios_base::openmode(0);
246 }
247
248 // Locales:
249 locale
250 pubimbue(const locale &__loc)
251 {
252 locale __tmp(this->getloc());
253 this->imbue(__loc);
254 return __tmp;
255 }
256
257 locale
258 getloc() const
259 { return _M_buf_locale; }
260
261 // Buffer and positioning:
262 __streambuf_type*
263 pubsetbuf(char_type* __s, streamsize __n)
264 { return this->setbuf(__s, __n); }
265
266 pos_type
267 pubseekoff(off_type __off, ios_base::seekdir __way,
268 ios_base::openmode __mode = ios_base::in | ios_base::out)
269 { return this->seekoff(__off, __way, __mode); }
270
271 pos_type
272 pubseekpos(pos_type __sp,
273 ios_base::openmode __mode = ios_base::in | ios_base::out)
274 { return this->seekpos(__sp, __mode); }
275
276 int
277 pubsync() { return this->sync(); }
278
279 // Get and put areas:
280 // Get area:
281 streamsize
282 in_avail()
283 {
284 streamsize __ret;
285 if (_M_in_cur && _M_in_cur < _M_in_end)
286 {
287 if (_M_pback_init)
288 {
289 size_t __save_len = _M_pback_end_save - _M_pback_cur_save;
290 size_t __pback_len = _M_in_cur - _M_pback;
291 __ret = __save_len - __pback_len;
292 }
293 else
294 __ret = this->egptr() - this->gptr();
295 }
296 else
297 __ret = this->showmanyc();
298 return __ret;
299 }
300
301 int_type
302 snextc()
303 {
304 int_type __eof = traits_type::eof();
305 return (traits_type::eq_int_type(this->sbumpc(), __eof)
306 ? __eof : this->sgetc());
307 }
308
309 int_type
310 sbumpc();
311
312 int_type
313 sgetc()
314 {
315 int_type __ret;
316 if (_M_in_cur && _M_in_cur < _M_in_end)
317 __ret = traits_type::to_int_type(*(this->gptr()));
318 else
319 __ret = this->underflow();
320 return __ret;
321 }
322
323 streamsize
324 sgetn(char_type* __s, streamsize __n)
325 { return this->xsgetn(__s, __n); }
326
327 // Putback:
328 int_type
329 sputbackc(char_type __c);
330
331 int_type
332 sungetc();
333
334 // Put area:
335 int_type
336 sputc(char_type __c);
337
338 streamsize
339 sputn(const char_type* __s, streamsize __n)
340 { return this->xsputn(__s, __n); }
341
342 protected:
343 basic_streambuf()
344 : _M_buf(NULL), _M_buf_size(0), _M_buf_size_opt(BUFSIZ),
345 _M_buf_unified(false), _M_in_beg(0), _M_in_cur(0), _M_in_end(0),
346 _M_out_beg(0), _M_out_cur(0), _M_out_end(0),
347 _M_mode(ios_base::openmode(0)), _M_buf_locale(locale()),
348 _M_pback_cur_save(0), _M_pback_end_save(0),
349 _M_pback_init(false)
350 { }
351
352 // Get area:
353 char_type*
354 eback() const { return _M_in_beg; }
355
356 char_type*
357 gptr() const { return _M_in_cur; }
358
359 char_type*
360 egptr() const { return _M_in_end; }
361
362 void
363 gbump(int __n) { _M_in_cur += __n; }
364
365 void
366 setg(char_type* __gbeg, char_type* __gnext, char_type* __gend)
367 {
368 _M_in_beg = __gbeg;
369 _M_in_cur = __gnext;
370 _M_in_end = __gend;
371 if (!(_M_mode & ios_base::in) && __gbeg && __gnext && __gend)
372 _M_mode = _M_mode | ios_base::in;
373 }
374
375 // Put area:
376 char_type*
377 pbase() const { return _M_out_beg; }
378
379 char_type*
380 pptr() const { return _M_out_cur; }
381
382 char_type*
383 epptr() const { return _M_out_end; }
384
385 void
386 pbump(int __n) { _M_out_cur += __n; }
387
388 void
389 setp(char_type* __pbeg, char_type* __pend)
390 {
391 _M_out_beg = _M_out_cur = __pbeg;
392 _M_out_end = __pend;
393 if (!(_M_mode & ios_base::out) && __pbeg && __pend)
394 _M_mode = _M_mode | ios_base::out;
395 }
396
397 // Virtual functions:
398 // Locales:
399 virtual void
400 imbue(const locale& __loc)
401 {
402 if (_M_buf_locale != __loc)
403 _M_buf_locale = __loc;
404 }
405
406 // Buffer management and positioning:
407 virtual basic_streambuf<char_type,_Traits>*
408 setbuf(char_type*, streamsize)
409 { return this; }
410
411 virtual pos_type
412 seekoff(off_type, ios_base::seekdir,
413 ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
414 { return pos_type(off_type(-1)); }
415
416 virtual pos_type
417 seekpos(pos_type,
418 ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
419 { return pos_type(off_type(-1)); }
420
421 virtual int
422 sync() { return 0; }
423
424 // Get area:
425 virtual streamsize
426 showmanyc() { return 0; }
427
428 virtual streamsize
429 xsgetn(char_type* __s, streamsize __n);
430
431 virtual int_type
432 underflow()
433 { return traits_type::eof(); }
434
435 virtual int_type
436 uflow()
437 {
438 int_type __ret = traits_type::eof();
439 bool __testeof = traits_type::eq_int_type(this->underflow(), __ret);
440 bool __testpending = _M_in_cur && _M_in_cur < _M_in_end;
441 if (!__testeof && __testpending)
442 {
443 __ret = traits_type::to_int_type(*_M_in_cur);
444 ++_M_in_cur;
445 if (_M_buf_unified && _M_mode & ios_base::out)
446 ++_M_out_cur;
447 }
448 return __ret;
449 }
450
451 // Putback:
452 virtual int_type
453 pbackfail(int_type /* __c */ = traits_type::eof())
454 { return traits_type::eof(); }
455
456 // Put area:
457 virtual streamsize
458 xsputn(const char_type* __s, streamsize __n);
459
460 virtual int_type
461 overflow(int_type /* __c */ = traits_type::eof())
462 { return traits_type::eof(); }
463
464#ifdef _GLIBCPP_DEPRECATED
465 public:
466 void
467 stossc()
468 {
469 if (_M_in_cur < _M_in_end)
470 ++_M_in_cur;
471 else
472 this->uflow();
473 }
474#endif
475
476#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
477 // Side effect of DR 50.
478 private:
479 basic_streambuf(const __streambuf_type&) { };
480
481 __streambuf_type&
482 operator=(const __streambuf_type&) { return *this; };
483#endif
484 };
485} // namespace std
486
487#ifdef _GLIBCPP_NO_TEMPLATE_EXPORT
488# define export
489#endif
490#ifdef _GLIBCPP_FULLY_COMPLIANT_HEADERS
491#include <bits/streambuf.tcc>
492#endif
493
494#endif
Note: See TracBrowser for help on using the repository browser.