ScummVM API documentation
memstream.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #ifndef COMMON_MEMSTREAM_H
23 #define COMMON_MEMSTREAM_H
24 
25 #include "common/stream.h"
26 #include "common/types.h"
27 #include "common/util.h"
28 
29 namespace Common {
30 
43 class MemoryReadStream : virtual public SeekableReadStream {
44 private:
45  struct CastFreeDeleter {
46  inline void operator()(const byte *object) {
47  free(const_cast<byte *>(object));
48  }
49  };
50 
51  // Note when using SharedPtr, then deleting is handled
52  // by SharedPtr and not by CastFreeDeleter
54  const byte *_ptr;
55  uint32 _size;
56  uint32 _pos;
57  bool _eos;
58 
59 public:
60  MemoryReadStream(MemoryReadStream &&other) : _ptrOrig(Common::move(other._ptrOrig)), _ptr(other._ptr), _size(other._size), _pos(other._pos), _eos(other._eos) {
61  // other must remaining in a valid state. Let's make it into zero-sized stream.
62  other._ptr = nullptr;
63  other._size = 0;
64  other._pos = 0;
65  other._eos = false;
66  }
67 
73  MemoryReadStream(const byte *dataPtr, uint32 dataSize, DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) :
74  _ptrOrig(dataPtr, disposeMemory),
75  _ptr(dataPtr),
76  _size(dataSize),
77  _pos(0),
78  _eos(false) {}
79 
80  MemoryReadStream(SharedPtr<byte> dataPtr, uint32 dataSize) :
81  _ptrOrig(dataPtr),
82  _ptr(dataPtr.get()),
83  _size(dataSize),
84  _pos(0),
85  _eos(false) {}
86 
87  uint32 read(void *dataPtr, uint32 dataSize);
88 
89  bool eos() const { return _eos; }
90  void clearErr() { _eos = false; }
91 
92  int64 pos() const { return _pos; }
93  int64 size() const { return _size; }
94 
95  bool seek(int64 offs, int whence = SEEK_SET);
96 };
97 
98 
104 public:
105  MemoryReadStreamEndian(const byte *buf, uint32 len, bool bigEndian, DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO)
106  : MemoryReadStream(buf, len, disposeMemory), SeekableReadStreamEndian(bigEndian), ReadStreamEndian(bigEndian) {}
107 
108  int64 pos() const override { return MemoryReadStream::pos(); }
109  int64 size() const override { return MemoryReadStream::size(); }
110 
111  bool seek(int64 offs, int whence = SEEK_SET) override { return MemoryReadStream::seek(offs, whence); }
112 
113  bool skip(uint32 offset) override { return MemoryReadStream::seek(offset, SEEK_CUR); }
114 };
115 
121 private:
122  const uint32 _bufSize;
123 protected:
124  byte *_ptr;
125  uint32 _pos;
126  bool _err;
127 public:
128  MemoryWriteStream(byte *buf, uint32 len) : _ptr(buf), _bufSize(len), _pos(0), _err(false) {}
129 
130  uint32 write(const void *dataPtr, uint32 dataSize) override {
131  // Write at most as many bytes as are still available...
132  if (dataSize > _bufSize - _pos) {
133  dataSize = _bufSize - _pos;
134  // We couldn't write all the data => set error indicator
135  _err = true;
136  }
137  memcpy(_ptr, dataPtr, dataSize);
138  _ptr += dataSize;
139  _pos += dataSize;
140  return dataSize;
141  }
142 
143  int64 pos() const override { return _pos; }
144  int64 size() const override { return _bufSize; }
145 
146  bool err() const override { return _err; }
147  void clearErr() override { _err = false; }
148 
149  bool seek(int64 offset, int whence = SEEK_SET) override { return false; }
150 };
151 
156 private:
157  byte *_ptrOrig;
158 public:
159  SeekableMemoryWriteStream(byte *buf, uint32 len) : MemoryWriteStream(buf, len), _ptrOrig(buf) {}
160 
161  bool seek(int64 offset, int whence = SEEK_SET) override {
162  switch (whence) {
163  case SEEK_END:
164  // SEEK_END works just like SEEK_SET, only 'reversed',
165  // i.e. from the end.
166  offset = size() + offset;
167  // Fall through
168  case SEEK_SET:
169  // Fall through
170  default:
171  _ptr = _ptrOrig + offset;
172  _pos = offset;
173  break;
174  case SEEK_CUR:
175  _ptr += offset;
176  _pos += offset;
177  break;
178  }
179  // Post-Condition
180  if ((int32)_pos > size()) {
181  _pos = size();
182  _ptr = _ptrOrig + _pos;
183  }
184 
185  return true;
186  }
187 };
188 
189 
195 protected:
196  uint32 _capacity;
197  uint32 _size;
198  byte *_ptr;
199  byte *_data;
200  uint32 _pos;
201  DisposeAfterUse::Flag _disposeMemory;
202 
203  void ensureCapacity(uint32 capacity) {
204  if (capacity <= _capacity)
205  return;
206 
207  byte *old_data = _data;
208 
209  _capacity = capacity;
210  _data = (byte *)malloc(_capacity);
211  _ptr = _data + _pos;
212 
213  if (old_data) {
214  // Copy old data
215  memcpy(_data, old_data, _size);
216  free(old_data);
217  }
218  }
219 
223  static size_t roundUpCapacity(size_t capacity) {
224  size_t capa = 8;
225  while (capa < capacity)
226  capa <<= 1;
227  return capa;
228  }
229 public:
230  explicit MemoryWriteStreamDynamic(DisposeAfterUse::Flag disposeMemory) : _capacity(0), _size(0), _ptr(nullptr), _data(nullptr), _pos(0), _disposeMemory(disposeMemory) {}
231 
233  if (_disposeMemory)
234  free(_data);
235  }
236 
237  uint32 write(const void *dataPtr, uint32 dataSize) override {
238  if ((_pos + dataSize) >= _capacity)
239  ensureCapacity(roundUpCapacity(_pos + dataSize));
240 
241  memcpy(_ptr, dataPtr, dataSize);
242  _ptr += dataSize;
243  _pos += dataSize;
244  if (_pos > _size)
245  _size = _pos;
246  return dataSize;
247  }
248 
249  int64 pos() const override { return _pos; }
250  int64 size() const override { return _size; }
251 
252  byte *getData() { return _data; }
253 
254  bool seek(int64 offs, int whence = SEEK_SET) override {
255  // Pre-Condition
256  assert(_pos <= _size);
257  switch (whence) {
258  case SEEK_END:
259  // SEEK_END works just like SEEK_SET, only 'reversed', i.e. from the end.
260  offs = _size + offs;
261  // Fall through
262  case SEEK_SET:
263  // Fall through
264  default:
265  _ptr = _data + offs;
266  _pos = offs;
267  break;
268 
269  case SEEK_CUR:
270  _ptr += offs;
271  _pos += offs;
272  break;
273  }
274 
275  assert(_pos <= _size);
276  return true;
277  }
278 };
279 
284 private:
285  uint32 _capacity;
286  uint32 _size;
287  byte *_data;
288  uint32 _writePos, _readPos, _pos, _length;
289  DisposeAfterUse::Flag _disposeMemory;
290  bool _eos;
291 
292  void ensureCapacity(uint32 new_len) {
293  if (new_len <= _capacity)
294  return;
295 
296  byte *old_data = _data;
297  uint32 oldCapacity = _capacity;
298 
299  _capacity = MAX(new_len + 32, _capacity * 2);
300  _data = (byte *)malloc(_capacity);
301 
302  if (old_data) {
303  // Copy old data
304  if (_readPos < _writePos) {
305  memcpy(_data, old_data + _readPos, _writePos - _readPos);
306  _writePos = _length;
307  _readPos = 0;
308  } else {
309  memcpy(_data, old_data + _readPos, oldCapacity - _readPos);
310  memcpy(_data + oldCapacity - _readPos, old_data, _writePos);
311  _writePos = _length;
312  _readPos = 0;
313  }
314  free(old_data);
315  }
316  }
317 public:
318  explicit MemoryReadWriteStream(DisposeAfterUse::Flag disposeMemory) : _capacity(0), _size(0), _data(nullptr), _writePos(0), _readPos(0), _pos(0), _length(0), _disposeMemory(disposeMemory), _eos(false) {}
319 
321  if (_disposeMemory)
322  free(_data);
323  }
324 
325  uint32 write(const void *dataPtr, uint32 dataSize) override {
326  if (dataSize == 0) {
327  return 0;
328  }
329  ensureCapacity(_length + dataSize);
330  if (_writePos + dataSize < _capacity) {
331  memcpy(_data + _writePos, dataPtr, dataSize);
332  } else {
333  memcpy(_data + _writePos, dataPtr, _capacity - _writePos);
334  const byte *shiftedPtr = (const byte *)dataPtr + _capacity - _writePos;
335  memcpy(_data, shiftedPtr, dataSize - (_capacity - _writePos));
336  }
337  _writePos = (_writePos + dataSize) % _capacity;
338  _pos += dataSize;
339  _length += dataSize;
340  if (_pos > _size)
341  _size = _pos;
342  return dataSize;
343  }
344 
345  uint32 read(void *dataPtr, uint32 dataSize) override {
346  if (_length < dataSize) {
347  dataSize = _length;
348  _eos = true;
349  }
350  if (dataSize == 0 || _capacity == 0) return 0;
351  if (_readPos + dataSize < _capacity) {
352  memcpy(dataPtr, _data + _readPos, dataSize);
353  } else {
354  memcpy(dataPtr, _data + _readPos, _capacity - _readPos);
355  byte *shiftedPtr = (byte *)dataPtr + _capacity - _readPos;
356  memcpy(shiftedPtr, _data, dataSize - (_capacity - _readPos));
357  }
358  _readPos = (_readPos + dataSize) % _capacity;
359  _length -= dataSize;
360  return dataSize;
361  }
362 
363  bool seek(int64 offset, int whence) override {
364  switch (whence) {
365  case SEEK_END:
366  // SEEK_END works just like SEEK_SET, only 'reversed',
367  // i.e. from the end.
368  offset = size() + offset;
369  // Fall through
370  case SEEK_SET:
371  // Fall through
372  default:
373  _writePos = offset;
374  _readPos = offset;
375  break;
376  case SEEK_CUR:
377  // Not supported
378  return false;
379  }
380 
381  // Post-Condition
382  _eos = (int64)_readPos >= size();
383  return true;
384  }
385 
386  int64 pos() const override { return _pos - _length; }
387  int64 size() const override { return _size; }
388  bool eos() const override { return _eos; }
389  void clearErr() override { _eos = false; }
390 
391  byte *getData() { return _data; }
392 };
393 
398 private:
399  const uint32 _bufSize;
400  byte *_ptrOrig;
401  byte *_ptr;
402  uint32 _pos;
403  bool _err;
404  bool _eos;
405  DisposeAfterUse::Flag _disposeMemory;
406 
407 public:
408  MemorySeekableReadWriteStream(byte *buf, uint32 len, DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) :
409  _ptrOrig(buf), _ptr(buf), _bufSize(len), _pos(0), _err(false), _eos(false), _disposeMemory(disposeMemory) {}
410 
412  if (_disposeMemory) {
413  free(_ptrOrig);
414  }
415  }
416 
417  uint32 write(const void *dataPtr, uint32 dataSize) override {
418  // Write at most as many bytes as are still available...
419  if (dataSize > _bufSize - _pos) {
420  dataSize = _bufSize - _pos;
421  // We couldn't write all the data => set error indicator
422  _err = true;
423  }
424  memcpy(_ptr, dataPtr, dataSize);
425  _ptr += dataSize;
426  _pos += dataSize;
427  return dataSize;
428  }
429 
430  int64 pos() const override { return _pos; }
431  int64 size() const override { return _bufSize; }
432 
433  bool eos() const override { return _eos; }
434 
435  bool err() const override { return _err; }
436  void clearErr() override { _err = false; }
437 
438  inline void rewind(int32 bytes) {
439  seek(pos() - bytes);
440  }
441 
442  byte peekByte() {
443  if (_bufSize - _pos <= 0) {
444  _eos = true;
445  return 0;
446  }
447  return *_ptr;
448  }
449 
450  uint32 read(void *dataPtr, uint32 dataSize) override {
451  // Read at most as many bytes as are still available...
452  if (dataSize > _bufSize - _pos) {
453  dataSize = _bufSize - _pos;
454  _eos = true;
455  }
456  memcpy(dataPtr, _ptr, dataSize);
457 
458  _ptr += dataSize;
459  _pos += dataSize;
460 
461  return dataSize;
462  }
463 
464  bool seek(int64 offset, int whence = SEEK_SET) override {
465  switch (whence) {
466  case SEEK_END:
467  // SEEK_END works just like SEEK_SET, only 'reversed',
468  // i.e. from the end.
469  offset = size() + offset;
470  // Fall through
471  case SEEK_SET:
472  // Fall through
473  default:
474  _ptr = _ptrOrig + offset;
475  _pos = offset;
476  break;
477  case SEEK_CUR:
478  _ptr += offset;
479  _pos += offset;
480  break;
481  }
482  // Post-Condition
483  if ((int32)_pos > size()) {
484  _pos = size();
485  _ptr = _ptrOrig + _pos;
486  }
487 
488  _eos = false;
489  return true;
490  }
491 };
492 
495 } // End of namespace Common
496 
497 #endif
void clearErr() override
Definition: memstream.h:147
Definition: stream.h:854
int64 size() const override
Definition: memstream.h:144
bool err() const override
Definition: memstream.h:146
uint32 write(const void *dataPtr, uint32 dataSize) override
Definition: memstream.h:417
bool eos() const override
Definition: memstream.h:388
int64 size() const override
Definition: memstream.h:431
int64 size() const override
Definition: memstream.h:250
Definition: memstream.h:397
uint32 read(void *dataPtr, uint32 dataSize) override
Definition: memstream.h:345
bool seek(int64 offset, int whence=SEEK_SET) override
Definition: memstream.h:464
int64 pos() const
Definition: memstream.h:92
int64 pos() const override
Definition: memstream.h:249
Definition: memstream.h:194
uint32 write(const void *dataPtr, uint32 dataSize) override
Definition: memstream.h:130
Definition: stream.h:745
int64 size() const override
Definition: memstream.h:109
bool seek(int64 offset, int whence=SEEK_SET) override
Definition: memstream.h:149
Definition: memstream.h:103
PointerType get() const
Definition: ptr.h:229
int64 pos() const override
Definition: memstream.h:430
void clearErr()
Definition: memstream.h:90
bool seek(int64 offset, int whence) override
Definition: memstream.h:363
bool seek(int64 offs, int whence=SEEK_SET) override
Definition: memstream.h:254
int64 pos() const override
Definition: memstream.h:386
bool err() const override
Definition: memstream.h:435
uint32 read(void *dataPtr, uint32 dataSize) override
Definition: memstream.h:450
static size_t roundUpCapacity(size_t capacity)
Definition: memstream.h:223
uint32 write(const void *dataPtr, uint32 dataSize) override
Definition: memstream.h:325
bool seek(int64 offs, int whence=SEEK_SET) override
Definition: memstream.h:111
int64 pos() const override
Definition: memstream.h:108
Definition: algorithm.h:29
int64 size() const
Definition: memstream.h:93
void clearErr() override
Definition: memstream.h:389
bool eos() const override
Definition: memstream.h:433
uint32 read(void *dataPtr, uint32 dataSize)
MemoryReadStream(const byte *dataPtr, uint32 dataSize, DisposeAfterUse::Flag disposeMemory=DisposeAfterUse::NO)
Definition: memstream.h:73
Definition: memstream.h:283
bool eos() const
Definition: memstream.h:89
Out move(In first, In last, Out dst)
Definition: algorithm.h:109
Definition: memstream.h:43
bool skip(uint32 offset) override
Definition: memstream.h:113
int64 size() const override
Definition: memstream.h:387
Definition: stream.h:351
Definition: stream.h:944
bool seek(int64 offs, int whence=SEEK_SET)
uint32 write(const void *dataPtr, uint32 dataSize) override
Definition: memstream.h:237
T MAX(T a, T b)
Definition: util.h:64
int64 pos() const override
Definition: memstream.h:143
Definition: memstream.h:120
void clearErr() override
Definition: memstream.h:436
Definition: memstream.h:155
bool seek(int64 offset, int whence=SEEK_SET) override
Definition: memstream.h:161