Category : Files from Magazines
Archive   : CUJ9301.ZIP
Filename : 1101046A

 
Output of file : 1101046A contained in archive : CUJ9301.ZIP
#if !defined TSTREAM_H
#define TSTREAM_H

#include // for base class definitions

// class tbuf<>. Derived publicly from streambuf to
// allow class ios which contains pointer to streambuf
// access to virtual functions. tbuf<> implements
// basic buffering, reading, writing and seeking on
// a stream. It also provides open, close, attach,
// and utility functions.
template
class tbuf : public streambuf {
public:
// openProtection provides a default parameter to the
// open functions to specify what protection a file
// will be created with. You can ignore this if it is
// not necessary
static const int openProtect;
// tbufSize specifies the default buffer size. It is
// set to 516 bytes.
static const int tbufSize;
// Default contructor. Make a buffer without a
// stream attached. mode has a dual meaning, if it
// is zero it means that any operation is allowable,
// and the stream should not be deleted when closing.
tbuf()
: stream(0), mode(0), opened(0)
{
makbuf();
}
// create buffer and attach to t. t is assumed to be
// already opened in read/write mode. t will not be
// deleted or closed when closing this buffer
tbuf(T &t)
: stream(&t), mode(0), opened(1)
{
makbuf();
}
// create buffer from parameters, and attach to t.
tbuf(T &t, char* b, int l)
: stream(&t), mode(0), opened(1)
{
setbuf(b, l);
}
// destroy buffer. If mode is not zero, t will be
// closed and deleted. Otherwise just flush the
// output buffer.
~tbuf()
{
if(mode)
close();
else
overflow(EOF);
}
// return open status
int is_open() const
{
return opened;
}
// return reference to stream
T &fd() const
{
return *stream;
}
// open stream. mode must not be zero. stream will
// be closed and deleted when closing buffer.
tbuf *open(const char *name, int mode,
int prot = tbuf::openProtect);
// close buffer and optionally delete stream.
tbuf *close();
// attach stream to buffer. Stream is assumed to
// be opened in read/write mode.
tbuf *attach(T &);
// write buffer to stream and reset pointers.
virtual int overflow(int = EOF);
// read data into buffer and reset pointers.
virtual int underflow();
// sync input and output.
virtual int sync();
// seek to offset and flush output buffers.
virtual long seekoff(long, ios::seek_dir, int);
// set buffer. For unbuffered i/o set char * to 0.
virtual streambuf *setbuf(char *, int);
protected:
int putBackSize()
{
return (blen() > 8) ? 4 : 1;
}
void resetpg(int end = 0);
void makbuf()
{
setbuf(new char[tbufSize], tbufSize);
}
int unbuffered()
{
return streambuf::unbuffered() | !base();
}
T *stream;
int mode;
short opened;
char lookAhead[2];
};

template
const int tbuf::tbufSize = 516;
template
const int tbuf::openProtect = 0;

// Attach an open stream to this buffer. When this
// buffer is closed don't try to close stream. If
// not yet buffered, try to create a buffer. Reset
// the put and get pointers. Return 0 on error, or
// this if OK.
template
tbuf* tbuf::attach(T &t)
{
if(opened) // if already opened, return 0
return 0;
stream = &t; // attach stream.
opened = 1; // set to opened.
mode = 0; // buffer doesn't own stream.
if(!base()) // if no buffer yet...
makbuf(); // try to make one.
else
resetpg(); // reset put and get pointers.
return this;
}

// Close buffer, and optionally stream attached to it.
// Flush buffer if data inside. Return 0 on error or
// this if OK.
template
tbuf* tbuf::close()
{
if(!*stream) // if stream closed,
opened = 0; // set opened off.
if(!opened) // if not on return 0.
return 0;
int ret = 0;
if(out_waiting()) // if output in buffer.
// flush output buffer.
ret = (overflow(EOF) == EOF) ? 1 : 0;
if(mode) // if mode is 0, don't
delete stream; // close or delete stream.
opened = 0; // set opened off.
return ret ? 0 : this;
}

// Write data from buffer to stream. This function
// is called when the buffer is full and we need to
// output more characters. The parameter c is the
// character that caused the overflow. If the
// stream is buffered, it will be placed in the
// buffer, otherwise it is written to the stream.
// If input char is EOF, don't write, just flush.
// Returns EOF on error, or 1 on success.
template
int tbuf::overflow(int c)
{
if(!opened || // check to see if stream
mode == 0 || // is on and mode is out.
!(mode&ios::out))
return EOF;
if(unbuffered())
{
if(c != EOF)
{ // if unbuffered,
char b = c; // write single char
if(stream->write(&b, 1) != 1)
return EOF;
}
}
else // else if buffered.
{
if(sync() != 0) // sync input and output
return EOF; // when writing
resetpg(1); // reset the put/get pointers
if(c != EOF)
{
sputc(c); // add c to the buffer
gbump(1); // move the get pointer
}
}
return 1; // return OK
}

