1/* This is part of libio/iostream, providing -*- C++ -*- input/output.
2Copyright (C) 1993 Free Software Foundation
3
4This file is part of the GNU IO Library.  This library is free
5software; you can redistribute it and/or modify it under the
6terms of the GNU General Public License as published by the
7Free Software Foundation; either version 2, or (at your option)
8any later version.
9
10This library is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this library; see the file COPYING.  If not, write to the Free
17Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19As a special exception, if you link this library with files
20compiled with a GNU compiler to produce an executable, this does not cause
21the resulting executable to be covered by the GNU General Public License.
22This exception does not however invalidate any other reasons why
23the executable file might be covered by the GNU General Public License. */
24
25#ifndef _STREAMBUF_H
26#define _STREAMBUF_H
27#ifdef __GNUG__
28#pragma interface
29#endif
30
31/* #define _G_IO_THROW */ /* Not implemented:  ios::failure */
32
33#define _IO_NEW_STREAMS // new optimizated stream representation
34
35extern "C" {
36#include <libio.h>
37}
38//#include <_G_config.h>
39#ifdef _G_NEED_STDARG_H
40#include <stdarg.h>
41#endif
42#ifndef _IO_va_list
43#define _IO_va_list char *
44#endif
45
46#ifndef EOF
47#define EOF (-1)
48#endif
49#ifndef NULL
50#ifdef __GNUG__
51#define NULL (__null)
52#else
53#define NULL (0)
54#endif
55#endif
56
57#ifndef _IO_wchar_t
58#if _G_IO_IO_FILE_VERSION == 0x20001
59#define _IO_wchar_t _G_wchar_t
60#else
61#define _IO_wchar_t wchar_t
62#endif
63#endif
64
65extern "C++" {
66class istream; /* Work-around for a g++ name mangling bug. Fixed in 2.6. */
67class ostream; class streambuf;
68
69// In case some header files defines these as macros.
70#undef open
71#undef close
72
73#if defined(_G_IO_IO_FILE_VERSION) && _G_IO_IO_FILE_VERSION == 0x20001
74typedef _IO_off64_t streamoff;
75typedef _IO_off64_t streampos;
76#else
77typedef _IO_off_t streamoff;
78typedef _IO_off_t streampos;
79#endif
80typedef _IO_ssize_t streamsize;
81
82typedef unsigned long __fmtflags;
83typedef unsigned char __iostate;
84
85struct _ios_fields
86{ // The data members of an ios.
87    streambuf *_strbuf;
88    ostream* _tie;
89    int _width;
90    __fmtflags _flags;
91    _IO_wchar_t _fill;
92    __iostate _state;
93    __iostate _exceptions;
94    int _precision;
95
96    void *_arrays; /* Support for ios::iword and ios::pword. */
97};
98
99#define _IOS_GOOD	0
100#define _IOS_EOF	1
101#define _IOS_FAIL	2
102#define _IOS_BAD	4
103
104#define _IO_INPUT	1
105#define _IO_OUTPUT	2
106#define _IO_ATEND	4
107#define _IO_APPEND	8
108#define _IO_TRUNC	16
109#define _IO_NOCREATE	32
110#define _IO_NOREPLACE	64
111#define _IO_BIN		128
112
113#ifdef _STREAM_COMPAT
114enum state_value {
115    _good = _IOS_GOOD,
116    _eof = _IOS_EOF,
117    _fail = _IOS_FAIL,
118    _bad = _IOS_BAD };
119enum open_mode {
120    input = _IO_INPUT,
121    output = _IO_OUTPUT,
122    atend = _IO_ATEND,
123    append = _IO_APPEND };
124#endif
125
126class ios : public _ios_fields {
127  ios& operator=(ios&);  /* Not allowed! */
128  ios (const ios&); /* Not allowed! */
129  public:
130    typedef __fmtflags fmtflags;
131    typedef int iostate;
132    typedef int openmode;
133    typedef _IO_ssize_t streamsize;
134    enum io_state {
135	goodbit = _IOS_GOOD,
136	eofbit = _IOS_EOF,
137	failbit = _IOS_FAIL,
138	badbit = _IOS_BAD };
139    enum open_mode {
140	in = _IO_INPUT,
141	out = _IO_OUTPUT,
142	ate = _IO_ATEND,
143	app = _IO_APPEND,
144	trunc = _IO_TRUNC,
145	nocreate = _IO_NOCREATE,
146	noreplace = _IO_NOREPLACE,
147	bin = _IOS_BIN, // Deprecated - ANSI uses ios::binary.
148	binary = _IOS_BIN };
149    enum seek_dir { beg, cur, end};
150    typedef enum seek_dir seekdir;
151    // NOTE: If adding flags here, before to update ios::bitalloc().
152    enum { skipws=_IO_SKIPWS,
153	   left=_IO_LEFT, right=_IO_RIGHT, internal=_IO_INTERNAL,
154	   dec=_IO_DEC, oct=_IO_OCT, hex=_IO_HEX,
155	   showbase=_IO_SHOWBASE, showpoint=_IO_SHOWPOINT,
156	   uppercase=_IO_UPPERCASE, showpos=_IO_SHOWPOS,
157	   scientific=_IO_SCIENTIFIC, fixed=_IO_FIXED,
158	   unitbuf=_IO_UNITBUF, stdio=_IO_STDIO
159#ifndef _IO_NEW_STREAMS
160	   , dont_close=_IO_DONT_CLOSE // Don't delete streambuf on stream destruction
161#endif
162	   };
163    enum { // Masks.
164	basefield=dec+oct+hex,
165	floatfield = scientific+fixed,
166	adjustfield = left+right+internal
167    };
168
169#ifdef _IO_THROW
170    class failure : public xmsg {
171	ios* _stream;
172      public:
173	failure(ios* stream) { _stream = stream; }
174	failure(string cause, ios* stream) { _stream = stream; }
175	ios* rdios() const { return _stream; }
176    };
177#endif
178
179    ostream* tie() const { return _tie; }
180    ostream* tie(ostream* val) { ostream* save=_tie; _tie=val; return save; }
181
182    // Methods to change the format state.
183    _IO_wchar_t fill() const { return _fill; }
184    _IO_wchar_t fill(_IO_wchar_t newf)
185	{_IO_wchar_t oldf = _fill; _fill = newf; return oldf;}
186    fmtflags flags() const { return _flags; }
187    fmtflags flags(fmtflags new_val) {
188	fmtflags old_val = _flags; _flags = new_val; return old_val; }
189    int precision() const { return _precision; }
190    int precision(int newp) {
191	unsigned short oldp = _precision; _precision = (unsigned short)newp;
192	return oldp; }
193    fmtflags setf(fmtflags val) {
194	fmtflags oldbits = _flags;
195	_flags |= val; return oldbits; }
196    fmtflags setf(fmtflags val, fmtflags mask) {
197	fmtflags oldbits = _flags;
198	_flags = (_flags & ~mask) | (val & mask); return oldbits; }
199    fmtflags unsetf(fmtflags mask) {
200	fmtflags oldbits = _flags;
201	_flags &= ~mask; return oldbits; }
202    int width() const { return _width; }
203    int width(int val) { int save = _width; _width = val; return save; }
204
205#ifdef _IO_THROW
206    void _throw_failure() const { throw new ios::failure(this); }
207#else
208    void _throw_failure() const { }
209#endif
210    void clear(iostate state = 0) {
211	_state = _strbuf ? state : state|badbit;
212	if (_state & _exceptions) _throw_failure(); }
213    void set(iostate flag) { _state |= flag;
214	if (_state & _exceptions) _throw_failure(); }
215    void setstate(iostate flag) { _state |= flag; // ANSI
216	if (_state & _exceptions) _throw_failure(); }
217    int good() const { return _state == 0; }
218    int eof() const { return _state & ios::eofbit; }
219    int fail() const { return _state & (ios::badbit|ios::failbit); }
220    int bad() const { return _state & ios::badbit; }
221    iostate rdstate() const { return _state; }
222    operator void*() const { return fail() ? (void*)0 : (void*)(-1); }
223    int operator!() const { return fail(); }
224    iostate exceptions() const { return _exceptions; }
225    void exceptions(iostate enable) {
226	_exceptions = enable;
227	if (_state & _exceptions) _throw_failure(); }
228
229    streambuf* rdbuf() const { return _strbuf; }
230    streambuf* rdbuf(streambuf *_s) {
231      streambuf *_old = _strbuf; _strbuf = _s; clear (); return _old; }
232
233    static int sync_with_stdio(int on);
234    static void sync_with_stdio() { sync_with_stdio(1); }
235    static fmtflags bitalloc();
236    static int xalloc();
237    void*& pword(int);
238    void* pword(int) const;
239    long& iword(int);
240    long iword(int) const;
241
242#ifdef _STREAM_COMPAT
243    void unset(state_value flag) { _state &= ~flag; }
244    void close();
245    int is_open();
246    int readable();
247    int writable();
248#endif
249
250    // Used to initialize standard streams. Not needed in this implementation.
251    class Init {
252    public:
253      Init () { }
254    };
255
256  protected:
257    inline ios(streambuf* sb = 0, ostream* tie_to = 0);
258    inline virtual ~ios();
259    inline void init(streambuf* sb, ostream* tie = 0);
260};
261
262#if __GNUG__==1
263typedef int _seek_dir;
264#else
265typedef ios::seek_dir _seek_dir;
266#endif
267
268// Magic numbers and bits for the _flags field.
269// The magic numbers use the high-order bits of _flags;
270// the remaining bits are abailable for variable flags.
271// Note: The magic numbers must all be negative if stdio
272// emulation is desired.
273
274// A streammarker remembers a position in a buffer.
275// You are guaranteed to be able to seek back to it if it is saving().
276class streammarker : private _IO_marker {
277    friend class streambuf;
278    void set_offset(int offset) { _pos = offset; }
279  public:
280    streammarker(streambuf *sb);
281    ~streammarker();
282    int saving() { return  1; }
283    int delta(streammarker&);
284    int delta();
285};
286
287struct streambuf : public _IO_FILE { // protected??
288    friend class ios;
289    friend class istream;
290    friend class ostream;
291    friend class streammarker;
292    const void *&_vtable() { return *(const void**)((_IO_FILE*)this + 1); }
293  protected:
294    static streambuf* _list_all; /* List of open streambufs. */
295    _IO_FILE*& xchain() { return _chain; }
296    void _un_link();
297    void _link_in();
298    char* gptr() const
299      { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_base : _IO_read_ptr; }
300    char* pptr() const { return _IO_write_ptr; }
301    char* egptr() const
302      { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_end : _IO_read_end; }
303    char* epptr() const { return _IO_write_end; }
304    char* pbase() const { return _IO_write_base; }
305    char* eback() const
306      { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_base : _IO_read_base;}
307    char* base() const { return _IO_buf_base; }
308    char* ebuf() const { return _IO_buf_end; }
309    int blen() const { return _IO_buf_end - _IO_buf_base; }
310    void xput_char(char c) { *_IO_write_ptr++ = c; }
311    int xflags() { return _IO_file_flags; }
312    int xflags(int f) {int fl = _IO_file_flags; _IO_file_flags = f; return fl;}
313    void xsetflags(int f) { _IO_file_flags |= f; }
314    void xsetflags(int f, int mask)
315      { _IO_file_flags = (_IO_file_flags & ~mask) | (f & mask); }
316    void gbump(int n)
317      { _IO_file_flags & _IO_IN_BACKUP ? (_IO_save_base+=n):(_IO_read_ptr+=n);}
318    void pbump(int n) { _IO_write_ptr += n; }
319    void setb(char* b, char* eb, int a=0);
320    void setp(char* p, char* ep)
321      { _IO_write_base=_IO_write_ptr=p; _IO_write_end=ep; }
322    void setg(char* eb, char* g, char *eg) {
323      if (_IO_file_flags & _IO_IN_BACKUP) _IO_free_backup_area(this);
324      _IO_read_base = eb; _IO_read_ptr = g; _IO_read_end = eg; }
325    char *shortbuf() { return _shortbuf; }
326
327    int in_backup() { return _flags & _IO_IN_BACKUP; }
328    // The start of the main get area:  FIXME:  wrong for write-mode filebuf?
329    char *Gbase() { return in_backup() ? _IO_save_base : _IO_read_base; }
330    // The end of the main get area:
331    char *eGptr() { return in_backup() ? _IO_save_end : _IO_read_end; }
332    // The start of the backup area:
333    char *Bbase() { return in_backup() ? _IO_read_base : _IO_save_base; }
334    char *Bptr() { return _IO_backup_base; }
335    // The end of the backup area:
336    char *eBptr() { return in_backup() ? _IO_read_end : _IO_save_end; }
337    char *Nbase() { return _IO_save_base; }
338    char *eNptr() { return _IO_save_end; }
339    int have_backup() { return _IO_save_base != NULL; }
340    int have_markers() { return _markers != NULL; }
341    void free_backup_area();
342    void unsave_markers(); // Make all streammarkers !saving().
343    int put_mode() { return _flags & _IO_CURRENTLY_PUTTING; }
344    int switch_to_get_mode();
345
346    streambuf(int flags=0);
347  public:
348    static int flush_all();
349    static void flush_all_linebuffered(); // Flush all line buffered files.
350    virtual ~streambuf();
351    virtual int overflow(int c = EOF); // Leave public for now
352    virtual int underflow(); // Leave public for now
353    virtual int uflow(); // Leave public for now
354    virtual int pbackfail(int c);
355//    virtual int showmany ();
356    virtual streamsize xsputn(const char* s, streamsize n);
357    virtual streamsize xsgetn(char* s, streamsize n);
358    virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
359    virtual streampos seekpos(streampos pos, int mode = ios::in|ios::out);
360
361    streampos pubseekoff(streamoff o, _seek_dir d, int mode=ios::in|ios::out)
362      { return _IO_seekoff (this, o, d, mode); }
363    streampos pubseekpos(streampos pos, int mode = ios::in|ios::out)
364      { return _IO_seekpos (this, pos, mode); }
365    streampos sseekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
366    streampos sseekpos(streampos pos, int mode = ios::in|ios::out);
367    virtual streambuf* setbuf(char* p, int len);
368    virtual int sync();
369    virtual int doallocate();
370
371    int seekmark(streammarker& mark, int delta = 0);
372    int sputbackc(char c);
373    int sungetc();
374    int unbuffered() { return _flags & _IO_UNBUFFERED ? 1 : 0; }
375    int linebuffered() { return _flags & _IO_LINE_BUF ? 1 : 0; }
376    void unbuffered(int i)
377	{ if (i) _flags |= _IO_UNBUFFERED; else _flags &= ~_IO_UNBUFFERED; }
378    void linebuffered(int i)
379	{ if (i) _flags |= _IO_LINE_BUF; else _flags &= ~_IO_LINE_BUF; }
380    int allocate() { // For AT&T compatibility
381	if (base() || unbuffered()) return 0;
382	else return doallocate(); }
383    // Allocate a buffer if needed; use _shortbuf if appropriate.
384    void allocbuf() { if (base() == NULL) doallocbuf(); }
385    void doallocbuf();
386    int in_avail() { return _IO_read_end - _IO_read_ptr; }
387    int out_waiting() { return _IO_write_ptr - _IO_write_base; }
388    streamsize sputn(const char* s, streamsize n) { return xsputn(s, n); }
389    streamsize padn(char pad, streamsize n) { return _IO_padn(this, pad, n); }
390    streamsize sgetn(char* s, streamsize n) { return _IO_sgetn(this, s, n); }
391    int ignore(int);
392    int get_column();
393    int set_column(int);
394    long sgetline(char* buf, _IO_size_t n, char delim, int putback_delim);
395    int sputc(int c) { return _IO_putc(c, this); }
396    int sbumpc() { return _IO_getc(this); }
397    int sgetc() { return _IO_peekc(this); }
398    int snextc() {
399	if (_IO_read_ptr >= _IO_read_end && __underflow(this) == EOF)
400	  return EOF;
401	else return _IO_read_ptr++, sgetc(); }
402    void stossc() { if (_IO_read_ptr < _IO_read_end) _IO_read_ptr++; }
403    int vscan(char const *fmt0, _IO_va_list ap, ios* stream = NULL);
404    int scan(char const *fmt0 ...);
405    int vform(char const *fmt0, _IO_va_list ap);
406    int form(char const *fmt0 ...);
407#if 0 /* Work in progress */
408    int column();  // Current column number (of put pointer). -1 is unknown.
409    void column(int c);  // Set column number of put pointer to c.
410#endif
411    virtual streamsize sys_read(char* buf, streamsize size);
412    virtual streamsize sys_write(const char*, streamsize);
413    virtual streampos sys_seek(streamoff, _seek_dir);
414    virtual int sys_close();
415    virtual int sys_stat(void*); // Actually, a (struct stat*)
416#if _G_IO_IO_FILE_VERSION == 0x20001
417    virtual int showmanyc();
418    virtual void imbue(void *);
419#endif
420};
421
422// A backupbuf is a streambuf with full backup and savepoints on reading.
423// All standard streambufs in the GNU iostream library are backupbufs.
424
425class filebuf : public streambuf {
426  protected:
427    void init();
428  public:
429    static const int openprot; // Non-ANSI AT&T-ism:  Default open protection.
430    filebuf();
431    filebuf(int fd);
432    filebuf(int fd, char* p, int len);
433#if !_IO_UNIFIED_JUMPTABLES
434    static filebuf *__new();
435#endif
436    ~filebuf();
437    filebuf* attach(int fd);
438    filebuf* open(const char *filename, const char *mode);
439    filebuf* open(const char *filename, ios::openmode mode, int prot = 0664);
440    virtual int underflow();
441    virtual int overflow(int c = EOF);
442    int is_open() const { return _fileno >= 0; }
443    int fd() const { return is_open() ? _fileno : EOF; }
444    filebuf* close();
445    virtual int doallocate();
446    virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out);
447    virtual streambuf* setbuf(char* p, int len);
448    streamsize xsputn(const char* s, streamsize n);
449    streamsize xsgetn(char* s, streamsize n);
450    virtual int sync();
451  protected: // See documentation in filebuf.C.
452//    virtual int pbackfail(int c);
453    int is_reading() { return eback() != egptr(); }
454    char* cur_ptr() { return is_reading() ?  gptr() : pptr(); }
455    /* System's idea of pointer */
456    char* file_ptr() { return eGptr(); }
457    // Low-level operations (Usually invoke system calls.)
458    virtual streamsize sys_read(char* buf, streamsize size);
459    virtual streampos sys_seek(streamoff, _seek_dir);
460    virtual streamsize sys_write(const char*, streamsize);
461    virtual int sys_stat(void*); // Actually, a (struct stat*)
462    virtual int sys_close();
463#if 0
464    virtual uflow;
465    virtual showmany;
466#endif
467};
468
469inline void ios::init(streambuf* sb, ostream* tie_to) {
470		_state = sb ? ios::goodbit : ios::badbit; _exceptions=0;
471		_strbuf=sb; _tie = tie_to; _width=0; _fill=' ';
472#ifdef _IO_NEW_STREAMS
473		_flags=ios::skipws|ios::dec;
474#else
475		_flags=ios::skipws|ios::dec|ios::dont_close;
476#endif
477		_precision=6; _arrays = 0; }
478
479inline ios::ios(streambuf* sb, ostream* tie_to) { init(sb, tie_to); }
480
481inline ios::~ios() {
482#ifndef _IO_NEW_STREAMS
483    if (!(_flags & (unsigned int)ios::dont_close)) delete rdbuf();
484#endif
485    // It is safe to use naked operator delete[] as we know elements have no
486    // dtor, and g++ does not add a new[] cookie for such cases.
487    operator delete[] (_arrays);
488}
489} // extern "C++"
490#endif /* _STREAMBUF_H */
491