Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4680 right-hear 1
// Stream buffer classes -*- C++ -*-
2
 
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.
10
 
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.
15
 
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.
20
 
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.
29
 
30
//
31
// ISO C++ 14882: 27.5  Stream buffers
32
//
33
 
34
#ifndef _CPP_STREAMBUF
35
#define _CPP_STREAMBUF	1
36
 
37
#pragma GCC system_header
38
 
39
#include 
40
#include 
41
#include  	// For SEEK_SET, SEEK_CUR, SEEK_END
42
#include 
43
#include 
44
 
45
namespace std
46
{
47
  template
48
    streamsize
49
    __copy_streambufs(basic_ios<_CharT, _Traits>& _ios,
50
		      basic_streambuf<_CharT, _Traits>* __sbin,
51
		      basic_streambuf<_CharT, _Traits>* __sbout);
52
 
53
  // 27.5.2 Template class basic_streambuf<_CharT, _Traits>
54
  template
55
    class basic_streambuf
56
    {
57
    public:
58
      // Types:
59
      typedef _CharT 					char_type;
60
      typedef _Traits 					traits_type;
61
      typedef typename traits_type::int_type 		int_type;
62
      typedef typename traits_type::pos_type 		pos_type;
63
      typedef typename traits_type::off_type 		off_type;
64
 
65
      // Non-standard Types:
66
      typedef ctype           		__ctype_type;
67
      typedef basic_streambuf  	__streambuf_type;
68
 
69
      friend class basic_ios;
70
      friend class basic_istream;
71
      friend class basic_ostream;
72
      friend class istreambuf_iterator;
73
      friend class ostreambuf_iterator;
74
 
75
      friend streamsize
76
      __copy_streambufs<>(basic_ios& __ios,
77
			  __streambuf_type* __sbin,__streambuf_type* __sbout);
78
 
79
    protected:
80
 
81
      // Pointer to the beginning of internally-allocated
82
      // space. Filebuf manually allocates/deallocates this, whereas
83
      // stringstreams attempt to use the built-in intelligence of the
84
      // string class. If you are managing memory, set this. If not,
85
      // leave it NULL.
86
      char_type*		_M_buf;
87
 
88
      // Actual size of allocated internal buffer, in bytes.
89
      int_type			_M_buf_size;
90
 
91
      // Optimal or preferred size of internal buffer, in bytes.
92
      int_type			_M_buf_size_opt;
93
 
94
      // True iff _M_in_* and _M_out_* buffers should always point to
95
      // the same place.  True for fstreams, false for sstreams.
96
      bool 			_M_buf_unified;
97
 
98
       // This is based on _IO_FILE, just reordered to be more
99
      // consistent, and is intended to be the most minimal abstraction
100
      // for an internal buffer.
101
      // get == input == read
102
      // put == output == write
103
      char_type* 		_M_in_beg;  	// Start of get area.
104
      char_type* 		_M_in_cur;	// Current read area.
105
      char_type* 		_M_in_end;	// End of get area.
106
      char_type* 		_M_out_beg; 	// Start of put area.
107
      char_type* 		_M_out_cur;  	// Current put area.
108
      char_type* 		_M_out_end;  	// End of put area.
109
 
110
      // Place to stash in || out || in | out settings for current streambuf.
111
      ios_base::openmode 	_M_mode;
112
 
113
      // Current locale setting.
114
      locale 			_M_buf_locale;
115
 
116
      // True iff locale is initialized.
117
      bool 			_M_buf_locale_init;
118
 
119
      // Necessary bits for putback buffer management. Only used in
120
      // the basic_filebuf class, as necessary for the standard
121
      // requirements. The only basic_streambuf member function that
122
      // needs access to these data members is in_avail...
123
      // NB: pbacks of over one character are not currently supported.
124
      int_type    		_M_pback_size;
125
      char_type*		_M_pback;
126
      char_type*		_M_pback_cur_save;
127
      char_type*		_M_pback_end_save;
128
      bool			_M_pback_init;
129
 
130
      // Initializes pback buffers, and moves normal buffers to safety.
131
      // Assumptions:
132
      // _M_in_cur has already been moved back
133
      void
134
      _M_pback_create()
135
      {
136
	if (!_M_pback_init)
137
	  {
138
	    int_type __dist = _M_in_end - _M_in_cur;
139
	    int_type __len = min(_M_pback_size, __dist);
140
	    traits_type::copy(_M_pback, _M_in_cur, __len);
141
	    _M_pback_cur_save = _M_in_cur;
142
	    _M_pback_end_save = _M_in_end;
143
	    this->setg(_M_pback, _M_pback, _M_pback + __len);
144
	    _M_pback_init = true;
145
	  }
146
      }
147
 
148
      // Deactivates pback buffer contents, and restores normal buffer.
149
      // Assumptions:
150
      // The pback buffer has only moved forward.
151
      void
152
      _M_pback_destroy()
153
      {
154
	if (_M_pback_init)
155
	  {
156
	    // Length _M_in_cur moved in the pback buffer.
157
	    int_type __off_cur = _M_in_cur - _M_pback;
158
 
159
	    // For in | out buffers, the end can be pushed back...
160
	    int_type __off_end = 0;
161
	    int_type __pback_len = _M_in_end - _M_pback;
162
	    int_type __save_len = _M_pback_end_save - _M_buf;
163
	    if (__pback_len > __save_len)
164
	      __off_end = __pback_len - __save_len;
165
 
166
	    this->setg(_M_buf, _M_pback_cur_save + __off_cur,
167
		       _M_pback_end_save + __off_end);
168
	    _M_pback_cur_save = NULL;
169
	    _M_pback_end_save = NULL;
170
	    _M_pback_init = false;
171
	  }
172
      }
173
 
174
      // Correctly sets the _M_in_cur pointer, and bumps the
175
      // _M_out_cur pointer as well if necessary.
176
      void
177
      _M_in_cur_move(off_type __n) // argument needs to be +-
178
      {
179
	bool __testout = _M_out_cur;
180
	_M_in_cur += __n;
181
	if (__testout && _M_buf_unified)
182
	  _M_out_cur += __n;
183
      }
184
 
185
      // Correctly sets the _M_out_cur pointer, and bumps the
186
      // appropriate _M_*_end pointers as well. Necessary for the
187
      // un-tied stringbufs, in in|out mode.
188
      // Invariant:
189
      // __n + _M_out_[cur, end] <= _M_buf + _M_buf_size
190
      // Assuming all _M_*_[beg, cur, end] pointers are operating on
191
      // the same range:
192
      // _M_buf <= _M_*_ <= _M_buf + _M_buf_size
193
      void
194
      _M_out_cur_move(off_type __n) // argument needs to be +-
195
      {
196
	bool __testin = _M_in_cur;
197
 
198
	_M_out_cur += __n;
199
	if (__testin && _M_buf_unified)
200
	  _M_in_cur += __n;
201
	if (_M_out_cur > _M_out_end)
202
	  {
203
	    _M_out_end = _M_out_cur;
204
	    // NB: in | out buffers drag the _M_in_end pointer along...
205
	    if (__testin)
206
	      _M_in_end += __n;
207
	  }
208
      }
209
 
210
      // Return the size of the output buffer.  This depends on the
211
      // buffer in use: allocated buffers have a stored size in
212
      // _M_buf_size and setbuf() buffers don't.
213
      off_type
214
      _M_out_buf_size()
215
      {
216
	off_type __ret = 0;
217
	if (_M_out_cur)
218
	  {
219
	    // Using allocated buffer.
220
	    if (_M_out_beg == _M_buf)
221
	      __ret = _M_out_beg + _M_buf_size - _M_out_cur;
222
	    // Using non-allocated buffer.
223
	    else
224
	      __ret = _M_out_end - _M_out_cur;
225
	  }
226
	return __ret;
227
      }
228
 
229
      // These three functions are used to clarify internal buffer
230
      // maintenance. After an overflow, or after a seekoff call that
231
      // started at beg or end, or possibly when the stream becomes
232
      // unbuffered, and a myrid other obscure corner cases, the
233
      // internal buffer does not truly reflect the contents of the
234
      // external buffer. At this point, for whatever reason, it is in
235
      // an indeterminate state.
236
      void
237
      _M_set_indeterminate(void)
238
      {
239
	if (_M_mode & ios_base::in)
240
	  this->setg(_M_buf, _M_buf, _M_buf);
241
	if (_M_mode & ios_base::out)
242
	  this->setp(_M_buf, _M_buf);
243
      }
244
 
245
      void
246
      _M_set_determinate(off_type __off)
247
      {
248
	bool __testin = _M_mode & ios_base::in;
249
	bool __testout = _M_mode & ios_base::out;
250
	if (__testin)
251
	  this->setg(_M_buf, _M_buf, _M_buf + __off);
252
	if (__testout)
253
	  this->setp(_M_buf, _M_buf + __off);
254
      }
255
 
256
      bool
257
      _M_is_indeterminate(void)
258
      {
259
	bool __ret = false;
260
	// Don't return true if unbuffered.
261
	if (_M_buf)
262
	  {
263
	    if (_M_mode & ios_base::in)
264
	      __ret = _M_in_beg == _M_in_cur && _M_in_cur == _M_in_end;
265
	    if (_M_mode & ios_base::out)
266
	      __ret = _M_out_beg == _M_out_cur && _M_out_cur == _M_out_end;
267
	  }
268
	return __ret;
269
      }
270
 
271
  public:
272
      virtual
273
      ~basic_streambuf()
274
      {
275
	_M_buf_unified = false;
276
	_M_buf_size = 0;
277
	_M_buf_size_opt = 0;
278
	_M_mode = ios_base::openmode(0);
279
	_M_buf_locale_init = false;
280
      }
281
 
282
      // Locales:
283
      locale
284
      pubimbue(const locale &__loc)
285
      {
286
	locale __tmp(this->getloc());
287
	this->imbue(__loc);
288
	return __tmp;
289
      }
290
 
291
      locale
292
      getloc() const
293
      {
294
	if (_M_buf_locale_init)
295
	  return _M_buf_locale;
296
	else
297
	  return locale();
298
      }
299
 
300
      // Buffer and positioning:
301
      __streambuf_type*
302
      pubsetbuf(char_type* __s, streamsize __n)
303
      { return this->setbuf(__s, __n); }
304
 
305
      pos_type
306
      pubseekoff(off_type __off, ios_base::seekdir __way,
307
		 ios_base::openmode __mode = ios_base::in | ios_base::out)
308
      { return this->seekoff(__off, __way, __mode); }
309
 
310
      pos_type
311
      pubseekpos(pos_type __sp,
312
		 ios_base::openmode __mode = ios_base::in | ios_base::out)
313
      { return this->seekpos(__sp, __mode); }
314
 
315
      int
316
      pubsync() { return this->sync(); }
317
 
318
      // Get and put areas:
319
      // Get area:
320
      streamsize
321
      in_avail()
322
      {
323
	streamsize __ret;
324
	if (_M_in_cur && _M_in_cur < _M_in_end)
325
	  {
326
	    if (_M_pback_init)
327
	      {
328
		int_type __save_len =  _M_pback_end_save - _M_pback_cur_save;
329
		int_type __pback_len = _M_in_cur - _M_pback;
330
		__ret = __save_len - __pback_len;
331
	      }
332
	    else
333
	      __ret = this->egptr() - this->gptr();
334
	  }
335
	else
336
	  __ret = this->showmanyc();
337
	return __ret;
338
      }
339
 
340
      int_type
341
      snextc()
342
      {
343
	int_type __eof = traits_type::eof();
344
	return (this->sbumpc() == __eof ? __eof : this->sgetc());
345
      }
346
 
347
      int_type
348
      sbumpc();
349
 
350
      int_type
351
      sgetc()
352
      {
353
	int_type __ret;
354
	if (_M_in_cur && _M_in_cur < _M_in_end)
355
	  __ret = traits_type::to_int_type(*(this->gptr()));
356
	else
357
	  __ret = this->underflow();
358
	return __ret;
359
      }
360
 
361
      streamsize
362
      sgetn(char_type* __s, streamsize __n)
363
      { return this->xsgetn(__s, __n); }
364
 
365
      // Putback:
366
      int_type
367
      sputbackc(char_type __c);
368
 
369
      int_type
370
      sungetc();
371
 
372
      // Put area:
373
      int_type
374
      sputc(char_type __c);
375
 
376
      streamsize
377
      sputn(const char_type* __s, streamsize __n)
378
      { return this->xsputn(__s, __n); }
379
 
380
    protected:
381
      basic_streambuf()
382
      : _M_buf(NULL), _M_buf_size(0),
383
      _M_buf_size_opt(static_cast(BUFSIZ)), _M_buf_unified(false),
384
      _M_in_beg(0), _M_in_cur(0), _M_in_end(0), _M_out_beg(0), _M_out_cur(0),
385
      _M_out_end(0), _M_mode(ios_base::openmode(0)), _M_buf_locale(locale()),
386
      _M_buf_locale_init(false), _M_pback_size(1), _M_pback(NULL),
387
      _M_pback_cur_save(NULL), _M_pback_end_save(NULL), _M_pback_init(false)
388
      { }
389
 
390
      // Get area:
391
      char_type*
392
      eback() const { return _M_in_beg; }
393
 
394
      char_type*
395
      gptr()  const { return _M_in_cur;  }
396
 
397
      char_type*
398
      egptr() const { return _M_in_end; }
399
 
400
      void
401
      gbump(int __n) { _M_in_cur += __n; }
402
 
403
      void
404
      setg(char_type* __gbeg, char_type* __gnext, char_type* __gend)
405
      {
406
	_M_in_beg = __gbeg;
407
	_M_in_cur = __gnext;
408
	_M_in_end = __gend;
409
	if (!(_M_mode & ios_base::in) && __gbeg && __gnext && __gend)
410
	  _M_mode = _M_mode | ios_base::in;
411
      }
412
 
413
      // Put area:
414
      char_type*
415
      pbase() const { return _M_out_beg; }
416
 
417
      char_type*
418
      pptr() const { return _M_out_cur; }
419
 
420
      char_type*
421
      epptr() const { return _M_out_end; }
422
 
423
      void
424
      pbump(int __n) { _M_out_cur += __n; }
425
 
426
      void
427
      setp(char_type* __pbeg, char_type* __pend)
428
      {
429
	_M_out_beg = _M_out_cur = __pbeg;
430
	_M_out_end = __pend;
431
	if (!(_M_mode & ios_base::out) && __pbeg && __pend)
432
	  _M_mode = _M_mode | ios_base::out;
433
      }
434
 
435
      // Virtual functions:
436
      // Locales:
437
      virtual void
438
      imbue(const locale& __loc)
439
      {
440
	_M_buf_locale_init = true;
441
	if (_M_buf_locale != __loc)
442
	  _M_buf_locale = __loc;
443
      }
444
 
445
      // Buffer management and positioning:
446
      virtual basic_streambuf*
447
      setbuf(char_type*, streamsize)
448
      {	return this; }
449
 
450
      virtual pos_type
451
      seekoff(off_type, ios_base::seekdir,
452
	      ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
453
      { return pos_type(off_type(-1)); }
454
 
455
      virtual pos_type
456
      seekpos(pos_type,
457
	      ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
458
      { return pos_type(off_type(-1)); }
459
 
460
      virtual int
461
      sync() { return 0; }
462
 
463
      // Get area:
464
      virtual streamsize
465
      showmanyc() { return 0; }
466
 
467
      virtual streamsize
468
      xsgetn(char_type* __s, streamsize __n);
469
 
470
      virtual int_type
471
      underflow()
472
      { return traits_type::eof(); }
473
 
474
      virtual int_type
475
      uflow()
476
      {
477
	int_type __ret = traits_type::eof();
478
	bool __testeof = this->underflow() == __ret;
479
	bool __testpending = _M_in_cur && _M_in_cur < _M_in_end;
480
	if (!__testeof && __testpending)
481
	  {
482
	    __ret = traits_type::to_int_type(*_M_in_cur);
483
	    ++_M_in_cur;
484
	    if (_M_buf_unified && _M_mode & ios_base::out)
485
	      ++_M_out_cur;
486
	  }
487
	return __ret;
488
      }
489
 
490
      // Putback:
491
      virtual int_type
492
      pbackfail(int_type /* __c */  = traits_type::eof())
493
      { return traits_type::eof(); }
494
 
495
      // Put area:
496
      virtual streamsize
497
      xsputn(const char_type* __s, streamsize __n);
498
 
499
      virtual int_type
500
      overflow(int_type /* __c */ = traits_type::eof())
501
      { return traits_type::eof(); }
502
 
503
#ifdef _GLIBCPP_DEPRECATED
504
    public:
505
      void
506
      stossc()
507
      {
508
	if (_M_in_cur < _M_in_end)
509
	  ++_M_in_cur;
510
	else
511
	  this->uflow();
512
      }
513
#endif
514
 
515
#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
516
    private:
517
      basic_streambuf(const __streambuf_type&);
518
 
519
      __streambuf_type&
520
      operator=(const __streambuf_type&);
521
#endif
522
    };
523
 
524
} // namespace std
525
 
526
#ifdef _GLIBCPP_NO_TEMPLATE_EXPORT
527
# define export
528
#ifdef  _GLIBCPP_FULLY_COMPLIANT_HEADERS
529
#include 
530
#endif
531
#endif
532
 
533
#endif	/* _CPP_STREAMBUF */
534