ScummVM API documentation
serializer.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_SERIALIZER_H
23 #define COMMON_SERIALIZER_H
24 
25 #include "common/stream.h"
26 #include "common/str.h"
27 #include "common/data-io.h"
28 
29 namespace Common {
30 
40 #define VER(x) Common::Serializer::Version(x)
41 
42 #define SYNC_AS(SUFFIX,TYPE,SIZE) \
43  template<typename T> \
44  void syncAs ## SUFFIX(T &val, Version minVersion = 0, Version maxVersion = kLastVersion) { \
45  if (_version < minVersion || _version > maxVersion) \
46  return; \
47  if (_loadStream) \
48  val = static_cast<T>(_loadStream->read ## SUFFIX()); \
49  else { \
50  TYPE tmp = val; \
51  _saveStream->write ## SUFFIX(tmp); \
52  } \
53  _bytesSynced += SIZE; \
54  }
55 
56 #define SYNC_PRIMITIVE(suffix) \
57  template <typename T> \
58  static inline void suffix(Serializer &s, T &value) { \
59  s.syncAs##suffix(value); \
60  }
61 
80 class Serializer {
81 public:
82  typedef uint32 Version;
83  static const Version kLastVersion = 0xFFFFFFFF;
84 
85  SYNC_PRIMITIVE(Uint32LE)
86  SYNC_PRIMITIVE(Uint32BE)
87  SYNC_PRIMITIVE(Sint32LE)
88  SYNC_PRIMITIVE(Sint32BE)
89  SYNC_PRIMITIVE(FloatLE)
90  SYNC_PRIMITIVE(FloatBE)
91  SYNC_PRIMITIVE(DoubleLE)
92  SYNC_PRIMITIVE(DoubleBE)
93  SYNC_PRIMITIVE(Uint16LE)
94  SYNC_PRIMITIVE(Uint16BE)
95  SYNC_PRIMITIVE(Sint16LE)
96  SYNC_PRIMITIVE(Sint16BE)
97  SYNC_PRIMITIVE(Byte)
98  SYNC_PRIMITIVE(SByte)
99 
100 protected:
101  SeekableReadStream *_loadStream;
102  WriteStream *_saveStream;
103 
104  uint _bytesSynced;
105 
106  Version _version;
107 
108 public:
110  : _loadStream(in), _saveStream(out), _bytesSynced(0), _version(0) {
111  assert(in || out);
112  }
113  virtual ~Serializer() {}
114 
115  inline bool isSaving() { return (_saveStream != 0); }
116  inline bool isLoading() { return (_loadStream != 0); }
117 
118  SYNC_AS(Byte, byte, 1)
119  SYNC_AS(SByte, int8, 1)
120 
121  SYNC_AS(Uint16LE, uint16, 2)
122  SYNC_AS(Uint16BE, uint16, 2)
123  SYNC_AS(Sint16LE, int16, 2)
124  SYNC_AS(Sint16BE, int16, 2)
125 
126  SYNC_AS(Uint32LE, uint32, 4)
127  SYNC_AS(Uint32BE, uint32, 4)
128  SYNC_AS(Sint32LE, int32, 4)
129  SYNC_AS(Sint32BE, int32, 4)
130  SYNC_AS(FloatLE, float, 4)
131  SYNC_AS(FloatBE, float, 4)
132 
133  SYNC_AS(DoubleLE, double, 8)
134  SYNC_AS(DoubleBE, double, 8)
135 
136 
141  bool err() const {
142  if (_saveStream)
143  return _saveStream->err();
144  else
145  return _loadStream->err();
146  }
147 
151  void clearErr() {
152  if (_saveStream)
153  _saveStream->clearErr();
154  else
155  _loadStream->clearErr();
156  }
157 
163  bool syncVersion(Version currentVersion) {
164  _version = currentVersion;
165  syncAsUint32LE(_version);
166  return _version <= currentVersion;
167  }
168 
173  Version getVersion() const { return _version; }
174 
178  void setVersion(Version version) { _version = version; }
179 
183  uint bytesSynced() const { return _bytesSynced; }
184 
189  void skip(uint32 size, Version minVersion = 0, Version maxVersion = kLastVersion) {
190  if (_version < minVersion || _version > maxVersion)
191  return; // Ignore anything which is not supposed to be present in this save game version
192 
193  _bytesSynced += size;
194  if (isLoading())
195  _loadStream->skip(size);
196  else {
197  while (size--)
198  _saveStream->writeByte(0);
199  }
200  }
201 
205  void syncBytes(byte *buf, uint32 size, Version minVersion = 0, Version maxVersion = kLastVersion) {
206  if (_version < minVersion || _version > maxVersion)
207  return; // Ignore anything which is not supposed to be present in this save game version
208 
209  if (isLoading())
210  _loadStream->read(buf, size);
211  else
212  _saveStream->write(buf, size);
213  _bytesSynced += size;
214  }
215 
228  bool matchBytes(const char *magic, byte size, Version minVersion = 0, Version maxVersion = kLastVersion) {
229  if (_version < minVersion || _version > maxVersion)
230  return true; // Ignore anything which is not supposed to be present in this save game version
231 
232  bool match;
233  if (isSaving()) {
234  _saveStream->write(magic, size);
235  match = true;
236  } else {
237  char buf[256];
238  _loadStream->read(buf, size);
239  match = (0 == memcmp(buf, magic, size));
240  }
241  _bytesSynced += size;
242  return match;
243  }
244 
249  void syncString(String &str, Version minVersion = 0, Version maxVersion = kLastVersion) {
250  if (_version < minVersion || _version > maxVersion)
251  return; // Ignore anything which is not supposed to be present in this save game version
252 
253  if (isLoading()) {
254  char c;
255  str.clear();
256  while ((c = _loadStream->readByte())) {
257  str += c;
258  _bytesSynced++;
259  }
260  _bytesSynced++;
261  } else {
262  _saveStream->writeString(str);
263  _saveStream->writeByte(0);
264  _bytesSynced += str.size() + 1;
265  }
266  }
267 
271  void syncString32(U32String &str, Version minVersion = 0, Version maxVersion = kLastVersion) {
272  if (_version < minVersion || _version > maxVersion)
273  return; // Ignore anything which is not supposed to be present in this save game version
274 
275  uint32 len = str.size();
276 
277  syncAsUint32LE(len);
278 
279  if (isLoading()) {
280  U32String::value_type *sl = new U32String::value_type[len];
281  for (uint i = 0; i < len; i++)
282  syncAsUint32LE(sl[i]);
283  str = U32String(sl, len);
284  delete[] sl;
285  } else {
286  for (uint i = 0; i < len; i++)
287  _saveStream->writeUint32LE(str[i]);
288  _bytesSynced += 4 * len;
289  }
290  }
291 
292  template <typename T>
293  void syncArray(T *arr, size_t entries, void (*serializer)(Serializer &, T &), Version minVersion = 0, Version maxVersion = kLastVersion) {
294  if (_version < minVersion || _version > maxVersion)
295  return;
296 
297  for (size_t i = 0; i < entries; ++i) {
298  serializer(*this, arr[i]);
299  }
300  }
301 
305  template<class TDataFormat, class... T>
306  void syncMultiple(const TDataFormat &dataFormat, T &...values) {
307  const TDataFormat dataFormatCopy = dataFormat; // Copy to help compiler alias analysis, parameter is const ref to ensure TDataFormat is a concrete type
308 
309  byte buffer[DataMultipleIO<TDataFormat, T...>::kMaxSize];
310  const uint actualSize = DataMultipleIO<TDataFormat, T...>::computeSize(dataFormatCopy);
311 
312  if (isLoading()) {
313  syncBytes(buffer, actualSize);
314  DataMultipleIO<TDataFormat, T...>::decode(dataFormatCopy, buffer, values...);
315  } else {
316  DataMultipleIO<TDataFormat, T...>::encode(dataFormatCopy, buffer, values...);
317  syncBytes(buffer, actualSize);
318  }
319  }
320 
324  template<class... T>
325  inline void syncMultipleEndian(bool isLittle, T &...values) {
326  this->syncMultiple<EndianStorageFormat, T...>(isLittle ? EndianStorageFormat::Little : EndianStorageFormat::Big, values...);
327  }
328 
332  template<class... T>
333  inline void syncMultipleLE(T &...values) {
334  this->syncMultiple<EndianStorageFormat, T...>(EndianStorageFormat::Little, values...);
335  }
336 
340  template<class... T>
341  inline void syncMultipleBE(T &...values) {
342  this->syncMultiple<EndianStorageFormat, T...>(EndianStorageFormat::Big, values...);
343  }
344 };
345 
346 #undef SYNC_PRIMITIVE
347 #undef SYNC_AS
348 
349 
350 // Mixin class / interface
351 // TODO: Maybe rename this to Syncable ?
353 public:
354  virtual ~Serializable() {}
355 
356  // Maybe rename this method to "syncWithSerializer" or "syncUsingSerializer" ?
357  virtual void saveLoadWithSerializer(Serializer &ser) = 0;
358 };
359 
362 } // End of namespace Common
363 
364 #endif
void syncBytes(byte *buf, uint32 size, Version minVersion=0, Version maxVersion=kLastVersion)
Definition: serializer.h:205
Definition: str.h:59
virtual bool err() const
Definition: stream.h:61
Definition: data-io.h:167
void writeUint32LE(uint32 value)
Definition: stream.h:159
Definition: stream.h:77
virtual void clearErr()
Definition: stream.h:71
uint bytesSynced() const
Definition: serializer.h:183
void clearErr()
Definition: serializer.h:151
Definition: stream.h:745
bool syncVersion(Version currentVersion)
Definition: serializer.h:163
void syncMultipleLE(T &...values)
Definition: serializer.h:333
Definition: serializer.h:80
byte readByte()
Definition: stream.h:434
void syncMultipleBE(T &...values)
Definition: serializer.h:341
Definition: ustr.h:57
void setVersion(Version version)
Definition: serializer.h:178
void syncMultiple(const TDataFormat &dataFormat, T &...values)
Definition: serializer.h:306
void syncString(String &str, Version minVersion=0, Version maxVersion=kLastVersion)
Definition: serializer.h:249
Definition: algorithm.h:29
bool err() const
Definition: serializer.h:141
Definition: serializer.h:352
void syncString32(U32String &str, Version minVersion=0, Version maxVersion=kLastVersion)
Definition: serializer.h:271
Version getVersion() const
Definition: serializer.h:173
void syncMultipleEndian(bool isLittle, T &...values)
Definition: serializer.h:325
bool matchBytes(const char *magic, byte size, Version minVersion=0, Version maxVersion=kLastVersion)
Definition: serializer.h:228
void skip(uint32 size, Version minVersion=0, Version maxVersion=kLastVersion)
Definition: serializer.h:189
virtual uint32 write(const void *dataPtr, uint32 dataSize)=0
void writeString(const String &str)
virtual uint32 read(void *dataPtr, uint32 dataSize)=0
virtual bool skip(uint32 offset)
Definition: stream.h:793
void writeByte(byte value)
Definition: stream.h:140