serialize.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  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. #include "serialize.h"
  8. namespace igl
  9. {
  10. template <typename T>
  11. IGL_INLINE bool serialize(const T& obj,const std::string& filename)
  12. {
  13. return serialize(obj,"obj",filename,true);
  14. }
  15. template <typename T>
  16. IGL_INLINE bool serialize(const T& obj,const std::string& objectName,const std::string& filename,bool overwrite)
  17. {
  18. bool success = false;
  19. std::vector<char> buffer;
  20. // open existing file for updating objects
  21. /*if(overwrite == false)
  22. {
  23. std::ifstream file(filename.c_str(),std::ios::binary);
  24. if(file.is_open())
  25. {
  26. file.seekg(0,std::ios::end);
  27. int size = file.tellg();
  28. file.seekg(0,std::ios::beg);
  29. buffer.resize(size);
  30. file.read(&buffer[0],size);
  31. file.close();
  32. }
  33. }*/
  34. std::ios_base::openmode mode = std::ios::out | std::ios::binary;
  35. if(overwrite)
  36. mode |= std::ios::trunc;
  37. else
  38. mode |= std::ios::app;
  39. std::ofstream file(filename.c_str(),mode);
  40. if(file.is_open())
  41. {
  42. serialize(obj,objectName,buffer);
  43. file.write(&buffer[0],buffer.size());
  44. file.close();
  45. success = true;
  46. }
  47. else
  48. {
  49. std::cerr << "saving binary serialization failed!" << std::endl;
  50. }
  51. return success;
  52. }
  53. template <typename T>
  54. IGL_INLINE bool serialize(const T& obj,const std::string& objectName,std::vector<char>& buffer)
  55. {
  56. static_assert(detail::is_serializable<T>::value,"'igl::serialize': type is not serializable");
  57. // serialize object data
  58. size_t size = detail::getByteSize(obj);
  59. std::vector<char> tmp(size);
  60. std::vector<char>::iterator it = tmp.begin();
  61. detail::serialize(obj,tmp,it);
  62. std::string objectType(typeid(obj).name());
  63. size_t newObjectSize = tmp.size();
  64. size_t newHeaderSize = detail::getByteSize(objectName) + detail::getByteSize(objectType) + sizeof(size_t);
  65. // size_t oldObjectSize = 0;
  66. // size_t oldHeaderSize = 0;
  67. // find object header to replace existing object
  68. /*std::vector<char>::const_iterator citer = buffer.cbegin();
  69. while(citer != buffer.cend())
  70. {
  71. std::vector<char>::const_iterator citerTemp = citer;
  72. std::string name;
  73. std::string type;
  74. detail::deserialize(name,citer);
  75. detail::deserialize(type,citer);
  76. detail::deserialize(oldObjectSize,citer);
  77. if(name == objectName)
  78. {
  79. if(type != typeid(obj).raw_name())
  80. std::cout << "object " + objectName + " was overwriten with different data type!" << std::endl;
  81. oldHeaderSize = citer - citerTemp;
  82. citer = citerTemp;
  83. break;
  84. }
  85. else
  86. citer+=oldObjectSize;
  87. }
  88. std::vector<char>::iterator iter = buffer.begin() + (citer-buffer.cbegin());
  89. if(iter != buffer.end())
  90. {
  91. std::vector<char>::iterator iterEndPart = iter+oldHeaderSize+oldObjectSize;
  92. size_t startPartSize = iter - buffer.begin();
  93. size_t endPartSize = buffer.end()-iterEndPart;
  94. // copy end part of buffer
  95. std::vector<char> endPartBuffer(endPartSize);
  96. std::copy(iterEndPart,buffer.end(),endPartBuffer.begin());
  97. size_t newSize = startPartSize + newHeaderSize + newObjectSize + endPartSize;
  98. buffer.resize(newSize);
  99. iter = buffer.begin() + startPartSize;
  100. // serialize object header (name/type/size)
  101. detail::serialize(objectName,buffer,iter);
  102. detail::serialize(objectType,buffer,iter);
  103. detail::serialize(newObjectSize,buffer,iter);
  104. // copy serialized data to buffer
  105. iter = std::copy(tmp.begin(),tmp.end(),iter);
  106. // copy back end part of buffer
  107. std::copy(endPartBuffer.begin(),endPartBuffer.end(),iter);
  108. }
  109. else*/
  110. {
  111. size_t curSize = buffer.size();
  112. size_t newSize = curSize + newHeaderSize + newObjectSize;
  113. buffer.resize(newSize);
  114. std::vector<char>::iterator iter = buffer.begin()+curSize;
  115. // serialize object header (name/type/size)
  116. detail::serialize(objectName,buffer,iter);
  117. detail::serialize(objectType,buffer,iter);
  118. detail::serialize(newObjectSize,buffer,iter);
  119. // copy serialized data to buffer
  120. iter = std::copy(tmp.begin(),tmp.end(),iter);
  121. }
  122. return true;
  123. }
  124. template <typename T>
  125. IGL_INLINE bool deserialize(T& obj,const std::string& filename)
  126. {
  127. return deserialize(obj,"obj",filename);
  128. }
  129. template <typename T>
  130. IGL_INLINE bool deserialize(T& obj,const std::string& objectName,const std::string& filename)
  131. {
  132. bool success = false;
  133. std::ifstream file(filename.c_str(),std::ios::binary);
  134. if(file.is_open())
  135. {
  136. file.seekg(0,std::ios::end);
  137. std::streamoff size = file.tellg();
  138. file.seekg(0,std::ios::beg);
  139. std::vector<char> buffer(size);
  140. file.read(&buffer[0],size);
  141. deserialize(obj,objectName,buffer);
  142. file.close();
  143. success = true;
  144. }
  145. else
  146. {
  147. std::cerr << "Loading binary serialization failed!" << std::endl;
  148. }
  149. return success;
  150. }
  151. template <typename T>
  152. IGL_INLINE bool deserialize(T& obj,const std::string& objectName,const std::vector<char>& buffer)
  153. {
  154. static_assert(detail::is_serializable<T>::value,"'igl::deserialize': type is not deserializable");
  155. bool success = false;
  156. // find suitable object header
  157. std::vector<char>::const_iterator objectIter = buffer.end();
  158. std::vector<char>::const_iterator iter = buffer.begin();
  159. while(iter != buffer.end())
  160. {
  161. std::string name;
  162. std::string type;
  163. size_t size;
  164. detail::deserialize(name,iter);
  165. detail::deserialize(type,iter);
  166. detail::deserialize(size,iter);
  167. if(name == objectName && type == typeid(obj).name())
  168. {
  169. objectIter = iter;
  170. //break; // find first suitable object header
  171. }
  172. iter+=size;
  173. }
  174. if(objectIter != buffer.end())
  175. {
  176. detail::deserialize(obj,objectIter);
  177. success = true;
  178. }
  179. else
  180. {
  181. obj = T();
  182. }
  183. return success;
  184. }
  185. IGL_INLINE bool Serializable::PreSerialization() const
  186. {
  187. return true;
  188. }
  189. IGL_INLINE void Serializable::PostSerialization() const
  190. {
  191. }
  192. IGL_INLINE bool Serializable::PreDeserialization()
  193. {
  194. return true;
  195. }
  196. IGL_INLINE void Serializable::PostDeserialization()
  197. {
  198. }
  199. IGL_INLINE void Serializable::Serialize(std::vector<char>& buffer) const
  200. {
  201. if(this->PreSerialization())
  202. {
  203. if(initialized == false)
  204. {
  205. objects.clear();
  206. (const_cast<Serializable*>(this))->InitSerialization();
  207. initialized = true;
  208. }
  209. for(unsigned int i=0;i<objects.size();i++)
  210. objects[i]->Serialize(buffer);
  211. this->PostSerialization();
  212. }
  213. }
  214. IGL_INLINE void Serializable::Deserialize(const std::vector<char>& buffer)
  215. {
  216. if(this->PreDeserialization())
  217. {
  218. if(initialized == false)
  219. {
  220. objects.clear();
  221. (const_cast<Serializable*>(this))->InitSerialization();
  222. initialized = true;
  223. }
  224. for(unsigned int i=0;i<objects.size();i++)
  225. objects[i]->Deserialize(buffer);
  226. this->PostDeserialization();
  227. }
  228. }
  229. IGL_INLINE Serializable::Serializable()
  230. {
  231. initialized = false;
  232. }
  233. IGL_INLINE Serializable::Serializable(const Serializable& obj)
  234. {
  235. initialized = false;
  236. objects.clear();
  237. }
  238. IGL_INLINE Serializable::~Serializable()
  239. {
  240. initialized = false;
  241. objects.clear();
  242. }
  243. IGL_INLINE Serializable& Serializable::operator=(const Serializable& obj)
  244. {
  245. if(this != &obj)
  246. {
  247. if(initialized)
  248. {
  249. initialized = false;
  250. objects.clear();
  251. }
  252. }
  253. return *this;
  254. }
  255. template <typename T>
  256. IGL_INLINE void Serializable::Add(T& obj,std::string name,bool binary)
  257. {
  258. SerializationObject<T>* object = new SerializationObject<T>();
  259. object->Binary = binary;
  260. object->Name = name;
  261. object->Object = &obj;
  262. objects.push_back(object);
  263. }
  264. namespace detail
  265. {
  266. // fundamental types
  267. template <typename T>
  268. IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value,size_t>::type getByteSize(const T& obj)
  269. {
  270. return sizeof(T);
  271. }
  272. template <typename T>
  273. 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)
  274. {
  275. const uint8_t* ptr = reinterpret_cast<const uint8_t*>(&obj);
  276. iter = std::copy(ptr,ptr+sizeof(T),iter);
  277. }
  278. template <typename T>
  279. IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter)
  280. {
  281. uint8_t* ptr = reinterpret_cast<uint8_t*>(&obj);
  282. std::copy(iter,iter+sizeof(T),ptr);
  283. iter += sizeof(T);
  284. }
  285. // std::string
  286. IGL_INLINE size_t getByteSize(const std::string& obj)
  287. {
  288. return getByteSize(obj.length())+obj.length()*sizeof(uint8_t);
  289. }
  290. IGL_INLINE void serialize(const std::string& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
  291. {
  292. detail::serialize(obj.length(),buffer,iter);
  293. for(const auto& cur : obj) { detail::serialize(cur,buffer,iter); }
  294. }
  295. IGL_INLINE void deserialize(std::string& obj,std::vector<char>::const_iterator& iter)
  296. {
  297. size_t size;
  298. detail::deserialize(size,iter);
  299. std::string str(size,'\0');
  300. for(size_t i=0; i<size; ++i)
  301. {
  302. detail::deserialize(str.at(i),iter);
  303. }
  304. obj = str;
  305. }
  306. // SerializableBase
  307. template <typename T>
  308. IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value,size_t>::type getByteSize(const T& obj)
  309. {
  310. return sizeof(std::vector<char>::size_type);
  311. }
  312. template <typename T>
  313. 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)
  314. {
  315. // data
  316. std::vector<char> tmp;
  317. obj.Serialize(tmp);
  318. // size
  319. size_t size = buffer.size();
  320. detail::serialize(tmp.size(),buffer,iter);
  321. size_t cur = iter - buffer.begin();
  322. buffer.resize(size+tmp.size());
  323. iter = buffer.begin()+cur;
  324. iter = std::copy(tmp.begin(),tmp.end(),iter);
  325. }
  326. template <typename T>
  327. IGL_INLINE typename std::enable_if<std::is_base_of<SerializableBase,T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter)
  328. {
  329. std::vector<char>::size_type size;
  330. detail::deserialize(size,iter);
  331. std::vector<char> tmp;
  332. tmp.resize(size);
  333. std::copy(iter,iter+size,tmp.begin());
  334. obj.Deserialize(tmp);
  335. iter += size;
  336. }
  337. // STL containers
  338. // std::pair
  339. template <typename T1,typename T2>
  340. IGL_INLINE size_t getByteSize(const std::pair<T1,T2>& obj)
  341. {
  342. return getByteSize(obj.first)+getByteSize(obj.second);
  343. }
  344. template <typename T1,typename T2>
  345. IGL_INLINE void serialize(const std::pair<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
  346. {
  347. detail::serialize(obj.first,buffer,iter);
  348. detail::serialize(obj.second,buffer,iter);
  349. }
  350. template <typename T1,typename T2>
  351. IGL_INLINE void deserialize(std::pair<T1,T2>& obj,std::vector<char>::const_iterator& iter)
  352. {
  353. detail::deserialize(obj.first,iter);
  354. detail::deserialize(obj.second,iter);
  355. }
  356. // std::vector
  357. template <typename T1,typename T2>
  358. IGL_INLINE size_t getByteSize(const std::vector<T1,T2>& obj)
  359. {
  360. return std::accumulate(obj.begin(),obj.end(),sizeof(size_t),[](const size_t& acc,const T1& cur) { return acc+getByteSize(cur); });
  361. }
  362. template <typename T1,typename T2>
  363. IGL_INLINE void serialize(const std::vector<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
  364. {
  365. size_t size = obj.size();
  366. detail::serialize(size,buffer,iter);
  367. for(const auto& cur : obj)
  368. {
  369. detail::serialize(cur,buffer,iter);
  370. }
  371. }
  372. template <typename T1,typename T2>
  373. IGL_INLINE void deserialize(std::vector<T1,T2>& obj,std::vector<char>::const_iterator& iter)
  374. {
  375. size_t size;
  376. detail::deserialize(size,iter);
  377. obj.resize(size);
  378. for(size_t i=0; i<size; ++i)
  379. {
  380. detail::deserialize(obj[i],iter);
  381. }
  382. }
  383. //std::set
  384. template <typename T>
  385. IGL_INLINE size_t getByteSize(const std::set<T>& obj)
  386. {
  387. return std::accumulate(obj.begin(),obj.end(),getByteSize(obj.size()),[](const size_t& acc,const T& cur) { return acc+getByteSize(cur); });
  388. }
  389. template <typename T>
  390. IGL_INLINE void serialize(const std::set<T>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
  391. {
  392. detail::serialize(obj.size(),buffer,iter);
  393. for(const auto& cur : obj) { detail::serialize(cur,buffer,iter); }
  394. }
  395. template <typename T>
  396. IGL_INLINE void deserialize(std::set<T>& obj,std::vector<char>::const_iterator& iter)
  397. {
  398. size_t size;
  399. detail::deserialize(size,iter);
  400. obj.clear();
  401. for(size_t i=0; i<size; ++i)
  402. {
  403. T val;
  404. detail::deserialize(val,iter);
  405. obj.insert(val);
  406. }
  407. }
  408. // std::map
  409. template <typename T1,typename T2>
  410. IGL_INLINE size_t getByteSize(const std::map<T1,T2>& obj)
  411. {
  412. return std::accumulate(obj.begin(),obj.end(),sizeof(size_t),[](const size_t& acc,const std::pair<T1,T2>& cur) { return acc+getByteSize(cur); });
  413. }
  414. template <typename T1,typename T2>
  415. IGL_INLINE void serialize(const std::map<T1,T2>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
  416. {
  417. detail::serialize(obj.size(),buffer,iter);
  418. for(const auto& cur : obj) { detail::serialize(cur,buffer,iter); }
  419. }
  420. template <typename T1,typename T2>
  421. IGL_INLINE void deserialize(std::map<T1,T2>& obj,std::vector<char>::const_iterator& iter)
  422. {
  423. size_t size;
  424. detail::deserialize(size,iter);
  425. obj.clear();
  426. for(size_t i=0; i<size; ++i)
  427. {
  428. std::pair<T1,T2> pair;
  429. detail::deserialize(pair,iter);
  430. obj.insert(pair);
  431. }
  432. }
  433. // Eigen types
  434. template<typename T,int R,int C,int P,int MR,int MC>
  435. IGL_INLINE size_t getByteSize(const Eigen::Matrix<T,R,C,P,MR,MC>& obj)
  436. {
  437. // space for numbers of rows,cols and data
  438. return 2*sizeof(typename Eigen::Matrix<T,R,C,P,MR,MC>::Index)+sizeof(T)*obj.rows()*obj.cols();
  439. }
  440. template<typename T,int R,int C,int P,int MR,int MC>
  441. IGL_INLINE void serialize(const Eigen::Matrix<T,R,C,P,MR,MC>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
  442. {
  443. detail::serialize(obj.rows(),buffer,iter);
  444. detail::serialize(obj.cols(),buffer,iter);
  445. size_t size = sizeof(T)*obj.rows()*obj.cols();
  446. const uint8_t* ptr = reinterpret_cast<const uint8_t*>(obj.data());
  447. iter = std::copy(ptr,ptr+size,iter);
  448. }
  449. template<typename T,int R,int C,int P,int MR,int MC>
  450. IGL_INLINE void deserialize(Eigen::Matrix<T,R,C,P,MR,MC>& obj,std::vector<char>::const_iterator& iter)
  451. {
  452. typename Eigen::Matrix<T,R,C,P,MR,MC>::Index rows,cols;
  453. detail::deserialize(rows,iter);
  454. detail::deserialize(cols,iter);
  455. size_t size = sizeof(T)*rows*cols;
  456. obj.resize(rows,cols);
  457. uint8_t* ptr = reinterpret_cast<uint8_t*>(obj.data());
  458. std::copy(iter,iter+size,ptr);
  459. iter+=size;
  460. }
  461. template<typename T,int P,typename I>
  462. IGL_INLINE size_t getByteSize(const Eigen::SparseMatrix<T,P,I>& obj)
  463. {
  464. // space for numbers of rows,cols,nonZeros and tripplets with data (rowIdx,colIdx,value)
  465. size_t size = sizeof(Eigen::SparseMatrix<T,P,I>::Index);
  466. return 3*size+(sizeof(T)+2*size)*obj.nonZeros();
  467. }
  468. template<typename T,int P,typename I>
  469. IGL_INLINE void serialize(const Eigen::SparseMatrix<T,P,I>& obj,std::vector<char>& buffer,std::vector<char>::iterator& iter)
  470. {
  471. detail::serialize(obj.rows(),buffer,iter);
  472. detail::serialize(obj.cols(),buffer,iter);
  473. detail::serialize(obj.nonZeros(),buffer,iter);
  474. for(int k=0;k<obj.outerSize();++k)
  475. {
  476. for(typename Eigen::SparseMatrix<T,P,I>::InnerIterator it(obj,k);it;++it)
  477. {
  478. detail::serialize(it.row(),buffer,iter);
  479. detail::serialize(it.col(),buffer,iter);
  480. detail::serialize(it.value(),buffer,iter);
  481. }
  482. }
  483. }
  484. template<typename T,int P,typename I>
  485. IGL_INLINE void deserialize(Eigen::SparseMatrix<T,P,I>& obj,std::vector<char>::const_iterator& iter)
  486. {
  487. typename Eigen::SparseMatrix<T,P,I>::Index rows,cols,nonZeros;
  488. detail::deserialize(rows,iter);
  489. detail::deserialize(cols,iter);
  490. detail::deserialize(nonZeros,iter);
  491. obj.resize(rows,cols);
  492. obj.setZero();
  493. std::vector<Eigen::Triplet<T,I> > triplets;
  494. for(int i=0;i<nonZeros;i++)
  495. {
  496. typename Eigen::SparseMatrix<T,P,I>::Index rowId,colId;
  497. detail::deserialize(rowId,iter);
  498. detail::deserialize(colId,iter);
  499. T value;
  500. detail::deserialize(value,iter);
  501. triplets.push_back(Eigen::Triplet<T,I>(rowId,colId,value));
  502. }
  503. obj.setFromTriplets(triplets.begin(),triplets.end());
  504. }
  505. // pointers
  506. template <typename T>
  507. IGL_INLINE typename std::enable_if<std::is_pointer<T>::value,size_t>::type getByteSize(const T& obj)
  508. {
  509. bool isNullPtr = (obj == NULL);
  510. size_t size = sizeof(bool);
  511. if(isNullPtr == false)
  512. size += getByteSize(*obj);
  513. return size;
  514. }
  515. template <typename T>
  516. 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)
  517. {
  518. bool isNullPtr = (obj == NULL);
  519. detail::serialize(isNullPtr,buffer,iter);
  520. if(isNullPtr == false)
  521. detail::serialize(*obj,buffer,iter);
  522. }
  523. template <typename T>
  524. IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type deserialize(T& obj,std::vector<char>::const_iterator& iter)
  525. {
  526. bool isNullPtr;
  527. detail::deserialize(isNullPtr,iter);
  528. if(isNullPtr)
  529. {
  530. if(obj != NULL)
  531. {
  532. std::cout << "deserialization: possible memory leak for '" << typeid(obj).name() << "'" << std::endl;
  533. obj = NULL;
  534. }
  535. }
  536. else
  537. {
  538. if(obj != NULL)
  539. std::cout << "deserialization: possible memory leak for '" << typeid(obj).name() << "'" << std::endl;
  540. obj = new typename std::remove_pointer<T>::type();
  541. detail::deserialize(*obj,iter);
  542. }
  543. }
  544. }
  545. }