ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

memstream.h

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #ifndef COMMON_MEMSTREAM_H
00024 #define COMMON_MEMSTREAM_H
00025 
00026 #include "common/stream.h"
00027 #include "common/types.h"
00028 #include "common/util.h"
00029 
00030 namespace Common {
00031 
00036 class MemoryReadStream : public SeekableReadStream {
00037 private:
00038     const byte * const _ptrOrig;
00039     const byte *_ptr;
00040     const uint32 _size;
00041     uint32 _pos;
00042     DisposeAfterUse::Flag _disposeMemory;
00043     bool _eos;
00044 
00045 public:
00046 
00052     MemoryReadStream(const byte *dataPtr, uint32 dataSize, DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) :
00053         _ptrOrig(dataPtr),
00054         _ptr(dataPtr),
00055         _size(dataSize),
00056         _pos(0),
00057         _disposeMemory(disposeMemory),
00058         _eos(false) {}
00059 
00060     ~MemoryReadStream() {
00061         if (_disposeMemory)
00062             free(const_cast<byte *>(_ptrOrig));
00063     }
00064 
00065     uint32 read(void *dataPtr, uint32 dataSize);
00066 
00067     bool eos() const { return _eos; }
00068     void clearErr() { _eos = false; }
00069 
00070     int32 pos() const { return _pos; }
00071     int32 size() const { return _size; }
00072 
00073     bool seek(int32 offs, int whence = SEEK_SET);
00074 };
00075 
00076 
00081 class MemoryReadStreamEndian : public MemoryReadStream, public ReadStreamEndian {
00082 public:
00083     MemoryReadStreamEndian(const byte *buf, uint32 len, bool bigEndian)
00084         : MemoryReadStream(buf, len), ReadStreamEndian(bigEndian) {}
00085 };
00086 
00091 class MemoryWriteStream : public SeekableWriteStream {
00092 private:
00093     const uint32 _bufSize;
00094 protected:
00095     byte *_ptr;
00096     uint32 _pos;
00097     bool _err;
00098 public:
00099     MemoryWriteStream(byte *buf, uint32 len) : _ptr(buf), _bufSize(len), _pos(0), _err(false) {}
00100 
00101     uint32 write(const void *dataPtr, uint32 dataSize) {
00102         // Write at most as many bytes as are still available...
00103         if (dataSize > _bufSize - _pos) {
00104             dataSize = _bufSize - _pos;
00105             // We couldn't write all the data => set error indicator
00106             _err = true;
00107         }
00108         memcpy(_ptr, dataPtr, dataSize);
00109         _ptr += dataSize;
00110         _pos += dataSize;
00111         return dataSize;
00112     }
00113 
00114     virtual int32 pos() const override { return _pos; }
00115     virtual int32 size() const override { return _bufSize; }
00116 
00117     virtual bool err() const override { return _err; }
00118     virtual void clearErr() override { _err = false; }
00119 
00120     virtual bool seek(int32 offset, int whence = SEEK_SET) override { return false; }
00121 };
00122 
00126 class SeekableMemoryWriteStream : public MemoryWriteStream {
00127 private:
00128     byte *_ptrOrig;
00129 public:
00130     SeekableMemoryWriteStream(byte *buf, uint32 len) : MemoryWriteStream(buf, len), _ptrOrig(buf) {}
00131 
00132     virtual bool seek(int32 offset, int whence = SEEK_SET) override {
00133         switch (whence) {
00134         case SEEK_END:
00135             // SEEK_END works just like SEEK_SET, only 'reversed',
00136             // i.e. from the end.
00137             offset = size() + offset;
00138             // Fall through
00139         case SEEK_SET:
00140             _ptr = _ptrOrig + offset;
00141             _pos = offset;
00142             break;
00143         case SEEK_CUR:
00144             _ptr += offset;
00145             _pos += offset;
00146             break;
00147         }
00148         // Post-Condition
00149         if ((int32)_pos > size()) {
00150             _pos = size();
00151             _ptr = _ptrOrig + _pos;
00152         }
00153 
00154         return true;
00155     }
00156 };
00157 
00158 
00163 class MemoryWriteStreamDynamic : public SeekableWriteStream {
00164 protected:
00165     uint32 _capacity;
00166     uint32 _size;
00167     byte *_ptr;
00168     byte *_data;
00169     uint32 _pos;
00170     DisposeAfterUse::Flag _disposeMemory;
00171 
00172     void ensureCapacity(uint32 new_len) {
00173         if (new_len <= _capacity)
00174             return;
00175 
00176         byte *old_data = _data;
00177 
00178         _capacity = MAX(new_len + 32, _capacity * 2);
00179         _data = (byte *)malloc(_capacity);
00180         _ptr = _data + _pos;
00181 
00182         if (old_data) {
00183             // Copy old data
00184             memcpy(_data, old_data, _size);
00185             free(old_data);
00186         }
00187 
00188         _size = new_len;
00189     }
00190 public:
00191     explicit MemoryWriteStreamDynamic(DisposeAfterUse::Flag disposeMemory) : _capacity(0), _size(0), _ptr(nullptr), _data(nullptr), _pos(0), _disposeMemory(disposeMemory) {}
00192 
00193     ~MemoryWriteStreamDynamic() {
00194         if (_disposeMemory)
00195             free(_data);
00196     }
00197 
00198     uint32 write(const void *dataPtr, uint32 dataSize) {
00199         ensureCapacity(_pos + dataSize);
00200         memcpy(_ptr, dataPtr, dataSize);
00201         _ptr += dataSize;
00202         _pos += dataSize;
00203         if (_pos > _size)
00204             _size = _pos;
00205         return dataSize;
00206     }
00207 
00208     virtual int32 pos() const override { return _pos; }
00209     virtual int32 size() const override { return _size; }
00210 
00211     byte *getData() { return _data; }
00212 
00213     virtual bool seek(int32 offs, int whence = SEEK_SET) override {
00214         // Pre-Condition
00215         assert(_pos <= _size);
00216         switch (whence) {
00217         case SEEK_END:
00218             // SEEK_END works just like SEEK_SET, only 'reversed', i.e. from the end.
00219             offs = _size + offs;
00220             // Fall through
00221         case SEEK_SET:
00222             _ptr = _data + offs;
00223             _pos = offs;
00224             break;
00225 
00226         case SEEK_CUR:
00227             _ptr += offs;
00228             _pos += offs;
00229             break;
00230         }
00231 
00232         assert(_pos <= _size);
00233         return true;
00234     }
00235 };
00236 
00240 class MemoryReadWriteStream : public SeekableReadStream, public SeekableWriteStream {
00241 private:
00242     uint32 _capacity;
00243     uint32 _size;
00244     byte *_data;
00245     uint32 _writePos, _readPos, _pos, _length;
00246     DisposeAfterUse::Flag _disposeMemory;
00247     bool _eos;
00248 
00249     void ensureCapacity(uint32 new_len) {
00250         if (new_len <= _capacity)
00251             return;
00252 
00253         byte *old_data = _data;
00254         uint32 oldCapacity = _capacity;
00255 
00256         _capacity = MAX(new_len + 32, _capacity * 2);
00257         _data = (byte *)malloc(_capacity);
00258 
00259         if (old_data) {
00260             // Copy old data
00261             if (_readPos < _writePos) {
00262                 memcpy(_data, old_data + _readPos, _writePos - _readPos);
00263                 _writePos = _length;
00264                 _readPos = 0;
00265             } else {
00266                 memcpy(_data, old_data + _readPos, oldCapacity - _readPos);
00267                 memcpy(_data + oldCapacity - _readPos, old_data, _writePos);
00268                 _writePos = _length;
00269                 _readPos = 0;
00270             }
00271             free(old_data);
00272         }
00273     }
00274 public:
00275     explicit MemoryReadWriteStream(DisposeAfterUse::Flag disposeMemory) : _capacity(0), _size(0), _data(nullptr), _writePos(0), _readPos(0), _pos(0), _length(0), _disposeMemory(disposeMemory), _eos(false) {}
00276 
00277     ~MemoryReadWriteStream() {
00278         if (_disposeMemory)
00279             free(_data);
00280     }
00281 
00282     uint32 write(const void *dataPtr, uint32 dataSize) {
00283         ensureCapacity(_length + dataSize);
00284         if (_writePos + dataSize < _capacity) {
00285             memcpy(_data + _writePos, dataPtr, dataSize);
00286         } else {
00287             memcpy(_data + _writePos, dataPtr, _capacity - _writePos);
00288             const byte *shiftedPtr = (const byte *)dataPtr + _capacity - _writePos;
00289             memcpy(_data, shiftedPtr, dataSize - (_capacity - _writePos));
00290         }
00291         _writePos = (_writePos + dataSize) % _capacity;
00292         _pos += dataSize;
00293         _length += dataSize;
00294         if (_pos > _size)
00295             _size = _pos;
00296         return dataSize;
00297     }
00298 
00299     virtual uint32 read(void *dataPtr, uint32 dataSize) override {
00300         if (_length < dataSize) {
00301             dataSize = _length;
00302             _eos = true;
00303         }
00304         if (dataSize == 0 || _capacity == 0) return 0;
00305         if (_readPos + dataSize < _capacity) {
00306             memcpy(dataPtr, _data + _readPos, dataSize);
00307         } else {
00308             memcpy(dataPtr, _data + _readPos, _capacity - _readPos);
00309             byte *shiftedPtr = (byte *)dataPtr + _capacity - _readPos;
00310             memcpy(shiftedPtr, _data, dataSize - (_capacity - _readPos));
00311         }
00312         _readPos = (_readPos + dataSize) % _capacity;
00313         _length -= dataSize;
00314         return dataSize;
00315     }
00316 
00317     virtual int32 pos() const override { return _pos - _length; }
00318     virtual int32 size() const override { return _size; }
00319     virtual bool seek(int32, int) override { return false; }
00320     virtual bool eos() const override { return _eos; }
00321     virtual void clearErr() override { _eos = false; }
00322 
00323     byte *getData() { return _data; }
00324 };
00325 
00326 } // End of namespace Common
00327 
00328 #endif


Generated on Sat Nov 16 2019 05:00:35 for ResidualVM by doxygen 1.7.1
curved edge   curved edge