summaryrefslogtreecommitdiffstats
path: root/private/crt32/iostream/streamb.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/iostream/streamb.cxx')
-rw-r--r--private/crt32/iostream/streamb.cxx514
1 files changed, 514 insertions, 0 deletions
diff --git a/private/crt32/iostream/streamb.cxx b/private/crt32/iostream/streamb.cxx
new file mode 100644
index 000000000..bcfb9a1eb
--- /dev/null
+++ b/private/crt32/iostream/streamb.cxx
@@ -0,0 +1,514 @@
+/***
+*streamb.cxx - fuctions for streambuf class.
+*
+* Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved.
+*
+*Purpose:
+* Functions for streambuf class.
+*
+*Revision History:
+* 09-10-90 WAJ Initial version.
+* 07-02-91 KRS Initial version completed.
+* 08-20-91 KRS Treat chars as unsigned; fix sgetn() function.
+* 09-06-91 KRS Do a sync() in ~streambuf before destroying buffer.
+* 11-18-91 KRS Split off stream1.cxx for input-specific code.
+* 12-09-91 KRS Fix up xsputn/xsgetn usage.
+* 03-03-92 KRS Added mthread lock init calls to constructors.
+* 06-02-92 KRS CAV #1745: Don't confuse 0xFF with EOF in xsputn()
+* call to overflow().
+*
+*******************************************************************************/
+
+#include <cruntime.h>
+#include <internal.h>
+#include <string.h>
+#include <stdlib.h>
+#include <iostream.h>
+#pragma hdrstop
+
+
+#ifndef BUFSIZ
+#define BUFSIZ 512
+#endif
+
+/***
+*streambuf::streambuf() -
+*
+*Purpose:
+* Default constructor.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+streambuf::streambuf()
+{
+ _fAlloc = 0;
+ _fUnbuf = 0;
+ x_lastc = EOF;
+ _base = NULL;
+ _ebuf = NULL;
+ _pbase = NULL;
+ _pptr = NULL;
+ _epptr = NULL;
+ _eback = NULL;
+ _gptr = NULL;
+ _egptr = NULL;
+
+#ifdef MTHREAD
+ LockFlg = 1; // default is no locking
+ _mtlockinit(lockptr());
+#endif /* MTHREAD */
+
+}
+
+/***
+*streambuf::streambuf(char* pBuf, int cbBuf) -
+*
+*Purpose:
+* Constructor which specifies a buffer area.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+streambuf::streambuf( char* pBuf, int cbBuf )
+{
+ _fAlloc = 0;
+ _fUnbuf = 0;
+ x_lastc = EOF;
+ _base = pBuf;
+ _ebuf = pBuf + (unsigned)cbBuf;
+ _pbase = NULL;
+ _pptr = NULL;
+ _epptr = NULL;
+ _eback = NULL;
+ _gptr = NULL;
+ _egptr = NULL;
+
+ if( pBuf == NULL || cbBuf == 0 ){
+ _fUnbuf = 1;
+ _base = NULL;
+ _ebuf = NULL;
+ }
+
+#ifdef MTHREAD
+ LockFlg = 1; // default is no locking
+ _mtlockinit(lockptr());
+#endif /* MTHREAD */
+
+}
+
+
+/***
+*virtual streambuf::~streambuf() -
+*
+*Purpose:
+* Destructor.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+streambuf::~streambuf()
+{
+ lock(); // make sure no one else still using it
+// x_lastc = EOF;
+ sync(); // make sure buffer empty before possibly destroying it
+ if( (_fAlloc) && (_base) )
+ delete _base;
+}
+
+
+/***
+* virtual streambuf * streambuf::setbuf(char * p, int len) -
+*
+*Purpose:
+* Offers the array at p with len bytes to be used as a reserve area.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+streambuf * streambuf::setbuf(char * p, int len)
+{
+ if (!_base)
+ {
+ if ((!p) || (!len))
+ _fUnbuf = 1; // mark as unbuffered
+ else
+ {
+ _base = p;
+ _ebuf = p + (unsigned)len;
+ _fUnbuf = 0;
+ }
+ return (this);
+ }
+ return((streambuf *)NULL);
+}
+
+
+/***
+*virtual int streambuf::xsputn( char* pBuf, int cbBuf ) -
+*
+*Purpose:
+* Tries to output cbBuf characters. Returns number of characters
+* that were outputted.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int streambuf::xsputn( const char* pBuf, int cbBuf )
+{
+ int cbOut;
+#if 0
+ if (!this)
+ printf("xsputn: this = NULL\n");
+#endif
+ for (cbOut = 0; cbBuf--; cbOut++)
+ {
+ if ((_fUnbuf) || (_pptr >= _epptr))
+ {
+// UNDONE: can be optimized like sgetn !!
+ if (overflow((unsigned char)*pBuf)==EOF) // 0-extend 0xFF !=EOF
+ break;
+ }
+ else
+ {
+ *(_pptr++) = *pBuf;
+ }
+ pBuf++;
+ }
+ return cbOut;
+}
+
+/***
+*virtual int streambuf::xsgetn( char* pBuf, int cbBuf ) -
+*
+*Purpose:
+* Tries to input cbBuf characters. Returns number of characters
+* that were read from streambuf.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+// #pragma intrinsic(memcpy,__min)
+
+int streambuf::xsgetn( char * pBuf, int cbBuf)
+{
+ int count;
+ int cbIn = 0;
+ if (_fUnbuf)
+ {
+ if (x_lastc==EOF)
+ x_lastc=underflow();
+
+ while (cbBuf--)
+ {
+ if (x_lastc==EOF)
+ break;
+ *(pBuf++) = (char)x_lastc;
+ cbIn++;
+ x_lastc=underflow();
+ }
+ }
+ else
+ {
+ while (cbBuf)
+ {
+ if (underflow()==EOF) // make sure something to read
+ break;
+ count = __min(egptr() - gptr(),cbBuf);
+ if (count>0)
+ {
+ memcpy(pBuf,gptr(),count);
+ pBuf += count;
+ _gptr += count;
+ cbIn += count;
+ cbBuf -= count;
+ }
+ }
+ }
+ return cbIn;
+}
+// #pragma function(memcpy, __min)
+
+/***
+*virtual int streambuf::sync() -
+*
+*Purpose:
+* Tries to flush all data in put area and give back any data in the
+* get area (if possible), leaving both areas empty on exit.
+* Default behavior is to fail unless buffers empty.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int streambuf::sync()
+{
+ if ((gptr() <_egptr) || (_pptr > _pbase))
+ {
+ return EOF;
+ }
+ return 0;
+}
+
+#if 0
+/***
+*int streambuf::sputn( char* pBuf, int cbBuf ) -
+*
+*Purpose:
+* Tries to output cbBuf characters. Returns number of characters
+* that were output.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int streambuf::sputn( const char* pBuf, int cbBuf )
+{
+// UNDONE:
+ return xsputn(pBuf, cbBuf);
+}
+
+/***
+*int streambuf::sgetn( char* pBuf, int cbBuf ) -
+*
+*Purpose:
+* Tries to input cbBuf characters. Returns number of characters
+* that were read from streambuf.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int streambuf::sgetn( char * pBuf, int cbBuf)
+{
+// UNDONE:
+ return xsgetn(pBuf, cbBuf);
+}
+#endif
+
+/***
+*int streambuf::allocate() -
+*
+*Purpose:
+* Tries to set up a Reserve Area. If one already exists, or if
+* unbuffered, just returns 0.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int streambuf::allocate()
+{
+ if ((_fUnbuf) || (_base))
+ return 0;
+ if (doallocate()==EOF) return EOF;
+
+ return(1);
+}
+
+/***
+*virtual int streambuf::doallocate() -
+*
+*Purpose:
+* Tries to set up a Reserve Area. Returns EOF if unsuccessful.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+int streambuf::doallocate()
+{
+ char * tptr;
+ if (!( tptr = new char[BUFSIZ]))
+ return(EOF);
+ setb(tptr, tptr + BUFSIZ, 1);
+ return(1);
+}
+
+/***
+*void streambuf::unbuffered(int fUnbuf) -
+*
+*Purpose:
+* Sets unbuffered status.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+// void streambuf::unbuffered(int fUnbuf)
+// {
+// _fUnbuf = fUnbuf;
+// if ((_fUnbuf) && (_base)) delete _base; // UNDONE: not doc'd as such ??
+// }
+
+/***
+*void streambuf::setb(char * b, char * eb, int a = 0) -
+*
+*Purpose:
+* Sets up reserve area.
+*
+*Entry:
+*
+*Exit:
+*
+*Exceptions:
+*
+*******************************************************************************/
+
+void streambuf::setb(char * b, char * eb, int a )
+{
+ if ((_fAlloc) && (_base)) delete _base;
+ _base = b;
+ _fAlloc = a;
+ _ebuf = eb;
+}
+
+#if 0
+int streambuf::overflow(int d)
+{
+ printf("Error: *%p streambuf::overflow(%d) called!\n",this,d);
+ return EOF;
+}
+
+int streambuf::underflow()
+{
+ printf("Error: *%p streambuf::underflow() called!\n",this);
+ return EOF;
+}
+#endif
+
+/***
+*virtual streampos streambuf::seekoff(streamoff off, ios::seekdir dir, int mode)
+*
+*Purpose:
+* seekoff member function. seek forward or backward in the stream.
+* Default behavior: returns EOF.
+*
+*Entry:
+* off = offset (+ or -) to seek by
+* dir = one of ios::beg, ios::end, or ios::cur.
+* mode = ios::in or ios::out.
+*
+*Exit:
+* Returns new file position or EOF if error or seeking not supported.
+*
+*Exceptions:
+* Returns EOF if error.
+*
+*******************************************************************************/
+streampos streambuf::seekoff(streamoff,ios::seek_dir,int)
+{
+return EOF;
+}
+
+/***
+*virtual streampos streambuf::seekpos(streampos pos, int mode) -
+*
+*Purpose:
+* seekoff member function. seek to absolute file position.
+* Default behavior: returns seekoff(streamoff(pos), ios::beg, mode).
+*
+*Entry:
+* pos = absolute offset to seek to
+* mode = ios::in or ios::out.
+*
+*Exit:
+* Returns new file position or EOF if error or seeking not supported.
+*
+*Exceptions:
+* Returns EOF if error.
+*
+*******************************************************************************/
+streampos streambuf::seekpos(streampos pos,int mode)
+{
+return seekoff(streamoff(pos), ios::beg, mode);
+}
+
+/***
+*virtual int streambuf::pbackfail(int c) - handle failure of putback
+*
+*Purpose:
+* pbackfail member function. Handle exception of pback function.
+* Default behavior: returns EOF. See spec. for details.
+*
+* Note: the following implementation gives default behavior, thanks
+* to the default seekoff, but also supports derived classes properly:
+*
+*Entry:
+* c = character to put back
+*
+*Exit:
+* Returns c if successful or EOF on error.
+*
+*Exceptions:
+* Returns EOF if error. Behavior is undefined if c was not the
+* previous character in the stream.
+*
+*******************************************************************************/
+int streambuf::pbackfail(int c)
+{
+ if (eback()<gptr()) return sputbackc((char)c); // CONSIDER: should never happen
+
+ if (seekoff( -1, ios::cur, ios::in)==EOF) // always EOF for streambufs
+ return EOF;
+ if (!unbuffered() && egptr())
+ {
+ memmove((gptr()+1),gptr(),(egptr()-(gptr()+1)));
+ *gptr()=(char)c;
+ }
+ return(c);
+}