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 WriteStream {
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     int32 pos() const { return _pos; }
00115     uint32 size() const { return _bufSize; }
00116 
00117     virtual bool err() const { return _err; }
00118     virtual void clearErr() { _err = false; }
00119 };
00120 
00124 class SeekableMemoryWriteStream : public MemoryWriteStream {
00125 private:
00126     byte *_ptrOrig;
00127 public:
00128     SeekableMemoryWriteStream(byte *buf, uint32 len) : MemoryWriteStream(buf, len), _ptrOrig(buf) {}
00129     uint32 seek(uint32 offset, int whence = SEEK_SET) {
00130         switch (whence) {
00131         case SEEK_END:
00132             // SEEK_END works just like SEEK_SET, only 'reversed',
00133             // i.e. from the end.
00134             offset = size() + offset;
00135             // Fall through
00136         case SEEK_SET:
00137             _ptr = _ptrOrig + offset;
00138             _pos = offset;
00139             break;
00140         case SEEK_CUR:
00141             _ptr += offset;
00142             _pos += offset;
00143             break;
00144         }
00145         // Post-Condition
00146         if (_pos > size()) {
00147             _pos = size();
00148             _ptr = _ptrOrig + _pos;
00149         }
00150         return _pos;
00151     }
00152 };
00153 
00154 
00159 class MemoryWriteStreamDynamic : public WriteStream {
00160 protected:
00161     uint32 _capacity;
00162     uint32 _size;
00163     byte *_ptr;
00164     byte *_data;
00165     uint32 _pos;
00166     DisposeAfterUse::Flag _disposeMemory;
00167 
00168     void ensureCapacity(uint32 new_len) {
00169         if (new_len <= _capacity)
00170             return;
00171 
00172         byte *old_data = _data;
00173 
00174         _capacity = MAX(new_len + 32, _capacity * 2);
00175         _data = (byte *)malloc(_capacity);
00176         _ptr = _data + _pos;
00177 
00178         if (old_data) {
00179             // Copy old data
00180             memcpy(_data, old_data, _size);
00181             free(old_data);
00182         }
00183 
00184         _size = new_len;
00185     }
00186 public:
00187     explicit MemoryWriteStreamDynamic(DisposeAfterUse::Flag disposeMemory) : _capacity(0), _size(0), _ptr(nullptr), _data(nullptr), _pos(0), _disposeMemory(disposeMemory) {}
00188 
00189     ~MemoryWriteStreamDynamic() {
00190         if (_disposeMemory)
00191             free(_data);
00192     }
00193 
00194     uint32 write(const void *dataPtr, uint32 dataSize) {
00195         ensureCapacity(_pos + dataSize);
00196         memcpy(_ptr, dataPtr, dataSize);
00197         _ptr += dataSize;
00198         _pos += dataSize;
00199         if (_pos > _size)
00200             _size = _pos;
00201         return dataSize;
00202     }
00203 
00204     int32 pos() const { return _pos; }
00205     uint32 size() const { return _size; }
00206 
00207     byte *getData() { return _data; }
00208 
00209     bool seek(int32 offset, int whence = SEEK_SET);
00210 };
00211 
00215 class MemoryReadWriteStream : public SeekableReadStream, public WriteStream {
00216 private:
00217     uint32 _capacity;
00218     uint32 _size;
00219     byte *_data;
00220     uint32 _writePos, _readPos, _pos, _length;
00221     DisposeAfterUse::Flag _disposeMemory;
00222     bool _eos;
00223 
00224     void ensureCapacity(uint32 new_len) {
00225         if (new_len <= _capacity)
00226             return;
00227 
00228         byte *old_data = _data;
00229         uint32 oldCapacity = _capacity;
00230 
00231         _capacity = MAX(new_len + 32, _capacity * 2);
00232         _data = (byte *)malloc(_capacity);
00233 
00234         if (old_data) {
00235             // Copy old data
00236             if (_readPos < _writePos) {
00237                 memcpy(_data, old_data + _readPos, _writePos - _readPos);
00238                 _writePos = _length;
00239                 _readPos = 0;
00240             } else {
00241                 memcpy(_data, old_data + _readPos, oldCapacity - _readPos);
00242                 memcpy(_data + oldCapacity - _readPos, old_data, _writePos);
00243                 _writePos = _length;
00244                 _readPos = 0;
00245             }
00246             free(old_data);
00247         }
00248     }
00249 public:
00250     explicit MemoryReadWriteStream(DisposeAfterUse::Flag disposeMemory) : _capacity(0), _size(0), _data(nullptr), _writePos(0), _readPos(0), _pos(0), _length(0), _disposeMemory(disposeMemory), _eos(false) {}
00251 
00252     ~MemoryReadWriteStream() {
00253         if (_disposeMemory)
00254             free(_data);
00255     }
00256 
00257     uint32 write(const void *dataPtr, uint32 dataSize) {
00258         ensureCapacity(_length + dataSize);
00259         if (_writePos + dataSize < _capacity) {
00260             memcpy(_data + _writePos, dataPtr, dataSize);
00261         } else {
00262             memcpy(_data + _writePos, dataPtr, _capacity - _writePos);
00263             const byte *shiftedPtr = (const byte *)dataPtr + _capacity - _writePos;
00264             memcpy(_data, shiftedPtr, dataSize - (_capacity - _writePos));
00265         }
00266         _writePos = (_writePos + dataSize) % _capacity;
00267         _pos += dataSize;
00268         _length += dataSize;
00269         if (_pos > _size)
00270             _size = _pos;
00271         return dataSize;
00272     }
00273 
00274     virtual uint32 read(void *dataPtr, uint32 dataSize) {
00275         if (_length < dataSize) {
00276             dataSize = _length;
00277             _eos = true;
00278         }
00279         if (dataSize == 0 || _capacity == 0) return 0;
00280         if (_readPos + dataSize < _capacity) {
00281             memcpy(dataPtr, _data + _readPos, dataSize);
00282         } else {
00283             memcpy(dataPtr, _data + _readPos, _capacity - _readPos);
00284             byte *shiftedPtr = (byte *)dataPtr + _capacity - _readPos;
00285             memcpy(shiftedPtr, _data, dataSize - (_capacity - _readPos));
00286         }
00287         _readPos = (_readPos + dataSize) % _capacity;
00288         _length -= dataSize;
00289         return dataSize;
00290     }
00291 
00292     int32 pos() const { return _pos - _length; } // 'read' position in the stream
00293     int32 size() const { return _size; } // that's also 'write' position in the stream, as it's append-only
00294     bool seek(int32, int) { return false; }
00295     bool eos() const { return _eos; }
00296     void clearErr() { _eos = false; }
00297 
00298     byte *getData() { return _data; }
00299 };
00300 
00301 } // End of namespace Common
00302 
00303 #endif


Generated on Sat Feb 16 2019 05:00:57 for ResidualVM by doxygen 1.7.1
curved edge   curved edge