/* * CSerializer.h, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */ #pragma once #include "../ConstTransitivePtr.h" #include "../GameConstants.h" const ui32 SERIALIZATION_VERSION = 774; const ui32 MINIMAL_SERIALIZATION_VERSION = 753; const std::string SAVEGAME_MAGIC = "VCMISVG"; class CHero; class CGHeroInstance; class CGObjectInstance; class CGameState; class LibClasses; extern DLL_LINKAGE LibClasses * VLC; struct TypeComparer { bool operator()(const std::type_info *a, const std::type_info *b) const { //#ifndef __APPLE__ // return a->before(*b); //#else return strcmp(a->name(), b->name()) < 0; //#endif } }; template struct VectorizedObjectInfo { const std::vector > *vector; //pointer to the appropriate vector std::function idRetriever; VectorizedObjectInfo(const std::vector< ConstTransitivePtr > *Vector, std::function IdGetter) :vector(Vector), idRetriever(IdGetter) { } }; /// Base class for serializers capable of reading or writing data class DLL_LINKAGE CSerializer { template static si32 idToNumber(const T &t, typename boost::enable_if >::type * dummy = 0) { return t; } template static NT idToNumber(const BaseForID &t) { return t.getNum(); } template void registerVectoredType(const std::vector *Vector, const std::function &idRetriever) { vectors[&typeid(T)] = VectorizedObjectInfo(Vector, idRetriever); } template void registerVectoredType(const std::vector > *Vector, const std::function &idRetriever) { vectors[&typeid(T)] = VectorizedObjectInfo(Vector, idRetriever); } typedef std::map TTypeVecMap; TTypeVecMap vectors; //entry must be a pointer to vector containing pointers to the objects of key type public: bool smartVectorMembersSerialization; bool sendStackInstanceByIds; CSerializer(); ~CSerializer(); virtual void reportState(CLogger * out){}; template const VectorizedObjectInfo *getVectorizedTypeInfo() { const std::type_info *myType = nullptr; myType = &typeid(T); TTypeVecMap::iterator i = vectors.find(myType); if(i == vectors.end()) return nullptr; else { assert(!i->second.empty()); assert(i->second.type() == typeid(VectorizedObjectInfo)); VectorizedObjectInfo *ret = &(boost::any_cast&>(i->second)); return ret; } } template T* getVectorItemFromId(const VectorizedObjectInfo &oInfo, U id) const { si32 idAsNumber = idToNumber(id); assert(oInfo.vector); assert(static_cast(oInfo.vector->size()) > idAsNumber); return const_cast((*oInfo.vector)[idAsNumber].get()); } template U getIdFromVectorItem(const VectorizedObjectInfo &oInfo, const T* obj) const { if(!obj) return U(-1); return oInfo.idRetriever(*obj); } void addStdVecItems(CGameState *gs, LibClasses *lib = VLC); }; /// Helper to detect classes with user-provided serialize(S&, int version) method template struct is_serializeable { typedef char (&Yes)[1]; typedef char (&No)[2]; template static Yes test(U * data, S* arg1 = 0, typename std::enable_ifserialize(*arg1, int(0))) >::value>::type * = 0); static No test(...); static const bool value = sizeof(Yes) == sizeof(is_serializeable::test((typename std::remove_reference::type>::type*)0)); }; template //metafunction returning CGObjectInstance if T is its derivate or T elsewise struct VectorizedTypeFor { typedef typename //if boost::mpl::eval_if, boost::mpl::identity, //else if boost::mpl::eval_if, boost::mpl::identity, //else boost::mpl::identity > >::type type; }; template struct VectorizedIDType { typedef typename //if boost::mpl::eval_if, boost::mpl::identity, //else if boost::mpl::eval_if, boost::mpl::identity, //else if boost::mpl::eval_if, boost::mpl::identity, //else if boost::mpl::eval_if, boost::mpl::identity, //else if boost::mpl::eval_if, boost::mpl::identity, //else if boost::mpl::eval_if, boost::mpl::identity, //else boost::mpl::identity > > > > > >::type type; }; /// Base class for deserializers class IBinaryReader : public virtual CSerializer { public: virtual int read(void * data, unsigned size) = 0; }; /// Base class for serializers class IBinaryWriter : public virtual CSerializer { public: virtual int write(const void * data, unsigned size) = 0; };