aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/bufferedstream.h68
-rw-r--r--common/iff_container.cpp81
-rw-r--r--common/iff_container.h62
-rw-r--r--common/macresman.cpp2
-rw-r--r--common/memstream.h199
-rw-r--r--common/module.mk1
-rw-r--r--common/stream.cpp5
-rw-r--r--common/stream.h295
-rw-r--r--common/substream.h129
-rw-r--r--common/unarj.cpp2
-rw-r--r--common/unzip.cpp1
-rw-r--r--common/xmlparser.cpp2
12 files changed, 494 insertions, 353 deletions
diff --git a/common/bufferedstream.h b/common/bufferedstream.h
new file mode 100644
index 0000000000..dc074422bb
--- /dev/null
+++ b/common/bufferedstream.h
@@ -0,0 +1,68 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef COMMON_BUFFEREDSTREAM_H
+#define COMMON_BUFFEREDSTREAM_H
+
+#include "common/stream.h"
+
+namespace Common {
+
+/**
+ * Take an arbitrary ReadStream and wrap it in a custom stream which
+ * transparently provides buffering.
+ * Users can specify how big the buffer should be, and whether the wrapped
+ * stream should be disposed when the wrapper is disposed.
+ *
+ * It is safe to call this with a NULL parameter (in this case, NULL is
+ * returned).
+ */
+ReadStream *wrapBufferedReadStream(ReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream);
+
+/**
+ * Take an arbitrary SeekableReadStream and wrap it in a custom stream which
+ * transparently provides buffering.
+ * Users can specify how big the buffer should be, and whether the wrapped
+ * stream should be disposed when the wrapper is disposed.
+ *
+ * It is safe to call this with a NULL parameter (in this case, NULL is
+ * returned).
+ */
+SeekableReadStream *wrapBufferedSeekableReadStream(SeekableReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream);
+
+/**
+ * Take an arbitrary WriteStream and wrap it in a custom stream which
+ * transparently provides buffering.
+ * Users can specify how big the buffer should be. Currently, the
+ * parent stream is \em always disposed when the wrapper is disposed.
+ *
+ * It is safe to call this with a NULL parameter (in this case, NULL is
+ * returned).
+ */
+WriteStream *wrapBufferedWriteStream(WriteStream *parentStream, uint32 bufSize);
+
+} // End of namespace Common
+
+#endif
diff --git a/common/iff_container.cpp b/common/iff_container.cpp
new file mode 100644
index 0000000000..c447d93f12
--- /dev/null
+++ b/common/iff_container.cpp
@@ -0,0 +1,81 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/iff_container.h"
+#include "common/substream.h"
+
+namespace Common {
+
+IFFParser::IFFParser(Common::ReadStream *stream, bool disposeStream) : _stream(stream), _disposeStream(disposeStream) {
+ setInputStream(stream);
+}
+
+IFFParser::~IFFParser() {
+ if (_disposeStream) {
+ delete _stream;
+ }
+ _stream = 0;
+}
+
+void IFFParser::setInputStream(Common::ReadStream *stream) {
+ assert(stream);
+ _formChunk.setInputStream(stream);
+ _chunk.setInputStream(stream);
+
+ _formChunk.readHeader();
+ if (_formChunk.id != ID_FORM) {
+ error("IFFParser input is not a FORM type IFF file");
+ }
+ _formSize = _formChunk.size;
+ _formType = _formChunk.readUint32BE();
+}
+
+void IFFParser::parse(IFFCallback &callback) {
+ bool stop;
+ do {
+ _chunk.feed();
+ _formChunk.incBytesRead(_chunk.size);
+
+ if (_formChunk.hasReadAll()) {
+ break;
+ }
+
+ _formChunk.incBytesRead(8);
+ _chunk.readHeader();
+
+ // invoke the callback
+ Common::SubReadStream stream(&_chunk, _chunk.size);
+ IFFChunk chunk(_chunk.id, _chunk.size, &stream);
+ stop = callback(chunk);
+
+ // eats up all the remaining data in the chunk
+ while (!stream.eos()) {
+ stream.readByte();
+ }
+
+ } while (!stop);
+}
+
+} // End of namespace Common
diff --git a/common/iff_container.h b/common/iff_container.h
index 6ff28574e5..16d4826238 100644
--- a/common/iff_container.h
+++ b/common/iff_container.h
@@ -223,41 +223,11 @@ protected:
Common::ReadStream *_stream;
bool _disposeStream;
- void setInputStream(Common::ReadStream *stream) {
- assert(stream);
- _formChunk.setInputStream(stream);
- _chunk.setInputStream(stream);
-
- _formChunk.readHeader();
- if (_formChunk.id != ID_FORM) {
- error("IFFParser input is not a FORM type IFF file");
- }
- _formSize = _formChunk.size;
- _formType = _formChunk.readUint32BE();
- }
+ void setInputStream(Common::ReadStream *stream);
public:
- IFFParser(Common::ReadStream *stream, bool disposeStream = false) : _stream(stream), _disposeStream(disposeStream) {
- setInputStream(stream);
- }
- ~IFFParser() {
- if (_disposeStream) {
- delete _stream;
- }
- _stream = 0;
- }
-
- /**
- * Returns the IFF FORM type.
- * @return the IFF FORM type of the stream, or 0 if FORM header is not found.
- */
- Common::IFF_ID getFORMType() const;
-
- /**
- * Returns the size of the data.
- * @return the size of the data in file, or -1 if FORM header is not found.
- */
- uint32 getFORMSize() const;
+ IFFParser(Common::ReadStream *stream, bool disposeStream = false);
+ ~IFFParser();
/**
* Callback type for the parser.
@@ -268,31 +238,7 @@ public:
* Parse the IFF container, invoking the callback on each chunk encountered.
* The callback can interrupt the parsing by returning 'true'.
*/
- void parse(IFFCallback &callback) {
- bool stop;
- do {
- _chunk.feed();
- _formChunk.incBytesRead(_chunk.size);
-
- if (_formChunk.hasReadAll()) {
- break;
- }
-
- _formChunk.incBytesRead(8);
- _chunk.readHeader();
-
- // invoke the callback
- Common::SubReadStream stream(&_chunk, _chunk.size);
- IFFChunk chunk(_chunk.id, _chunk.size, &stream);
- stop = callback(chunk);
-
- // eats up all the remaining data in the chunk
- while (!stream.eos()) {
- stream.readByte();
- }
-
- } while (!stop);
- }
+ void parse(IFFCallback &callback);
};
diff --git a/common/macresman.cpp b/common/macresman.cpp
index 22216763b8..f9a49cfe04 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -30,6 +30,8 @@
#include "common/fs.h"
#include "common/macresman.h"
#include "common/md5.h"
+#include "common/substream.h"
+#include "common/memstream.h"
#ifdef MACOSX
#include "common/config-manager.h"
diff --git a/common/memstream.h b/common/memstream.h
new file mode 100644
index 0000000000..0cb88b6126
--- /dev/null
+++ b/common/memstream.h
@@ -0,0 +1,199 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef COMMON_MEMSTREAM_H
+#define COMMON_MEMSTREAM_H
+
+#include "common/stream.h"
+
+namespace Common {
+
+/**
+ * Simple memory based 'stream', which implements the ReadStream interface for
+ * a plain memory block.
+ */
+class MemoryReadStream : public SeekableReadStream {
+private:
+ const byte * const _ptrOrig;
+ const byte *_ptr;
+ const uint32 _size;
+ uint32 _pos;
+ byte _encbyte;
+ DisposeAfterUse::Flag _disposeMemory;
+ bool _eos;
+
+public:
+
+ /**
+ * This constructor takes a pointer to a memory buffer and a length, and
+ * wraps it. If disposeMemory is true, the MemoryReadStream takes ownership
+ * of the buffer and hence free's it when destructed.
+ */
+ MemoryReadStream(const byte *dataPtr, uint32 dataSize, DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) :
+ _ptrOrig(dataPtr),
+ _ptr(dataPtr),
+ _size(dataSize),
+ _pos(0),
+ _encbyte(0),
+ _disposeMemory(disposeMemory),
+ _eos(false) {}
+
+ ~MemoryReadStream() {
+ if (_disposeMemory)
+ free(const_cast<byte *>(_ptrOrig));
+ }
+
+ void setEnc(byte value) { _encbyte = value; }
+
+ uint32 read(void *dataPtr, uint32 dataSize);
+
+ bool eos() const { return _eos; }
+ void clearErr() { _eos = false; }
+
+ int32 pos() const { return _pos; }
+ int32 size() const { return _size; }
+
+ bool seek(int32 offs, int whence = SEEK_SET);
+};
+
+
+/**
+ * This is a wrapper around MemoryReadStream, but it adds non-endian
+ * read methods whose endianness is set on the stream creation.
+ */
+class MemoryReadStreamEndian : public MemoryReadStream {
+private:
+ const bool _bigEndian;
+
+public:
+ MemoryReadStreamEndian(const byte *buf, uint32 len, bool bigEndian = false) : MemoryReadStream(buf, len), _bigEndian(bigEndian) {}
+
+ uint16 readUint16() {
+ uint16 val;
+ read(&val, 2);
+ return (_bigEndian) ? TO_BE_16(val) : TO_LE_16(val);
+ }
+
+ uint32 readUint32() {
+ uint32 val;
+ read(&val, 4);
+ return (_bigEndian) ? TO_BE_32(val) : TO_LE_32(val);
+ }
+
+ FORCEINLINE int16 readSint16() {
+ return (int16)readUint16();
+ }
+
+ FORCEINLINE int32 readSint32() {
+ return (int32)readUint32();
+ }
+};
+
+/**
+ * Simple memory based 'stream', which implements the WriteStream interface for
+ * a plain memory block.
+ */
+class MemoryWriteStream : public WriteStream {
+private:
+ byte *_ptr;
+ const uint32 _bufSize;
+ uint32 _pos;
+public:
+ MemoryWriteStream(byte *buf, uint32 len) : _ptr(buf), _bufSize(len), _pos(0) {}
+
+ uint32 write(const void *dataPtr, uint32 dataSize) {
+ // Write at most as many bytes as are still available...
+ if (dataSize > _bufSize - _pos)
+ dataSize = _bufSize - _pos;
+ memcpy(_ptr, dataPtr, dataSize);
+ _ptr += dataSize;
+ _pos += dataSize;
+ return dataSize;
+ }
+
+ uint32 pos() const { return _pos; }
+ uint32 size() const { return _bufSize; }
+};
+
+/**
+ * A sort of hybrid between MemoryWriteStream and Array classes. A stream
+ * that grows as it's written to.
+ */
+class MemoryWriteStreamDynamic : public WriteStream {
+private:
+ uint32 _capacity;
+ uint32 _size;
+ byte *_ptr;
+ byte *_data;
+ uint32 _pos;
+ DisposeAfterUse::Flag _disposeMemory;
+
+ void ensureCapacity(uint32 new_len) {
+ if (new_len <= _capacity)
+ return;
+
+ byte *old_data = _data;
+
+ _capacity = new_len + 32;
+ _data = (byte *)malloc(_capacity);
+ _ptr = _data + _pos;
+
+ if (old_data) {
+ // Copy old data
+ memcpy(_data, old_data, _size);
+ free(old_data);
+ }
+
+ _size = new_len;
+ }
+public:
+ MemoryWriteStreamDynamic(DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) : _capacity(0), _size(0), _ptr(0), _data(0), _pos(0), _disposeMemory(disposeMemory) {}
+
+ ~MemoryWriteStreamDynamic() {
+ if (_disposeMemory)
+ free(_data);
+ }
+
+ uint32 write(const void *dataPtr, uint32 dataSize) {
+ ensureCapacity(_pos + dataSize);
+ memcpy(_ptr, dataPtr, dataSize);
+ _ptr += dataSize;
+ _pos += dataSize;
+ if (_pos > _size)
+ _size = _pos;
+ return dataSize;
+ }
+
+ uint32 pos() const { return _pos; }
+ uint32 size() const { return _size; }
+
+ byte *getData() { return _data; }
+
+ bool seek(int32 offset, int whence = SEEK_SET);
+};
+
+} // End of namespace Common
+
+#endif
diff --git a/common/module.mk b/common/module.mk
index 239f8e9ccf..1bff1b6c29 100644
--- a/common/module.mk
+++ b/common/module.mk
@@ -11,6 +11,7 @@ MODULE_OBJS := \
file.o \
fs.o \
hashmap.o \
+ iff_container.o \
macresman.o \
memorypool.o \
md5.o \
diff --git a/common/stream.cpp b/common/stream.cpp
index 2abd6fc986..89653592f4 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);
diff --git a/common/stream.h b/common/stream.h
index 9674375dd2..1dceb31f16 100644
--- a/common/stream.h
+++ b/common/stream.h
@@ -32,7 +32,7 @@
namespace Common {
class String;
-class MemoryReadStream;
+class SeekableReadStream;
/**
* Virtual base class for both ReadStream and WriteStream.
@@ -301,7 +301,7 @@ public:
* the end of the stream was reached. Which can be determined by
* calling err() and eos().
*/
- MemoryReadStream *readStream(uint32 dataSize);
+ SeekableReadStream *readStream(uint32 dataSize);
};
@@ -389,297 +389,6 @@ public:
virtual String readLine();
};
-
-/**
- * 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;
- DisposeAfterUse::Flag _disposeParentStream;
- uint32 _pos;
- uint32 _end;
- bool _eos;
-public:
- SubReadStream(ReadStream *parentStream, uint32 end, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO)
- : _parentStream(parentStream),
- _disposeParentStream(disposeParentStream),
- _pos(0),
- _end(end),
- _eos(false) {
- assert(parentStream);
- }
- ~SubReadStream() {
- if (_disposeParentStream)
- delete _parentStream;
- }
-
- 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);
-};
-
-/*
- * SeekableSubReadStream provides access to a SeekableReadStream restricted to
- * the range [begin, end).
- * The same caveats apply to SeekableSubReadStream as do to SeekableReadStream.
- *
- * Manipulating the parent stream directly /will/ mess up a substream.
- * @see SubReadStream
- */
-class SeekableSubReadStream : public SubReadStream, public SeekableReadStream {
-protected:
- SeekableReadStream *_parentStream;
- uint32 _begin;
-public:
- SeekableSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO);
-
- virtual int32 pos() const { return _pos - _begin; }
- virtual int32 size() const { return _end - _begin; }
-
- virtual bool seek(int32 offset, int whence = SEEK_SET);
-};
-
-/**
- * This is a wrapper around SeekableSubReadStream, but it adds non-endian
- * read methods whose endianness is set on the stream creation.
- *
- * Manipulating the parent stream directly /will/ mess up a substream.
- * @see SubReadStream
- */
-class SeekableSubReadStreamEndian : public SeekableSubReadStream {
-private:
- const bool _bigEndian;
-
-public:
- SeekableSubReadStreamEndian(SeekableReadStream *parentStream, uint32 begin, uint32 end, bool bigEndian = false, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO)
- : SeekableSubReadStream(parentStream, begin, end, disposeParentStream), _bigEndian(bigEndian) {
- }
-
- uint16 readUint16() {
- uint16 val;
- read(&val, 2);
- return (_bigEndian) ? TO_BE_16(val) : TO_LE_16(val);
- }
-
- uint32 readUint32() {
- uint32 val;
- read(&val, 4);
- return (_bigEndian) ? TO_BE_32(val) : TO_LE_32(val);
- }
-
- FORCEINLINE int16 readSint16() {
- return (int16)readUint16();
- }
-
- FORCEINLINE int32 readSint32() {
- return (int32)readUint32();
- }
-};
-
-/**
- * Take an arbitrary ReadStream and wrap it in a custom stream which
- * transparently provides buffering.
- * Users can specify how big the buffer should be, and whether the wrapped
- * stream should be disposed when the wrapper is disposed.
- *
- * It is safe to call this with a NULL parameter (in this case, NULL is
- * returned).
- */
-ReadStream *wrapBufferedReadStream(ReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream);
-
-/**
- * Take an arbitrary SeekableReadStream and wrap it in a custom stream which
- * transparently provides buffering.
- * Users can specify how big the buffer should be, and whether the wrapped
- * stream should be disposed when the wrapper is disposed.
- *
- * It is safe to call this with a NULL parameter (in this case, NULL is
- * returned).
- */
-SeekableReadStream *wrapBufferedSeekableReadStream(SeekableReadStream *parentStream, uint32 bufSize, DisposeAfterUse::Flag disposeParentStream);
-
-/**
- * Take an arbitrary WriteStream and wrap it in a custom stream which
- * transparently provides buffering.
- * Users can specify how big the buffer should be. Currently, the
- * parent stream is \em always disposed when the wrapper is disposed.
- *
- * It is safe to call this with a NULL parameter (in this case, NULL is
- * returned).
- */
-WriteStream *wrapBufferedWriteStream(WriteStream *parentStream, uint32 bufSize);
-
-/**
- * Simple memory based 'stream', which implements the ReadStream interface for
- * a plain memory block.
- */
-class MemoryReadStream : public SeekableReadStream {
-private:
- const byte * const _ptrOrig;
- const byte *_ptr;
- const uint32 _size;
- uint32 _pos;
- byte _encbyte;
- DisposeAfterUse::Flag _disposeMemory;
- bool _eos;
-
-public:
-
- /**
- * This constructor takes a pointer to a memory buffer and a length, and
- * wraps it. If disposeMemory is true, the MemoryReadStream takes ownership
- * of the buffer and hence free's it when destructed.
- */
- MemoryReadStream(const byte *dataPtr, uint32 dataSize, DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) :
- _ptrOrig(dataPtr),
- _ptr(dataPtr),
- _size(dataSize),
- _pos(0),
- _encbyte(0),
- _disposeMemory(disposeMemory),
- _eos(false) {}
-
- ~MemoryReadStream() {
- if (_disposeMemory)
- free(const_cast<byte *>(_ptrOrig));
- }
-
- void setEnc(byte value) { _encbyte = value; }
-
- uint32 read(void *dataPtr, uint32 dataSize);
-
- bool eos() const { return _eos; }
- void clearErr() { _eos = false; }
-
- int32 pos() const { return _pos; }
- int32 size() const { return _size; }
-
- bool seek(int32 offs, int whence = SEEK_SET);
-};
-
-
-/**
- * This is a wrapper around MemoryReadStream, but it adds non-endian
- * read methods whose endianness is set on the stream creation.
- */
-class MemoryReadStreamEndian : public MemoryReadStream {
-private:
- const bool _bigEndian;
-
-public:
- MemoryReadStreamEndian(const byte *buf, uint32 len, bool bigEndian = false) : MemoryReadStream(buf, len), _bigEndian(bigEndian) {}
-
- uint16 readUint16() {
- uint16 val;
- read(&val, 2);
- return (_bigEndian) ? TO_BE_16(val) : TO_LE_16(val);
- }
-
- uint32 readUint32() {
- uint32 val;
- read(&val, 4);
- return (_bigEndian) ? TO_BE_32(val) : TO_LE_32(val);
- }
-
- FORCEINLINE int16 readSint16() {
- return (int16)readUint16();
- }
-
- FORCEINLINE int32 readSint32() {
- return (int32)readUint32();
- }
-};
-
-/**
- * Simple memory based 'stream', which implements the WriteStream interface for
- * a plain memory block.
- */
-class MemoryWriteStream : public WriteStream {
-private:
- byte *_ptr;
- const uint32 _bufSize;
- uint32 _pos;
-public:
- MemoryWriteStream(byte *buf, uint32 len) : _ptr(buf), _bufSize(len), _pos(0) {}
-
- uint32 write(const void *dataPtr, uint32 dataSize) {
- // Write at most as many bytes as are still available...
- if (dataSize > _bufSize - _pos)
- dataSize = _bufSize - _pos;
- memcpy(_ptr, dataPtr, dataSize);
- _ptr += dataSize;
- _pos += dataSize;
- return dataSize;
- }
-
- uint32 pos() const { return _pos; }
- uint32 size() const { return _bufSize; }
-};
-
-/**
- * A sort of hybrid between MemoryWriteStream and Array classes. A stream
- * that grows as it's written to.
- */
-class MemoryWriteStreamDynamic : public WriteStream {
-private:
- uint32 _capacity;
- uint32 _size;
- byte *_ptr;
- byte *_data;
- uint32 _pos;
- DisposeAfterUse::Flag _disposeMemory;
-
- void ensureCapacity(uint32 new_len) {
- if (new_len <= _capacity)
- return;
-
- byte *old_data = _data;
-
- _capacity = new_len + 32;
- _data = (byte *)malloc(_capacity);
- _ptr = _data + _pos;
-
- if (old_data) {
- // Copy old data
- memcpy(_data, old_data, _size);
- free(old_data);
- }
-
- _size = new_len;
- }
-public:
- MemoryWriteStreamDynamic(DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) : _capacity(0), _size(0), _ptr(0), _data(0), _pos(0), _disposeMemory(disposeMemory) {}
-
- ~MemoryWriteStreamDynamic() {
- if (_disposeMemory)
- free(_data);
- }
-
- uint32 write(const void *dataPtr, uint32 dataSize) {
- ensureCapacity(_pos + dataSize);
- memcpy(_ptr, dataPtr, dataSize);
- _ptr += dataSize;
- _pos += dataSize;
- if (_pos > _size)
- _size = _pos;
- return dataSize;
- }
-
- uint32 pos() const { return _pos; }
- uint32 size() const { return _size; }
-
- byte *getData() { return _data; }
-
- bool seek(int32 offset, int whence = SEEK_SET);
-};
-
} // End of namespace Common
#endif
diff --git a/common/substream.h b/common/substream.h
new file mode 100644
index 0000000000..cf794cfa7e
--- /dev/null
+++ b/common/substream.h
@@ -0,0 +1,129 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef COMMON_SUBSTREAM_H
+#define COMMON_SUBSTREAM_H
+
+#include "common/stream.h"
+
+namespace Common {
+
+/**
+ * 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;
+ DisposeAfterUse::Flag _disposeParentStream;
+ uint32 _pos;
+ uint32 _end;
+ bool _eos;
+public:
+ SubReadStream(ReadStream *parentStream, uint32 end, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO)
+ : _parentStream(parentStream),
+ _disposeParentStream(disposeParentStream),
+ _pos(0),
+ _end(end),
+ _eos(false) {
+ assert(parentStream);
+ }
+ ~SubReadStream() {
+ if (_disposeParentStream)
+ delete _parentStream;
+ }
+
+ 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);
+};
+
+/*
+ * SeekableSubReadStream provides access to a SeekableReadStream restricted to
+ * the range [begin, end).
+ * The same caveats apply to SeekableSubReadStream as do to SeekableReadStream.
+ *
+ * Manipulating the parent stream directly /will/ mess up a substream.
+ * @see SubReadStream
+ */
+class SeekableSubReadStream : public SubReadStream, public SeekableReadStream {
+protected:
+ SeekableReadStream *_parentStream;
+ uint32 _begin;
+public:
+ SeekableSubReadStream(SeekableReadStream *parentStream, uint32 begin, uint32 end, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO);
+
+ virtual int32 pos() const { return _pos - _begin; }
+ virtual int32 size() const { return _end - _begin; }
+
+ virtual bool seek(int32 offset, int whence = SEEK_SET);
+};
+
+/**
+ * This is a wrapper around SeekableSubReadStream, but it adds non-endian
+ * read methods whose endianness is set on the stream creation.
+ *
+ * Manipulating the parent stream directly /will/ mess up a substream.
+ * @see SubReadStream
+ */
+class SeekableSubReadStreamEndian : public SeekableSubReadStream {
+private:
+ const bool _bigEndian;
+
+public:
+ SeekableSubReadStreamEndian(SeekableReadStream *parentStream, uint32 begin, uint32 end, bool bigEndian = false, DisposeAfterUse::Flag disposeParentStream = DisposeAfterUse::NO)
+ : SeekableSubReadStream(parentStream, begin, end, disposeParentStream), _bigEndian(bigEndian) {
+ }
+
+ uint16 readUint16() {
+ uint16 val;
+ read(&val, 2);
+ return (_bigEndian) ? TO_BE_16(val) : TO_LE_16(val);
+ }
+
+ uint32 readUint32() {
+ uint32 val;
+ read(&val, 4);
+ return (_bigEndian) ? TO_BE_32(val) : TO_LE_32(val);
+ }
+
+ FORCEINLINE int16 readSint16() {
+ return (int16)readUint16();
+ }
+
+ FORCEINLINE int32 readSint32() {
+ return (int32)readUint32();
+ }
+};
+
+
+} // End of namespace Common
+
+#endif
diff --git a/common/unarj.cpp b/common/unarj.cpp
index 050c7e65a2..89acf51cb5 100644
--- a/common/unarj.cpp
+++ b/common/unarj.cpp
@@ -34,6 +34,8 @@
#include "common/unarj.h"
#include "common/file.h"
#include "common/hash-str.h"
+#include "common/memstream.h"
+#include "common/bufferedstream.h"
namespace Common {
diff --git a/common/unzip.cpp b/common/unzip.cpp
index 3f084ad861..da9bb65f43 100644
--- a/common/unzip.cpp
+++ b/common/unzip.cpp
@@ -106,6 +106,7 @@ typedef struct {
#include "common/fs.h"
#include "common/unzip.h"
#include "common/file.h"
+#include "common/memstream.h"
#include "common/hashmap.h"
#include "common/hash-str.h"
diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp
index 4dd0e09f53..b53a9a33c2 100644
--- a/common/xmlparser.cpp
+++ b/common/xmlparser.cpp
@@ -27,7 +27,7 @@
#include "common/util.h"
#include "common/archive.h"
#include "common/fs.h"
-#include "common/stream.h"
+#include "common/memstream.h"
namespace Common {