aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorAlexander Tkachev2016-05-16 01:05:40 +0600
committerAlexander Tkachev2016-08-24 16:07:55 +0600
commit9c22b7cc64a3bd074f7cec012bd2f29f210d4ccf (patch)
treeacadc794ca373710e6e6a69d23867feb03f19c50 /common
parent01abba4f1dc9febbe99a4af6af19eb2afa3f618a (diff)
downloadscummvm-rg350-9c22b7cc64a3bd074f7cec012bd2f29f210d4ccf.tar.gz
scummvm-rg350-9c22b7cc64a3bd074f7cec012bd2f29f210d4ccf.tar.bz2
scummvm-rg350-9c22b7cc64a3bd074f7cec012bd2f29f210d4ccf.zip
CLOUD: Rewrite NetworkReadStream
Now it is based on MemoryReadWriteStream, which is introduced by this commit. This stream is using ring buffer and is dynamically increasing its size when necessary.
Diffstat (limited to 'common')
-rw-r--r--common/memstream.h83
1 files changed, 83 insertions, 0 deletions
diff --git a/common/memstream.h b/common/memstream.h
index 59d5f15b1a..963637cb27 100644
--- a/common/memstream.h
+++ b/common/memstream.h
@@ -209,6 +209,89 @@ public:
bool seek(int32 offset, int whence = SEEK_SET);
};
+/**
+* MemoryStream based on RingBuffer. Grows if has insufficient buffer size.
+*/
+class MemoryReadWriteStream : public WriteStream {
+private:
+ uint32 _capacity;
+ uint32 _size;
+ byte *_data;
+ uint32 _writePos, _readPos, _pos, _length;
+ DisposeAfterUse::Flag _disposeMemory;
+
+ void ensureCapacity(uint32 new_len) {
+ if (new_len <= _capacity)
+ return;
+
+ byte *old_data = _data;
+ uint32 oldCapacity = _capacity;
+
+ _capacity = MAX(new_len + 32, _capacity * 2);
+ _data = (byte *)malloc(_capacity);
+
+ if (old_data) {
+ // Copy old data
+ if (_readPos < _writePos) {
+ memcpy(_data, old_data + _readPos, _writePos - _readPos);
+ _writePos -= _readPos;
+ _readPos = 0;
+ } else {
+ memcpy(_data, old_data + _readPos, oldCapacity - _readPos);
+ memcpy(_data + oldCapacity - _readPos, old_data, _writePos);
+ _writePos += oldCapacity - _readPos;
+ _readPos = 0;
+ }
+ free(old_data);
+ }
+ }
+public:
+ MemoryReadWriteStream(DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) : _capacity(0), _size(0), _data(0), _writePos(0), _readPos(0), _pos(0), _length(0), _disposeMemory(disposeMemory) {}
+
+ ~MemoryReadWriteStream() {
+ if (_disposeMemory)
+ free(_data);
+ }
+
+ uint32 write(const void *dataPtr, uint32 dataSize) {
+ ensureCapacity(_length + dataSize);
+ if (_writePos + dataSize < _capacity) {
+ memcpy(_data + _writePos, dataPtr, dataSize);
+ } else {
+ memcpy(_data + _writePos, dataPtr, _capacity - _writePos);
+ const byte *shiftedPtr = (const byte *)dataPtr + _capacity - _writePos;
+ memcpy(_data, shiftedPtr, dataSize - (_capacity - _writePos));
+ }
+ _writePos = (_writePos + dataSize) % _capacity;
+ _pos += dataSize;
+ _length += dataSize;
+ if (_pos > _size)
+ _size = _pos;
+ return dataSize;
+ }
+
+ uint32 read(void *dataPtr, uint32 dataSize) {
+ uint32 length = _length;
+ if (length < dataSize) dataSize = length;
+ if (dataSize == 0 || _capacity == 0) return 0;
+ if (_readPos + dataSize < _capacity) {
+ memcpy(dataPtr, _data + _readPos, dataSize);
+ } else {
+ memcpy(dataPtr, _data + _readPos, _capacity - _readPos);
+ byte *shiftedPtr = (byte *)dataPtr + _capacity - _readPos;
+ memcpy(shiftedPtr, _data, dataSize - (_capacity - _readPos));
+ }
+ _readPos = (_readPos + dataSize) % _capacity;
+ _length -= dataSize;
+ return dataSize;
+ }
+
+ uint32 pos() const { return _pos - _length; } //'read' position in the stream
+ uint32 size() const { return _size; } //that's also 'write' position in the stream, as it's append-only
+
+ byte *getData() { return _data; }
+};
+
} // End of namespace Common
#endif