diff options
-rw-r--r-- | common/stream.cpp | 73 | ||||
-rw-r--r-- | common/stream.h | 25 |
2 files changed, 94 insertions, 4 deletions
diff --git a/common/stream.cpp b/common/stream.cpp index 84b712a562..e4b6aab818 100644 --- a/common/stream.cpp +++ b/common/stream.cpp @@ -230,13 +230,21 @@ BufferedReadStream::BufferedReadStream(ReadStream *parentStream, uint32 bufSize, _realBufSize(bufSize) { assert(parentStream); - _buf = new byte[bufSize]; + allocBuf(bufSize); assert(_buf); } +void BufferedReadStream::allocBuf(uint32 bufSize) { + _buf = new byte[bufSize]; +} + BufferedReadStream::~BufferedReadStream() { if (_disposeParentStream) delete _parentStream; + deallocBuf(); +} + +void BufferedReadStream::deallocBuf() { delete[] _buf; } @@ -259,7 +267,7 @@ uint32 BufferedReadStream::read(void *dataPtr, uint32 dataSize) { // At this point the buffer is empty. Now if the read request // exceeds the buffer size, just satisfy it directly. - if (dataSize > _bufSize) + if (dataSize > _realBufSize) return alreadyRead + _parentStream->read(dataPtr, dataSize); // Refill the buffer. @@ -303,6 +311,67 @@ bool BufferedSeekableReadStream::seek(int32 offset, int whence) { return true; // FIXME: STREAM REWRITE } +BufferedWriteStream::BufferedWriteStream(WriteStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream) + : _parentStream(parentStream), + _disposeParentStream(disposeParentStream), + _pos(0), + _bufSize(bufSize) { + + assert(parentStream); + allocBuf(bufSize); + assert(_buf); +} + +BufferedWriteStream::~BufferedWriteStream() { + assert(flush()); + + if (_disposeParentStream) + delete _parentStream; + + deallocBuf(); +} + +void BufferedWriteStream::allocBuf(uint32 bufSize) { + _buf = new byte[bufSize]; +} + +void BufferedWriteStream::deallocBuf() { + delete[] _buf; +} + +uint32 BufferedWriteStream::write(const void *dataPtr, uint32 dataSize) { + // check if we have enough space for writing to the buffer + if (_bufSize - _pos >= dataSize) { + memcpy(_buf + _pos, dataPtr, dataSize); + _pos += dataSize; + } else if (_bufSize >= dataSize) { // check if we can flush the buffer and load the data + // flush the buffer + assert(flushBuffer()); + memcpy(_buf, dataPtr, dataSize); + _pos += dataSize; + } else { // too big for our buffer + // flush the buffer + assert(flushBuffer()); + return _parentStream->write(dataPtr, dataSize); + } + return dataSize; +} + +bool BufferedWriteStream::flushBuffer() { + uint32 bytesToWrite = _pos; + + if (bytesToWrite) { + _pos = 0; + if (_parentStream->write(_buf, bytesToWrite) != bytesToWrite) + return false; + } + return true; +} + +bool BufferedWriteStream::flush() { + return flushBuffer(); +} + bool MemoryWriteStreamDynamic::seek(int32 offs, int whence) { // Pre-Condition assert(_pos <= _size); diff --git a/common/stream.h b/common/stream.h index 5e0d7149b0..ce02f90ca9 100644 --- a/common/stream.h +++ b/common/stream.h @@ -149,7 +149,6 @@ public: void writeString(const String &str); }; - /** * Generic interface for a readable data stream. */ @@ -497,10 +496,12 @@ protected: uint32 _pos; uint32 _bufSize; uint32 _realBufSize; + virtual void allocBuf(uint32 bufSize); // virtual functions to allocate/deallocate the buffer + virtual void deallocBuf(); public: BufferedReadStream(ReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO); - ~BufferedReadStream(); + virtual ~BufferedReadStream(); virtual bool eos() const { return (_pos == _bufSize) && _parentStream->eos(); } virtual bool err() const { return _parentStream->err(); } @@ -525,7 +526,27 @@ public: virtual bool seek(int32 offset, int whence = SEEK_SET); }; +/** + * Wrapper class which adds buffering to any WriteStream. + */ +class BufferedWriteStream : public WriteStream { +protected: + WriteStream *_parentStream; + DisposeAfterUse::Flag _disposeParentStream; + byte *_buf; + uint32 _pos; + uint32 _bufSize; + bool flushBuffer(); // write out the data in the buffer + virtual void allocBuf(uint32 bufSize); // virtual functions to allocate/deallocate the buffer + virtual void deallocBuf(); +public: + BufferedWriteStream(WriteStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO); + virtual ~BufferedWriteStream(); + + virtual uint32 write(const void *dataPtr, uint32 dataSize); + virtual bool flush(); +}; /** * Simple memory based 'stream', which implements the ReadStream interface for |