aboutsummaryrefslogtreecommitdiff
path: root/common/stream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/stream.cpp')
-rw-r--r--common/stream.cpp235
1 files changed, 165 insertions, 70 deletions
diff --git a/common/stream.cpp b/common/stream.cpp
index 9f8f6127f1..c0783b2352 100644
--- a/common/stream.cpp
+++ b/common/stream.cpp
@@ -24,6 +24,9 @@
*/
#include "common/stream.h"
+#include "common/memstream.h"
+#include "common/substream.h"
+#include "common/bufferedstream.h"
#include "common/str.h"
#include "common/util.h"
@@ -33,7 +36,7 @@ void WriteStream::writeString(const String &str) {
write(str.c_str(), str.size());
}
-MemoryReadStream *ReadStream::readStream(uint32 dataSize) {
+SeekableReadStream *ReadStream::readStream(uint32 dataSize) {
void *buf = malloc(dataSize);
dataSize = read(buf, dataSize);
assert(dataSize > 0);
@@ -49,13 +52,6 @@ uint32 MemoryReadStream::read(void *dataPtr, uint32 dataSize) {
}
memcpy(dataPtr, _ptr, dataSize);
- if (_encbyte) {
- byte *p = (byte *)dataPtr;
- byte *end = p + dataSize;
- while (p < end)
- *p++ ^= _encbyte;
- }
-
_ptr += dataSize;
_pos += dataSize;
@@ -89,6 +85,33 @@ bool MemoryReadStream::seek(int32 offs, int whence) {
return true; // FIXME: STREAM REWRITE
}
+bool MemoryWriteStreamDynamic::seek(int32 offs, int whence) {
+ // Pre-Condition
+ assert(_pos <= _size);
+ switch (whence) {
+ case SEEK_END:
+ // SEEK_END works just like SEEK_SET, only 'reversed',
+ // i.e. from the end.
+ offs = _size + offs;
+ // Fall through
+ case SEEK_SET:
+ _ptr = _data + offs;
+ _pos = offs;
+ break;
+
+ case SEEK_CUR:
+ _ptr += offs;
+ _pos += offs;
+ break;
+ }
+ // Post-Condition
+ assert(_pos <= _size);
+
+ return true; // FIXME: STREAM REWRITE
+}
+
+#pragma mark -
+
enum {
LF = 0x0A,
CR = 0x0D
@@ -222,6 +245,37 @@ bool SeekableSubReadStream::seek(int32 offset, int whence) {
return ret;
}
+
+#pragma mark -
+
+namespace {
+
+/**
+ * Wrapper class which adds buffering to any given ReadStream.
+ * Users can specify how big the buffer should be, and whether the
+ * wrapped stream should be disposed when the wrapper is disposed.
+ */
+class BufferedReadStream : virtual public ReadStream {
+protected:
+ ReadStream *_parentStream;
+ DisposeAfterUse::Flag _disposeParentStream;
+ byte *_buf;
+ uint32 _pos;
+ bool _eos; // end of stream
+ uint32 _bufSize;
+ uint32 _realBufSize;
+
+public:
+ BufferedReadStream(ReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream);
+ virtual ~BufferedReadStream();
+
+ virtual bool eos() const { return _eos; }
+ virtual bool err() const { return _parentStream->err(); }
+ virtual void clearErr() { _eos = false; _parentStream->clearErr(); }
+
+ virtual uint32 read(void *dataPtr, uint32 dataSize);
+};
+
BufferedReadStream::BufferedReadStream(ReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream)
: _parentStream(parentStream),
_disposeParentStream(disposeParentStream),
@@ -290,6 +344,35 @@ uint32 BufferedReadStream::read(void *dataPtr, uint32 dataSize) {
return alreadyRead + dataSize;
}
+} // End of nameless namespace
+
+
+ReadStream *wrapBufferedReadStream(ReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream) {
+ if (parentStream)
+ return new BufferedReadStream(parentStream, bufSize, disposeParentStream);
+ return 0;
+}
+
+#pragma mark -
+
+namespace {
+
+/**
+ * Wrapper class which adds buffering to any given SeekableReadStream.
+ * @see BufferedReadStream
+ */
+class BufferedSeekableReadStream : public BufferedReadStream, public SeekableReadStream {
+protected:
+ SeekableReadStream *_parentStream;
+public:
+ BufferedSeekableReadStream(SeekableReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO);
+
+ virtual int32 pos() const { return _parentStream->pos() - (_bufSize - _pos); }
+ virtual int32 size() const { return _parentStream->size(); }
+
+ virtual bool seek(int32 offset, int whence = SEEK_SET);
+};
+
BufferedSeekableReadStream::BufferedSeekableReadStream(SeekableReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream)
: BufferedReadStream(parentStream, bufSize, disposeParentStream),
_parentStream(parentStream) {
@@ -319,82 +402,94 @@ bool BufferedSeekableReadStream::seek(int32 offset, int whence) {
return true;
}
-BufferedWriteStream::BufferedWriteStream(WriteStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream)
- : _parentStream(parentStream),
- _disposeParentStream(disposeParentStream),
- _pos(0),
- _bufSize(bufSize) {
+} // End of nameless namespace
- assert(parentStream);
- _buf = new byte[bufSize];
- assert(_buf);
+SeekableReadStream *wrapBufferedSeekableReadStream(SeekableReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream) {
+ if (parentStream)
+ return new BufferedSeekableReadStream(parentStream, bufSize, disposeParentStream);
+ return 0;
}
-BufferedWriteStream::~BufferedWriteStream() {
- assert(flush());
-
- if (_disposeParentStream)
- delete _parentStream;
+#pragma mark -
- delete[] _buf;
-}
+namespace {
-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);
+/**
+ * Wrapper class which adds buffering to any WriteStream.
+ */
+class BufferedWriteStream : public WriteStream {
+protected:
+ WriteStream *_parentStream;
+ byte *_buf;
+ uint32 _pos;
+ const uint32 _bufSize;
+
+ /**
+ * Write out the data in the buffer.
+ *
+ * @note This method is identical to flush() (which actually is
+ * implemented by calling this method), except that it is not
+ * virtual, hence there is less overhead calling it.
+ */
+ bool flushBuffer() {
+ const uint32 bytesToWrite = _pos;
+
+ if (bytesToWrite) {
+ _pos = 0;
+ if (_parentStream->write(_buf, bytesToWrite) != bytesToWrite)
+ return false;
+ }
+ return true;
}
- return dataSize;
-}
-bool BufferedWriteStream::flushBuffer() {
- uint32 bytesToWrite = _pos;
+public:
+ BufferedWriteStream(WriteStream *parentStream, uint32 bufSize)
+ : _parentStream(parentStream),
+ _pos(0),
+ _bufSize(bufSize) {
- if (bytesToWrite) {
- _pos = 0;
- if (_parentStream->write(_buf, bytesToWrite) != bytesToWrite)
- return false;
+ assert(parentStream);
+ _buf = new byte[bufSize];
+ assert(_buf);
}
- return true;
-}
-bool BufferedWriteStream::flush() {
- return flushBuffer();
-}
+ virtual ~BufferedWriteStream() {
+ const bool flushResult = flushBuffer();
+ assert(flushResult);
-bool MemoryWriteStreamDynamic::seek(int32 offs, int whence) {
- // Pre-Condition
- assert(_pos <= _size);
- switch (whence) {
- case SEEK_END:
- // SEEK_END works just like SEEK_SET, only 'reversed',
- // i.e. from the end.
- offs = _size + offs;
- // Fall through
- case SEEK_SET:
- _ptr = _data + offs;
- _pos = offs;
- break;
+ delete _parentStream;
- case SEEK_CUR:
- _ptr += offs;
- _pos += offs;
- break;
+ delete[] _buf;
}
- // Post-Condition
- assert(_pos <= _size);
- return true; // FIXME: STREAM REWRITE
+ virtual uint32 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
+ const bool flushResult = flushBuffer();
+ assert(flushResult);
+ memcpy(_buf, dataPtr, dataSize);
+ _pos += dataSize;
+ } else { // too big for our buffer
+ const bool flushResult = flushBuffer();
+ assert(flushResult);
+ return _parentStream->write(dataPtr, dataSize);
+ }
+ return dataSize;
+ }
+
+ virtual bool flush() { return flushBuffer(); }
+
+};
+
+} // End of nameless namespace
+
+WriteStream *wrapBufferedWriteStream(WriteStream *parentStream, uint32 bufSize) {
+ if (parentStream)
+ return new BufferedWriteStream(parentStream, bufSize);
+ return 0;
}
} // End of namespace Common