// Open stream. If mode ios::ate (at end) is on,
// seek to end
template
tbuf* tbuf::open(const char* n, int m, int p)
{
if(opened || !m) // if already on, or no mode,
return 0; // return error.
stream = new T; // make new stream pointer.
stream->open(n, m, p);// open stream.
if(!*stream) // if stream not open,
return 0; // return error.
opened = 1; // set to on.
mode = m; // remeber mode.
if((mode & ios::ate) &&
stream->seek(0L, ios::end) == EOF)
return 0; // seek to end if ios::ate.
resetpg(); // reset put/get pointers.
return this; // return OK.
}

// Set the buffer, reset the put/get pointers.
// Return 0 on error, this if OK.
template
streambuf* tbuf::setbuf(char* b, int l)
{
if(!b) // turn off buffering.
{
streambuf::unbuffered(1);
return this;
}
if(opened && base())// check if stream is opened,
return 0; // , and no buffer yet.
setb(b, b+l, 0); // set buffer pointers.
resetpg(); // reset put/get pointers.
return this; // return OK.
}

// Seek to offset. dir indicates the relativity of
// the offset, ethier from beginning, current postion,
// or end (ios::beg, ios::cur, ios::end).
// First make sure there's nothing in the buffer.
template
long tbuf::seekoff(long off, ios::seek_dir dir,
int /* mode ignored */)
{
long loff = off;
int count = out_waiting(); // flush output first.
if(count)
{
if(stream->write(pbase(), count) != count)
return EOF;
}
else if(dir == ios::cur && // if relative seek,
(count = in_avail()) != 0)
loff -= count; // discount input.
resetpg(); // reset pointers.
return stream->seek(loff, dir);
}

// sync input and output buffer pointers. If output
// is waiting, write it, if input is waiting,
// back up to read it again
template
int tbuf::sync()
{
if (!opened) // check if opened.
return EOF;
int count = out_waiting(); // check for output,
if(count) // in buffer.
{
if(stream->write(pbase(), count) != count)
return EOF; // write output.
resetpg(1);
}
else if(in_avail()) // check for input
{ // in buffer
long pos = stream->seek(long(-in_avail()),
ios::cur);
setg(eback(), gptr(), gptr());
setp(gptr(), gptr()); // set up to re-read.
if(pos == EOF)
return EOF;
}
return 0;
}

// Read from stream to fill buffer. Must be opened and
// in input mode. If there is input in the buffer,
// return it. Otherwise call sync, read from stream,
// and set pointers. If the input is unbuffered,
// use the lookahead buffer.
template
int tbuf::underflow()
{
if(!opened || mode == 0 || !(mode&ios::in))
return EOF; // check for correct mode.
if(in_avail()) // if available from buffer,
return *gptr()&0xFF; // don't bother.
int c;
int count;
if(unbuffered()) // if unbuffered.
{
count = stream->read(lookAhead, 1);
if(count == EOF) // read one char
{ // into look ahead
c = EOF; // buffer.
setg(0, 0, 0);
}
else
{
c = lookAhead[0]&0xFF;
setg(lookAhead, lookAhead, lookAhead+1);
}
}
else // else buffered.
{
if(sync() != 0) // sync pointers.
return EOF;
int pb = putBackSize();
char *b = base(); // read into buffer.
count = stream->read(b+pb, blen()-pb);
if(count == EOF) // check read return.
return EOF;
setg(b, b+pb, b+pb+count);
setp(b+pb, b+pb); // set pointers.
if(count) // return first char.
c = *gptr()&0xFF;
}
if(!count)
c = EOF;
return c;
}

// reset the put and get pointers. If end is
// true set the end pointers to the end of
// the buffer.
template
void tbuf::resetpg(int end)
{
char *buf = base(); // get the start of buffer.
char *sbuf = buf + (buf ? putBackSize() : 0);
char *ebuf; // set start and end pointers.
if(end)
ebuf = buf + blen();
else
ebuf = sbuf;
setp(sbuf, ebuf); // set put pointer
setg(buf, sbuf, sbuf);// set get pointer
}

