serialize_xml.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 Christian Schüller <schuellchr@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "serialize_xml.h"
  9. #include <iterator>
  10. namespace igl
  11. {
  12. namespace xml
  13. {
  14. template <typename T>
  15. IGL_INLINE void serialize_xml(const T& obj,const std::string& filename)
  16. {
  17. serialize_xml(obj,"object",filename,false,true);
  18. }
  19. template <typename T>
  20. IGL_INLINE void serialize_xml(const T& obj,const std::string& objectName,const std::string& filename,bool binary,bool overwrite)
  21. {
  22. tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
  23. if(overwrite == false)
  24. {
  25. // Check if file exists
  26. tinyxml2::XMLError error = doc->LoadFile(filename.c_str());
  27. if(error != tinyxml2::XML_NO_ERROR)
  28. {
  29. doc->Clear();
  30. }
  31. }
  32. tinyxml2::XMLElement* element = doc->FirstChildElement("serialization");
  33. if(element == NULL)
  34. {
  35. element = doc->NewElement("serialization");
  36. doc->InsertEndChild(element);
  37. }
  38. serialize_xml(obj,objectName,doc,element,binary);
  39. // Save
  40. tinyxml2::XMLError error = doc->SaveFile(filename.c_str());
  41. if(error != tinyxml2::XML_NO_ERROR)
  42. {
  43. doc->PrintError();
  44. }
  45. delete doc;
  46. }
  47. template <typename T>
  48. IGL_INLINE void serialize_xml(const T& obj,const std::string& objectName,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,bool binary)
  49. {
  50. static_assert(serialization_xml::is_serializable<T>::value,"'igl::xml::serialize_xml': type is not serializable");
  51. std::string name(objectName);
  52. serialization_xml::encodeXMLElementName(name);
  53. tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
  54. if(child != NULL)
  55. element->DeleteChild(child);
  56. child = doc->NewElement(name.c_str());
  57. element->InsertEndChild(child);
  58. if(binary)
  59. {
  60. std::vector<char> buffer;
  61. serialize(obj,name,buffer);
  62. std::string data = serialization_xml::base64_encode(reinterpret_cast<const unsigned char*>(buffer.data()),buffer.size());
  63. child->SetAttribute("binary",true);
  64. serialization_xml::serialize(data,doc,element,name);
  65. }
  66. else
  67. {
  68. serialization_xml::serialize(obj,doc,element,name);
  69. }
  70. }
  71. template <typename T>
  72. IGL_INLINE void deserialize_xml(T& obj,const std::string& filename)
  73. {
  74. deserialize_xml(obj,"object",filename);
  75. }
  76. template <typename T>
  77. IGL_INLINE void deserialize_xml(T& obj,const std::string& objectName,const std::string& filename)
  78. {
  79. tinyxml2::XMLDocument* doc = new tinyxml2::XMLDocument();
  80. tinyxml2::XMLError error = doc->LoadFile(filename.c_str());
  81. if(error != tinyxml2::XML_NO_ERROR)
  82. {
  83. std::cerr << "File not found!" << std::endl;
  84. doc->PrintError();
  85. doc = NULL;
  86. }
  87. else
  88. {
  89. tinyxml2::XMLElement* element = doc->FirstChildElement("serialization");
  90. if(element == NULL)
  91. {
  92. std::cerr << "Name of object not found! Initialized with default value." << std::endl;
  93. obj = T();
  94. }
  95. else
  96. {
  97. deserialize_xml(obj,objectName,doc,element);
  98. }
  99. delete doc;
  100. }
  101. }
  102. template <typename T>
  103. IGL_INLINE void deserialize_xml(T& obj,const std::string& objectName,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element)
  104. {
  105. static_assert(serialization::is_serializable<T>::value,"'igl::xml::deserialize_xml': type is not deserializable");
  106. std::string name(objectName);
  107. serialization_xml::encodeXMLElementName(name);
  108. const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
  109. if(child != NULL)
  110. {
  111. bool isBinary = false;
  112. const tinyxml2::XMLAttribute* attr = child->FindAttribute("binary");
  113. if(attr != NULL)
  114. {
  115. std::string code;
  116. serialization_xml::deserialize(code,doc,element,name);
  117. std::string decoded = serialization_xml::base64_decode(code);
  118. std::vector<char> buffer;
  119. std::copy(decoded.c_str(),decoded.c_str()+decoded.length(),std::back_inserter(buffer));
  120. deserialize(obj,name,buffer);
  121. }
  122. else
  123. {
  124. serialization_xml::deserialize(obj,doc,element,name);
  125. }
  126. }
  127. }
  128. IGL_INLINE bool XMLSerializable::PreSerialization() const
  129. {
  130. return true;
  131. }
  132. IGL_INLINE void XMLSerializable::PostSerialization() const
  133. {
  134. }
  135. IGL_INLINE bool XMLSerializable::PreDeserialization()
  136. {
  137. return true;
  138. }
  139. IGL_INLINE void XMLSerializable::PostDeserialization()
  140. {
  141. }
  142. IGL_INLINE void XMLSerializable::Serialize(std::vector<char>& buffer) const
  143. {
  144. if(this->PreSerialization())
  145. {
  146. if(initialized == false)
  147. {
  148. objects.clear();
  149. (const_cast<XMLSerializable*>(this))->InitSerialization();
  150. initialized = true;
  151. }
  152. for(unsigned int i=0;i<objects.size();i++)
  153. objects[i]->Serialize(buffer);
  154. this->PostSerialization();
  155. }
  156. }
  157. IGL_INLINE void XMLSerializable::Deserialize(const std::vector<char>& buffer)
  158. {
  159. if(this->PreDeserialization())
  160. {
  161. if(initialized == false)
  162. {
  163. objects.clear();
  164. (const_cast<XMLSerializable*>(this))->InitSerialization();
  165. initialized = true;
  166. }
  167. for(unsigned int i=0;i<objects.size();i++)
  168. objects[i]->Deserialize(buffer);
  169. this->PostDeserialization();
  170. }
  171. }
  172. IGL_INLINE void XMLSerializable::Serialize(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element) const
  173. {
  174. if(this->PreSerialization())
  175. {
  176. if(initialized == false)
  177. {
  178. objects.clear();
  179. (const_cast<XMLSerializable*>(this))->InitSerialization();
  180. initialized = true;
  181. }
  182. for(unsigned int i=0;i<objects.size();i++)
  183. objects[i]->Serialize(doc,element);
  184. this->PostSerialization();
  185. }
  186. }
  187. IGL_INLINE void XMLSerializable::Deserialize(const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element)
  188. {
  189. if(this->PreDeserialization())
  190. {
  191. if(initialized == false)
  192. {
  193. objects.clear();
  194. (const_cast<XMLSerializable*>(this))->InitSerialization();
  195. initialized = true;
  196. }
  197. for(unsigned int i=0;i<objects.size();i++)
  198. objects[i]->Deserialize(doc,element);
  199. this->PostDeserialization();
  200. }
  201. }
  202. IGL_INLINE XMLSerializable::XMLSerializable()
  203. {
  204. initialized = false;
  205. }
  206. IGL_INLINE XMLSerializable::XMLSerializable(const XMLSerializable& obj)
  207. {
  208. initialized = false;
  209. objects.clear();
  210. }
  211. IGL_INLINE XMLSerializable::~XMLSerializable()
  212. {
  213. initialized = false;
  214. objects.clear();
  215. }
  216. IGL_INLINE XMLSerializable& XMLSerializable::operator=(const XMLSerializable& obj)
  217. {
  218. if(this != &obj)
  219. {
  220. if(initialized)
  221. {
  222. initialized = false;
  223. objects.clear();
  224. }
  225. }
  226. return *this;
  227. }
  228. template <typename T>
  229. IGL_INLINE void XMLSerializable::Add(T& obj,std::string name,bool binary)
  230. {
  231. XMLSerializationObject<T>* object = new XMLSerializationObject<T>();
  232. object->Binary = binary;
  233. object->Name = name;
  234. object->Object = &obj;
  235. objects.push_back(object);
  236. }
  237. namespace serialization_xml
  238. {
  239. // fundamental types
  240. template <typename T>
  241. IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value>::type serialize(const T& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
  242. {
  243. tinyxml2::XMLElement* child = getElement(doc,element,name.c_str());
  244. child->SetAttribute("val",obj);
  245. }
  246. template <typename T>
  247. IGL_INLINE typename std::enable_if<std::is_fundamental<T>::value>::type deserialize(T& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
  248. {
  249. const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
  250. if(child != NULL)
  251. {
  252. getAttribute(child->Attribute("val"),obj);
  253. }
  254. else
  255. {
  256. obj = T();
  257. }
  258. }
  259. // std::string
  260. IGL_INLINE void serialize(const std::string& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
  261. {
  262. tinyxml2::XMLElement* child = getElement(doc,element,name.c_str());
  263. child->SetAttribute("val",obj.c_str());
  264. }
  265. IGL_INLINE void deserialize(std::string& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
  266. {
  267. const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
  268. if(child != NULL)
  269. {
  270. getAttribute(child->Attribute("val"),obj);
  271. }
  272. else
  273. {
  274. obj = std::string("");
  275. }
  276. }
  277. // Serializable
  278. template <typename T>
  279. IGL_INLINE typename std::enable_if<std::is_base_of<XMLSerializableBase,T>::value>::type serialize(const T& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
  280. {
  281. // Serialize object implementing Serializable interface
  282. const XMLSerializableBase& object = dynamic_cast<const XMLSerializableBase&>(obj);
  283. tinyxml2::XMLElement* child = getElement(doc,element,name.c_str());
  284. object.Serialize(doc,child);
  285. }
  286. template <typename T>
  287. IGL_INLINE typename std::enable_if<std::is_base_of<XMLSerializableBase,T>::value>::type deserialize(T& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
  288. {
  289. const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
  290. if(child != NULL)
  291. {
  292. obj.Deserialize(doc,child);
  293. }
  294. else
  295. {
  296. obj = T();
  297. }
  298. }
  299. // STL containers
  300. template <typename T1,typename T2>
  301. IGL_INLINE void serialize(const std::pair<T1,T2>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
  302. {
  303. tinyxml2::XMLElement* pair = getElement(doc,element,name.c_str());
  304. serialize(obj.first,doc,pair,"first");
  305. serialize(obj.second,doc,pair,"second");
  306. }
  307. template <typename T1,typename T2>
  308. IGL_INLINE void deserialize(std::pair<T1,T2>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
  309. {
  310. const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
  311. if(child != NULL)
  312. {
  313. deserialize(obj.first,doc,child,"first");
  314. deserialize(obj.second,doc,child,"second");
  315. }
  316. else
  317. {
  318. obj.first = T1();
  319. obj.second = T2();
  320. }
  321. }
  322. template <typename T1,typename T2>
  323. IGL_INLINE void serialize(const std::vector<T1,T2>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
  324. {
  325. tinyxml2::XMLElement* vector = getElement(doc,element,name.c_str());
  326. vector->SetAttribute("size",(unsigned int)obj.size());
  327. std::stringstream num;
  328. for(unsigned int i=0;i<obj.size();i++)
  329. {
  330. num.str("");
  331. num << "value" << i;
  332. serialize(obj[i],doc,vector,num.str());
  333. }
  334. }
  335. template <typename T1,typename T2>
  336. IGL_INLINE void deserialize(std::vector<T1,T2>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
  337. {
  338. obj.clear();
  339. const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
  340. if(child != NULL)
  341. {
  342. unsigned int size = child->UnsignedAttribute("size");
  343. obj.resize(size);
  344. std::stringstream num;
  345. for(unsigned int i=0;i<size;i++)
  346. {
  347. num.str("");
  348. num << "value" << i;
  349. deserialize(obj[i],doc,child,num.str());
  350. }
  351. }
  352. else
  353. {
  354. obj.clear();
  355. }
  356. }
  357. template <typename T>
  358. IGL_INLINE void serialize(const std::set<T>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
  359. {
  360. tinyxml2::XMLElement* set = getElement(doc,element,name.c_str());
  361. set->SetAttribute("size",(unsigned int)obj.size());
  362. std::stringstream num;
  363. typename std::set<T>::iterator iter = obj.begin();
  364. for(int i=0;iter!=obj.end();iter++,i++)
  365. {
  366. num.str("");
  367. num << "value" << i;
  368. serialize((T)*iter,doc,set,num.str());
  369. }
  370. }
  371. template <typename T>
  372. IGL_INLINE void deserialize(std::set<T>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
  373. {
  374. obj.clear();
  375. const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
  376. if(child != NULL)
  377. {
  378. unsigned int size = child->UnsignedAttribute("size");
  379. std::stringstream num;
  380. typename std::set<T>::iterator iter = obj.begin();
  381. for(int i=0;i<size;i++)
  382. {
  383. num.str("");
  384. num << "value" << i;
  385. T val;
  386. deserialize(val,doc,child,num.str());
  387. obj.insert(val);
  388. }
  389. }
  390. else
  391. {
  392. obj.clear();
  393. }
  394. }
  395. template <typename T1,typename T2>
  396. IGL_INLINE void serialize(const std::map<T1,T2>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
  397. {
  398. tinyxml2::XMLElement* map = getElement(doc,element,name.c_str());
  399. map->SetAttribute("size",(unsigned int)obj.size());
  400. std::stringstream num;
  401. typename std::map<T1,T2>::const_iterator iter = obj.cbegin();
  402. for(int i=0;iter!=obj.end();iter++,i++)
  403. {
  404. num.str("");
  405. num << "value" << i;
  406. serialize((std::pair<T1,T2>)*iter,doc,map,num.str());
  407. }
  408. }
  409. template <typename T1,typename T2>
  410. IGL_INLINE void deserialize(std::map<T1,T2>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
  411. {
  412. obj.clear();
  413. const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
  414. if(child != NULL)
  415. {
  416. unsigned int size = child->UnsignedAttribute("size");
  417. std::stringstream num;
  418. typename std::map<T1,T2>::iterator iter = obj.begin();
  419. for(int i=0;i<size;i++)
  420. {
  421. num.str("");
  422. num << "value" << i;
  423. std::pair<T1,T2> pair;
  424. deserialize(pair,doc,child,num.str());
  425. obj.insert(pair);
  426. }
  427. }
  428. else
  429. {
  430. obj.clear();
  431. }
  432. }
  433. // Eigen types
  434. template<typename T,int R,int C,int P,int MR,int MC>
  435. IGL_INLINE void serialize(const Eigen::Matrix<T,R,C,P,MR,MC>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
  436. {
  437. tinyxml2::XMLElement* matrix = getElement(doc,element,name.c_str());
  438. const unsigned int rows = obj.rows();
  439. const unsigned int cols = obj.cols();
  440. matrix->SetAttribute("rows",rows);
  441. matrix->SetAttribute("cols",cols);
  442. char buffer[200];
  443. std::stringstream ms;
  444. ms << "\n";
  445. for(unsigned int r=0;r<rows;r++)
  446. {
  447. for(unsigned int c=0;c<cols;c++)
  448. {
  449. tinyxml2::XMLUtil::ToStr(obj(r,c),buffer,200);
  450. ms << buffer << ",";
  451. }
  452. ms << "\n";
  453. }
  454. std::string mString = ms.str();
  455. if(mString.size() > 1)
  456. mString[mString.size()-2] = '\0';
  457. matrix->SetAttribute("matrix",mString.c_str());
  458. }
  459. template<typename T,int R,int C,int P,int MR,int MC>
  460. IGL_INLINE void deserialize(Eigen::Matrix<T,R,C,P,MR,MC>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
  461. {
  462. const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
  463. bool initialized = false;
  464. if(child != NULL)
  465. {
  466. const unsigned int rows = child->UnsignedAttribute("rows");
  467. const unsigned int cols = child->UnsignedAttribute("cols");
  468. if(rows > 0 && cols > 0)
  469. {
  470. obj.resize(rows,cols);
  471. const tinyxml2::XMLAttribute* attribute = child->FindAttribute("matrix");
  472. if(attribute != NULL)
  473. {
  474. std::string matTemp;
  475. getAttribute(attribute->Value(),matTemp);
  476. std::string line,srows,scols;
  477. std::stringstream mats;
  478. mats << matTemp;
  479. int r=0;
  480. std::string val;
  481. // for each line
  482. getline(mats,line);
  483. while(getline(mats,line))
  484. {
  485. // get current line
  486. std::stringstream liness(line);
  487. for(unsigned int c=0;c<cols-1;c++)
  488. {
  489. // split line
  490. getline(liness,val,',');
  491. // push pack the data if any
  492. if(!val.empty())
  493. getAttribute(val.c_str(),obj.coeffRef(r,c));
  494. }
  495. getline(liness,val);
  496. getAttribute(val.c_str(),obj.coeffRef(r,cols-1));
  497. r++;
  498. }
  499. initialized = true;
  500. }
  501. }
  502. }
  503. if(!initialized)
  504. {
  505. obj = Eigen::Matrix<T,R,C,P,MR,MC>();
  506. }
  507. }
  508. template<typename T,int P,typename I>
  509. IGL_INLINE void serialize(const Eigen::SparseMatrix<T,P,I>& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
  510. {
  511. tinyxml2::XMLElement* matrix = getElement(doc,element,name.c_str());
  512. const unsigned int rows = obj.rows();
  513. const unsigned int cols = obj.cols();
  514. matrix->SetAttribute("rows",rows);
  515. matrix->SetAttribute("cols",cols);
  516. char buffer[200];
  517. std::stringstream ms;
  518. ms << "\n";
  519. for(int k=0;k<obj.outerSize();++k)
  520. {
  521. for(typename Eigen::SparseMatrix<T,P,I>::InnerIterator it(obj,k);it;++it)
  522. {
  523. tinyxml2::XMLUtil::ToStr(it.value(),buffer,200);
  524. ms << it.row() << "," << it.col() << "," << buffer << "\n";
  525. }
  526. }
  527. std::string mString = ms.str();
  528. if(mString.size() > 0)
  529. mString[mString.size()-1] = '\0';
  530. matrix->SetAttribute("matrix",mString.c_str());
  531. }
  532. template<typename T,int P,typename I>
  533. IGL_INLINE void deserialize(Eigen::SparseMatrix<T,P,I>& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
  534. {
  535. const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
  536. bool initialized = false;
  537. if(child != NULL)
  538. {
  539. const unsigned int rows = child->UnsignedAttribute("rows");
  540. const unsigned int cols = child->UnsignedAttribute("cols");
  541. if(rows > 0 && cols > 0)
  542. {
  543. obj.resize(rows,cols);
  544. obj.setZero();
  545. const tinyxml2::XMLAttribute* attribute = child->FindAttribute("matrix");
  546. if(attribute != NULL)
  547. {
  548. std::string matTemp;
  549. getAttribute(attribute->Value(),matTemp);
  550. std::string line,srows,scols;
  551. std::stringstream mats;
  552. mats << matTemp;
  553. std::vector<Eigen::Triplet<T,I> > triplets;
  554. int r=0;
  555. std::string val;
  556. // for each line
  557. getline(mats,line);
  558. while(getline(mats,line))
  559. {
  560. // get current line
  561. std::stringstream liness(line);
  562. // row
  563. getline(liness,val,',');
  564. int row = atoi(val.c_str());
  565. // col
  566. getline(liness,val,',');
  567. int col = atoi(val.c_str());
  568. // val
  569. getline(liness,val);
  570. T value;
  571. getAttribute(val.c_str(),value);
  572. triplets.push_back(Eigen::Triplet<T,I>(row,col,value));
  573. r++;
  574. }
  575. obj.setFromTriplets(triplets.begin(),triplets.end());
  576. initialized = true;
  577. }
  578. }
  579. }
  580. if(!initialized)
  581. {
  582. obj = Eigen::SparseMatrix<T,P,I>();
  583. }
  584. }
  585. // pointers
  586. template <typename T>
  587. IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type serialize(const T& obj,tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
  588. {
  589. tinyxml2::XMLElement* pointer = getElement(doc,element,name.c_str());
  590. bool isNullPtr = (obj == NULL);
  591. pointer->SetAttribute("isNullPtr",isNullPtr);
  592. if(isNullPtr == false)
  593. serialization_xml::serialize(*obj,doc,element,name);
  594. }
  595. template <typename T>
  596. IGL_INLINE typename std::enable_if<std::is_pointer<T>::value>::type deserialize(T& obj,const tinyxml2::XMLDocument* doc,const tinyxml2::XMLElement* element,const std::string& name)
  597. {
  598. const tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
  599. if(child != NULL)
  600. {
  601. bool isNullPtr = child->BoolAttribute("isNullPtr");
  602. if(isNullPtr)
  603. {
  604. if(obj != NULL)
  605. {
  606. std::cout << "deserialization: possible memory leak for '" << typeid(obj).name() << "'" << std::endl;
  607. obj = NULL;
  608. }
  609. }
  610. else
  611. {
  612. if(obj != NULL)
  613. std::cout << "deserialization: possible memory leak for '" << typeid(obj).name() << "'" << std::endl;
  614. obj = new typename std::remove_pointer<T>::type();
  615. serialization_xml::deserialize(*obj,doc,element,name);
  616. }
  617. }
  618. }
  619. // helper functions
  620. IGL_INLINE tinyxml2::XMLElement* getElement(tinyxml2::XMLDocument* doc,tinyxml2::XMLElement* element,const std::string& name)
  621. {
  622. tinyxml2::XMLElement* child = element->FirstChildElement(name.c_str());
  623. if(child == NULL)
  624. {
  625. child = doc->NewElement(name.c_str());
  626. element->InsertEndChild(child);
  627. }
  628. return child;
  629. }
  630. IGL_INLINE void getAttribute(const char* src,bool& dest)
  631. {
  632. tinyxml2::XMLUtil::ToBool(src,&dest);
  633. }
  634. IGL_INLINE void getAttribute(const char* src,char& dest)
  635. {
  636. dest = (char)atoi(src);
  637. }
  638. IGL_INLINE void getAttribute(const char* src,std::string& dest)
  639. {
  640. dest = src;
  641. }
  642. IGL_INLINE void getAttribute(const char* src,float& dest)
  643. {
  644. tinyxml2::XMLUtil::ToFloat(src,&dest);
  645. }
  646. IGL_INLINE void getAttribute(const char* src,double& dest)
  647. {
  648. tinyxml2::XMLUtil::ToDouble(src,&dest);
  649. }
  650. template<typename T>
  651. IGL_INLINE typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value>::type getAttribute(const char* src,T& dest)
  652. {
  653. unsigned int val;
  654. tinyxml2::XMLUtil::ToUnsigned(src,&val);
  655. dest = (T)val;
  656. }
  657. template<typename T>
  658. IGL_INLINE typename std::enable_if<std::is_integral<T>::value && !std::is_unsigned<T>::value>::type getAttribute(const char* src,T& dest)
  659. {
  660. int val;
  661. tinyxml2::XMLUtil::ToInt(src,&val);
  662. dest = (T)val;
  663. }
  664. // tinyXML2 related stuff
  665. static const int numForbiddenChars = 8;
  666. static const char forbiddenChars[] ={' ','/','~','#','&','>','<','='};
  667. IGL_INLINE void replaceSubString(std::string& str,const std::string& search,const std::string& replace)
  668. {
  669. size_t pos = 0;
  670. while((pos = str.find(search,pos)) != std::string::npos)
  671. {
  672. str.replace(pos,search.length(),replace);
  673. pos += replace.length();
  674. }
  675. }
  676. IGL_INLINE void encodeXMLElementName(std::string& name)
  677. {
  678. // must not start with a digit
  679. if(isdigit(*name.begin()))
  680. {
  681. name = ":::" + name;
  682. }
  683. std::stringstream stream;
  684. for(int i=0;i<numForbiddenChars;i++)
  685. {
  686. std::string search;
  687. search = forbiddenChars[i];
  688. std::stringstream replaces;
  689. replaces << ":" << (int)forbiddenChars[i];
  690. std::string replace = replaces.str();
  691. replaceSubString(name,search,replace);
  692. }
  693. }
  694. IGL_INLINE void decodeXMLElementName(std::string& name)
  695. {
  696. if(name.find("::",0) == 0)
  697. name.replace(0,3,"");
  698. for(auto chr : forbiddenChars)
  699. {
  700. std::stringstream searchs;
  701. searchs << ":" << (int)chr;
  702. std::string search = searchs.str();
  703. std::string replace;
  704. replace = chr;
  705. replaceSubString(name,search,replace);
  706. }
  707. }
  708. /* Copyright(C) 2004-2008 Ren� Nyffenegger
  709. This source code is provided 'as-is',without any express or implied
  710. warranty.In no event will the author be held liable for any damages
  711. arising from the use of this software.
  712. Permission is granted to anyone to use this software for any purpose,
  713. including commercial applications,and to alter it and redistribute it
  714. freely,subject to the following restrictions:
  715. 1. The origin of this source code must not be misrepresented; you must not
  716. claim that you wrote the original source code.If you use this source code
  717. in a product,an acknowledgment in the product documentation would be
  718. appreciated but is not required.
  719. 2. Altered source versions must be plainly marked as such,and must not be
  720. misrepresented as being the original source code.
  721. 3. This notice may not be removed or altered from any source distribution.
  722. Ren� Nyffenegger rene.nyffenegger@adp-gmbh.ch
  723. */
  724. static const std::string base64_chars =
  725. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  726. "abcdefghijklmnopqrstuvwxyz"
  727. "0123456789+/";
  728. static inline bool is_base64(unsigned char c) {
  729. return (isalnum(c) || (c == '+') || (c == '/'));
  730. }
  731. std::string base64_encode(unsigned char const* bytes_to_encode,unsigned int in_len)
  732. {
  733. std::string ret;
  734. int i = 0;
  735. int j = 0;
  736. unsigned char char_array_3[3];
  737. unsigned char char_array_4[4];
  738. while(in_len--) {
  739. char_array_3[i++] = *(bytes_to_encode++);
  740. if(i == 3) {
  741. char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
  742. char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
  743. char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
  744. char_array_4[3] = char_array_3[2] & 0x3f;
  745. for(i = 0; (i <4) ; i++)
  746. ret += base64_chars[char_array_4[i]];
  747. i = 0;
  748. }
  749. }
  750. if(i)
  751. {
  752. for(j = i; j < 3; j++)
  753. char_array_3[j] = '\0';
  754. char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
  755. char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
  756. char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
  757. char_array_4[3] = char_array_3[2] & 0x3f;
  758. for(j = 0; (j < i + 1); j++)
  759. ret += base64_chars[char_array_4[j]];
  760. while((i++ < 3))
  761. ret += '=';
  762. }
  763. return ret;
  764. }
  765. std::string base64_decode(std::string const& encoded_string)
  766. {
  767. int in_len = encoded_string.size();
  768. int i = 0;
  769. int j = 0;
  770. int in_ = 0;
  771. unsigned char char_array_4[4],char_array_3[3];
  772. std::string ret;
  773. // construct fast lookup table
  774. // added by Christian Sch�ller (schuellc@inf.ethz.ch)
  775. int charLookup[200];
  776. for(int i=0;i<(int)(base64_chars.length());i++)
  777. charLookup[(int)base64_chars[i]] = i;
  778. while(in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
  779. char_array_4[i++] = encoded_string[in_]; in_++;
  780. if(i ==4) {
  781. for(i = 0; i <4; i++)
  782. char_array_4[i] = charLookup[char_array_4[i]]; // new fast lookup
  783. //char_array_4[i] = base64_chars.find(char_array_4[i]); // original version
  784. char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
  785. char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
  786. char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
  787. for(i = 0; (i < 3); i++)
  788. ret += char_array_3[i];
  789. i = 0;
  790. }
  791. }
  792. if(i) {
  793. for(j = i; j <4; j++)
  794. char_array_4[j] = 0;
  795. for(j = 0; j <4; j++)
  796. char_array_4[j] = base64_chars.find(char_array_4[j]);
  797. char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
  798. char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
  799. char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
  800. for(j = 0; (j < i - 1);
  801. j++) ret += char_array_3[j];
  802. }
  803. return ret;
  804. }
  805. }
  806. }
  807. }
  808. #ifdef IGL_STATIC_LIBRARY
  809. // Explicit template specialization
  810. template void igl::xml::serialize_xml<std::vector<float, std::allocator<float> > >(std::vector<float, std::allocator<float> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool, bool);
  811. template void igl::xml::deserialize_xml<std::vector<float, std::allocator<float> > >(std::vector<float, std::allocator<float> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&);
  812. #endif