1 /* This is part of libio/iostream, providing -*- C++ -*- input/output.
2 Copyright (C) 1993 Free Software Foundation
3
4 This file is part of the GNU IO Library. This library is free
5 software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this library; see the file COPYING. If not, write to the Free
17 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 As a special exception, if you link this library with files
20 compiled with a GNU compiler to produce an executable, this does not cause
21 the resulting executable to be covered by the GNU General Public License.
22 This exception does not however invalidate any other reasons why
23 the 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
35 extern "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
65 extern "C++" {
66 class istream; /* Work-around for a g++ name mangling bug. Fixed in 2.6. */
67 class 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
74 typedef _IO_off64_t streamoff;
75 typedef _IO_off64_t streampos;
76 #else
77 typedef _IO_off_t streamoff;
78 typedef _IO_off_t streampos;
79 #endif
80 typedef _IO_ssize_t streamsize;
81
82 typedef unsigned long __fmtflags;
83 typedef unsigned char __iostate;
84
85 struct _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
114 enum state_value {
115 _good = _IOS_GOOD,
116 _eof = _IOS_EOF,
117 _fail = _IOS_FAIL,
118 _bad = _IOS_BAD };
119 enum open_mode {
120 input = _IO_INPUT,
121 output = _IO_OUTPUT,
122 atend = _IO_ATEND,
123 append = _IO_APPEND };
124 #endif
125
126 class 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:
failure(ios * stream)173 failure(ios* stream) { _stream = stream; }
failure(string cause,ios * stream)174 failure(string cause, ios* stream) { _stream = stream; }
rdios()175 ios* rdios() const { return _stream; }
176 };
177 #endif
178
tie()179 ostream* tie() const { return _tie; }
tie(ostream * val)180 ostream* tie(ostream* val) { ostream* save=_tie; _tie=val; return save; }
181
182 // Methods to change the format state.
fill()183 _IO_wchar_t fill() const { return _fill; }
fill(_IO_wchar_t newf)184 _IO_wchar_t fill(_IO_wchar_t newf)
185 {_IO_wchar_t oldf = _fill; _fill = newf; return oldf;}
flags()186 fmtflags flags() const { return _flags; }
flags(fmtflags new_val)187 fmtflags flags(fmtflags new_val) {
188 fmtflags old_val = _flags; _flags = new_val; return old_val; }
precision()189 int precision() const { return _precision; }
precision(int newp)190 int precision(int newp) {
191 unsigned short oldp = _precision; _precision = (unsigned short)newp;
192 return oldp; }
setf(fmtflags val)193 fmtflags setf(fmtflags val) {
194 fmtflags oldbits = _flags;
195 _flags |= val; return oldbits; }
setf(fmtflags val,fmtflags mask)196 fmtflags setf(fmtflags val, fmtflags mask) {
197 fmtflags oldbits = _flags;
198 _flags = (_flags & ~mask) | (val & mask); return oldbits; }
unsetf(fmtflags mask)199 fmtflags unsetf(fmtflags mask) {
200 fmtflags oldbits = _flags;
201 _flags &= ~mask; return oldbits; }
width()202 int width() const { return _width; }
width(int val)203 int width(int val) { int save = _width; _width = val; return save; }
204
205 #ifdef _IO_THROW
_throw_failure()206 void _throw_failure() const { throw new ios::failure(this); }
207 #else
_throw_failure()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(); }
set(iostate flag)213 void set(iostate flag) { _state |= flag;
214 if (_state & _exceptions) _throw_failure(); }
setstate(iostate flag)215 void setstate(iostate flag) { _state |= flag; // ANSI
216 if (_state & _exceptions) _throw_failure(); }
good()217 int good() const { return _state == 0; }
eof()218 int eof() const { return _state & ios::eofbit; }
fail()219 int fail() const { return _state & (ios::badbit|ios::failbit); }
bad()220 int bad() const { return _state & ios::badbit; }
rdstate()221 iostate rdstate() const { return _state; }
222 operator void*() const { return fail() ? (void*)0 : (void*)(-1); }
223 int operator!() const { return fail(); }
exceptions()224 iostate exceptions() const { return _exceptions; }
exceptions(iostate enable)225 void exceptions(iostate enable) {
226 _exceptions = enable;
227 if (_state & _exceptions) _throw_failure(); }
228
rdbuf()229 streambuf* rdbuf() const { return _strbuf; }
rdbuf(streambuf * _s)230 streambuf* rdbuf(streambuf *_s) {
231 streambuf *_old = _strbuf; _strbuf = _s; clear (); return _old; }
232
233 static int sync_with_stdio(int on);
sync_with_stdio()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
unset(state_value flag)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:
Init()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
263 typedef int _seek_dir;
264 #else
265 typedef 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().
276 class streammarker : private _IO_marker {
277 friend class streambuf;
set_offset(int offset)278 void set_offset(int offset) { _pos = offset; }
279 public:
280 streammarker(streambuf *sb);
281 ~streammarker();
saving()282 int saving() { return 1; }
283 int delta(streammarker&);
284 int delta();
285 };
286
287 struct streambuf : public _IO_FILE { // protected??
288 friend class ios;
289 friend class istream;
290 friend class ostream;
291 friend class streammarker;
_vtablestreambuf292 const void *&_vtable() { return *(const void**)((_IO_FILE*)this + 1); }
293 protected:
294 static streambuf* _list_all; /* List of open streambufs. */
xchainstreambuf295 _IO_FILE*& xchain() { return _chain; }
296 void _un_link();
297 void _link_in();
gptrstreambuf298 char* gptr() const
299 { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_base : _IO_read_ptr; }
pptrstreambuf300 char* pptr() const { return _IO_write_ptr; }
egptrstreambuf301 char* egptr() const
302 { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_end : _IO_read_end; }
epptrstreambuf303 char* epptr() const { return _IO_write_end; }
pbasestreambuf304 char* pbase() const { return _IO_write_base; }
ebackstreambuf305 char* eback() const
306 { return _IO_file_flags & _IO_IN_BACKUP ? _IO_save_base : _IO_read_base;}
basestreambuf307 char* base() const { return _IO_buf_base; }
ebufstreambuf308 char* ebuf() const { return _IO_buf_end; }
blenstreambuf309 int blen() const { return _IO_buf_end - _IO_buf_base; }
xput_charstreambuf310 void xput_char(char c) { *_IO_write_ptr++ = c; }
xflagsstreambuf311 int xflags() { return _IO_file_flags; }
xflagsstreambuf312 int xflags(int f) {int fl = _IO_file_flags; _IO_file_flags = f; return fl;}
xsetflagsstreambuf313 void xsetflags(int f) { _IO_file_flags |= f; }
xsetflagsstreambuf314 void xsetflags(int f, int mask)
315 { _IO_file_flags = (_IO_file_flags & ~mask) | (f & mask); }
gbumpstreambuf316 void gbump(int n)
317 { _IO_file_flags & _IO_IN_BACKUP ? (_IO_save_base+=n):(_IO_read_ptr+=n);}
pbumpstreambuf318 void pbump(int n) { _IO_write_ptr += n; }
319 void setb(char* b, char* eb, int a=0);
setpstreambuf320 void setp(char* p, char* ep)
321 { _IO_write_base=_IO_write_ptr=p; _IO_write_end=ep; }
setgstreambuf322 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; }
shortbufstreambuf325 char *shortbuf() { return _shortbuf; }
326
in_backupstreambuf327 int in_backup() { return _flags & _IO_IN_BACKUP; }
328 // The start of the main get area: FIXME: wrong for write-mode filebuf?
Gbasestreambuf329 char *Gbase() { return in_backup() ? _IO_save_base : _IO_read_base; }
330 // The end of the main get area:
eGptrstreambuf331 char *eGptr() { return in_backup() ? _IO_save_end : _IO_read_end; }
332 // The start of the backup area:
Bbasestreambuf333 char *Bbase() { return in_backup() ? _IO_read_base : _IO_save_base; }
Bptrstreambuf334 char *Bptr() { return _IO_backup_base; }
335 // The end of the backup area:
eBptrstreambuf336 char *eBptr() { return in_backup() ? _IO_read_end : _IO_save_end; }
Nbasestreambuf337 char *Nbase() { return _IO_save_base; }
eNptrstreambuf338 char *eNptr() { return _IO_save_end; }
have_backupstreambuf339 int have_backup() { return _IO_save_base != NULL; }
have_markersstreambuf340 int have_markers() { return _markers != NULL; }
341 void free_backup_area();
342 void unsave_markers(); // Make all streammarkers !saving().
put_modestreambuf343 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();
unbufferedstreambuf374 int unbuffered() { return _flags & _IO_UNBUFFERED ? 1 : 0; }
linebufferedstreambuf375 int linebuffered() { return _flags & _IO_LINE_BUF ? 1 : 0; }
unbufferedstreambuf376 void unbuffered(int i)
377 { if (i) _flags |= _IO_UNBUFFERED; else _flags &= ~_IO_UNBUFFERED; }
linebufferedstreambuf378 void linebuffered(int i)
379 { if (i) _flags |= _IO_LINE_BUF; else _flags &= ~_IO_LINE_BUF; }
allocatestreambuf380 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.
allocbufstreambuf384 void allocbuf() { if (base() == NULL) doallocbuf(); }
385 void doallocbuf();
in_availstreambuf386 int in_avail() { return _IO_read_end - _IO_read_ptr; }
out_waitingstreambuf387 int out_waiting() { return _IO_write_ptr - _IO_write_base; }
sputnstreambuf388 streamsize sputn(const char* s, streamsize n) { return xsputn(s, n); }
padnstreambuf389 streamsize padn(char pad, streamsize n) { return _IO_padn(this, pad, n); }
sgetnstreambuf390 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);
sputcstreambuf395 int sputc(int c) { return _IO_putc(c, this); }
sbumpcstreambuf396 int sbumpc() { return _IO_getc(this); }
sgetcstreambuf397 int sgetc() { return _IO_peekc(this); }
snextcstreambuf398 int snextc() {
399 if (_IO_read_ptr >= _IO_read_end && __underflow(this) == EOF)
400 return EOF;
401 else return _IO_read_ptr++, sgetc(); }
stosscstreambuf402 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
425 class 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);
is_open()442 int is_open() const { return _fileno >= 0; }
fd()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);
is_reading()453 int is_reading() { return eback() != egptr(); }
cur_ptr()454 char* cur_ptr() { return is_reading() ? gptr() : pptr(); }
455 /* System's idea of pointer */
file_ptr()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
init(streambuf * sb,ostream * tie_to)469 inline 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
ios(streambuf * sb,ostream * tie_to)479 inline ios::ios(streambuf* sb, ostream* tie_to) { init(sb, tie_to); }
480
~ios()481 inline 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