You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

244 lines
7.0 KiB

////////////////////////////////////////////////////////////////////
// Streams.h
//
// Copyright 2007 cDc@seacave
// Distributed under the Boost Software License, Version 1.0
// (See http://www.boost.org/LICENSE_1_0.txt)
#ifndef __SEACAVE_STREAMS_H__
#define __SEACAVE_STREAMS_H__
// I N C L U D E S /////////////////////////////////////////////////
#include "AutoPtr.h"
// D E F I N E S ///////////////////////////////////////////////////
#define SIZE_NA ((size_f_t)-1)
#define STREAM_ERROR ((size_t)-1)
namespace SEACAVE {
// S T R U C T S ///////////////////////////////////////////////////
class InputStream;
typedef InputStream ISTREAM;
class OutputStream;
typedef OutputStream OSTREAM;
class IOStream;
typedef IOStream IOSTREAM;
class GENERAL_API NOINITVTABLE Stream {
public:
virtual ~Stream() { }
// Identify stream type
virtual InputStream* getInputStream(int) { return NULL; }
virtual OutputStream* getOutputStream(int) { return NULL; }
virtual IOStream* getIOStream(int, int) { return NULL; }
// Get the length of the stream.
// SIZE_NA if there were errors.
virtual size_f_t getSize() const = 0;
// Position the stream at the given offset from the beginning.
virtual bool setPos(size_f_t pos) = 0;
// Get the current position in the stream (offset from the beginning).
// SIZE_NA if there were errors.
virtual size_f_t getPos() const = 0;
};
class GENERAL_API NOINITVTABLE InputStream : public Stream {
public:
virtual ~InputStream() { }
/**
* Call this function until it returns 0 to get all bytes.
* @return The number of bytes read. len reflects the number of bytes
* actually read from the stream source in this call.
* STREAM_ERROR if there were errors.
*/
virtual size_t read(void* buf, size_t len) = 0;
enum { LAYER_ID_IN=0 };
InputStream* getInputStream(int typ=LAYER_ID_IN) override { return (typ == LAYER_ID_IN ? this : (InputStream*)NULL); }
};
class GENERAL_API NOINITVTABLE OutputStream : public Stream {
public:
virtual ~OutputStream() { }
/**
* @return The actual number of bytes written. len bytes will always be
* consumed, but fewer or more bytes may actually be written,
* for example if the stream is being compressed.
* STREAM_ERROR if there were errors.
*/
virtual size_t write(const void* buf, size_t len) = 0;
inline size_t print(LPCTSTR szFormat, ...) {
va_list args;
va_start(args, szFormat);
TCHAR szBuffer[2048];
const size_t len((size_t)_vsntprintf(szBuffer, 2048, szFormat, args));
if (len > 2048) {
const size_t count((size_t)_vsctprintf(szFormat, args));
ASSERT(count != (size_t)-1);
CAutoPtrArr<TCHAR> szBufferDyn(new TCHAR[count+1]);
_vsntprintf(szBufferDyn, count+1, szFormat, args);
va_end(args);
return write(szBufferDyn, count);
}
va_end(args);
return write(szBuffer, len);
}
inline size_t print(const std::string& str) {
return write(str.c_str(), str.length());
}
template<class T>
inline OutputStream& operator<<(const T& val) {
std::ostringstream ostr;
ostr << val;
print(ostr.str());
return *this;
}
/**
* This must be called before destroying the object to make sure all data
* is properly written. Note that some implementations
* might not need it...
*
* @return The actual number of bytes written.
* STREAM_ERROR if there were errors.
*/
virtual size_t flush() = 0;
enum { LAYER_ID_OUT=0 };
OutputStream* getOutputStream(int typ=LAYER_ID_OUT) override { return (typ == LAYER_ID_OUT ? this : (OutputStream*)NULL); }
};
class GENERAL_API NOINITVTABLE IOStream : public InputStream, public OutputStream {
public:
InputStream* getInputStream(int typ=LAYER_ID_IN) override { return InputStream::getInputStream(typ); }
OutputStream* getOutputStream(int typ=LAYER_ID_OUT) override { return OutputStream::getOutputStream(typ); }
IOStream* getIOStream(int typIn=LAYER_ID_IN, int typOut=LAYER_ID_OUT) override {
return ((InputStream*)this)->getInputStream(typIn) != NULL &&
((OutputStream*)this)->getOutputStream(typOut) != NULL ? this : (IOStream*)NULL;
}
};
/*----------------------------------------------------------------*/
template<bool managed=true>
class LayerInputStream : public InputStream {
public:
LayerInputStream(InputStream* aStream) : s(aStream) { ASSERT(s != NULL); }
virtual ~LayerInputStream() noexcept { if (managed) delete s; }
InputStream* getInputStream(int typ=InputStream::LAYER_ID_IN) override { return s->getInputStream(typ); }
size_t read(void* wbuf, size_t len) override {
return s->read(wbuf, len);
}
size_f_t getSize() const override {
return s->getSize();
}
bool setPos(size_f_t wpos) override {
return s->setPos(wpos);
}
size_f_t getPos() const override {
return s->getPos();
}
protected:
InputStream* const s;
};
template<bool managed=true>
class LayerOutputStream : public OutputStream {
public:
LayerOutputStream(OutputStream* aStream) : s(aStream) {}
virtual ~LayerOutputStream() noexcept { if (managed) delete s; }
OutputStream* getOutputStream(int typ=OutputStream::LAYER_ID_OUT) override { return s->getOutputStream(typ); }
size_t write(const void* buf, size_t len) override {
return s->write(buf, len);
}
size_t flush() override {
return s->flush();
}
size_f_t getSize() const override {
return s->getSize();
}
bool setPos(size_f_t wpos) override {
return s->setPos(wpos);
}
size_f_t getPos() const override {
return s->getPos();
}
protected:
OutputStream* const s;
};
/*----------------------------------------------------------------*/
template<bool managed=true>
class LayerIOStream : public IOStream {
public:
LayerIOStream(InputStream* aStream) : s(aStream), sIn(aStream), sOut(NULL) { ASSERT(aStream != NULL); }
LayerIOStream(OutputStream* aStream) : s(aStream), sIn(NULL), sOut(aStream) { ASSERT(aStream != NULL); }
LayerIOStream(InputStream* streamIn, OutputStream* streamOut) : s(NULL), sIn(streamIn), sOut(streamOut) { ASSERT(sIn != NULL || sOut != NULL); }
virtual ~LayerIOStream() noexcept { if (managed) { delete sIn; delete sOut; } }
InputStream* getInputStream(int typ=InputStream::LAYER_ID_IN) override { return (sIn ? sIn->getInputStream(typ) : NULL); }
OutputStream* getOutputStream(int typ=OutputStream::LAYER_ID_OUT) override { return (sOut ? sOut->getOutputStream(typ) : NULL); }
size_f_t getSize() const override {
return s->getSize();
}
bool setPos(size_f_t wpos) override {
return s->setPos(wpos);
}
size_f_t getPos() const override {
return s->getPos();
}
size_t read(void* wbuf, size_t len) override {
return sIn->read(wbuf, len);
}
size_t write(const void* buf, size_t len) override {
return sOut->write(buf, len);
}
size_t flush() override {
return sOut->flush();
}
operator InputStream* () const { return sIn; }
operator OutputStream* () const { return sOut; }
protected:
Stream* const s;
InputStream* const sIn;
OutputStream* const sOut;
};
/*----------------------------------------------------------------*/
} // namespace SEACAVE
#endif // __SEACAVE_STREAMS_H__