ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

serializer.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_SERIALIZER_H
00024 #define COMMON_SERIALIZER_H
00025 
00026 #include "common/stream.h"
00027 #include "common/str.h"
00028 
00029 namespace Common {
00030 
00031 #define VER(x) Common::Serializer::Version(x)
00032 
00033 #define SYNC_AS(SUFFIX,TYPE,SIZE) \
00034     template<typename T> \
00035     void syncAs ## SUFFIX(T &val, Version minVersion = 0, Version maxVersion = kLastVersion) { \
00036         if (_version < minVersion || _version > maxVersion) \
00037             return; \
00038         if (_loadStream) \
00039             val = static_cast<T>(_loadStream->read ## SUFFIX()); \
00040         else { \
00041             TYPE tmp = val; \
00042             _saveStream->write ## SUFFIX(tmp); \
00043         } \
00044         _bytesSynced += SIZE; \
00045     }
00046 
00047 #define SYNC_PRIMITIVE(suffix) \
00048     template <typename T> \
00049     static inline void suffix(Serializer &s, T &value) { \
00050         s.syncAs##suffix(value); \
00051     }
00052 
00071 class Serializer {
00072 public:
00073     typedef uint32 Version;
00074     static const Version kLastVersion = 0xFFFFFFFF;
00075 
00076     SYNC_PRIMITIVE(Uint32LE)
00077     SYNC_PRIMITIVE(Uint32BE)
00078     SYNC_PRIMITIVE(Sint32LE)
00079     SYNC_PRIMITIVE(Sint32BE)
00080     SYNC_PRIMITIVE(Uint16LE)
00081     SYNC_PRIMITIVE(Uint16BE)
00082     SYNC_PRIMITIVE(Sint16LE)
00083     SYNC_PRIMITIVE(Sint16BE)
00084     SYNC_PRIMITIVE(Byte)
00085     SYNC_PRIMITIVE(SByte)
00086 
00087 protected:
00088     SeekableReadStream *_loadStream;
00089     WriteStream *_saveStream;
00090 
00091     uint _bytesSynced;
00092 
00093     Version _version;
00094 
00095 public:
00096     Serializer(SeekableReadStream *in, WriteStream *out)
00097         : _loadStream(in), _saveStream(out), _bytesSynced(0), _version(0) {
00098         assert(in || out);
00099     }
00100     virtual ~Serializer() {}
00101 
00102     inline bool isSaving() { return (_saveStream != 0); }
00103     inline bool isLoading() { return (_loadStream != 0); }
00104 
00105     // WORKAROUND for bugs #2892515 "BeOS: tinsel does not compile" and
00106     // #2892510 "BeOS: Cruise does not compile". gcc 2.95.3, which is used
00107     // for BeOS fails due to an internal compiler error, when we place the
00108     // following function definitions in another place. Before this work-
00109     // around the following SYNC_AS definitions were placed at the end
00110     // of the class declaration. This caused an internal compiler error
00111     // in the line "syncAsUint32LE(_version);" of
00112     // "bool syncVersion(Version currentVersion)".
00113     SYNC_AS(Byte, byte, 1)
00114     SYNC_AS(SByte, int8, 1)
00115 
00116     SYNC_AS(Uint16LE, uint16, 2)
00117     SYNC_AS(Uint16BE, uint16, 2)
00118     SYNC_AS(Sint16LE, int16, 2)
00119     SYNC_AS(Sint16BE, int16, 2)
00120 
00121     SYNC_AS(Uint32LE, uint32, 4)
00122     SYNC_AS(Uint32BE, uint32, 4)
00123     SYNC_AS(Sint32LE, int32, 4)
00124     SYNC_AS(Sint32BE, int32, 4)
00125 
00131     bool err() const {
00132         if (_saveStream)
00133             return _saveStream->err();
00134         else
00135             return _loadStream->err();
00136     }
00137 
00141     void clearErr() {
00142         if (_saveStream)
00143             _saveStream->clearErr();
00144         else
00145             _loadStream->clearErr();
00146     }
00147 
00153     bool syncVersion(Version currentVersion) {
00154         _version = currentVersion;
00155         syncAsUint32LE(_version);
00156         return _version <= currentVersion;
00157     }
00158 
00163     Version getVersion() const { return _version; }
00164 
00168     void setVersion(Version version) { _version = version; }
00169 
00173     uint bytesSynced() const { return _bytesSynced; }
00174 
00179     void skip(uint32 size, Version minVersion = 0, Version maxVersion = kLastVersion) {
00180         if (_version < minVersion || _version > maxVersion)
00181             return; // Ignore anything which is not supposed to be present in this save game version
00182 
00183         _bytesSynced += size;
00184         if (isLoading())
00185             _loadStream->skip(size);
00186         else {
00187             while (size--)
00188                 _saveStream->writeByte(0);
00189         }
00190     }
00191 
00195     void syncBytes(byte *buf, uint32 size, Version minVersion = 0, Version maxVersion = kLastVersion) {
00196         if (_version < minVersion || _version > maxVersion)
00197             return; // Ignore anything which is not supposed to be present in this save game version
00198 
00199         if (isLoading())
00200             _loadStream->read(buf, size);
00201         else
00202             _saveStream->write(buf, size);
00203         _bytesSynced += size;
00204     }
00205 
00218     bool matchBytes(const char *magic, byte size, Version minVersion = 0, Version maxVersion = kLastVersion) {
00219         if (_version < minVersion || _version > maxVersion)
00220             return true; // Ignore anything which is not supposed to be present in this save game version
00221 
00222         bool match;
00223         if (isSaving()) {
00224             _saveStream->write(magic, size);
00225             match = true;
00226         } else {
00227             char buf[256];
00228             _loadStream->read(buf, size);
00229             match = (0 == memcmp(buf, magic, size));
00230         }
00231         _bytesSynced += size;
00232         return match;
00233     }
00234 
00239     void syncString(String &str, Version minVersion = 0, Version maxVersion = kLastVersion) {
00240         if (_version < minVersion || _version > maxVersion)
00241             return; // Ignore anything which is not supposed to be present in this save game version
00242 
00243         if (isLoading()) {
00244             char c;
00245             str.clear();
00246             while ((c = _loadStream->readByte())) {
00247                 str += c;
00248                 _bytesSynced++;
00249             }
00250             _bytesSynced++;
00251         } else {
00252             _saveStream->writeString(str);
00253             _saveStream->writeByte(0);
00254             _bytesSynced += str.size() + 1;
00255         }
00256     }
00257 
00258     template <typename T>
00259     void syncArray(T *arr, size_t entries, void (*serializer)(Serializer &, T &), Version minVersion = 0, Version maxVersion = kLastVersion) {
00260         if (_version < minVersion || _version > maxVersion)
00261             return;
00262 
00263         for (size_t i = 0; i < entries; ++i) {
00264             serializer(*this, arr[i]);
00265         }
00266     }
00267 };
00268 
00269 #undef SYNC_PRIMITIVE
00270 #undef SYNC_AS
00271 
00272 
00273 // Mixin class / interface
00274 // TODO: Maybe rename this to Syncable ?
00275 class Serializable {
00276 public:
00277     virtual ~Serializable() {}
00278 
00279     // Maybe rename this method to "syncWithSerializer" or "syncUsingSerializer" ?
00280     virtual void saveLoadWithSerializer(Serializer &ser) = 0;
00281 };
00282 
00283 
00284 } // End of namespace Common
00285 
00286 #endif


Generated on Sat Mar 23 2019 05:02:10 for ResidualVM by doxygen 1.7.1
curved edge   curved edge