OSDN Git Service

2002-01-11 Chris Sears <cbsears_sf@yahoo.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / std / std_streambuf.h
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 /** @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.
37  */
38
39 #ifndef _CPP_STREAMBUF
40 #define _CPP_STREAMBUF  1
41
42 #pragma GCC system_header
43
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>
49
50 namespace std
51 {
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);
57   
58   // 27.5.2 Template class basic_streambuf<_CharT, _Traits>
59   template<typename _CharT, typename _Traits>
60     class basic_streambuf 
61     {
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;
69
70       // Non-standard Types:
71       typedef ctype<char_type>                          __ctype_type;
72       typedef basic_streambuf<char_type, traits_type>   __streambuf_type;
73       
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>;
79
80       friend streamsize
81       __copy_streambufs<>(basic_ios<char_type, traits_type>& __ios,
82                           __streambuf_type* __sbin,__streambuf_type* __sbout);
83       
84     protected:
85
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;         
92
93       // Actual size of allocated internal buffer, in bytes.
94       int_type                  _M_buf_size;
95
96       // Optimal or preferred size of internal buffer, in bytes.
97       int_type                  _M_buf_size_opt;
98
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; 
102
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. 
114
115       // Place to stash in || out || in | out settings for current streambuf.
116       ios_base::openmode        _M_mode;        
117
118       // Current locale setting.
119       locale                    _M_buf_locale;  
120
121       // True iff locale is initialized.
122       bool                      _M_buf_locale_init;
123
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; 
134
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()
140       {
141         if (!_M_pback_init)
142           {
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;
150           }
151       }
152
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()
158       {
159         if (_M_pback_init)
160           {
161             // Length _M_in_cur moved in the pback buffer.
162             int_type __off_cur = _M_in_cur - _M_pback;
163             
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;
170
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;
176           }
177       }
178
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 +-
183       {
184         bool __testout = _M_out_cur;
185         _M_in_cur += __n;
186         if (__testout && _M_buf_unified)
187           _M_out_cur += __n;
188       }
189
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 +-
200       {
201         bool __testin = _M_in_cur;
202
203         _M_out_cur += __n;
204         if (__testin && _M_buf_unified)
205           _M_in_cur += __n;
206         if (_M_out_cur > _M_out_end)
207           {
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;
212           }
213       }
214
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()
220       {
221         off_type __ret = 0;
222         if (_M_out_cur)
223           {
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;
230           }
231         return __ret;
232       }
233
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)
243       {
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);
248       }
249
250       void
251       _M_set_determinate(off_type __off)
252       {
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);
259       }
260
261       bool
262       _M_is_indeterminate(void)
263       { 
264         bool __ret = false;
265         // Don't return true if unbuffered.
266         if (_M_buf)
267           {
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;
272           }
273         return __ret;
274       }
275
276   public:
277       virtual 
278       ~basic_streambuf() 
279       {
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;
285       }
286
287       // Locales:
288       locale 
289       pubimbue(const locale &__loc)
290       {
291         locale __tmp(this->getloc());
292         this->imbue(__loc);
293         return __tmp;
294       }
295
296       locale   
297       getloc() const
298       {
299         if (_M_buf_locale_init)
300           return _M_buf_locale; 
301         else 
302           return locale();
303       } 
304
305       // Buffer and positioning:
306       __streambuf_type* 
307       pubsetbuf(char_type* __s, streamsize __n) 
308       { return this->setbuf(__s, __n); }
309
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); }
314
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); }
319
320       int 
321       pubsync() { return this->sync(); }
322
323       // Get and put areas:
324       // Get area:
325       streamsize 
326       in_avail() 
327       { 
328         streamsize __ret;
329         if (_M_in_cur && _M_in_cur < _M_in_end)
330           {
331             if (_M_pback_init)
332               {
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;
336               }
337             else
338               __ret = this->egptr() - this->gptr();
339           }
340         else
341           __ret = this->showmanyc();
342         return __ret;
343       }
344
345       int_type 
346       snextc()
347       {
348         int_type __eof = traits_type::eof();
349         return (this->sbumpc() == __eof ? __eof : this->sgetc()); 
350       }
351
352       int_type 
353       sbumpc();
354
355       int_type 
356       sgetc()
357       {
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;
364       }
365
366       streamsize 
367       sgetn(char_type* __s, streamsize __n)
368       { return this->xsgetn(__s, __n); }
369
370       // Putback:
371       int_type 
372       sputbackc(char_type __c);
373
374       int_type 
375       sungetc();
376
377       // Put area:
378       int_type 
379       sputc(char_type __c);
380
381       streamsize 
382       sputn(const char_type* __s, streamsize __n)
383       { return this->xsputn(__s, __n); }
384
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)
393       { }
394
395       // Get area:
396       char_type* 
397       eback() const { return _M_in_beg; }
398
399       char_type* 
400       gptr()  const { return _M_in_cur;  }
401
402       char_type* 
403       egptr() const { return _M_in_end; }
404
405       void 
406       gbump(int __n) { _M_in_cur += __n; }
407
408       void 
409       setg(char_type* __gbeg, char_type* __gnext, char_type* __gend)
410       {
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;
416       }
417
418       // Put area:
419       char_type* 
420       pbase() const { return _M_out_beg; }
421
422       char_type* 
423       pptr() const { return _M_out_cur; }
424
425       char_type* 
426       epptr() const { return _M_out_end; }
427
428       void 
429       pbump(int __n) { _M_out_cur += __n; }
430
431       void 
432       setp(char_type* __pbeg, char_type* __pend)
433       { 
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;
438       }
439
440       // Virtual functions:
441       // Locales:
442       virtual void 
443       imbue(const locale& __loc) 
444       { 
445         _M_buf_locale_init = true;
446         if (_M_buf_locale != __loc)
447           _M_buf_locale = __loc;
448       }
449
450       // Buffer management and positioning:
451       virtual basic_streambuf<char_type,_Traits>* 
452       setbuf(char_type*, streamsize)
453       { return this; }
454       
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)); } 
459
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)); } 
464
465       virtual int 
466       sync() { return 0; }
467
468       // Get area:
469       virtual streamsize 
470       showmanyc() { return 0; }
471
472       virtual streamsize 
473       xsgetn(char_type* __s, streamsize __n);
474
475       virtual int_type 
476       underflow()
477       { return traits_type::eof(); }
478
479       virtual int_type 
480       uflow() 
481       {
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)
486           {
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;
491           }
492         return __ret;    
493       }
494
495       // Putback:
496       virtual int_type 
497       pbackfail(int_type /* __c */  = traits_type::eof())
498       { return traits_type::eof(); }
499
500       // Put area:
501       virtual streamsize 
502       xsputn(const char_type* __s, streamsize __n);
503
504       virtual int_type 
505       overflow(int_type /* __c */ = traits_type::eof())
506       { return traits_type::eof(); }
507
508 #ifdef _GLIBCPP_DEPRECATED
509     public:
510       void 
511       stossc() 
512       {
513         if (_M_in_cur < _M_in_end) 
514           ++_M_in_cur;
515         else 
516           this->uflow();
517       }
518 #endif
519
520 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
521     // Side effect of DR 50.
522     private:
523       basic_streambuf(const __streambuf_type&);
524
525       __streambuf_type& 
526       operator=(const __streambuf_type&);
527 #endif
528     };
529
530 } // namespace std
531
532 #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT
533 # define export
534 #ifdef  _GLIBCPP_FULLY_COMPLIANT_HEADERS
535 #include <bits/streambuf.tcc>
536 #endif
537 #endif
538
539 #endif  /* _CPP_STREAMBUF */
540