// // Copyright (C) 2014 Christian Schüller // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. // ----------------------------------------------------------------------------- // Functions to save and load a serialization of fundamental c++ data types to // and from a binary file. STL containers, Eigen matrix types and nested data // structures are also supported. To serialize a user defined class implement // the interface Serializable or SerializableBase. // // See also: xml/serialize_xml.h // ----------------------------------------------------------------------------- // TODOs: // * non-intrusive serialization example // * arbitrary pointer graph structures // * cross-platform compatibility (big-, little-endian) // ----------------------------------------------------------------------------- #ifndef IGL_SERIALIZE_H #define IGL_SERIALIZE_H #include #include #include #include #include #include #include #include #include #include #include #include #include "igl_inline.h" // non-intrusive serialization helper macros #define SERIALIZE_TYPE(Type,Params) \ namespace igl { namespace serialization { \ void _serialization(bool s,Type& obj,std::vector& buffer) {Params} \ void serialize(const Type& obj,std::vector& buffer) { \ _serialization(true,const_cast(obj),buffer); \ } \ void deserialize(Type& obj,const std::vector& buffer) { \ _serialization(false,obj,const_cast&>(buffer)); \ } \ }} #define SERIALIZE_MEMBER(Object) ::igl::serializer(s,obj.##Object,std::string(#Object),buffer); #define SERIALIZE_MEMBER_NAME(Object,Name) ::igl::serializer(s,obj.##Object,std::string(Name),buffer); namespace igl { struct IndexedPointerBase; // Serializes the given object either to a file or to a provided buffer // Templates: // T type of the object to serialize // Inputs: // obj object to serialize // objectName unique object name,used for the identification // overwrite set to true to overwrite an existing file // filename name of the file containing the serialization // Outputs: // buffer binary serialization // template IGL_INLINE bool serialize(const T& obj,const std::string& filename); template IGL_INLINE bool serialize(const T& obj,const std::string& objectName,const std::string& filename,bool overwrite = false); template IGL_INLINE bool serialize(const T& obj,const std::string& objectName,std::vector& buffer); // Deserializes the given data from a file or buffer back to the provided object // // Templates: // T type of the object to serialize // Inputs: // buffer binary serialization // objectName unique object name, used for the identification // filename name of the file containing the serialization // Outputs: // obj object to load back serialization to // template IGL_INLINE bool deserialize(T& obj,const std::string& filename); template IGL_INLINE bool deserialize(T& obj,const std::string& objectName,const std::string& filename); template IGL_INLINE bool deserialize(T& obj,const std::string& objectName,const std::vector& buffer); // Wrapper to expose both, the de- and serialization as one function // template IGL_INLINE bool serializer(bool serialize,T& obj,std::string& filename); template IGL_INLINE bool serializer(bool serialize,T& obj,std::string& objectName,const std::string& filename,bool overwrite = false); template IGL_INLINE bool serializer(bool serialize,T& obj,std::string& objectName,std::vector& buffer); // User defined types have to either overload the function igl::serialization::serialize() // and igl::serialization::deserialize() for their type (non-intrusive serialization): // // namespace igl { namespace serialization // { // IGL_INLINE void serialize(const UserType& obj,std::vector& buffer) { // ::igl::serialize(obj.var,"var",buffer); // } // // IGL_INLINE void deserialize(UserType& obj,const std::vector& buffer) { // ::igl::deserialize(obj.var,"var",buffer); // } // }} // // or use this macro for convenience: // // SERIALIZE_TYPE(UserType, // SERIALIZE_MEMBER(var) // ) // // or to derive from the class Serializable and add their the members // in InitSerialization like the following: // // class UserType : public igl::Serializable { // // int var; // // void InitSerialization() { // this->Add(var,"var"); // } // }; // Base interface for user defined types struct SerializableBase { virtual void Serialize(std::vector& buffer) const = 0; virtual void Deserialize(const std::vector& buffer) = 0; }; // Convenient interface for user defined types class Serializable: public SerializableBase { private: template struct SerializationObject : public SerializableBase { bool Binary; std::string Name; std::unique_ptr Object; void Serialize(std::vector& buffer) const override { igl::serialize(*Object,Name,buffer); } void Deserialize(const std::vector& buffer) override { igl::deserialize(*Object,Name,buffer); } }; mutable bool initialized; mutable std::vector objects; public: // Override this function to add your member variables which should be serialized IGL_INLINE virtual void InitSerialization() = 0; // Following functions can be overridden to handle the specific events. // Return false to prevent the de-/serialization of an object. IGL_INLINE virtual bool PreSerialization() const; IGL_INLINE virtual void PostSerialization() const; IGL_INLINE virtual bool PreDeserialization(); IGL_INLINE virtual void PostDeserialization(); // Default implementation of SerializableBase interface IGL_INLINE void Serialize(std::vector& buffer) const override final; IGL_INLINE void Deserialize(const std::vector& buffer) override final; // Default constructor, destructor, assignment and copy constructor IGL_INLINE Serializable(); IGL_INLINE Serializable(const Serializable& obj); IGL_INLINE ~Serializable(); IGL_INLINE Serializable& operator=(const Serializable& obj); // Use this function to add your variables which should be serialized template IGL_INLINE void Add(T& obj,std::string name,bool binary = false); }; // structure for pointer handling struct IndexedPointerBase { enum { BEGIN,END } Type; size_t Index; }; template struct IndexedPointer: public IndexedPointerBase { const T* Object; }; // internal functions namespace serialization { // compile time type checks template struct is_stl_container { static const bool value = false; }; template struct is_stl_container > { static const bool value = true; }; template struct is_stl_container > { static const bool value = true; }; template struct is_stl_container > { static const bool value = true; }; template struct is_stl_container > { static const bool value = true; }; template struct is_eigen_type { static const bool value = false; }; template struct is_eigen_type > { static const bool value = true; }; template struct is_eigen_type > { static const bool value = true; }; template struct is_smart_ptr { static const bool value = false; }; template struct is_smart_ptr > { static const bool value = true; }; template struct is_smart_ptr > { static const bool value = true; }; template struct is_smart_ptr > { static const bool value = true; }; template struct is_serializable { static const bool value = std::is_fundamental::value || std::is_same::value || std::is_base_of::value || is_stl_container::value || is_eigen_type::value || std::is_pointer::value || serialization::is_smart_ptr::value; }; // non serializable types template IGL_INLINE typename std::enable_if::value,size_t>::type getByteSize(const T& obj); template IGL_INLINE typename std::enable_if::value>::type serialize(const T& obj,std::vector& buffer,std::vector::iterator& iter); template IGL_INLINE typename std::enable_if::value>::type deserialize(T& obj,std::vector::const_iterator& iter); // fundamental types template IGL_INLINE typename std::enable_if::value,size_t>::type getByteSize(const T& obj); template IGL_INLINE typename std::enable_if::value>::type serialize(const T& obj,std::vector& buffer,std::vector::iterator& iter); template IGL_INLINE typename std::enable_if::value>::type deserialize(T& obj,std::vector::const_iterator& iter); // std::string IGL_INLINE size_t getByteSize(const std::string& obj); IGL_INLINE void serialize(const std::string& obj,std::vector& buffer,std::vector::iterator& iter); IGL_INLINE void deserialize(std::string& obj,std::vector::const_iterator& iter); // SerializableBase template IGL_INLINE typename std::enable_if::value,size_t>::type getByteSize(const T& obj); template IGL_INLINE typename std::enable_if::value>::type serialize(const T& obj,std::vector& buffer,std::vector::iterator& iter); template IGL_INLINE typename std::enable_if::value>::type deserialize(T& obj,std::vector::const_iterator& iter); // stl containers // std::pair template IGL_INLINE size_t getByteSize(const std::pair& obj); template IGL_INLINE void serialize(const std::pair& obj,std::vector& buffer,std::vector::iterator& iter); template IGL_INLINE void deserialize(std::pair& obj,std::vector::const_iterator& iter); // std::vector template IGL_INLINE size_t getByteSize(const std::vector& obj); template IGL_INLINE void serialize(const std::vector& obj,std::vector& buffer,std::vector::iterator& iter); template IGL_INLINE void deserialize(std::vector& obj,std::vector::const_iterator& iter); // std::set template IGL_INLINE size_t getByteSize(const std::set& obj); template IGL_INLINE void serialize(const std::set& obj,std::vector& buffer,std::vector::iterator& iter); template IGL_INLINE void deserialize(std::set& obj,std::vector::const_iterator& iter); // std::map template IGL_INLINE size_t getByteSize(const std::map& obj); template IGL_INLINE void serialize(const std::map& obj,std::vector& buffer,std::vector::iterator& iter); template IGL_INLINE void deserialize(std::map& obj,std::vector::const_iterator& iter); // Eigen types template IGL_INLINE size_t getByteSize(const Eigen::Matrix& obj); template IGL_INLINE void serialize(const Eigen::Matrix& obj,std::vector& buffer,std::vector::iterator& iter); template IGL_INLINE void deserialize(Eigen::Matrix& obj,std::vector::const_iterator& iter); template IGL_INLINE size_t getByteSize(const Eigen::SparseMatrix& obj); template IGL_INLINE void serialize(const Eigen::SparseMatrix& obj,std::vector& buffer,std::vector::iterator& iter); template IGL_INLINE void deserialize(Eigen::SparseMatrix& obj,std::vector::const_iterator& iter); // raw pointers template IGL_INLINE typename std::enable_if::value,size_t>::type getByteSize(const T& obj); template IGL_INLINE typename std::enable_if::value>::type serialize(const T& obj,std::vector& buffer,std::vector::iterator& iter); template IGL_INLINE typename std::enable_if::value>::type deserialize(T& obj,std::vector::const_iterator& iter); // std::shared_ptr and std::unique_ptr /*template IGL_INLINE typename std::enable_if::value,size_t>::type getByteSize(const T& obj); template IGL_INLINE typename std::enable_if::value>::type serialize(const T& obj,std::vector& buffer,std::vector::iterator& iter); template class T0, typename T1> IGL_INLINE typename std::enable_if >::value>::type deserialize(T0& obj,std::vector::const_iterator& iter); // std::weak_ptr template IGL_INLINE size_t getByteSize(const std::weak_ptr& obj); template IGL_INLINE void serialize(const std::weak_ptr& obj,std::vector& buffer,std::vector::iterator& iter); template IGL_INLINE void deserialize(std::weak_ptr& obj,std::vector::const_iterator& iter);*/ // functions to overload for non-intrusive serialization template IGL_INLINE void serialize(const T& obj,std::vector& buffer); template IGL_INLINE void deserialize(T& obj,const std::vector& buffer); // helper functions template IGL_INLINE void updateMemoryMap(T& obj,size_t size,std::map& memoryMap); } } #ifndef IGL_STATIC_LIBRARY #include "serialize.cpp" #endif #endif