/*** *stdiostr.cpp - * * Copyright (c) 1991-1997, Microsoft Corporation. All rights reserved. * *Purpose: * *******************************************************************************/ #include #include #include #include #include #pragma hdrstop extern "C" { #include #include } #include stdiobuf::stdiobuf(FILE * f) : streambuf() { unbuffered(1); // initially unbuffered _str = f; } stdiobuf::~stdiobuf() // : ~streambuf() { stdiobuf::sync(); // make sure buffer flushed } int stdiobuf::setrwbuf(int readsize, int writesize) { char * tbuf; unbuffered(!(readsize+writesize)); if (unbuffered()) return(0); tbuf = _new_crt char[(readsize+writesize)]; if (!tbuf) return(EOF); setb( tbuf, tbuf + (readsize+writesize), 1); if (readsize) { setg(base(),base()+readsize,base()+readsize); } else { setg(0,0,0); } if (writesize) { setp(base()+readsize,ebuf()); } else { setp(0,0); } return(1); } int stdiobuf::overflow(int c) { long count, nout; if (allocate()==EOF) // make sure there is a reserve area return EOF; if (!unbuffered() && epptr()) { if ((count = pptr() - pbase()) > 0) { nout=fwrite((void *) pbase(), 1, (int)count, _str); pbump(-(int)nout); if (nout != count) { memmove(pbase(),pbase()+nout,(int)(count-nout)); return(EOF); } } } if ((!unbuffered()) && (!epptr())) setp(base()+(blen()>>1),ebuf()); if (c!=EOF) { if ((!unbuffered()) && (pptr() < epptr())) // guard against recursion sputc(c); else return fputc(c, _str); } return(1); // return something other than EOF if successful } int stdiobuf::underflow() { int count; if (allocate()==EOF) // make sure there is a reserve area return EOF; if ((!unbuffered()) && (!egptr())) setg(base(),(base()+(blen()>>1)),(base()+(blen()>>1))); if (unbuffered() || (!egptr())) return fgetc(_str); if (gptr() >= egptr()) // buffer empty, try for more { if (!(count = fread((void *)eback(), 1, (size_t)(egptr()-eback()), _str))) return(EOF); // reach EOF, nothing read setg(eback(),(egptr()-count),egptr()); // _gptr = _egptr - count if (gptr()!=eback()) { memmove(gptr(), eback(), count); // overlapping memory! } } return sbumpc(); } streampos stdiobuf::seekoff(streamoff off, ios::seek_dir dir, int) { int fdir; long retpos; switch (dir) { case ios::beg : fdir = SEEK_SET; break; case ios::cur : fdir = SEEK_CUR; break; case ios::end : fdir = SEEK_END; break; default: // error return(EOF); } stdiobuf::overflow(EOF); if (fseek(_str, off, fdir)) return (EOF); if ((retpos=ftell(_str))==-1L) return(EOF); return((streampos)retpos); } int stdiobuf::pbackfail(int c) { if (eback()0) { #ifdef _WIN32 flags = _osfile_safe(_fileno(_str)); #else /* _WIN32 */ flags = _osfile[_fileno(_str)]; #endif /* _WIN32 */ if (flags & FTEXT) { // If text mode, need to account for CR/LF etc. for (p = gptr(); p < egptr(); p++) if (*p == '\n') count++; // account for EOF if read, not counted by _read if (_str->_flag & _IOCTRLZ) count++; } if (stdiobuf::seekoff( -count, ios::cur, ios::in)==EOF) return(EOF); setg(eback(),egptr(),egptr()); // empty get area (_gptr = _egptr;) } } return(0); } stdiostream::stdiostream(FILE * file) : iostream(_new_crt stdiobuf(file)) { istream::delbuf(1); ostream::delbuf(1); } stdiostream::~stdiostream() { } // include here for better granularity int ios::sunk_with_stdio = 0; void ios::sync_with_stdio() { if (!sunk_with_stdio) // first time only { cin = _new_crt stdiobuf(stdin); cin.delbuf(1); cin.setf(ios::stdio); cout = _new_crt stdiobuf(stdout); cout.delbuf(1); cout.setf(ios::stdio|ios::unitbuf); ((stdiobuf*)(cout.rdbuf()))->setrwbuf(0,80); cerr = _new_crt stdiobuf(stderr); cerr.delbuf(1); cerr.setf(ios::stdio|ios::unitbuf); ((stdiobuf*)(cerr.rdbuf()))->setrwbuf(0,80); clog = _new_crt stdiobuf(stderr); clog.delbuf(1); clog.setf(ios::stdio); ((stdiobuf*)(clog.rdbuf()))->setrwbuf(0,BUFSIZ); sunk_with_stdio++; } }