XMLSerializer.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. /* ---------------------------------------------------------------------------
  2. // XMLSerializer.h
  3. // Author: Christian Schüller on 08/05/13.
  4. ------------------------------------------------------------------------------
  5. This class allows to save and load a serialization of basic c++ data types like
  6. char, char*, std::string, bool, uint, int, float, double to and from a xml file.
  7. Containers like std::vector, std::std::pair, Eigen dense and sparse matrices are supported
  8. as well as combination of them (like vector<pair<string,bool>> or vector<vector<int>>).
  9. To serialize an arbitary object use the XMLSerializable interface.
  10. The serialized objects are organised in groups in the xml file and have
  11. their own names which must be unique within one group.
  12. You can find examples how to use it in the test case class XMLSerializerTest.
  13. ----------------------------------------------------------------------------*/
  14. #ifndef XML_SERIALIZER_H
  15. #define XML_SERIALIZER_H
  16. #include <iostream>
  17. //#include <array>
  18. #include <vector>
  19. #include <map>
  20. #include <Eigen/Dense>
  21. #include <Eigen/Sparse>
  22. #include <tinyxml2.h>
  23. namespace igl
  24. {
  25. void EncodeXMLElementName(std::string& name);
  26. //void DecodeXMLElementName(std::string& name);
  27. void ReplaceSubString(std::string& str, const std::string& search, const std::string& replace);
  28. // Forward declaration
  29. class XMLSerializer;
  30. /**
  31. * interface XMLSerializable
  32. * Inherit from this interface to have full control over the serialization of you user defined class.
  33. */
  34. class XMLSerializable
  35. {
  36. public:
  37. std::string Name;
  38. /**
  39. * This function gets called if the objects were not found during deserialization.
  40. * Initialize your objects as you like.
  41. */
  42. virtual void Init() = 0;
  43. /**
  44. * Serialize your stuff within this function.
  45. * It contains the current serialization xml file. You can use SaveToXMLDoc or SaveGroupToXMLElement to add your objects.
  46. */
  47. virtual bool Serialize(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element) = 0;
  48. /**
  49. * Deserialize your stuff within this function.
  50. * It contains the current serialization xml file. You can use LoadFromXMLDoc or LoadGroupFromXMLElement to read out your objects.
  51. */
  52. virtual bool Deserialize(tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element) = 0;
  53. };
  54. /**
  55. * class XMLSerialization
  56. * Inherit from this class to have the easiest way to serialize your user defined class.
  57. */
  58. class XMLSerialization : public XMLSerializable
  59. {
  60. public:
  61. igl::XMLSerializer* xmlSerializer;
  62. /**
  63. * Default implementation of XMLSerializable interface
  64. */
  65. virtual void Init();
  66. virtual bool Serialize(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element);
  67. virtual bool Deserialize(tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element);
  68. XMLSerialization(const std::string& name);
  69. ~XMLSerialization();
  70. /**
  71. * Following functions can be overwritten to handle the specific events.
  72. * Return false to prevent serialization of object.
  73. */
  74. virtual bool BeforeSerialization();
  75. virtual void AfterSerialization();
  76. virtual bool BeforeDeserialization();
  77. virtual void AfterDeserialization();
  78. };
  79. /**
  80. * class XMLSerializableObject
  81. * internal usage
  82. */
  83. class XMLSerializableObject : public XMLSerializable
  84. {
  85. public:
  86. XMLSerializableObject(const std::string& name, const std::string& group);
  87. virtual ~XMLSerializableObject();
  88. // set attribute conversion functions
  89. void SetAttribute(tinyxml2::XMLElement* element, const char* name, char& dest);
  90. void SetAttribute(tinyxml2::XMLElement* element, const char* name, char*& dest);
  91. void SetAttribute(tinyxml2::XMLElement* element, const char* name, std::string& dest);
  92. void SetAttribute(tinyxml2::XMLElement* element, const char* name, bool& dest);
  93. void SetAttribute(tinyxml2::XMLElement* element, const char* name, unsigned int& dest);
  94. void SetAttribute(tinyxml2::XMLElement* element, const char* name, int& dest);
  95. void SetAttribute(tinyxml2::XMLElement* element, const char* name, float& dest);
  96. void SetAttribute(tinyxml2::XMLElement* element, const char* name, double& dest);
  97. // get attribute conversion functions
  98. void GetAttribute(const char* src, char& dest);
  99. void GetAttribute(const char* src, char*& dest);
  100. void GetAttribute(const char* src, std::string& dest);
  101. void GetAttribute(const char* src, bool& dest);
  102. void GetAttribute(const char* src, unsigned int& dest);
  103. void GetAttribute(const char* src, int& dest);
  104. void GetAttribute(const char* src, float& dest);
  105. void GetAttribute(const char* src, double& dest);
  106. // Initialization
  107. // Basic data types
  108. using XMLSerializable::Init;
  109. void Init(char& val);
  110. void Init(char*& val);
  111. void Init(std::string& val);
  112. void Init(bool& val);
  113. void Init(unsigned int& val);
  114. void Init(int& val);
  115. void Init(float& val);
  116. void Init(double& val);
  117. // XMLSerializable*
  118. template<typename T>
  119. void Init(T& obj);
  120. template<typename T>
  121. void Init(T*& obj);
  122. // STL containers
  123. /*template<typename T, int S>
  124. void Init(std::array<T,S>& obj);*/
  125. template<typename T0, typename T1>
  126. void Init(std::pair<T0,T1>& obj);
  127. template<typename T>
  128. void Init(std::vector<T>& obj);
  129. // Eigen types
  130. template<typename T, int R, int C>
  131. void Init(Eigen::Matrix<T,R,C>& obj);
  132. template<typename T>
  133. void Init(Eigen::SparseMatrix<T>& obj);
  134. // Serialization
  135. // Basic data types
  136. using XMLSerializable::Serialize;
  137. bool Serialize(char& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  138. bool Serialize(char*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  139. bool Serialize(std::string& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  140. bool Serialize(std::string*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  141. bool Serialize(bool& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  142. bool Serialize(bool*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  143. bool Serialize(unsigned int& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  144. bool Serialize(unsigned int*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  145. bool Serialize(int& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  146. bool Serialize(int*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  147. bool Serialize(float& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  148. bool Serialize(float*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  149. bool Serialize(double& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  150. bool Serialize(double*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  151. // XMLSerializable*
  152. template<typename T>
  153. bool Serialize(T& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  154. template<typename T>
  155. bool Serialize(T*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  156. // STL containers
  157. /*template<typename T, size_t S>
  158. bool Serialize(std::array<T,S>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  159. template<typename T, size_t S>
  160. bool Serialize(std::array<T,S>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);*/
  161. template<typename T0, typename T1>
  162. bool Serialize(std::pair<T0,T1>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  163. template<typename T0, typename T1>
  164. bool Serialize(std::pair<T0,T1>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  165. template<typename T>
  166. bool Serialize(std::vector<T>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  167. template<typename T>
  168. bool Serialize(std::vector<T>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  169. // Eigen types
  170. template<typename T, int R, int C>
  171. bool Serialize(Eigen::Matrix<T,R,C>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  172. template<typename T, int R, int C>
  173. bool Serialize(Eigen::Matrix<T,R,C>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  174. template<typename T>
  175. bool Serialize(Eigen::SparseMatrix<T>& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  176. template<typename T>
  177. bool Serialize(Eigen::SparseMatrix<T>*& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  178. // Serialization
  179. // Basic data types
  180. using XMLSerializable::Deserialize;
  181. bool Deserialize(char& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  182. bool Deserialize(char*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  183. bool Deserialize(std::string& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  184. bool Deserialize(std::string*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  185. bool Deserialize(bool& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  186. bool Deserialize(bool*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  187. bool Deserialize(unsigned int& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  188. bool Deserialize(unsigned int*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  189. bool Deserialize(int& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  190. bool Deserialize(int*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  191. bool Deserialize(float& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  192. bool Deserialize(float*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  193. bool Deserialize(double& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  194. bool Deserialize(double*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  195. // XMLSerializable*
  196. template<typename T>
  197. bool Deserialize(T& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  198. template<typename T>
  199. bool Deserialize(T*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  200. // STL containers
  201. /*template<typename T, size_t S>
  202. bool Deserialize(std::array<T,S>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  203. template<typename T, size_t S>
  204. bool Deserialize(std::array<T,S>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);*/
  205. template<typename T0, typename T1>
  206. bool Deserialize(std::pair<T0,T1>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  207. template<typename T0, typename T1>
  208. bool Deserialize(std::pair<T0,T1>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  209. template<typename T>
  210. bool Deserialize(std::vector<T>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  211. template<typename T>
  212. bool Deserialize(std::vector<T>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  213. // Eigen types
  214. template<typename T, int R, int C>
  215. bool Deserialize(Eigen::Matrix<T,R,C>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  216. template<typename T, int R, int C>
  217. bool Deserialize(Eigen::Matrix<T,R,C>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  218. template<typename T>
  219. bool Deserialize(Eigen::SparseMatrix<T>& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  220. template<typename T>
  221. bool Deserialize(Eigen::SparseMatrix<T>*& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  222. private:
  223. template<typename T>
  224. bool setElementAttribute(T& obj, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  225. template<typename T>
  226. bool getElementAttribute(T& obj, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element, const std::string& name);
  227. };
  228. /**
  229. * class XMLSerializableInstance
  230. * internal usage
  231. */
  232. template<typename T>
  233. class XMLSerializableInstance : public XMLSerializableObject
  234. {
  235. public:
  236. T& Object;
  237. T DefaultValue;
  238. XMLSerializableInstance(T& obj, const std::string& name, const std::string group);
  239. XMLSerializableInstance(T& obj, const std::string& name, const std::string group, T defaultValue);
  240. ~XMLSerializableInstance();
  241. // XMLSerializable interface implementation
  242. void Init();
  243. bool Serialize(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element);
  244. bool Deserialize(tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element);
  245. };
  246. /**
  247. * struct XMLSerializerGroup
  248. * internal usage
  249. */
  250. struct XMLSerializerGroup
  251. {
  252. std::string Name;
  253. std::vector<XMLSerializable*>* Objects;
  254. };
  255. /**
  256. * class XMLSerializer
  257. * This is the core class which takes care of saving and loading of serialization of object structures.
  258. */
  259. class XMLSerializer
  260. {
  261. public:
  262. /**
  263. * Serializes an object to a file
  264. */
  265. template<typename T>
  266. static bool SaveObject(T& object, const char* filename);
  267. template<typename T>
  268. static bool SaveObject(T& object, const std::string& objectName, const std::string& groupName, const char* filename, bool overwrite);
  269. /**
  270. * Loads the serialization of an object from a file.
  271. */
  272. template<typename T>
  273. static bool LoadObject(T& object, const char* filename);
  274. template<typename T>
  275. static bool LoadObject(T& object, const std::string& objectName, const std::string& groupName, const char* filename);
  276. /**
  277. * Constructor which sets the default group
  278. */
  279. XMLSerializer(const std::string& defaultGroup);
  280. ~XMLSerializer();
  281. /**
  282. * Save the serialization of all groups to file.
  283. * Parameter overwrite specifies if file gets overwritten or updated
  284. */
  285. bool Save(const char* filename, bool overwrite);
  286. bool Save(const std::string& groupName, const char* filename, bool overwrite);
  287. bool Save(const std::string& objectName, const std::string& groupName, const char* filename, bool overwrite);
  288. /**
  289. * Save the serialization of all groups to a XMLDocument instance.
  290. */
  291. bool SaveToXMLDoc(tinyxml2::XMLDocument* doc);
  292. bool SaveToXMLDoc(const std::string& groupName, tinyxml2::XMLDocument* doc);
  293. bool SaveToXMLDoc(const std::string& objectName, const std::string& groupName, tinyxml2::XMLDocument* doc);
  294. /**
  295. * Save the serialization of a group with a new provided name to given XMLElement instance.
  296. */
  297. bool SaveGroupToXMLElement(tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  298. bool SaveGroupToXMLElement(const std::string& groupName, tinyxml2::XMLDocument* doc, tinyxml2::XMLElement* element, const std::string& name);
  299. /**
  300. * Load the serialization from a file.
  301. */
  302. bool Load(const char* filename);
  303. bool Load(const std::string& groupName, const char* filename);
  304. bool Load(const std::string& objectName, const std::string& groupName, const char* filename);
  305. /**
  306. * Load the serialization from an XMLDocument instance.
  307. */
  308. bool LoadFromXMLDoc(tinyxml2::XMLDocument* doc);
  309. bool LoadFromXMLDoc(const std::string& groupName, tinyxml2::XMLDocument* doc);
  310. bool LoadFromXMLDoc(const std::string& objectName, const std::string& groupName, tinyxml2::XMLDocument* doc);
  311. /**
  312. * Load the serialization from a XMLElement instance to given group.
  313. */
  314. bool LoadGroupFromXMLElement(const std::string& groupName, tinyxml2::XMLDocument* doc, const tinyxml2::XMLElement* element);
  315. /**
  316. * Set/Get current group. Every object which is added afterwards will be in this group, except it specifies another group.
  317. */
  318. void SetCurrentGroup(const std::string& group);
  319. std::string GetCurrentGroup();
  320. /**
  321. * Add an object to the serializer. Can be simple types like char, char*, string, unsigned int, int, float, double or containers like std::array, std::pair, std::vector.
  322. * Also Eigen dense or sparse matrices are supported and all objects of type Serializable* and combinations of thoses types like vector<vector>, vector<pair> or even vector<pair<vector,Serializable*>>>.
  323. * Also pointers to those objects can be used (for instance like vector<vector<pair<int,float>*>*>).
  324. * char* is also possible as base type and represents a array of chars, but be carefull that the pointer is not just a copy but a valid instance in the current programm scope.
  325. */
  326. // Basic types
  327. bool Add(char& obj, const std::string& name);
  328. bool Add(char*& obj, const std::string& name);
  329. bool Add(std::string& obj, const std::string& name);
  330. bool Add(bool& obj, const std::string& name);
  331. bool Add(unsigned int& obj, const std::string& name);
  332. bool Add(int& obj, const std::string& name);
  333. bool Add(float& obj, const std::string& name);
  334. bool Add(double& obj, const std::string& name);
  335. bool Add(char& obj, const std::string& name, char defaultValue);
  336. bool Add(char*& obj, const std::string& name, char* defaultValue);
  337. bool Add(std::string& obj, const std::string& name, std::string defaultValue);
  338. bool Add(bool& obj, const std::string& name, bool defaultValue);
  339. bool Add(unsigned int& obj, const std::string& name, unsigned int defaultValue);
  340. bool Add(int& obj, const std::string& name, int defaultValue);
  341. bool Add(float& obj, const std::string& name, float defaultValue);
  342. bool Add(double& obj, const std::string& name, double defaultValue);
  343. // XMLSerializable*
  344. template<typename T>
  345. bool Add(T& object, const std::string& name);
  346. template<typename T>
  347. bool Add(T& object, const std::string& name, T defaultValue);
  348. // STL containers
  349. /*template<typename T, size_t S>
  350. bool Add(std::array<T,S>& obj, const std::string& name);*/
  351. template<typename T0, typename T1>
  352. bool Add(std::pair<T0,T1>& obj, const std::string& name);
  353. template<typename T>
  354. bool Add(std::vector<T>& obj, const std::string& name);
  355. // Eigen types
  356. template<typename T, int R, int C>
  357. bool Add(Eigen::Matrix<T,R,C>& obj, const std::string& name);
  358. template<typename T>
  359. bool Add(Eigen::SparseMatrix<T>& obj, const std::string& name);
  360. private:
  361. std::map<std::string,XMLSerializerGroup*>::iterator currentGroup;
  362. std::map<std::string,XMLSerializerGroup*> groups;
  363. template<typename T>
  364. bool add(T& object, const std::string& name);
  365. template<typename T>
  366. bool add(T& object, const std::string& name, T defaultValue);
  367. bool addObjectToGroup(XMLSerializable* object, const std::string& group);
  368. bool addObjectToGroup(XMLSerializable* object, std::map<std::string,XMLSerializerGroup*>::iterator it);
  369. std::map<std::string,XMLSerializerGroup*>::iterator setGetGroup(const std::string& group);
  370. tinyxml2::XMLDocument* openDoc(const char* filename);
  371. tinyxml2::XMLElement* findAddGroup(tinyxml2::XMLDocument* doc, const char* groupName);
  372. };
  373. /**
  374. * class XMLSerializerTest
  375. * Used to test the functionality of the library and also shows howto use it.
  376. */
  377. class XMLSerializerTest : public igl::XMLSerialization
  378. {
  379. public:
  380. int testInt;
  381. std::vector<float> testVector;
  382. XMLSerializerTest();
  383. bool Test();
  384. };
  385. }
  386. #ifdef IGL_HEADER_ONLY
  387. #include "XMLSerializer.cpp"
  388. #else
  389. #endif
  390. #endif