summaryrefslogtreecommitdiffstats
path: root/private/crt32/iostream/stdiostr.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/iostream/stdiostr.cxx')
-rw-r--r--private/crt32/iostream/stdiostr.cxx266
1 files changed, 266 insertions, 0 deletions
diff --git a/private/crt32/iostream/stdiostr.cxx b/private/crt32/iostream/stdiostr.cxx
new file mode 100644
index 000000000..58c385a78
--- /dev/null
+++ b/private/crt32/iostream/stdiostr.cxx
@@ -0,0 +1,266 @@
+/***
+*stdiostr.cxx -
+*
+* Copyright (c) 1991-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+*
+*Revision History:
+*
+* 07-10-91 KRS Created.
+* 08-26-91 KRS Switch out cout/cerr. etc. for Windows non-QuickWin.
+* 09-09-91 KRS Modify sync_with_stdio() for filebuf defaults.
+* 09-12-91 KRS Add stdiostream class.
+* 09-19-91 KRS Use delbuf(1) in stdiostream constructor.
+* 09-20-91 KRS C700 #4453: Improve efficiency in overflow().
+* 10-21-91 KRS Eliminate last use of default iostream constructor.
+* 10-24-91 KRS Avoid virtual calls from virtual functions.
+* 11-13-91 KRS Split out streambuf::dbp() into separate file.
+* Improve default buffer handling in underflow/overflow.
+* Fix bug in sync().
+* 01-20-92 KRS C700 #5803: account for CR/LF pairs in ssync().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <string.h>
+#include <stdiostr.h>
+#pragma hdrstop
+
+extern "C" {
+#include <file2.h>
+#include <msdos.h>
+}
+#include <dos.h>
+
+ stdiobuf::stdiobuf(FILE * f)
+: streambuf()
+{
+ unbuffered(1); // initially unbuffered
+ _str = f;
+}
+
+ stdiobuf::~stdiobuf()
+// : ~streambuf()
+{
+ stdiobuf::sync(); // make sure buffer flushed
+// _str = 0;
+}
+
+ int stdiobuf::setrwbuf(int readsize, int writesize)
+{
+ char * tbuf;
+ unbuffered(!(readsize+writesize));
+ if (unbuffered())
+ return(0);
+
+ tbuf = new 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()); // hack: default to 2nd half
+ 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))); // hack: default
+
+ 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())
+ {
+ // CONSIDER: expensive, is there a better sol'n?
+ memmove(gptr(), eback(), count); // overlapping memory!
+ }
+ }
+ return sbumpc(); // CONSIDER: possible recursion
+}
+
+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);
+ }
+
+// CONSIDER: is this needed?
+ 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()<gptr()) return sputbackc((char)c); // CONSIDER: should never happen
+
+ if (stdiobuf::seekoff( -1, ios::cur, ios::in)==EOF)
+ return EOF;
+ if (!unbuffered() && egptr())
+ {
+ memmove((gptr()+1),gptr(),(egptr()-(gptr()+1)));
+ *gptr()=(char)c;
+ }
+ return(c);
+}
+
+int stdiobuf::sync()
+{
+ long count;
+ char * p;
+ char flags;
+ if (!unbuffered())
+ {
+ if (stdiobuf::overflow(EOF)==EOF)
+ return(EOF);
+ if ((count=in_avail())>0)
+ {
+ flags = _osfile[_fileno(_str)];
+ 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
+ // UNDONE: is this necessary?
+ if (_str->_flag & _IOCTRLZ)
+ count++;
+#if 0
+ // UNDONE: is this correct?
+ if ((gptr()==eback()) && (flags & FCRLF))
+ count--;
+#endif
+ }
+ 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 stdiobuf(file))
+{
+istream::delbuf(1);
+ostream::delbuf(1);
+// CONSIDER: do anything else?
+}
+
+ stdiostream::~stdiostream()
+{
+// CONSIDER: do anything else?
+}
+
+// include here for better granularity
+
+int ios::sunk_with_stdio = 0;
+
+void ios::sync_with_stdio()
+{
+#if ((!defined(_WINDOWS)) || defined(_QWIN))
+ if (!sunk_with_stdio) // first time only
+ {
+// printf("In sync_with_stdio\n");
+
+ cin = new stdiobuf(stdin);
+ cin.delbuf(1);
+ cin.setf(ios::stdio);
+
+ cout = new stdiobuf(stdout);
+ cout.delbuf(1);
+ cout.setf(ios::stdio|ios::unitbuf);
+ ((stdiobuf*)(cout.rdbuf()))->setrwbuf(0,80); // UNDONE: size??
+
+ cerr = new stdiobuf(stderr);
+ cerr.delbuf(1);
+ cerr.setf(ios::stdio|ios::unitbuf);
+ ((stdiobuf*)(cerr.rdbuf()))->setrwbuf(0,80); // UNDONE: size??
+
+ clog = new stdiobuf(stderr);
+ clog.delbuf(1);
+ clog.setf(ios::stdio);
+ ((stdiobuf*)(clog.rdbuf()))->setrwbuf(0,BUFSIZ);
+
+ sunk_with_stdio++;
+ }
+#endif
+}