serialize.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. //
  2. // Copyright (C) 2014 Christian Schüller <schuellchr@gmail.com>
  3. //
  4. // This Source Code Form is subject to the terms of the Mozilla Public License
  5. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  6. // obtain one at http://mozilla.org/MPL/2.0/.
  7. // -----------------------------------------------------------------------------
  8. // Functions to save and load a serialization of fundamental c++ data types to
  9. // and from a binary file. STL containers, Eigen matrix types and nested data
  10. // structures are also supported. To serialize a user defined class implement
  11. // the interface Serializable or SerializableBase.
  12. //
  13. // See also: xml/serialize_xml.h
  14. // -----------------------------------------------------------------------------
  15. // TODOs:
  16. // * non-intrusive serialization example
  17. // * arbitrary pointer graph structures
  18. // * cross-platform compatibility (big-, little-endian)
  19. // -----------------------------------------------------------------------------
  20. #ifndef IGL_SERIALIZE_H
  21. #define IGL_SERIALIZE_H
  22. #include <type_traits>
  23. #include <iostream>
  24. #include <fstream>
  25. #include <cstdint>
  26. #include <numeric>
  27. #include <vector>
  28. #include <set>
  29. #include <map>
  30. #include <memory>
  31. #include <cstdint>
  32. #include <Eigen/Dense>
  33. #include <Eigen/Sparse>
  34. #include "igl_inline.h"
  35. // non-intrusive serialization helper macros
  36. #define SERIALIZE_TYPE(Type,Params) \
  37. namespace igl { namespace serialization { \
  38. void _serialization(bool s,Type& obj,std::vector<char>& buffer) {Params} \
  39. void serialize(const Type& obj,std::vector<char>& buffer) { \
  40. _serialization(true,const_cast<Type&>(obj),buffer); \
  41. } \
  42. void deserialize(Type& obj,const std::vector<char>& buffer) { \
  43. _serialization(false,obj,const_cast<std::vector<char>&>(buffer)); \
  44. } \
  45. }}
  46. #define SERIALIZE_MEMBER(Object) ::igl::serializer(s,obj.##Object,std::string(#Object),buffer);
  47. #define SERIALIZE_MEMBER_NAME(Object,Name) ::igl::serializer(s,obj.##Object,std::string(Name),buffer);
  48. namespace igl
  49. {
  50. struct IndexedPointerBase;
  51. // Serializes the given object either to a file or to a provided buffer
  52. // Templates:
  53. // T type of the object to serialize
  54. // Inputs:
  55. // obj object to serialize
  56. // objectName unique object name,used for the identification
  57. // overwrite set to true to overwrite an existing file
  58. // filename name of the file containing the serialization
  59. // Outputs:
  60. // buffer binary serialization
  61. //
  62. template <typename T>
  63. IGL_INLINE bool serialize(const T& obj,const std::string& filename);
  64. template <typename T>
  65. IGL_INLINE bool serialize(const T& obj,const std::string& objectName,const std::string& filename,bool overwrite = false);
  66. template <typename T>
  67. IGL_INLINE bool serialize(const T& obj,const std::string& objectName,std::vector<char>& buffer);
  68. template <typename T>
  69. IGL_INLINE bool serialize(const T& obj,const std::string& objectName,std::vector<char>& buffer);
  70. // Deserializes the given data from a file or buffer back to the provided object
  71. //
  72. // Templates:
  73. // T type of the object to serialize
  74. // Inputs:
  75. // buffer binary serialization
  76. // objectName unique object name, used for the identification
  77. // filename name of the file containing the serialization
  78. // Outputs:
  79. // obj object to load back serialization to
  80. //
  81. template <typename T>
  82. IGL_INLINE bool deserialize(T& obj,const std::string& filename);
  83. template <typename T>
  84. IGL_INLINE bool deserialize(T& obj,const std::string& objectName,const std::string& filename);
  85. template <typename T>
  86. IGL_INLINE bool deserialize(T& obj,const std::string& objectName,const std::vector<char>& buffer);
  87. // Wrapper to expose both, the de- and serialization as one function
  88. //
  89. template <typename T>
  90. IGL_INLINE bool serializer(bool serialize,T& obj,std::string& filename);
  91. template <typename T>
  92. IGL_INLINE bool serializer(bool serialize,T& obj,std::string& objectName,const std::string& filename,bool overwrite = false);
  93. template <typename T>
  94. IGL_INLINE bool serializer(bool serialize,T& obj,std::string& objectName,std::vector<char>& buffer);
  95. // User defined types have to either overload the function igl::serialization::serialize()
  96. // and igl::serialization::deserialize() for their type (non-intrusive serialization):
  97. //
  98. // namespace igl { namespace serialization
  99. // {
  100. // IGL_INLINE void serialize(const UserType& obj,std::vector<char>& buffer) {
  101. // ::igl::serialize(obj.var,"var",buffer);
  102. // }
  103. //
  104. // IGL_INLINE void deserialize(UserType& obj,const std::vector<char>& buffer) {
  105. // ::igl::deserialize(obj.var,"var",buffer);
  106. // }
  107. // }}
  108. //
  109. // or use this macro for convenience:
  110. //
  111. // SERIALIZE_TYPE(UserType,
  112. // SERIALIZE_MEMBER(var)
  113. // )
  114. //
  115. // or to derive from the class Serializable and add their the members
  116. // in InitSerialization like the following:
  117. //
  118. // class UserType : public igl::Serializable {
  119. //
  120. // int var;
  121. //
  122. // void InitSerialization() {
  123. // this->Add(var,"var");
  124. // }
  125. // };
  126. // Base interface for user defined types
  127. struct SerializableBase
  128. {
  129. virtual void Serialize(std::vector<char>& buffer) const = 0;
  130. virtual void Deserialize(const std::vector<char>& buffer) = 0;
  131. };
  132. // Convenient interface for user defined types
  133. class Serializable: public SerializableBase
  134. {
  135. private:
  136. template <typename T>
  137. struct SerializationObject : public SerializableBase
  138. {
  139. bool Binary;
  140. std::string Name;
  141. std::unique_ptr<T> Object;
  142. void Serialize(std::vector<char>& buffer) const override {
  143. igl::serialize(*Object,Name,buffer);
  144. }
  145. void Deserialize(const std::vector<char>& buffer) override {
  146. igl::deserialize(*Object,Name,buffer);
  147. }
  148. };
  149. mutable bool initialized;
  150. mutable std::vector<SerializableBase*> objects;
  151. public:
  152. // Override this function to add your member variables which should be serialized
  153. IGL_INLINE virtual void InitSerialization() = 0;
  154. // Following functions can be overridden to handle the specific events.
  155. // Return false to prevent the de-/serialization of an object.
  156. IGL_INLINE virtual bool PreSerialization() const;
  157. IGL_INLINE virtual void PostSerialization() const;
  158. IGL_INLINE virtual bool PreDeserialization();
  159. IGL_INLINE virtual void PostDeserialization();
  160. // Default implementation of SerializableBase interface
  161. IGL_INLINE void Serialize(std::vector<char>& buffer) const override final;
  162. IGL_INLINE void Deserialize(const std::vector<char>& buffer) override final;
  163. // Default constructor, destructor, assignment and copy constructor
  164. IGL_INLINE Serializable();
  165. IGL_INLINE Serializable(const Serializable& obj);
  166. IGL_INLINE ~Serializable();
  167. IGL_INLINE Serializable& operator=(const Serializable& obj);
  168. // Use this function to add your variables which should be serialized
  169. template <typename T>
  170. IGL_INLINE void Add(T& obj,std::string name,bool binary = false);
  171. };
  172. // structure for pointer handling
  173. struct IndexedPointerBase
  174. {
  175. enum { BEGIN,END } Type;
  176. size_t Index;
  177. };
  178. template<typename T>
  179. struct IndexedPointer: public IndexedPointerBase
  180. {
  181. const T* Object;
  182. };
  183. // internal functions
  184. namespace serialization
  185. {
  186. // compile time type checks
  187. template <typename T>
  188. struct is_stl_container { static const bool value = false; };
  189. template <typename T1,typename T2>
  190. struct is_stl_container<std::pair<T1,T2> > { static const bool value = true; };
  191. template <typename T1,typename T2>
  192. struct is_stl_container<std::vector<T1,T2> > { static const bool value = true; };
  193. template <typename T>
  194. struct is_stl_container<std::set<T> > { static const bool value = true; };
  195. template <typename T1,typename T2>
  196. struct is_stl_container<std::map<T1,T2> > { static const bool value = true; };
  197. template <typename T>
  198. struct is_eigen_type { static const bool value = false; };
  199. template <typename T,int R,int C,int P,int MR,int MC>
  200. struct is_eigen_type<Eigen::Matrix<T,R,C,P,MR,MC> > { static const bool value = true; };
  201. template <typename T,int P,typename I>
  202. struct is_eigen_type<Eigen::SparseMatrix<T,P,I> > { static const bool value = true; };
  203. template <typename T>
  204. struct is_smart_ptr { static const bool value = false; };
  205. template <typename T>
  206. struct is_smart_ptr<std::shared_ptr<T> > { static const bool value = true; };
  207. template <typename T>
  208. struct is_smart_ptr<std::unique_ptr<T> > { static const bool value = true; };
  209. template <typename T>
  210. struct is_smart_ptr<std::weak_ptr<T> > { static const bool value = true; };
  211. template <typename T>
  212. struct is_serializable {
  213. static const bool value = std::is_fundamental<T>::value || std::is_same<std::string,T>::value || std::is_base_of<SerializableBase,T>::value
  214. || is_stl_container<T>::value || is_eigen_type<T>::value || std::is_pointer<T>::value || serialization::is_smart_ptr<T>::value;
  215. };
  216. // non serializable types
  217. template <typename T>
  218. IGL_INLINE typename std::enable_if<!is_serializable<T>::value,size_t>::type getByteSize(const T& obj);
  219. template <typename T>
  220. IGL_INLINE typename std::enable_if<!is_serializable<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
  221. template <typename T>
  222. IGL_INLINE typename std::enable_if<!is_serializable<T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter);
  223. // fundamental types
  224. template <typename T>
  225. IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value,size_t>::type getByteSize(const T& obj);
  226. template <typename T>
  227. IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
  228. template <typename T>
  229. IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter);
  230. // std::string
  231. IGL_INLINE size_t getByteSize(const std::string& obj);
  232. IGL_INLINE void serialize(const std::string& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
  233. IGL_INLINE void deserialize(std::string& obj,std::vector<char>::const_iterator& iter);
  234. // SerializableBase
  235. template <typename T>
  236. IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value,size_t>::type getByteSize(const T& obj);
  237. template <typename T>
  238. IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
  239. template <typename T>
  240. IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter);
  241. // stl containers
  242. // std::pair
  243. template <typename T1,typename T2>
  244. IGL_INLINE size_t getByteSize(const std::pair<T1,T2>& obj);
  245. template <typename T1,typename T2>
  246. IGL_INLINE void serialize(const std::pair<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
  247. template <typename T1,typename T2>
  248. IGL_INLINE void deserialize(std::pair<T1,T2>& obj,std::vector<char>::const_iterator& iter);
  249. // std::vector
  250. template <typename T1,typename T2>
  251. IGL_INLINE size_t getByteSize(const std::vector<T1,T2>& obj);
  252. template <typename T1,typename T2>
  253. IGL_INLINE void serialize(const std::vector<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
  254. template <typename T1,typename T2>
  255. IGL_INLINE void deserialize(std::vector<T1,T2>& obj,std::vector<char>::const_iterator& iter);
  256. template <typename T2>
  257. IGL_INLINE void deserialize(std::vector<bool,T2>& obj,std::vector<char>::const_iterator& iter);
  258. // std::set
  259. template <typename T>
  260. IGL_INLINE size_t getByteSize(const std::set<T>& obj);
  261. template <typename T>
  262. IGL_INLINE void serialize(const std::set<T>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
  263. template <typename T>
  264. IGL_INLINE void deserialize(std::set<T>& obj,std::vector<char>::const_iterator& iter);
  265. // std::map
  266. template <typename T1,typename T2>
  267. IGL_INLINE size_t getByteSize(const std::map<T1,T2>& obj);
  268. template <typename T1,typename T2>
  269. IGL_INLINE void serialize(const std::map<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
  270. template <typename T1,typename T2>
  271. IGL_INLINE void deserialize(std::map<T1,T2>& obj,std::vector<char>::const_iterator& iter);
  272. // Eigen types
  273. template<typename T,int R,int C,int P,int MR,int MC>
  274. IGL_INLINE size_t getByteSize(const Eigen::Matrix<T,R,C,P,MR,MC>& obj);
  275. template<typename T,int R,int C,int P,int MR,int MC>
  276. IGL_INLINE void serialize(const Eigen::Matrix<T,R,C,P,MR,MC>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
  277. template<typename T,int R,int C,int P,int MR,int MC>
  278. IGL_INLINE void deserialize(Eigen::Matrix<T,R,C,P,MR,MC>& obj,std::vector<char>::const_iterator& iter);
  279. template<typename T,int P,typename I>
  280. IGL_INLINE size_t getByteSize(const Eigen::SparseMatrix<T,P,I>& obj);
  281. template<typename T,int P,typename I>
  282. IGL_INLINE void serialize(const Eigen::SparseMatrix<T,P,I>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
  283. template<typename T,int P,typename I>
  284. IGL_INLINE void deserialize(Eigen::SparseMatrix<T,P,I>& obj,std::vector<char>::const_iterator& iter);
  285. // raw pointers
  286. template <typename T>
  287. IGL_INLINE typename std::enable_if<std::is_pointer<T>::value,size_t>::type getByteSize(const T& obj);
  288. template <typename T>
  289. IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
  290. template <typename T>
  291. IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter);
  292. // std::shared_ptr and std::unique_ptr
  293. template <typename T>
  294. IGL_INLINE typename std::enable_if<serialization::is_smart_ptr<T>::value,size_t>::type getByteSize(const T& obj);
  295. template <typename T>
  296. IGL_INLINE typename std::enable_if<serialization::is_smart_ptr<T>::value>::type serialize(const T& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
  297. template <template<typename> class T0, typename T1>
  298. IGL_INLINE typename std::enable_if<serialization::is_smart_ptr<T0<T1> >::value>::type deserialize(T0<T1>& obj,std::vector<char>::const_iterator& iter);
  299. // std::weak_ptr
  300. template <typename T>
  301. IGL_INLINE size_t getByteSize(const std::weak_ptr<T>& obj);
  302. template <typename T>
  303. IGL_INLINE void serialize(const std::weak_ptr<T>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter);
  304. template <typename T>
  305. IGL_INLINE void deserialize(std::weak_ptr<T>& obj,std::vector<char>::const_iterator& iter);
  306. // functions to overload for non-intrusive serialization
  307. template <typename T>
  308. IGL_INLINE void serialize(const T& obj,std::vector<char>& buffer);
  309. template <typename T>
  310. IGL_INLINE void deserialize(T& obj,const std::vector<char>& buffer);
  311. // helper functions
  312. template <typename T>
  313. IGL_INLINE void updateMemoryMap(T& obj,size_t size);
  314. }
  315. }
  316. #ifndef IGL_STATIC_LIBRARY
  317. #include "serialize.cpp"
  318. #endif
  319. #endif