serialize_xml.cpp 25 KB

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