// tstreambase is virtually derived from ios. ios
// does not define any functionality for tstreambase
// but allows communication between tstreambase and
// istream, ostream and stream classes. The functions
// defined in tstreambase typically call the same
// named function for its tbuf<> member and set ios
// status flags. When a tstreambase is constructed
// ios is initialized with a pointer to the tbuf<>
// member. ios see this pointer as a streambuf
// pointer, and only has access to tbuf<> through the
// virtual functions, overflow, underflow, sync, and
// seekoff.
template
class tstreambase : virtual public ios {
public:
// Default constructor. Make an unattached
// buffer, and initialize ios with it's pointer.
tstreambase()
: tbbuf()
{
ios::init(&tbbuf);
}
// Make a buffer attach to named stream, and open
// stream
tstreambase(const char* n, int m,
int p = tbuf::openProtect)
: tbbuf()
{
ios::init(&tbbuf);
open(n, m, p);
}
// Make a buffer attached to already opened stream.
tstreambase(T &f)
: tbbuf(f)
{
ios::init(&tbbuf);
}
// Make a buffer using parameters, and attach
// to already opened stream.
tstreambase(T &f, char* b, int l)
: tbbuf(f, b, l)
{
ios::init(&tbbuf);
}
// Destroy buffer
~tstreambase()
{
;
}
// close attached stream and set ios flags.
void close()
{
if(tbbuf.close())
clear(ios::goodbit);
else
setstate(ios::failbit);
}
// set buffer and set ios flags.
void tstreambase::setbuf(char* b, int l)
{
if(tbbuf.setbuf(b, l))
clear(ios::goodbit);
else
setstate(ios::failbit);
}
// open stream and set ios flags.
void open(const char *, int,
int = tbuf::openProtect);
// attach opened stream and set ios flags.
void attach(T &);
// return the buffer.
tbuf *rdbuf()
{
return &tbbuf;
}
private:
tbuf tbbuf;
};

// Attempt to open tbuf<>, and set ios flags
// accordingly. Opening an already open stream
// results in an error. If ios::app (append to
// file) is set, also set ios::out. If ios::out
// is set, and ios::app, ios::in, and ios::ate
// (start at end) are not set, set the ios::trunc bit.
template
void tstreambase::open(const char *n, int m, int p)
{
if(m & ios::app)
m |= ios::out;
else if((m & (ios::out|ios::ate|ios::app|ios::in))
== ios::out)
m |= ios::trunc;
if(tbbuf.is_open())
clear(ios::failbit);
else if(tbbuf.open(n, m, p))
clear(ios::goodbit);
else
clear(ios::badbit);
}

// Attach an opened stream to buffer, and set the ios
// bits accordingly.
template
void tstreambase::attach(T &f)
{
if(tbbuf.is_open())
setstate(ios::failbit);
else if(tbbuf.attach(f))
clear(ios::goodbit);
else
clear(ios::badbit);
}

// The itstream, otstream and tstream class are merely
// "shell" classes, and serve only to combine the
// functionality of it's base class. The only functions
// defined are the constructor and destructors, and
// open and rdbuf. There are no addition data members
// and all functions call directly the functions of the
// base class. The default open mode is ios::in for
// itstream, ios::out for otstream, and both for
// tstream.
template
class itstream : public tstreambase,
public istream {
public:
itstream()
{
;
}
itstream(const char* n, int m = ios::in,
int p = tbuf::openProtect)
: tstreambase(n, m | ios::in, p)
{
;
}
itstream(T &f)
: tstreambase(f)
{
;
}
itstream(T &f, char* b, int l)
: tstreambase(f, b, l)
{
;
}
~itstream()
{
;
}
tbuf *rdbuf()
{
return tstreambase::rdbuf();
}
void open(const char *n, int m = ios::in,
int p = tbuf::openProtect)
{
tstreambase::open(n, m | ios::in, p);
}
};

template
class otstream : public tstreambase,
public ostream {
public:
otstream()
{
;
}
otstream(const char* n, int m = ios::out,
int p = tbuf::openProtect)
: tstreambase(n, m | ios::out, p)
{
;
}
otstream(T &f)
: tstreambase(f)
{
;
}
otstream(T &f, char* b, int l)
: tstreambase(f, b, l)
{
;
}
~otstream()
{
;
}
tbuf *rdbuf()
{
return tstreambase::rdbuf();
}
void open(const char *n, int m = ios::out,
int p = tbuf::openProtect)
{
tstreambase::open(n, m | ios::out, p);
}
};

template
class tstream : public tstreambase,
public iostream {
public:
tstream()
{
;
}
tstream(const char *n, int m,
int p = tbuf::openProtect)
: tstreambase(n, m, p)
{
;
}
tstream(T &f)
: tstreambase(f)
{
;
}
tstream(T &f, char *b, int l)
: tstreambase(f, b, l), iostream()
{
;
}
~tstream()
{
;
}
tbuf *rdbuf()
{
return tstreambase::rdbuf();
}
void open(const char *n, int m,
int p = tbuf::openProtect)
{
tstreambase::open(n, m, p);
}
};

#endif



  3 Responses to “Category : Files from Magazines
Archive   : CUJ9301.ZIP
Filename : 1101046A

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/