xml_encoder.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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_ENCODER_H
  17. #define __X_PACK_XML_ENCODER_H
  18. #include <list>
  19. #include <sstream>
  20. #include "xencoder.h"
  21. namespace xpack {
  22. class XmlEncoder:public XEncoder<XmlEncoder>, private noncopyable {
  23. private:
  24. struct Attr {
  25. const char* key;
  26. std::string val;
  27. Attr(const char*_key, const std::string&_val):key(_key), val(_val){}
  28. };
  29. struct Node {
  30. Node(const char*_key=NULL, const Extend *ext=NULL) {
  31. if (_key != NULL && strlen(_key)>0) {
  32. key = _key;
  33. } else { // vector case
  34. if (NULL != ext && NULL != ext->alias) {
  35. std::string vl = ext->alias->Flag("xml", "vl"); // vl:vector label
  36. if (!vl.empty()) {
  37. key = vl;
  38. } else {
  39. key = "x";
  40. }
  41. } else {
  42. key = "x"; // for vector
  43. }
  44. }
  45. }
  46. ~Node() {
  47. std::list<Node*>::iterator it;
  48. for (it = childs.begin(); it!=childs.end(); ++it) {
  49. delete *it;
  50. }
  51. }
  52. std::string key; // key for this node
  53. std::string val; // value for this node, only for leaf node
  54. std::list<Attr> attrs; // attribute
  55. std::list<Node*> childs;// child nodes
  56. };
  57. public:
  58. friend class XEncoder<XmlEncoder>;
  59. using xdoc_type::encode;
  60. XmlEncoder(int indentCount=-1, char indentChar=' '):_indentCount(indentCount),_indentChar(indentChar) {
  61. if (_indentCount > 0) {
  62. if (_indentChar!=' ' && _indentChar!='\t') {
  63. throw std::runtime_error("indentChar must be space or tab");
  64. }
  65. }
  66. _cur = &_root;
  67. }
  68. ~XmlEncoder() {
  69. }
  70. std::string String() {
  71. merge();
  72. return _output;
  73. }
  74. public:
  75. inline const char *Type() const {
  76. return "xml";
  77. }
  78. inline const char *IndexKey(size_t index) {
  79. (void)index;
  80. return NULL;//"x";
  81. }
  82. void ArrayBegin(const char *key, const Extend *ext) {
  83. Node *n = new Node(key, ext);
  84. _cur->childs.push_back(n);
  85. _stack.push_back(_cur);
  86. _cur = n;
  87. }
  88. void ArrayEnd(const char *key, const Extend *ext) {
  89. (void)key;
  90. (void)ext;
  91. _cur = _stack.back();
  92. _stack.pop_back();
  93. }
  94. void ObjectBegin(const char *key, const Extend *ext) {
  95. Node *n = new Node(key, ext);
  96. _cur->childs.push_back(n);
  97. _stack.push_back(_cur);
  98. _cur = n;
  99. }
  100. void ObjectEnd(const char *key, const Extend *ext) {
  101. (void)key;
  102. (void)ext;
  103. _cur = _stack.back();
  104. _stack.pop_back();
  105. }
  106. bool writeNull(const char*key, const Extend *ext) {
  107. static std::string empty;
  108. return this->encode(key, empty, ext);
  109. }
  110. // string
  111. bool encode(const char*key, const std::string &val, const Extend *ext) {
  112. if (val.empty() && Extend::OmitEmpty(ext)) {
  113. return false;
  114. } else if (Extend::Attribute(ext)) {
  115. _cur->attrs.push_back(Attr(key, StringQuote(val)));
  116. } else {
  117. Node *n = new Node(key);
  118. n->val = StringQuote(val);
  119. _cur->childs.push_back(n);
  120. }
  121. return true;
  122. }
  123. // bool
  124. bool encode(const char*key, const bool &val, const Extend *ext) {
  125. if (!val && Extend::OmitEmpty(ext)) {
  126. return false;
  127. } else {
  128. std::string bval;
  129. if (val) {
  130. bval = "true";
  131. } else {
  132. bval = "false";
  133. }
  134. if (Extend::Attribute(ext)) {
  135. _cur->attrs.push_back(Attr(key, bval));
  136. } else {
  137. Node *n = new Node(key);
  138. n->val = bval;
  139. _cur->childs.push_back(n);
  140. }
  141. }
  142. return true;
  143. }
  144. #define XPACK_XML_ENCODE_INTEGER(type) \
  145. bool encode(const char*key, const type&val, const Extend*ext) {return this->encode_integer(key, val, ext);}
  146. XPACK_XML_ENCODE_INTEGER(char)
  147. XPACK_XML_ENCODE_INTEGER(signed char)
  148. XPACK_XML_ENCODE_INTEGER(unsigned char)
  149. XPACK_XML_ENCODE_INTEGER(short)
  150. XPACK_XML_ENCODE_INTEGER(unsigned short)
  151. XPACK_XML_ENCODE_INTEGER(int)
  152. XPACK_XML_ENCODE_INTEGER(unsigned int)
  153. XPACK_XML_ENCODE_INTEGER(long)
  154. XPACK_XML_ENCODE_INTEGER(unsigned long)
  155. XPACK_XML_ENCODE_INTEGER(long long)
  156. XPACK_XML_ENCODE_INTEGER(unsigned long long)
  157. #define XPACK_XML_ENCODE_FLOAT(type) \
  158. bool encode(const char*key, const type&val, const Extend*ext) {return this->encode_float(key, val, ext);}
  159. XPACK_XML_ENCODE_FLOAT(float)
  160. XPACK_XML_ENCODE_FLOAT(double)
  161. XPACK_XML_ENCODE_FLOAT(long double)
  162. // escape string
  163. static std::string StringQuote(const std::string &val) {
  164. std::string ret;
  165. ret.reserve(val.length()*2);
  166. for (size_t i=0; i<val.length(); ++i) {
  167. int c = (int)(val[i]) & 0xFF;
  168. switch (c) {
  169. case '<':
  170. ret += "&lt;";
  171. break;
  172. case '>':
  173. ret += "&gt;";
  174. break;
  175. case '&':
  176. ret += "&amp;";
  177. break;
  178. case '\'':
  179. ret += "&apos;";
  180. break;
  181. case '\"':
  182. ret += "&quot;";
  183. break;
  184. default:
  185. if(c >= ' ') {
  186. ret.push_back(val[i]);
  187. } else {
  188. ret += "\\x";
  189. unsigned char uch = (unsigned char)val[i];
  190. unsigned char h = (uch>>4)&0xf;
  191. unsigned char l = uch&0xf;
  192. if (h < 10) {
  193. ret.push_back(h+'0');
  194. } else {
  195. ret.push_back(h-10+'A');
  196. }
  197. if (l < 10) {
  198. ret.push_back(l+'0');
  199. } else {
  200. ret.push_back(l-10+'A');
  201. }
  202. }
  203. }
  204. }
  205. return ret;
  206. }
  207. private:
  208. // integer
  209. template <class T>
  210. typename x_enable_if<numeric<T>::is_integer, bool>::type encode_integer(const char*key, const T& val, const Extend *ext) {
  211. if (val==0 && Extend::OmitEmpty(ext)) {
  212. return false;
  213. } else if (Extend::Attribute(ext)) {
  214. _cur->attrs.push_back(Attr(key, Util::itoa(val)));
  215. } else {
  216. Node *n = new Node(key);
  217. n->val = Util::itoa(val);
  218. _cur->childs.push_back(n);
  219. }
  220. return true;
  221. }
  222. // float
  223. template <class T>
  224. typename x_enable_if<numeric<T>::is_float, bool>::type encode_float(const char*key, const T &val, const Extend *ext) {
  225. if (val==0 && Extend::OmitEmpty(ext)) {
  226. return false;
  227. } else {
  228. std::ostringstream os;
  229. os<<val;
  230. std::string fval = os.str();
  231. if (Extend::Attribute(ext)) {
  232. _cur->attrs.push_back(Attr(key, fval));
  233. } else {
  234. Node *n = new Node(key);
  235. n->val = fval;
  236. _cur->childs.push_back(n);
  237. }
  238. }
  239. return true;
  240. }
  241. void appendNode(const Node *nd, int depth) {
  242. bool indentEnd = true;
  243. indent(depth);
  244. _output.push_back('<');
  245. _output += nd->key;
  246. std::list<Attr>::const_iterator it;
  247. for (it=nd->attrs.begin(); it!=nd->attrs.end(); ++it) {
  248. _output.push_back(' ');
  249. _output += it->key;
  250. _output += "=\"";
  251. _output += it->val;
  252. _output.push_back('"');
  253. }
  254. if (nd->val.empty() && nd->childs.size()==0) {
  255. _output += "/>";
  256. return;
  257. } else if (!nd->val.empty()) {
  258. _output.push_back('>');
  259. _output += nd->val;
  260. indentEnd = false;
  261. } else {
  262. _output.push_back('>');
  263. std::list<Node*>::const_iterator it;
  264. for (it=nd->childs.begin(); it!=nd->childs.end(); ++it) {
  265. appendNode(*it, depth+1);
  266. }
  267. }
  268. if (indentEnd) {
  269. indent(depth);
  270. }
  271. _output += "</";
  272. _output += nd->key;
  273. _output.push_back('>');
  274. }
  275. void merge() {
  276. if (_output.length() > 0 || _root.childs.size()==0) {
  277. return;
  278. }
  279. appendNode(_root.childs.front(), 0);
  280. }
  281. void indent(int depth) {
  282. if (_indentCount < 0) {
  283. return;
  284. }
  285. _output.push_back('\n');
  286. if (_indentCount == 0) {
  287. return;
  288. }
  289. for (int i=0; i<depth*_indentCount; ++i) {
  290. _output.push_back(_indentChar);
  291. }
  292. }
  293. Node _root;
  294. Node *_cur;
  295. std::list<Node*> _stack;
  296. std::string _output;
  297. int _indentCount;
  298. char _indentChar;
  299. };
  300. }
  301. #endif