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  ensureCapacity(_length + dataSize);
327  if (_writePos + dataSize < _capacity) {
328  memcpy(_data + _writePos, dataPtr, dataSize);
329  } else {
330  memcpy(_data + _writePos, dataPtr, _capacity - _writePos);
331  const byte *shiftedPtr = (const byte *)dataPtr + _capacity - _writePos;
332  memcpy(_data, shiftedPtr, dataSize - (_capacity - _writePos));
333  }
334  _writePos = (_writePos + dataSize) % _capacity;
335  _pos += dataSize;
336  _length += dataSize;
337  if (_pos > _size)
338  _size = _pos;
339  return dataSize;
340  }
341 
342  uint32 read(void *dataPtr, uint32 dataSize) override {
343  if (_length < dataSize) {
344  dataSize = _length;
345  _eos = true;
346  }
347  if (dataSize == 0 || _capacity == 0) return 0;
348  if (_readPos + dataSize < _capacity) {
349  memcpy(dataPtr, _data + _readPos, dataSize);
350  } else {
351  memcpy(dataPtr, _data + _readPos, _capacity - _readPos);
352  byte *shiftedPtr = (byte *)dataPtr + _capacity - _readPos;
353  memcpy(shiftedPtr, _data, dataSize - (_capacity - _readPos));
354  }
355  _readPos = (_readPos + dataSize) % _capacity;
356  _length -= dataSize;
357  return dataSize;
358  }
359 
360  bool seek(int64 offset, int whence) override {
361  switch (whence) {
362  case SEEK_END:
363  // SEEK_END works just like SEEK_SET, only 'reversed',
364  // i.e. from the end.
365  offset = size() + offset;
366  // Fall through
367  case SEEK_SET:
368  // Fall through
369  default:
370  _writePos = offset;
371  _readPos = offset;
372  break;
373  case SEEK_CUR:
374  // Not supported
375  return false;
376  }
377 
378  // Post-Condition
379  _eos = (int64)_readPos >= size();
380  return true;
381  }
382 
383  int64 pos() const override { return _pos - _length; }
384  int64 size() const override { return _size; }
385  bool eos() const override { return _eos; }
386  void clearErr() override { _eos = false; }
387 
388  byte *getData() { return _data; }
389 };
390 
395 private:
396  const uint32 _bufSize;
397  byte *_ptrOrig;
398  byte *_ptr;
399  uint32 _pos;
400  bool _err;
401  bool _eos;
402  DisposeAfterUse::Flag _disposeMemory;
403 
404 public:
405  MemorySeekableReadWriteStream(byte *buf, uint32 len, DisposeAfterUse::Flag disposeMemory = DisposeAfterUse::NO) :
406  _ptrOrig(buf), _ptr(buf), _bufSize(len), _pos(0), _err(false), _eos(false), _disposeMemory(disposeMemory) {}
407 
409  if (_disposeMemory) {
410  free(_ptrOrig);
411  }
412  }
413 
414  uint32 write(const void *dataPtr, uint32 dataSize) override {
415  // Write at most as many bytes as are still available...
416  if (dataSize > _bufSize - _pos) {
417  dataSize = _bufSize - _pos;
418  // We couldn't write all the data => set error indicator
419  _err = true;
420  }
421  memcpy(_ptr, dataPtr, dataSize);
422  _ptr += dataSize;
423  _pos += dataSize;
424  return dataSize;
425  }
426 
427  int64 pos() const override { return _pos; }
428  int64 size() const override { return _bufSize; }
429 
430  bool eos() const override { return _eos; }
431 
432  bool err() const override { return _err; }
433  void clearErr() override { _err = false; }
434 
435  inline void rewind(int32 bytes) {
436  seek(pos() - bytes);
437  }
438 
439  byte peekByte() {
440  if (_bufSize - _pos <= 0) {
441  _eos = true;
442  return 0;
443  }
444  return *_ptr;
445  }
446 
447  uint32 read(void *dataPtr, uint32 dataSize) override {
448  // Read at most as many bytes as are still available...
449  if (dataSize > _bufSize - _pos) {
450  dataSize = _bufSize - _pos;
451  _eos = true;
452  }
453  memcpy(dataPtr, _ptr, dataSize);
454 
455  _ptr += dataSize;
456  _pos += dataSize;
457 
458  return dataSize;
459  }
460 
461  bool seek(int64 offset, int whence = SEEK_SET) override {
462  switch (whence) {
463  case SEEK_END:
464  // SEEK_END works just like SEEK_SET, only 'reversed',
465  // i.e. from the end.
466  offset = size() + offset;
467  // Fall through
468  case SEEK_SET:
469  // Fall through
470  default:
471  _ptr = _ptrOrig + offset;
472  _pos = offset;
473  break;
474  case SEEK_CUR:
475  _ptr += offset;
476  _pos += offset;
477  break;
478  }
479  // Post-Condition
480  if ((int32)_pos > size()) {
481  _pos = size();
482  _ptr = _ptrOrig + _pos;
483  }
484 
485  _eos = false;
486  return true;
487  }
488 };
489 
492 } // End of namespace Common
493 
494 #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:414
bool eos() const override
Definition: memstream.h:385
int64 size() const override
Definition: memstream.h:428
int64 size() const override
Definition: memstream.h:250
Definition: memstream.h:394
uint32 read(void *dataPtr, uint32 dataSize) override
Definition: memstream.h:342
bool seek(int64 offset, int whence=SEEK_SET) override
Definition: memstream.h:461
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:427
void clearErr()
Definition: memstream.h:90
bool seek(int64 offset, int whence) override
Definition: memstream.h:360
bool seek(int64 offs, int whence=SEEK_SET) override
Definition: memstream.h:254
int64 pos() const override
Definition: memstream.h:383
bool err() const override
Definition: memstream.h:432
uint32 read(void *dataPtr, uint32 dataSize) override
Definition: memstream.h:447
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:386
bool eos() const override
Definition: memstream.h:430
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:384
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:62
int64 pos() const override
Definition: memstream.h:143
Definition: memstream.h:120
void clearErr() override
Definition: memstream.h:433
Definition: memstream.h:155
bool seek(int64 offset, int whence=SEEK_SET) override
Definition: memstream.h:161