serialize.cpp 18 KB

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