xml_decoder.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. /*
  2. * Copyright (C) 2021 Duowan Inc. All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing,
  11. * software distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #ifndef __X_PACK_XML_DECODER_H
  17. #define __X_PACK_XML_DECODER_H
  18. #include <map>
  19. #include <vector>
  20. #include <fstream>
  21. #include <cstdlib>
  22. #include <string.h>
  23. #include "thirdparty/rapidxml/rapidxml.hpp"
  24. #include "xdecoder.h"
  25. namespace xpack {
  26. class XmlDecoder:public XDecoder<XmlDecoder>, private noncopyable {
  27. typedef rapidxml::xml_document<> XML_READER_DOCUMENT;
  28. typedef rapidxml::xml_node<> XML_READER_NODE;
  29. friend class XDecoder<XmlDecoder>;
  30. class MemberIterator {
  31. friend class XmlDecoder;
  32. public:
  33. MemberIterator(size_t iter, XmlDecoder* parent):_iter(iter),_parent(parent){}
  34. bool operator != (const MemberIterator &that) const {
  35. return _iter != that._iter;
  36. }
  37. MemberIterator& operator ++ () {
  38. ++_iter;
  39. return *this;
  40. }
  41. const char* Key() const {
  42. if (NULL != _parent) {
  43. return _parent->get_iter_key(_iter);
  44. }
  45. return "";
  46. }
  47. XmlDecoder& Val() const {
  48. return _parent->member(*this, *_parent->alloc());
  49. }
  50. private:
  51. size_t _iter;
  52. XmlDecoder* _parent;
  53. };
  54. public:
  55. using xdoc_type::decode;
  56. typedef MemberIterator Iterator;
  57. XmlDecoder(const std::string& str, bool isfile=false):xdoc_type(NULL, ""),_doc(new XML_READER_DOCUMENT),_node(NULL) {
  58. std::string err;
  59. _xml_data = NULL;
  60. do {
  61. try {
  62. if (isfile) {
  63. std::ifstream fs(str.c_str(), std::ifstream::binary);
  64. if (!fs) {
  65. err = "Open file["+str+"] fail.";
  66. break;
  67. }
  68. std::string data((std::istreambuf_iterator<char>(fs)), std::istreambuf_iterator<char>());
  69. _xml_data = new char[data.length()+1];
  70. memcpy(_xml_data, data.data(), data.length());
  71. _xml_data[data.length()] = '\0';
  72. } else {
  73. _xml_data = new char[str.length()+1];
  74. memcpy(_xml_data, str.data(), str.length());
  75. _xml_data[str.length()] = '\0';
  76. }
  77. _doc->parse<0>(_xml_data);
  78. } catch (const rapidxml::parse_error&e) {
  79. err = std::string("parse xml fail. err=")+e.what()+". "+std::string(e.where<char>()).substr(0, 32);
  80. } catch (const std::exception&e) {
  81. err = std::string("parse xml fail. unknow exception. err=")+e.what();
  82. }
  83. if (!err.empty()) {
  84. break;
  85. }
  86. _node = _doc->first_node(); // root
  87. _parent = this;
  88. init();
  89. return;
  90. } while (false);
  91. delete _doc;
  92. _doc = NULL;
  93. if (NULL != _xml_data) {
  94. delete []_xml_data;
  95. _xml_data = NULL;
  96. }
  97. throw std::runtime_error(err);
  98. }
  99. ~XmlDecoder() {
  100. if (NULL != _doc) {
  101. delete _doc;
  102. delete []_xml_data;
  103. _doc = NULL;
  104. _xml_data = NULL;
  105. }
  106. }
  107. const char * Type() {
  108. return "xml";
  109. }
  110. public: // decode
  111. #define XPACK_XML_DECODE_CHECK() \
  112. bool exists; std::string v = get_val(key, exists); \
  113. if (!exists) { \
  114. if (Extend::Mandatory(ext)) { \
  115. decode_exception("mandatory key not found", key); \
  116. } \
  117. return false; \
  118. }
  119. #define XPACK_XML_DECODE_INTEGER(type) \
  120. bool decode(const char*key, type&val, const Extend*ext) {return this->decode_integer(key, val, ext);}
  121. XPACK_XML_DECODE_INTEGER(char)
  122. XPACK_XML_DECODE_INTEGER(signed char)
  123. XPACK_XML_DECODE_INTEGER(unsigned char)
  124. XPACK_XML_DECODE_INTEGER(short)
  125. XPACK_XML_DECODE_INTEGER(unsigned short)
  126. XPACK_XML_DECODE_INTEGER(int)
  127. XPACK_XML_DECODE_INTEGER(unsigned int)
  128. XPACK_XML_DECODE_INTEGER(long)
  129. XPACK_XML_DECODE_INTEGER(unsigned long)
  130. XPACK_XML_DECODE_INTEGER(long long)
  131. XPACK_XML_DECODE_INTEGER(unsigned long long)
  132. // string
  133. bool decode(const char *key, std::string &val, const Extend *ext) {
  134. XPACK_XML_DECODE_CHECK();
  135. val = v;
  136. return true;
  137. }
  138. bool decode(const char *key, bool &val, const Extend *ext) {
  139. XPACK_XML_DECODE_CHECK();
  140. if (v=="1" || v=="true" || v=="TRUE" || v=="True") {
  141. val = true;
  142. } else if (v=="0" || v=="false" || v=="FALSE" || v=="False") {
  143. val = false;
  144. } else {
  145. decode_exception("parse bool fail.", key);
  146. return false;
  147. }
  148. return true;
  149. }
  150. bool decode(const char *key, double &val, const Extend *ext) {
  151. XPACK_XML_DECODE_CHECK();
  152. if (1==v.length() && v[0]=='-') {
  153. return false;
  154. }
  155. const char *data = v.c_str();
  156. char *end;
  157. double d = strtod(data, &end);
  158. if ((size_t)(end-data) == v.length()) {
  159. val = d;
  160. return true;
  161. }
  162. decode_exception("parse double fail.", key);
  163. return false;
  164. }
  165. bool decode(const char *key, float &val, const Extend *ext) {
  166. double d;
  167. bool ret = this->decode(key, d, ext);
  168. if (ret) {
  169. val = (float)d;
  170. }
  171. return ret;
  172. }
  173. bool decode(const char *key, long double &val, const Extend *ext) {
  174. double d;
  175. bool ret = this->decode(key, d, ext);
  176. if (ret) {
  177. val = (long double)d;
  178. }
  179. return ret;
  180. }
  181. size_t Size() {
  182. return _childs.size();
  183. }
  184. XmlDecoder& operator[](size_t index) {
  185. XmlDecoder *d = alloc();
  186. member(index, *d);
  187. return *d;
  188. }
  189. XmlDecoder& operator[](const char* key) {
  190. XmlDecoder *d = alloc();
  191. member(key, *d);
  192. return *d;
  193. }
  194. Iterator Begin() {
  195. return Iterator(0, this);
  196. }
  197. Iterator End() {
  198. return Iterator(_childs.size(), this);
  199. }
  200. operator bool() const {
  201. return NULL != _node;
  202. }
  203. private:
  204. // integer. if we named this as decode, clang and msvc will fail
  205. template <class T>
  206. typename x_enable_if<numeric<T>::is_integer, bool>::type decode_integer(const char *key, T &val, const Extend *ext) {
  207. XPACK_XML_DECODE_CHECK();
  208. if (Util::atoi(v, val)) {
  209. return true;
  210. } else {
  211. decode_exception("parse int fail. not integer or overflow", key);
  212. return false;
  213. }
  214. }
  215. typedef std::map<const char*, size_t, cmp_str> node_index; // index of _childs
  216. XmlDecoder():xdoc_type(NULL, ""),_doc(NULL),_xml_data(NULL),_node(NULL) {
  217. init();
  218. }
  219. XmlDecoder& member(size_t index, XmlDecoder&d) {
  220. if (index < _childs.size()) {
  221. d.init_base(this, index);
  222. d._node = _childs[index];
  223. d.init();
  224. } else {
  225. decode_exception("Out of index", NULL);
  226. }
  227. return d;
  228. }
  229. XmlDecoder& member(const char*key, XmlDecoder&d) {
  230. node_index::iterator iter;
  231. if (_childs_index.end() != (iter=_childs_index.find(key))) {
  232. d.init_base(this, key);
  233. d._node = _childs[iter->second];
  234. d.init();
  235. }
  236. return d;
  237. }
  238. XmlDecoder& member(const Iterator &iter, XmlDecoder&d) const {
  239. const XML_READER_NODE* node = _childs[iter._iter];
  240. d.init_base(iter._parent, node->name());
  241. d._node = node;
  242. d.init();
  243. return d;
  244. }
  245. const char *get_iter_key(size_t iter) const {
  246. if (iter < _childs.size()) {
  247. return _childs[iter]->name();
  248. }
  249. return "";
  250. }
  251. void init() {
  252. _childs.clear();
  253. _childs_index.clear();
  254. if (NULL != _node) {
  255. XML_READER_NODE *tmp = _node->first_node();
  256. for (size_t i=0; tmp; tmp=tmp->next_sibling(), ++i) {
  257. _childs.push_back(tmp);
  258. _childs_index[tmp->name()] = i;
  259. }
  260. }
  261. }
  262. std::string get_val(const char *key, bool &exists) {
  263. exists = true;
  264. if (NULL == key) {
  265. return _node->value();
  266. } else {
  267. node_index::iterator iter;
  268. if (_childs_index.end()!=(iter=_childs_index.find(key))) {
  269. return _childs[iter->second]->value();
  270. } else {
  271. rapidxml::xml_attribute<char> *attr = _node->first_attribute(key);
  272. if (NULL != attr) {
  273. return attr->value();
  274. }
  275. }
  276. }
  277. exists = false;
  278. return "";
  279. }
  280. // for parse xml file. only root has this
  281. XML_READER_DOCUMENT* _doc;
  282. char *_xml_data;
  283. const XML_READER_NODE* _node; // current node
  284. std::vector<XML_READER_NODE*> _childs; // childs
  285. node_index _childs_index;
  286. size_t _iter;
  287. };
  288. }
  289. #endif