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
This commit is contained in:
Yotam Barnoy 2010-08-24 11:18:48 +00:00
parent cb93679ea2
commit efdbb076a2
2 changed files with 94 additions and 4 deletions

View file

@ -230,13 +230,21 @@ BufferedReadStream::BufferedReadStream(ReadStream *parentStream, uint32 bufSize,
_realBufSize(bufSize) { _realBufSize(bufSize) {
assert(parentStream); assert(parentStream);
_buf = new byte[bufSize]; allocBuf(bufSize);
assert(_buf); assert(_buf);
} }
void BufferedReadStream::allocBuf(uint32 bufSize) {
_buf = new byte[bufSize];
}
BufferedReadStream::~BufferedReadStream() { BufferedReadStream::~BufferedReadStream() {
if (_disposeParentStream) if (_disposeParentStream)
delete _parentStream; delete _parentStream;
deallocBuf();
}
void BufferedReadStream::deallocBuf() {
delete[] _buf; 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 // At this point the buffer is empty. Now if the read request
// exceeds the buffer size, just satisfy it directly. // exceeds the buffer size, just satisfy it directly.
if (dataSize > _bufSize) if (dataSize > _realBufSize)
return alreadyRead + _parentStream->read(dataPtr, dataSize); return alreadyRead + _parentStream->read(dataPtr, dataSize);
// Refill the buffer. // Refill the buffer.
@ -303,6 +311,67 @@ bool BufferedSeekableReadStream::seek(int32 offset, int whence) {
return true; // FIXME: STREAM REWRITE 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) { bool MemoryWriteStreamDynamic::seek(int32 offs, int whence) {
// Pre-Condition // Pre-Condition
assert(_pos <= _size); assert(_pos <= _size);

View file

@ -149,7 +149,6 @@ public:
void writeString(const String &str); void writeString(const String &str);
}; };
/** /**
* Generic interface for a readable data stream. * Generic interface for a readable data stream.
*/ */
@ -497,10 +496,12 @@ protected:
uint32 _pos; uint32 _pos;
uint32 _bufSize; uint32 _bufSize;
uint32 _realBufSize; uint32 _realBufSize;
virtual void allocBuf(uint32 bufSize); // virtual functions to allocate/deallocate the buffer
virtual void deallocBuf();
public: public:
BufferedReadStream(ReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO); BufferedReadStream(ReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO);
~BufferedReadStream(); virtual ~BufferedReadStream();
virtual bool eos() const { return (_pos == _bufSize) && _parentStream->eos(); } virtual bool eos() const { return (_pos == _bufSize) && _parentStream->eos(); }
virtual bool err() const { return _parentStream->err(); } virtual bool err() const { return _parentStream->err(); }
@ -525,7 +526,27 @@ public:
virtual bool seek(int32 offset, int whence = SEEK_SET); 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 * Simple memory based 'stream', which implements the ReadStream interface for