// This is part of the iostream library, providing -*- C++ -*- input/output. // Copyright (C) 1991 Per Bothner. // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public // License along with this library; if not, write to the Free // Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #ifndef _STREAMBUF_H #define _STREAMBUF_H #ifdef __GNUG__ #pragma interface #endif #include #ifndef fpos_t #define fpos_t _G_fpos_t #endif #ifndef atarist #ifndef EOF #define EOF (-1) #endif #ifndef NULL #define NULL ((void*)0) #endif #ifndef BUFSIZ #define BUFSIZ 1024 #endif #else /* atari */ #include #include extern "C" unsigned long __DEFAULT_BUFSIZ__; #endif class ostream; class streambuf; typedef long streamoff, streampos; struct _ios_fields { // The data members of an ios. streambuf *_strbuf; ostream* _tie; int _width; unsigned long _flags; char _fill; unsigned char _state; unsigned short _precision; }; #define _IOS_GOOD 0 #define _IOS_EOF 1 #define _IOS_FAIL 2 #define _IOS_BAD 4 #define _IOS_INPUT 1 #define _IOS_OUTPUT 2 #define _IOS_ATEND 4 #define _IOS_APPEND 8 #define _IOS_TRUNC 16 #define _IOS_NOCREATE 32 #define _IOS_NOREPLACE 64 #ifdef atarist #define _IOS_INPUT_BIN (1|256) #define _IOS_OUTPUT_BIN (2|256) #define _IOS_APPEND_BIN (8|256) /* force text mode */ #define _IOS_INPUT_TEXT (1|512) #define _IOS_OUTPUT_TEXT (2|512) #define _IOS_APPEND_TEXT (8|512) #endif #ifdef _STREAM_COMPAT enum state_value { _good = _IOS_GOOD, _eof = _IOS_EOF, _fail = _IOS_FAIL, _bad = _IOS_BAD }; enum open_mode { input = _IOS_INPUT, output = _IOS_OUTPUT, atend = _IOS_ATEND, append = _IOS_APPEND #ifdef atarist , in_bin=1|256, // force bin mode regardless of default mode out_bin=2|256, app_bin=8|256, in_text=1|512, // force text mode out_text=2|512, app_text=8|512 #endif }; #endif class ios : public _ios_fields { public: enum io_state { goodbit = _IOS_GOOD, eofbit = _IOS_EOF, failbit = _IOS_FAIL, badbit = _IOS_BAD }; enum open_mode { in = _IOS_INPUT, out = _IOS_OUTPUT, ate = _IOS_ATEND, app = _IOS_APPEND, trunc = _IOS_TRUNC, nocreate = _IOS_NOCREATE, noreplace = _IOS_NOREPLACE #ifdef atarist , in_bin = _IOS_INPUT_BIN, out_bin = _IOS_OUTPUT_BIN, app_bin = _IOS_APPEND_BIN, in_text = _IOS_INPUT_TEXT, out_text = _IOS_OUTPUT_TEXT, app_text = _IOS_APPEND_TEXT #endif }; enum seek_dir { beg, cur, end}; enum { skipws=01, left=02, right=04, internal=010, dec=020, oct=040, hex=0100, showbase=0200, showpoint=0400, uppercase=01000, showpos=02000, scientific=04000, fixed=0100000, unitbuf=020000, stdio=040000, dont_close=0x80000000 //Don't close streambuf when destroying stream }; ostream* tie() const { return _tie; } ostream* tie(ostream* val) { ostream* save=_tie; _tie=val; return save; } // Methods to change the format state. char fill() const { return _fill; } char fill(char newf) { char oldf = _fill; _fill = newf; return oldf; } unsigned long flags() const { return _flags; } unsigned long flags(unsigned long new_val) { unsigned long old_val = _flags; _flags = new_val; return old_val; } unsigned short precision() const { return _precision; } unsigned short precision(int newp) { unsigned short oldp = _precision; _precision = (unsigned short)newp; return oldp; } unsigned long setf(unsigned long val) { unsigned long oldbits = _flags; _flags |= val; return oldbits; } unsigned long setf(unsigned long val, unsigned long mask) { unsigned long oldbits = _flags; _flags = (_flags & ~mask) | (val & mask); return oldbits; } unsigned long unsetf(unsigned long mask) { unsigned long oldbits = _flags & mask; _flags &= ~mask; return oldbits; } long width() const { return _width; } long width(long val) { long save = _width; _width = val; return save; } static const unsigned long basefield; static const unsigned long adjustfield; static const unsigned long floatfield; streambuf* rdbuf() const { return _strbuf; } void clear(int state = 0) { _state = state; } int good() const { return _state == 0; } int eof() const { return _state & ios::eofbit; } int fail() const { return _state & (ios::badbit|ios::failbit); } int bad() const { return _state & ios::badbit; } int rdstate() const { return _state; } void set(int flag) { _state |= flag; } operator void*() const { return fail() ? (void*)0 : (void*)this; } int operator!() const { return fail(); } #ifdef _STREAM_COMPAT void unset(state_value flag) { _state &= ~flag; } void close(); int is_open(); int readable(); int writable(); #endif protected: ios(streambuf*sb) { _strbuf=sb; _state=0; _width=0; _fill=' '; _flags=ios::skipws; _precision=6; } }; #if __GNUG__==1 typedef int _seek_dir; #else typedef ios::seek_dir _seek_dir; #endif // Magic numbers and bits for the _flags field. // The magic numbers use the high-order bits of _flags; // the remaining bits are abailable for variable flags. // Note: The magic numbers must all be negative if stdio // emulation is desired. #define _IO_MAGIC 0xFBAD0000 /* Magic number */ #define _OLD_STDIO_MAGIC 0xFABC0000 /* Emulate old stdio. */ #define _IO_MAGIC_MASK 0xFFFF0000 #define _S_USER_BUF 1 /* User owns buffer; don't delete it on close. */ #define _S_UNBUFFERED 2 #define _S_CAN_READ 4 #define _S_CAN_WRITE 8 #define _S_EOF_SEEN 16 #define _S_ERR_SEEN 32 #define _S_DELETE_DONT_CLOSE 64 #define _S_LINKED 128 // Set if linked (using _chain) to streambuf::_list_all. #define _S_LINE_BUF 0x4000 #define _S_IS_FILEBUF 0x8000 #ifdef atarist #define _S_IS_BINARY 256 #endif #if 0 // A streammarker remembers a position in a buffer. // You are guaranteed to be able to seek back to it. class streammarker { struct streammarker *_next; streambuf *_buf; char *_pos; ??? public: streammarker(streambuf *sb); ~streamarker(); }; #endif struct __streambuf { // NOTE: If this is changed, also change __FILE in stdio/stdio.h! unsigned long _flags; /* High-order word is _IO_MAGIC; rest is flags. */ char* _gptr; /* Current get pointer */ char* _egptr; /* End of get area. */ char* _eback; /* Start of putback+get area. */ char* _pbase; /* Start of put area. */ char* _pptr; /* Current put pointer. */ char* _epptr; /* End of put area. */ char* _base; /* Start of reserve area. */ char* _ebuf; /* End of reserve area. */ struct streambuf *_chain; #if 0 // Work in progress int _collumn; // Current collumn in line at _pbase; -1 if unknown. streammarker *_markers; #endif }; struct streambuf : private __streambuf { friend class ios; friend class istream; friend class ostream; protected: static streambuf* _list_all; /* List of open streambufs. */ streambuf*& xchain() { return _chain; } void _un_link(); void _link_in(); char* gptr() const { return _gptr; } char* pptr() const { return _pptr; } char* egptr() const { return _egptr; } char* epptr() const { return _epptr; } char* pbase() const { return _pbase; } char* eback() const { return _eback; } char* ebuf() const { return _ebuf; } char* base() const { return _base; } void xput_char(char c) { *_pptr++ = c; } #ifdef atarist int is_binary() { return _flags & _S_IS_BINARY ? 1 : 0; } void set_binary() { _flags |= _S_IS_BINARY; } #endif unsigned long xflags() { return _flags; } unsigned long xflags(unsigned long f) { unsigned long fl = _flags; _flags = f; return fl; } void xsetflags(unsigned long f) { _flags |= f; } void gbump(int n) { _gptr += n; } void pbump(int n) { _pptr += n; } void setb(char* b, char* eb, int a=0); void setp(char* p, char* ep) { _pbase=_pptr=p; _epptr=ep; } void setg(char* eb, char* g, char *eg) { _eback=eb; _gptr=g; _egptr=eg; } public: static int flush_all(); static void flush_all_linebuffered(); // Flush all line buffered files. virtual int underflow(); // Leave public for now virtual int overflow(int c = EOF); // Leave public for now virtual int doallocate(); virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); virtual streampos seekpos(streampos pos, int mode = ios::in|ios::out); int sputbackc(char c); int sungetc(); streambuf(); virtual ~streambuf(); int unbuffered() { return _flags & _S_UNBUFFERED ? 1 : 0; } int linebuffered() { return _flags & _S_LINE_BUF ? 1 : 0; } void unbuffered(int i) { if (i) _flags |= _S_UNBUFFERED; else _flags &= ~_S_UNBUFFERED; } void linebuffered(int i) { if (i) _flags |= _S_LINE_BUF; else _flags &= ~_S_LINE_BUF; } int allocate() { if (base() || unbuffered()) return 0; else return doallocate(); } virtual int sync(); virtual int pbackfail(int c); virtual int ungetfail(); virtual streambuf* setbuf(char* p, size_t len); int in_avail() { return _egptr - _gptr; } int out_waiting() { return _pptr - _pbase; } virtual size_t sputn(const char* s, size_t n); virtual size_t sgetn(char* s, size_t n); long sgetline(char* buf, _G_size_t n, char delim, int putback_delim); int sbumpc() { if (_gptr >= _egptr && underflow() == EOF) return EOF; #ifndef atarist return *(unsigned char*)_gptr++; #else { int ch = *(unsigned char*)_gptr++; if((!is_binary()) && (ch == '\r')) return sbumpc(); return ch; } #endif } int sgetc() { if (_gptr >= _egptr && underflow() == EOF) return EOF; #ifndef atarist return *(unsigned char*)_gptr; #else { int ch = *(unsigned char *)_gptr; if((!is_binary()) && (ch == '\r')) return snextc(); return ch; } #endif } int snextc() { if (++_gptr >= _egptr && underflow() == EOF) return EOF; #ifndef atarist return *(unsigned char*)_gptr; #else { int ch = *(unsigned char *)_gptr; if((!is_binary()) && (ch == '\r')) return snextc(); return ch; } #endif } #ifdef atarist int _atari_putc(int c) { if ((!is_binary()) && ((c == '\n') || (c == '\r'))) { if(c == '\r') return (int)c; if (_pptr >= _epptr) { if(overflow((int)'\r') == EOF) return EOF; } else *_pptr++ = '\r'; } if (_pptr >= _epptr) return overflow(c); return *_pptr++ = c, (unsigned char)c; } #endif int sputc(int c) { #ifndef atarist if (_pptr >= _epptr) return overflow(c); return *_pptr++ = c, (unsigned char)c; #else return _atari_putc(c); #endif } int vscan(char const *fmt0, _G_va_list ap); int vform(char const *fmt0, _G_va_list ap); #if 0 /* Work in progress */ int collumn(); // Current collumn number (of put pointer). -1 is unknown. void collumn(int c); // Set collumn number of put pointer to c. friend extern "C" int _handle_overflow(int c); friend class streammarker; #endif }; struct __file_fields { char _fake; char _shortbuf[1]; short _fileno; int _blksize; char* _save_gptr; char* _save_egptr; fpos_t _offset; }; class filebuf : public streambuf { struct __file_fields _fb; void init(); public: filebuf(); filebuf(int fd); filebuf(int fd, char* p, size_t len); ~filebuf(); filebuf* attach(int fd); filebuf* open(const char *filename, const char *mode); filebuf* open(const char *filename, int mode, int prot = 0664); virtual int underflow(); virtual int overflow(int c = EOF); int is_open() { return _fb._fileno >= 0; } int fd() { return is_open() ? _fb._fileno : EOF; } filebuf* close(); virtual int doallocate(); virtual streampos seekoff(streamoff, _seek_dir, int mode=ios::in|ios::out); size_t sputn(const char* s, size_t n); size_t sgetn(char* s, size_t n); virtual int sync(); protected: // See documentation in filebuf.C. virtual int pbackfail(int c); int is_reading() { return eback() != egptr(); } char* cur_ptr() { return is_reading() ? gptr() : pptr(); } /* System's idea of pointer */ char* file_ptr() { return _fb._save_gptr ? _fb._save_egptr : egptr(); } int do_flush(); // Low-level operations (Usually invoke system calls.) #ifndef atarist virtual int sys_read(char* buf, _G_size_t size); virtual fpos_t sys_seek(fpos_t, _seek_dir); #else virtual long sys_read(char* buf, size_t size); virtual long sys_seek(long, _seek_dir); #endif virtual long sys_write(const void*, long); virtual int sys_stat(void*); // Actually, a (struct stat*) virtual int sys_close(); }; #ifdef _STREAM_COMPAT inline int ios::readable() { return rdbuf()->_flags & _S_CAN_READ; } inline int ios::writable() { return rdbuf()->_flags & _S_CAN_WRITE; } inline int ios::is_open() {return rdbuf()->_flags & _S_CAN_READ+_S_CAN_WRITE;} #endif #endif /* _STREAMBUF_H */