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
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__
|
|
|