serialize.cpp 18 KB

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