OSDN Git Service

6aa9204c51048af247637729f4ec50a48a622868
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / bits / std_streambuf.h
1 // Stream buffer classes -*- C++ -*-
2
3 // Copyright (C) 1997-1999 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 #include <bits/c++config.h>
38 #include <bits/std_iosfwd.h>
39 #include <bits/std_cstdio.h>    // For SEEK_SET, SEEK_CUR, SEEK_END
40 #include <bits/localefwd.h>
41 #include <bits/ios_base.h>
42
43 namespace std {
44
45   template<typename _CharT, typename _Traits>
46     static streamsize
47     _S_copy_streambufs(basic_ios<_CharT, _Traits>& __ios,
48                        basic_streambuf<_CharT, _Traits>* __sbin,
49                        basic_streambuf<_CharT, _Traits>* __sbout);
50   
51   // 27.5.2 Template class basic_streambuf<_CharT, _Traits>
52   template<typename _CharT, typename _Traits>
53     class basic_streambuf 
54     {
55     public:
56       // Types:
57       typedef _CharT                                    char_type;
58       typedef typename _Traits::int_type                int_type;
59       typedef typename _Traits::pos_type                pos_type;
60       typedef typename _Traits::off_type                off_type;
61       typedef _Traits                                   traits_type;
62
63       // Non-standard Types:
64       typedef ctype<_CharT>                             __ctype_type;
65       typedef basic_streambuf<_CharT, _Traits>          __streambuf_type;
66       
67       friend class basic_ios<char_type, traits_type>;
68       friend class basic_istream<char_type, traits_type>;
69       friend class basic_ostream<char_type, traits_type>;
70       friend class istreambuf_iterator<char_type, traits_type>;
71       friend class ostreambuf_iterator<char_type, traits_type>;
72
73       friend streamsize
74       _S_copy_streambufs<>(basic_ios<_CharT, _Traits>& __ios,
75                          basic_streambuf<_CharT, _Traits>* __sbin,
76                          basic_streambuf<_CharT, _Traits>* __sbout);
77       
78     protected:
79
80       // Pointer to the beginning of internally-allocated
81       // space. Filebuf manually allocates/deallocates this, whereas
82       // stringstreams attempt to use the built-in intelligence of the
83       // string class. If you are managing memory, set this. If not,
84       // leave it NULL.
85       char_type*                _M_buf;         
86
87       // Size of internal buffer, in bytes.
88       int_type                  _M_buf_size;
89
90       // True iff _M_in_* and _M_out_* buffers should always point to
91       // the same place.  True for fstreams, false for sstreams.
92       bool                      _M_buf_unified; 
93
94        // This is based on _IO_FILE, just reordered to be more
95       // consistent, and is intended to be the most minimal abstraction
96       // for an internal buffer.
97       // get == input == read
98       // put == output == write
99       char_type*                _M_in_cur;      // Current read area. 
100       char_type*                _M_in_beg;      // Start of get area. 
101       char_type*                _M_in_end;      // End of get area. 
102       char_type*                _M_out_cur;     // Current put area. 
103       char_type*                _M_out_beg;     // Start of put area. 
104       char_type*                _M_out_end;     // End of put area. 
105
106       // Place to stash in || out || in | out settings for current streambuf.
107       ios_base::openmode        _M_mode;        
108
109       // Current locale setting.
110       locale                    _M_locale_buf;  
111
112       // True iff locale is initialized.
113       bool                      _M_locale_set;
114
115       // Cached use_facet<ctype>, which is based on the current locale info.
116       const __ctype_type*       _M_fctype_buf;      
117
118       // Correctly sets the _M_out_cur pointer, and bumps the
119       // appropriate _M_*_end pointers as well. Necessary for the
120       // un-tied stringbufs, in in|out mode.
121       // Invariant:
122       // __n + _M_out_[cur, end] <= _M_buf + _M_buf_size
123       // Assuming all _M_*_[beg, cur, end] pointers are operating on
124       // the same range:
125       // _M_buf <= _M_*_ <= _M_buf + _M_buf_size
126       void 
127       _M_buf_bump(off_type __n) // argument needs to be +-
128       {
129         bool __testin = _M_mode & ios_base::in;
130         bool __testout = _M_mode & ios_base::out;
131         _M_out_cur += __n;
132         if (_M_buf_unified && __testin)
133           _M_in_cur = _M_out_cur;
134         if (_M_out_cur > _M_out_end)
135           {
136             _M_out_end = _M_out_cur;
137             if (__testin && __testout && _M_out_end > _M_in_end)
138               _M_in_end = _M_out_cur;
139           }
140       }
141
142       // These three functions are used to clarify internal buffer
143       // maintance. After an overflow, or after a seekoff call that
144       // started at beg or end, or possibly when the stream becomes
145       // unbuffered, and a myrid other obscure corner cases, the
146       // internal buffer does not truly reflect the contents of the
147       // external buffer. At this point, for whatever reason, it is in
148       // an indeterminate state.
149       void
150       _M_set_indeterminate(void)
151       {
152         if (_M_mode & ios_base::in)
153           this->setg(_M_buf, _M_buf, _M_buf);
154         if (_M_mode & ios_base::out)
155           this->setp(_M_buf, _M_buf);
156       }
157
158       void
159       _M_set_determinate(off_type __off)
160       {
161         bool __testin = _M_mode & ios_base::in;
162         bool __testout = _M_mode & ios_base::out;
163         if (__testin)
164           {
165             this->setg(_M_buf, _M_buf, _M_buf + __off);
166             if (!__testout)
167               _M_buf_size = static_cast<int_type>(__off);
168           }
169         if (__testout)
170           this->setp(_M_buf, _M_buf + __off);
171
172       }
173
174       bool
175       _M_is_indeterminate(void)
176       { 
177         bool __retval = false;
178         if (_M_mode & ios_base::in)
179           __retval = _M_in_beg == _M_in_cur && _M_in_cur == _M_in_end;
180         if (_M_mode & ios_base::out)
181           __retval = _M_out_beg == _M_out_cur && _M_out_cur == _M_out_end;
182         return __retval;
183       }
184
185   public:
186       virtual 
187       ~basic_streambuf() 
188       {
189         _M_buf_unified = false;
190         _M_buf_size = 0;
191         _M_mode = ios_base::openmode(0);
192         _M_fctype_buf = NULL;
193         _M_locale_set = false;
194       }
195
196       // Locales:
197       locale 
198       pubimbue(const locale &__loc)
199       {
200         locale __tmp(this->getloc());
201         this->imbue(__loc);
202         return __tmp;
203       }
204
205       locale   
206       getloc() const
207       {
208         if (_M_locale_set)
209           return _M_locale_buf; 
210         else 
211           return locale();
212       } 
213
214       // Buffer and positioning:
215       __streambuf_type* 
216       pubsetbuf(char_type* __s, streamsize __n) 
217       { return this->setbuf(__s, __n); }
218
219       pos_type 
220       pubseekoff(off_type __off, ios_base::seekdir __way, 
221                  ios_base::openmode __mode = ios_base::in | ios_base::out)
222       { return this->seekoff(__off, __way, __mode); }
223
224       pos_type 
225       pubseekpos(pos_type __sp,
226                  ios_base::openmode __mode = ios_base::in | ios_base::out)
227       { return this->seekpos(__sp, __mode); }
228
229       int 
230       pubsync() { return this->sync(); }
231
232       // Get and put areas:
233       // Get area:
234       streamsize 
235       in_avail() 
236       { 
237         streamsize __retval;
238         if (_M_in_cur && _M_in_cur < _M_in_end)
239           __retval = this->egptr() - this->gptr();
240         else
241           __retval = this->showmanyc();
242         return __retval;
243       }
244
245       int_type 
246       snextc()
247       {
248         int_type __eof = traits_type::eof();
249         return (this->sbumpc() == __eof ? __eof : this->sgetc()); 
250       }
251
252       int_type 
253       sbumpc();
254
255       int_type 
256       sgetc()
257       {
258         int_type __retval;
259         if (_M_in_cur && _M_in_cur < _M_in_end)
260           __retval = traits_type::to_int_type(*gptr());
261         else 
262           __retval = this->underflow();
263         return __retval;
264       }
265
266       streamsize 
267       sgetn(char_type* __s, streamsize __n)
268       { return this->xsgetn(__s, __n); }
269
270       // Putback:
271       int_type 
272       sputbackc(char_type __c);
273
274       int_type 
275       sungetc();
276
277       // Put area:
278       int_type 
279       sputc(char_type __c);
280
281       streamsize 
282       sputn(const char_type* __s, streamsize __n)
283       { return this->xsputn(__s, __n); }
284
285     protected:
286       basic_streambuf()
287       : _M_buf(NULL), _M_buf_size(0), _M_buf_unified(false),
288         _M_in_cur(0), _M_in_beg(0), _M_in_end(0), _M_out_cur(0), _M_out_beg(0),
289         _M_out_end(0), _M_mode(ios_base::openmode(0)), 
290         _M_locale_buf(locale()), _M_locale_set(false) 
291       { _M_fctype_buf =  &use_facet<__ctype_type>(this->getloc()); }
292
293       // Get area:
294       char_type* 
295       eback() const { return _M_in_beg; }
296
297       char_type* 
298       gptr()  const { return _M_in_cur;  }
299
300       char_type* 
301       egptr() const { return _M_in_end; }
302
303       void 
304       gbump(int __n) { _M_in_cur += __n; }
305
306       void 
307       setg(char_type* __gbeg, char_type* __gnext, char_type* __gend)
308       {
309         _M_in_beg = __gbeg;
310         _M_in_cur = __gnext;
311         _M_in_end = __gend;
312         if (!(_M_mode & ios_base::in) && __gbeg && __gnext && __gend)
313           _M_mode = _M_mode | ios_base::in;
314       }
315
316       // Put area:
317       char_type* 
318       pbase() const { return _M_out_beg; }
319
320       char_type* 
321       pptr() const { return _M_out_cur; }
322
323       char_type* 
324       epptr() const { return _M_out_end; }
325
326       void 
327       pbump(int __n) { _M_out_cur += __n; }
328
329       void 
330       setp(char_type* __pbeg, char_type* __pend)
331       { 
332         _M_out_beg = _M_out_cur = __pbeg; 
333         _M_out_end = __pend; 
334         if (!(_M_mode & ios_base::out) && __pbeg && __pend)
335           _M_mode = _M_mode | ios_base::out;
336         // The output sequence is highly tied to _M_buf and
337         // _M_buf_size in addition to the actual pointers into the
338         // buffer. Because of this, (re)set _M_buf_size here, as
339         // sputc/xsputn need _M_buf_size to be accurate. (The
340         // corresponding input functions rely instead on _M_in_end.)
341         _M_buf_size = max(_M_buf_size, static_cast<int_type>(__pend - __pbeg));
342       }
343
344       // Virtual functions:
345       // Locales:
346       virtual void 
347       imbue(const locale& __loc) 
348       { 
349         _M_locale_set = true;
350         if (_M_locale_buf != __loc)
351          {
352            _M_locale_buf = __loc;
353            _M_fctype_buf = &use_facet<__ctype_type>(_M_locale_buf); 
354          }      
355       }
356
357       // Buffer management and positioning:
358       virtual basic_streambuf<char_type,_Traits>* 
359       setbuf(char_type*, streamsize)
360       { return this; }
361       
362       virtual pos_type 
363       seekoff(off_type, ios_base::seekdir,
364               ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
365       { return pos_type(off_type(-1)); } 
366
367       virtual pos_type 
368       seekpos(pos_type, 
369               ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out)
370       { return pos_type(off_type(-1)); } 
371
372       virtual int 
373       sync() { return 0; }
374
375       // Get area:
376       virtual streamsize 
377       showmanyc() { return 0; }
378
379       virtual streamsize 
380       xsgetn(char_type* __s, streamsize __n);
381
382       virtual int_type 
383       underflow()
384       { return traits_type::eof(); }
385
386       virtual int_type 
387       uflow() 
388       {
389         int_type __retval = traits_type::eof();
390         bool __testeof = this->underflow() == __retval;
391         bool __testpending = _M_in_cur && _M_in_cur < _M_in_end;
392         
393         if (!__testeof && __testpending)
394           {
395             __retval = traits_type::to_int_type(*_M_in_cur);
396             ++_M_in_cur;
397             if (_M_buf_unified && _M_mode & ios_base::out)
398               ++_M_out_cur;
399           }
400         return __retval;    
401       }
402
403       // Putback:
404       virtual int_type 
405       pbackfail(int_type /* __c */  = traits_type::eof())
406       { return traits_type::eof(); }
407
408       // Put area:
409       virtual streamsize 
410       xsputn(const char_type* __s, streamsize __n);
411
412       virtual int_type 
413       overflow(int_type /* __c */ = traits_type::eof())
414       { return traits_type::eof(); }
415
416 #ifdef _GLIBCPP_DEPRICATED
417     public:
418       void 
419       stossc() 
420       {
421         if (_M_in_cur < _M_in_end) 
422           ++_M_in_cur;
423         else 
424           this->uflow();
425       }
426 #endif
427
428 #ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
429     private:
430       basic_streambuf(const __streambuf_type&);
431
432       __streambuf_type& 
433       operator=(const __streambuf_type&);
434 #endif
435     };
436
437   typedef basic_streambuf<char>         streambuf;
438   typedef basic_streambuf<wchar_t>      wstreambuf;
439
440 } // namespace std
441
442 #ifdef _GLIBCPP_NO_TEMPLATE_EXPORT
443 # define export
444 #ifdef  _GLIBCPP_FULLY_COMPLIANT_HEADERS
445 #include <bits/streambuf.tcc>
446 #endif
447 #endif
448
449 #endif  /* _CPP_STREAMBUF */
450
451
452
453
454
455
456
457
458
459
460