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) override {
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             // Fall through
00141         default:
00142             _ptr = _ptrOrig + offset;
00143             _pos = offset;
00144             break;
00145         case SEEK_CUR:
00146             _ptr += offset;
00147             _pos += offset;
00148             break;
00149         }
00150         // Post-Condition
00151         if ((int32)_pos > size()) {
00152             _pos = size();
00153             _ptr = _ptrOrig + _pos;
00154         }
00155 
00156         return true;
00157     }
00158 };
00159 
00160 
00165 class MemoryWriteStreamDynamic : public SeekableWriteStream {
00166 protected:
00167     uint32 _capacity;
00168     uint32 _size;
00169     byte *_ptr;
00170     byte *_data;
00171     uint32 _pos;
00172     DisposeAfterUse::Flag _disposeMemory;
00173 
00174     void ensureCapacity(uint32 new_len) {
00175         if (new_len <= _capacity)
00176             return;
00177 
00178         byte *old_data = _data;
00179 
00180         _capacity = MAX(new_len + 32, _capacity * 2);
00181         _data = (byte *)malloc(_capacity);
00182         _ptr = _data + _pos;
00183 
00184         if (old_data) {
00185             // Copy old data
00186             memcpy(_data, old_data, _size);
00187             free(old_data);
00188         }
00189 
00190         _size = new_len;
00191     }
00192 public:
00193     explicit MemoryWriteStreamDynamic(DisposeAfterUse::Flag disposeMemory) : _capacity(0), _size(0), _ptr(nullptr), _data(nullptr), _pos(0), _disposeMemory(disposeMemory) {}
00194 
00195     ~MemoryWriteStreamDynamic() {
00196         if (_disposeMemory)
00197             free(_data);
00198     }
00199 
00200     uint32 write(const void *dataPtr, uint32 dataSize) override {
00201         ensureCapacity(_pos + dataSize);
00202         memcpy(_ptr, dataPtr, dataSize);
00203         _ptr += dataSize;
00204         _pos += dataSize;
00205         if (_pos > _size)
00206             _size = _pos;
00207         return dataSize;
00208     }
00209 
00210     virtual int32 pos() const override { return _pos; }
00211     virtual int32 size() const override { return _size; }
00212 
00213     byte *getData() { return _data; }
00214 
00215     virtual bool seek(int32 offs, int whence = SEEK_SET) override {
00216         // Pre-Condition
00217         assert(_pos <= _size);
00218         switch (whence) {
00219         case SEEK_END:
00220             // SEEK_END works just like SEEK_SET, only 'reversed', i.e. from the end.
00221             offs = _size + offs;
00222             // Fall through
00223         case SEEK_SET:
00224             // Fall through
00225         default:
00226             _ptr = _data + offs;
00227             _pos = offs;
00228             break;
00229 
00230         case SEEK_CUR:
00231             _ptr += offs;
00232             _pos += offs;
00233             break;
00234         }
00235 
00236         assert(_pos <= _size);
00237         return true;
00238     }
00239 };
00240 
00244 class MemoryReadWriteStream : public SeekableReadStream, public SeekableWriteStream {
00245 private:
00246     uint32 _capacity;
00247     uint32 _size;
00248     byte *_data;
00249     uint32 _writePos, _readPos, _pos, _length;
00250     DisposeAfterUse::Flag _disposeMemory;
00251     bool _eos;
00252 
00253     void ensureCapacity(uint32 new_len) {
00254         if (new_len <= _capacity)
00255             return;
00256 
00257         byte *old_data = _data;
00258         uint32 oldCapacity = _capacity;
00259 
00260         _capacity = MAX(new_len + 32, _capacity * 2);
00261         _data = (byte *)malloc(_capacity);
00262 
00263         if (old_data) {
00264             // Copy old data
00265             if (_readPos < _writePos) {
00266                 memcpy(_data, old_data + _readPos, _writePos - _readPos);
00267                 _writePos = _length;
00268                 _readPos = 0;
00269             } else {
00270                 memcpy(_data, old_data + _readPos, oldCapacity - _readPos);
00271                 memcpy(_data + oldCapacity - _readPos, old_data, _writePos);
00272                 _writePos = _length;
00273                 _readPos = 0;
00274             }
00275             free(old_data);
00276         }
00277     }
00278 public:
00279     explicit MemoryReadWriteStream(DisposeAfterUse::Flag disposeMemory) : _capacity(0), _size(0), _data(nullptr), _writePos(0), _readPos(0), _pos(0), _length(0), _disposeMemory(disposeMemory), _eos(false) {}
00280 
00281     ~MemoryReadWriteStream() {
00282         if (_disposeMemory)
00283             free(_data);
00284     }
00285 
00286     uint32 write(const void *dataPtr, uint32 dataSize) override {
00287         ensureCapacity(_length + dataSize);
00288         if (_writePos + dataSize < _capacity) {
00289             memcpy(_data + _writePos, dataPtr, dataSize);
00290         } else {
00291             memcpy(_data + _writePos, dataPtr, _capacity - _writePos);
00292             const byte *shiftedPtr = (const byte *)dataPtr + _capacity - _writePos;
00293             memcpy(_data, shiftedPtr, dataSize - (_capacity - _writePos));
00294         }
00295         _writePos = (_writePos + dataSize) % _capacity;
00296         _pos += dataSize;
00297         _length += dataSize;
00298         if (_pos > _size)
00299             _size = _pos;
00300         return dataSize;
00301     }
00302 
00303     virtual uint32 read(void *dataPtr, uint32 dataSize) override {
00304         if (_length < dataSize) {
00305             dataSize = _length;
00306             _eos = true;
00307         }
00308         if (dataSize == 0 || _capacity == 0) return 0;
00309         if (_readPos + dataSize < _capacity) {
00310             memcpy(dataPtr, _data + _readPos, dataSize);
00311         } else {
00312             memcpy(dataPtr, _data + _readPos, _capacity - _readPos);
00313             byte *shiftedPtr = (byte *)dataPtr + _capacity - _readPos;
00314             memcpy(shiftedPtr, _data, dataSize - (_capacity - _readPos));
00315         }
00316         _readPos = (_readPos + dataSize) % _capacity;
00317         _length -= dataSize;
00318         return dataSize;
00319     }
00320 
00321     virtual int32 pos() const override { return _pos - _length; }
00322     virtual int32 size() const override { return _size; }
00323     virtual bool seek(int32, int) override { return false; }
00324     virtual bool eos() const override { return _eos; }
00325     virtual void clearErr() override { _eos = false; }
00326 
00327     byte *getData() { return _data; }
00328 };
00329 
00330 } // End of namespace Common
00331 
00332 #endif


Generated on Sat Jun 27 2020 05:00:33 for ResidualVM by doxygen 1.7.1
curved edge   curved edge