summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/SNIP/mystream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/CONTRIB/SNIP/mystream.cpp')
-rwxr-xr-xreference/C/CONTRIB/SNIP/mystream.cpp142
1 files changed, 142 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/SNIP/mystream.cpp b/reference/C/CONTRIB/SNIP/mystream.cpp
new file mode 100755
index 0000000..4776728
--- /dev/null
+++ b/reference/C/CONTRIB/SNIP/mystream.cpp
@@ -0,0 +1,142 @@
+// Mystream.cpp
+// Implementation of ios interface classes for Myio
+//
+// Written by David L. Nugent
+//
+
+# include <iostream.h>
+# include "Mystream.h"
+# if defined(_MSC_VER)
+# include <memory.h>
+# else
+# include <stdlib.h>
+# endif
+
+ // Mystreambuf constructor
+ // This simply initialises the base class streambuf
+ // (it is initially empty with no buffer allocated)
+ // and register the Myio object
+ // Note: we _could_ set the stream unbuffered here,
+ // which is useful for stdio handles, so that the
+ // streambuf functions overflow() and underflow()
+ // get called on every character rather than when
+ // the streambuf buffer is full
+
+Mystreambuf::Mystreambuf (Myio * mPtr)
+ : streambuf (), mptr(mPtr)
+{
+// unbuffered(1); // Uncomment to make unbuffered
+}
+
+ // Mystreambuf()
+ // Called when streambuf owned buffer is full
+ // or when stream is flushed
+ // Our job here is to empty the streambuf
+ // write buffer and reset the 'put' pointers.
+
+int
+Mystreambuf::overflow (int c)
+{
+ int written;
+
+ // Handle unbuffered stream
+
+ if (unbuffered()) // Handle the simple case first
+ {
+ if (c == EOF) // Special case, this only flushes
+ return 0;
+ char ch = char(c); // Write the byte directly
+ written = mptr->write (&ch, 1);
+ return (written) ? c : EOF;
+ }
+
+ // Handle buffered stream
+
+ if (!base()) // Need to allocate a buffer
+ allocate();
+
+ if (base()) // Test for memory allocation error
+ {
+ char * ep = base() + (blen() / 2);
+ if (!pbase()) // Set put pointers if not set up
+ setp (base(), ep);
+ int bytes = pptr() - pbase(); // Bytes to write
+ if (bytes)
+ {
+ written = mptr->write (pbase(), bytes);
+ if (!written)
+ return EOF;
+ bytes += written;
+ if (bytes) // Some is still waiting to be written
+ memcpy (base(), base() + written, bytes);
+ }
+ setp (base() + bytes, ep); // Reset 'put' pointers
+ return (c == EOF) ? 0 : sputc (c); // Put pending chr in buf
+ }
+ return EOF;
+}
+
+ //
+ // underflow() indicates that the input queue
+ // is empty and needs more data
+ //
+
+int
+Mystreambuf::underflow (void)
+{
+ int bytes;
+
+ // Handle an unbuffered stream
+
+ if (unbuffered())
+ {
+ bytes = mptr->read (&_back[1], 1);
+ if (!bytes)
+ {
+ setg (0, 0, 0);
+ return EOF;
+ }
+ setg (_back, _back + 1, _back + 2);
+ return (unsigned char)_back[1];
+ }
+
+ // Handle a buffered stream
+
+ if (!base()) // Need to allocate a buffer
+ allocate();
+
+ if (base())
+ {
+ char * gp = base() + blen() / 2;
+ if (gptr() >= egptr())
+ { // Read into the buffer from stream
+ overflow (); // Flush output in case we need it
+ bytes = mptr->read (gp + 1, blen() / 2 - 1);
+ setg (gp, gp + 1, gp + bytes + 1);
+ }
+ if (gptr() < egptr()) // Get from buffer
+ return (unsigned char) *gptr();
+ }
+ return EOF;
+}
+
+ //
+ // sync() needs to empty both put and get
+ // buffered. It will do this by calling
+ // overflow and simply resetting the get
+ // pointers to their default location.
+ //
+
+int
+Mystreambuf::sync (void)
+{
+ if (!unbuffered())
+ {
+ overflow (); // Force output
+ char * gp = base();
+ setp (gp, gp + blen() / 2);
+ gp = base() + blen() / 2;
+ setg (0, 0, 0);
+ }
+ return 0;
+}