aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorMax Horn2006-11-13 20:58:21 +0000
committerMax Horn2006-11-13 20:58:21 +0000
commitcce7cba3b4d9efd123192aebdbbdb8dad7531509 (patch)
treea6f8c06e752a338dcb01b839d44ddba395890c35 /common
parent86d988132c8e422d34fd5732e18277253865791b (diff)
downloadscummvm-rg350-cce7cba3b4d9efd123192aebdbbdb8dad7531509.tar.gz
scummvm-rg350-cce7cba3b4d9efd123192aebdbbdb8dad7531509.tar.bz2
scummvm-rg350-cce7cba3b4d9efd123192aebdbbdb8dad7531509.zip
Patch #1583931: (Seekable)SubReadStream
svn-id: r24713
Diffstat (limited to 'common')
-rw-r--r--common/stream.cpp40
-rw-r--r--common/stream.h41
2 files changed, 78 insertions, 3 deletions
diff --git a/common/stream.cpp b/common/stream.cpp
index 1e9c3134d1..94ca514ad1 100644
--- a/common/stream.cpp
+++ b/common/stream.cpp
@@ -105,7 +105,7 @@ char *SeekableReadStream::readLine(char *buf, size_t bufSize) {
c = readByte();
}
-
+
// This should fix a bug while using readLine with Common::File
// it seems that it sets the eos flag after an invalid read
// and at the same time the ioFailed flag
@@ -118,5 +118,43 @@ char *SeekableReadStream::readLine(char *buf, size_t bufSize) {
return buf;
}
+uint32 SubReadStream::read(void *dataPtr, uint32 dataSize) {
+ dataSize = MIN(dataSize, _end - _pos);
+
+ dataSize = _parentStream->read(dataPtr, dataSize);
+ _pos += dataSize;
+
+ return dataSize;
+}
+
+SeekableSubReadStream::SeekableSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end)
+ : SubReadStream(parentStream, end),
+ _parentStream(parentStream),
+ _begin(begin) {
+ assert(_begin <= _end);
+ _pos = _begin;
+ _parentStream->seek(_pos);
+}
+
+void SeekableSubReadStream::seek(int32 offset, int whence) {
+ assert(_pos >= _begin);
+ assert(_pos <= _end);
+
+ switch(whence) {
+ case SEEK_END:
+ offset = size() - offset;
+ // fallthrough
+ case SEEK_SET:
+ _pos = _begin + offset;
+ break;
+ case SEEK_CUR:
+ _pos += offset;
+ }
+
+ assert(_pos >= _begin);
+ assert(_pos <= _end);
+
+ _parentStream->seek(_pos);
+}
} // End of namespace Common
diff --git a/common/stream.h b/common/stream.h
index 16b129d9c4..84eac2ac44 100644
--- a/common/stream.h
+++ b/common/stream.h
@@ -210,14 +210,14 @@ public:
* @todo We really need better error handling here!
* Like seek should somehow indicate whether it failed.
*/
-class SeekableReadStream : public ReadStream {
+class SeekableReadStream : virtual public ReadStream {
public:
virtual uint32 pos() const = 0;
virtual uint32 size() const = 0;
virtual void seek(int32 offset, int whence = SEEK_SET) = 0;
-
+
void skip(uint32 offset) { seek(offset, SEEK_CUR); }
/**
@@ -233,6 +233,43 @@ public:
virtual char *readLine(char *buf, size_t bufSize);
};
+/**
+ * SubReadStream provides access to a ReadStream restricted to the range
+ * [currentPosition, currentPosition+end).
+ * Manipulating the parent stream directly /will/ mess up a substream.
+ * Likewise, manipulating two substreams of a parent stream will cause them to
+ * step on each others toes.
+ */
+class SubReadStream : virtual public ReadStream {
+protected:
+ ReadStream *_parentStream;
+ uint32 _pos;
+ uint32 _end;
+public:
+ SubReadStream(ReadStream *parentStream, uint32 end)
+ : _parentStream(parentStream), _pos(0), _end(end) {}
+
+ virtual bool eos() const { return _pos == _end; }
+ virtual uint32 read(void *dataPtr, uint32 dataSize);
+};
+
+/*
+ * SeekableSubReadStream provides access to a SeekableReadStream restricted to
+ * the range [begin, end).
+ * The same caveats apply to SeekableSubReadStream as do to SeekableReadStream.
+ */
+class SeekableSubReadStream : public SubReadStream, public SeekableReadStream {
+protected:
+ SeekableReadStream *_parentStream;
+ uint32 _begin;
+public:
+ SeekableSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end);
+
+ virtual uint32 pos() const { return _pos - _begin; }
+ virtual uint32 size() const { return _end - _begin; }
+
+ virtual void seek(int32 offset, int whence = SEEK_SET);
+};
/**
* XORReadStream is a wrapper around an arbitrary other ReadStream,