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 : virtual 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 SeekableReadStreamEndian {
00082 public:
00083     MemoryReadStreamEndian(const byte *buf, uint32 len, bool bigEndian, DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO)
00084         : MemoryReadStream(buf, len, disposeMemory), SeekableReadStreamEndian(bigEndian), ReadStreamEndian(bigEndian) {}
00085 
00086     int32 pos() const { return MemoryReadStream::pos(); }
00087     int32 size() const { return MemoryReadStream::size(); }
00088 
00089     bool seek(int32 offs, int whence = SEEK_SET) { return MemoryReadStream::seek(offs, whence); }
00090 
00091     bool skip(uint32 offset) { return MemoryReadStream::seek(offset, SEEK_CUR); }
00092 };
00093 
00098 class MemoryWriteStream : public SeekableWriteStream {
00099 private:
00100     const uint32 _bufSize;
00101 protected:
00102     byte *_ptr;
00103     uint32 _pos;
00104     bool _err;
00105 public:
00106     MemoryWriteStream(byte *buf, uint32 len) : _ptr(buf), _bufSize(len), _pos(0), _err(false) {}
00107 
00108     uint32 write(const void *dataPtr, uint32 dataSize) override {
00109         // Write at most as many bytes as are still available...
00110         if (dataSize > _bufSize - _pos) {
00111             dataSize = _bufSize - _pos;
00112             // We couldn't write all the data => set error indicator
00113             _err = true;
00114         }
00115         memcpy(_ptr, dataPtr, dataSize);
00116         _ptr += dataSize;
00117         _pos += dataSize;
00118         return dataSize;
00119     }
00120 
00121     virtual int32 pos() const override { return _pos; }
00122     virtual int32 size() const override { return _bufSize; }
00123 
00124     virtual bool err() const override { return _err; }
00125     virtual void clearErr() override { _err = false; }
00126 
00127     virtual bool seek(int32 offset, int whence = SEEK_SET) override { return false; }
00128 };
00129 
00133 class SeekableMemoryWriteStream : public MemoryWriteStream {
00134 private:
00135     byte *_ptrOrig;
00136 public:
00137     SeekableMemoryWriteStream(byte *buf, uint32 len) : MemoryWriteStream(buf, len), _ptrOrig(buf) {}
00138 
00139     virtual bool seek(int32 offset, int whence = SEEK_SET) override {
00140         switch (whence) {
00141         case SEEK_END:
00142             // SEEK_END works just like SEEK_SET, only 'reversed',
00143             // i.e. from the end.
00144             offset = size() + offset;
00145             // Fall through
00146         case SEEK_SET:
00147             // Fall through
00148         default:
00149             _ptr = _ptrOrig + offset;
00150             _pos = offset;
00151             break;
00152         case SEEK_CUR:
00153             _ptr += offset;
00154             _pos += offset;
00155             break;
00156         }
00157         // Post-Condition
00158         if ((int32)_pos > size()) {
00159             _pos = size();
00160             _ptr = _ptrOrig + _pos;
00161         }
00162 
00163         return true;
00164     }
00165 };
00166 
00167 
00172 class MemoryWriteStreamDynamic : public SeekableWriteStream {
00173 protected:
00174     uint32 _capacity;
00175     uint32 _size;
00176     byte *_ptr;
00177     byte *_data;
00178     uint32 _pos;
00179     DisposeAfterUse::Flag _disposeMemory;
00180 
00181     void ensureCapacity(uint32 new_len) {
00182         if (new_len <= _capacity)
00183             return;
00184 
00185         byte *old_data = _data;
00186 
00187         _capacity = MAX(new_len + 32, _capacity * 2);
00188         _data = (byte *)malloc(_capacity);
00189         _ptr = _data + _pos;
00190 
00191         if (old_data) {
00192             // Copy old data
00193             memcpy(_data, old_data, _size);
00194             free(old_data);
00195         }
00196 
00197         _size = new_len;
00198     }
00199 public:
00200     explicit MemoryWriteStreamDynamic(DisposeAfterUse::Flag disposeMemory) : _capacity(0), _size(0), _ptr(nullptr), _data(nullptr), _pos(0), _disposeMemory(disposeMemory) {}
00201 
00202     ~MemoryWriteStreamDynamic() {
00203         if (_disposeMemory)
00204             free(_data);
00205     }
00206 
00207     uint32 write(const void *dataPtr, uint32 dataSize) override {
00208         ensureCapacity(_pos + dataSize);
00209         memcpy(_ptr, dataPtr, dataSize);
00210         _ptr += dataSize;
00211         _pos += dataSize;
00212         if (_pos > _size)
00213             _size = _pos;
00214         return dataSize;
00215     }
00216 
00217     virtual int32 pos() const override { return _pos; }
00218     virtual int32 size() const override { return _size; }
00219 
00220     byte *getData() { return _data; }
00221 
00222     virtual bool seek(int32 offs, int whence = SEEK_SET) override {
00223         // Pre-Condition
00224         assert(_pos <= _size);
00225         switch (whence) {
00226         case SEEK_END:
00227             // SEEK_END works just like SEEK_SET, only 'reversed', i.e. from the end.
00228             offs = _size + offs;
00229             // Fall through
00230         case SEEK_SET:
00231             // Fall through
00232         default:
00233             _ptr = _data + offs;
00234             _pos = offs;
00235             break;
00236 
00237         case SEEK_CUR:
00238             _ptr += offs;
00239             _pos += offs;
00240             break;
00241         }
00242 
00243         assert(_pos <= _size);
00244         return true;
00245     }
00246 };
00247 
00251 class MemoryReadWriteStream : public SeekableReadStream, public SeekableWriteStream {
00252 private:
00253     uint32 _capacity;
00254     uint32 _size;
00255     byte *_data;
00256     uint32 _writePos, _readPos, _pos, _length;
00257     DisposeAfterUse::Flag _disposeMemory;
00258     bool _eos;
00259 
00260     void ensureCapacity(uint32 new_len) {
00261         if (new_len <= _capacity)
00262             return;
00263 
00264         byte *old_data = _data;
00265         uint32 oldCapacity = _capacity;
00266 
00267         _capacity = MAX(new_len + 32, _capacity * 2);
00268         _data = (byte *)malloc(_capacity);
00269 
00270         if (old_data) {
00271             // Copy old data
00272             if (_readPos < _writePos) {
00273                 memcpy(_data, old_data + _readPos, _writePos - _readPos);
00274                 _writePos = _length;
00275                 _readPos = 0;
00276             } else {
00277                 memcpy(_data, old_data + _readPos, oldCapacity - _readPos);
00278                 memcpy(_data + oldCapacity - _readPos, old_data, _writePos);
00279                 _writePos = _length;
00280                 _readPos = 0;
00281             }
00282             free(old_data);
00283         }
00284     }
00285 public:
00286     explicit MemoryReadWriteStream(DisposeAfterUse::Flag disposeMemory) : _capacity(0), _size(0), _data(nullptr), _writePos(0), _readPos(0), _pos(0), _length(0), _disposeMemory(disposeMemory), _eos(false) {}
00287 
00288     ~MemoryReadWriteStream() {
00289         if (_disposeMemory)
00290             free(_data);
00291     }
00292 
00293     uint32 write(const void *dataPtr, uint32 dataSize) override {
00294         ensureCapacity(_length + dataSize);
00295         if (_writePos + dataSize < _capacity) {
00296             memcpy(_data + _writePos, dataPtr, dataSize);
00297         } else {
00298             memcpy(_data + _writePos, dataPtr, _capacity - _writePos);
00299             const byte *shiftedPtr = (const byte *)dataPtr + _capacity - _writePos;
00300             memcpy(_data, shiftedPtr, dataSize - (_capacity - _writePos));
00301         }
00302         _writePos = (_writePos + dataSize) % _capacity;
00303         _pos += dataSize;
00304         _length += dataSize;
00305         if (_pos > _size)
00306             _size = _pos;
00307         return dataSize;
00308     }
00309 
00310     virtual uint32 read(void *dataPtr, uint32 dataSize) override {
00311         if (_length < dataSize) {
00312             dataSize = _length;
00313             _eos = true;
00314         }
00315         if (dataSize == 0 || _capacity == 0) return 0;
00316         if (_readPos + dataSize < _capacity) {
00317             memcpy(dataPtr, _data + _readPos, dataSize);
00318         } else {
00319             memcpy(dataPtr, _data + _readPos, _capacity - _readPos);
00320             byte *shiftedPtr = (byte *)dataPtr + _capacity - _readPos;
00321             memcpy(shiftedPtr, _data, dataSize - (_capacity - _readPos));
00322         }
00323         _readPos = (_readPos + dataSize) % _capacity;
00324         _length -= dataSize;
00325         return dataSize;
00326     }
00327 
00328     virtual int32 pos() const override { return _pos - _length; }
00329     virtual int32 size() const override { return _size; }
00330     virtual bool seek(int32, int) override { return false; }
00331     virtual bool eos() const override { return _eos; }
00332     virtual void clearErr() override { _eos = false; }
00333 
00334     byte *getData() { return _data; }
00335 };
00336 
00337 } // End of namespace Common
00338 
00339 #endif


Generated on Sat Sep 19 2020 05:01:07 for ResidualVM by doxygen 1.7.1
curved edge   curved edge