aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorYotam Barnoy2010-08-24 11:18:48 +0000
committerYotam Barnoy2010-08-24 11:18:48 +0000
commitefdbb076a2c33623a06f4cb02a333655c96de3f8 (patch)
tree4ba63bd6bdacc2ee382801e6592563e0e75b205b /common
parentcb93679ea24c8304da7ebc8870ea2421a94f044e (diff)
downloadscummvm-rg350-efdbb076a2c33623a06f4cb02a333655c96de3f8.tar.gz
scummvm-rg350-efdbb076a2c33623a06f4cb02a333655c96de3f8.tar.bz2
scummvm-rg350-efdbb076a2c33623a06f4cb02a333655c96de3f8.zip
COMMON: implemented BufferedWriteStream and fixed bug in BufferedReadStream
I need the write buffering for the new version of the PSP streams and thought the simplest way to implement it would be along the lines of BufferedReadStream. Sadly, I found a nasty little bug in BRS but that's taken care of. Also, I adapted these streams for target-specific memory allocation by using virtual functions for allocation/deallocation. svn-id: r52325
Diffstat (limited to 'common')
-rw-r--r--common/stream.cpp73
-rw-r--r--common/stream.h25
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