xencoder.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  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_ENCODER_H
  17. #define __X_PACK_ENCODER_H
  18. #include <map>
  19. #include <set>
  20. #include <vector>
  21. #include <list>
  22. #include "extend.h"
  23. #include "traits.h"
  24. #include "numeric.h"
  25. #include "xtype.h"
  26. #ifdef XPACK_SUPPORT_QT
  27. #include <QString>
  28. #include <QList>
  29. #include <QMap>
  30. #include <QVector>
  31. #endif
  32. #ifdef X_PACK_SUPPORT_CXX0X
  33. #include <memory>
  34. #include <unordered_map>
  35. #endif
  36. namespace xpack {
  37. /*
  38. DOC need implement:
  39. const char *Type() const; "json/bson/...."
  40. ArrayBegin(const char *key, const Extend *ext) begin encode array
  41. ArrayEnd(const char *key, const Extend *ext) end encode array
  42. ObjectBegin(const char *key, const Extend *ext) begin encode object
  43. ObjectEnd(const char *key, const Extend *ext) end encode object
  44. writeNull(const char *key, const Extend *ext)
  45. */
  46. template<typename DOC>
  47. class XEncoder {
  48. protected:
  49. typedef DOC doc_type;
  50. typedef XEncoder<DOC> xdoc_type;
  51. public:
  52. // for array
  53. template <class T, size_t N>
  54. inline bool encode(const char*key, const T (&val)[N], const Extend *ext) {
  55. return this->encode(key, val, N, ext);
  56. }
  57. template <class T>
  58. bool encode(const char *key, const T *val, size_t N, const Extend *ext) {
  59. if (N==0 && Extend::OmitEmpty(ext)) {
  60. return false;
  61. }
  62. doc_type *dt = (doc_type*)this;
  63. dt->ArrayBegin(key, ext);
  64. for (size_t i=0; i<N; ++i) {
  65. dt->encode(dt->IndexKey(i), val[i], ext);
  66. }
  67. dt->ArrayEnd(key, ext);
  68. return true;
  69. }
  70. bool encode(const char*key, const char *val, size_t N, const Extend *ext) {
  71. (void)N;
  72. std::string str(val);
  73. return ((doc_type*)this)->encode(key, str, ext);
  74. }
  75. // vector
  76. template <class T>
  77. bool encode(const char*key, const std::vector<T> &val, const Extend *ext) {
  78. size_t s = val.size();
  79. if (s==0 && Extend::OmitEmpty(ext)) {
  80. return false;
  81. }
  82. doc_type *dt = (doc_type*)this;
  83. dt->ArrayBegin(key, ext);
  84. for (size_t i=0; i<s; ++i) {
  85. dt->encode(dt->IndexKey(i), val[i], ext);
  86. }
  87. dt->ArrayEnd(key, ext);
  88. return true;
  89. }
  90. // list
  91. template <class T>
  92. bool encode(const char*key, const std::list<T> &val, const Extend *ext) {
  93. size_t s = val.size();
  94. if (s==0 && Extend::OmitEmpty(ext)) {
  95. return false;
  96. }
  97. doc_type *dt = (doc_type*)this;
  98. dt->ArrayBegin(key, ext);
  99. size_t i = 0;
  100. for (typename std::list<T>::const_iterator it=val.begin(); it!=val.end(); ++it, ++i) {
  101. dt->encode(dt->IndexKey(i), *it, ext);
  102. }
  103. dt->ArrayEnd(key, ext);
  104. return true;
  105. }
  106. // set
  107. template <class T>
  108. bool encode(const char*key, const std::set<T> &val, const Extend *ext) {
  109. size_t s = val.size();
  110. if (s==0 && Extend::OmitEmpty(ext)) {
  111. return false;
  112. }
  113. doc_type *dt = (doc_type*)this;
  114. dt->ArrayBegin(key, ext);
  115. size_t i = 0;
  116. for (typename std::set<T>::const_iterator it=val.begin(); it!=val.end(); ++it, ++i) {
  117. dt->encode(dt->IndexKey(i), *it, ext);
  118. }
  119. dt->ArrayEnd(key, ext);
  120. return true;
  121. }
  122. // map
  123. template <class T>
  124. bool encode(const char*key, const std::map<std::string, T> &val, const Extend *ext) {
  125. size_t s = val.size();
  126. if (s==0 && Extend::OmitEmpty(ext)) {
  127. return false;
  128. }
  129. doc_type *dt = (doc_type*)this;
  130. dt->ObjectBegin(key, ext);
  131. for (typename std::map<std::string, T>::const_iterator it=val.begin(); it!=val.end(); ++it) {
  132. dt->encode(it->first.c_str(), it->second, ext);
  133. }
  134. dt->ObjectEnd(key, ext);
  135. return true;
  136. }
  137. // class/struct that defined macro XPACK
  138. template <class T>
  139. typename x_enable_if<T::__x_pack_value&&!is_xpack_out<T>::value, bool>::type encode(const char*key, const T& val, const Extend *ext) {
  140. bool inherit = 0!=(X_PACK_CTRL_FLAG_INHERIT&Extend::CtrlFlag(ext));
  141. doc_type *dt = (doc_type*)this;
  142. if (!inherit) {
  143. dt->ObjectBegin(key, ext);
  144. }
  145. val.__x_pack_encode(*dt, val, ext);
  146. if (!inherit) {
  147. dt->ObjectEnd(key, ext);
  148. }
  149. return true;
  150. }
  151. // class/struct that defined macro XPACK_OUT
  152. template <class T>
  153. typename x_enable_if<is_xpack_out<T>::value, bool>::type encode(const char*key, const T& val, const Extend *ext) {
  154. bool inherit = 0!=(X_PACK_CTRL_FLAG_INHERIT&Extend::CtrlFlag(ext));
  155. doc_type *dt = (doc_type*)this;
  156. if (!inherit) {
  157. dt->ObjectBegin(key, ext);
  158. }
  159. __x_pack_encode_out(*dt, val, ext);
  160. if (!inherit) {
  161. dt->ObjectEnd(key, ext);
  162. }
  163. return true;
  164. }
  165. // XType. add && !is_xpack_out<T>::value to fix SFINAE bug of vs2005
  166. template <class T>
  167. typename x_enable_if<is_xpack_xtype<T>::value && !is_xpack_out<T>::value, bool>::type encode(const char*key, const T& val, const Extend *ext) {
  168. return xpack_xtype_encode(*(doc_type*)this, key, val, ext);
  169. }
  170. #ifdef X_PACK_SUPPORT_CXX0X
  171. // unordered_map
  172. template <class T>
  173. bool encode(const char*key, const std::unordered_map<std::string, T> &val, const Extend *ext) {
  174. size_t s = val.size();
  175. if (s==0 && Extend::OmitEmpty(ext)) {
  176. return false;
  177. }
  178. doc_type *dt = (doc_type*)this;
  179. dt->ObjectBegin(key, ext);
  180. for (typename std::unordered_map<std::string, T>::const_iterator it=val.begin(); it!=val.end(); ++it) {
  181. dt->encode(it->first.c_str(), it->second, ext);
  182. }
  183. dt->ObjectEnd(key, ext);
  184. return true;
  185. }
  186. // shared_ptr
  187. template <class T>
  188. bool encode(const char*key, const std::shared_ptr<T>& val, const Extend *ext) {
  189. if (val.get() == NULL) { // if shared ptr is null
  190. return ((doc_type*)this)->writeNull(key, ext);
  191. }
  192. return ((doc_type*)this)->encode(key, *val, ext);
  193. }
  194. // enum is_enum implementation is too complicated, so in c++03, we use macro E
  195. template <class T>
  196. typename x_enable_if<std::is_enum<T>::value, bool>::type decode(const char*key, const T& val, const Extend *ext) {
  197. return ((doc_type*)this)->encode(key, (const int&)val, ext);
  198. }
  199. #endif // cxx
  200. #ifdef XPACK_SUPPORT_QT
  201. bool encode(const char*key, const QString &val, const Extend *ext) {
  202. std::string str = val.toStdString();
  203. return ((doc_type*)this)->encode(key, str, ext);
  204. }
  205. template<typename T>
  206. bool encode(const char*key, const QList<T>&data, const Extend *ext) {
  207. std::list<T> sl = std::list<T>(data.begin(), data.end());
  208. return ((doc_type*)this)->encode(key, sl, ext);
  209. }
  210. template<typename T>
  211. bool encode(const char*key, const QMap<std::string, T>&data, const Extend *ext) {
  212. std::map<std::string, T> sm = data.toStdMap();
  213. return ((doc_type*)this)->encode(key, sm, ext);
  214. }
  215. template<typename T>
  216. bool encode(const char*key, const QMap<QString, T>&data, const Extend *ext) {
  217. std::map<std::string, T> sm;
  218. for (typename QMap<QString, T>::const_iterator iter=data.begin(); iter!=data.end(); ++iter) {
  219. sm[iter.key().toStdString()] = iter.value();
  220. }
  221. return ((doc_type*)this)->encode(key, sm, ext);
  222. }
  223. template<typename T>
  224. bool encode(const char*key, const QVector<T>&data, const Extend *ext) {
  225. std::vector<T> sv = data.toStdVector();
  226. return ((doc_type*)this)->encode(key, sv, ext);
  227. }
  228. #endif
  229. // wrapper for encode manual
  230. template <class T>
  231. doc_type& add(const char *key, const T&val, const Extend *ext=NULL) {
  232. doc_type *dt = (doc_type*)this;
  233. dt->encode(key, val, ext);
  234. return *dt;
  235. }
  236. // object begin
  237. doc_type& ob(const char *key) {
  238. doc_type *dt = (doc_type*)this;
  239. dt->ObjectBegin(key, NULL);
  240. return *dt;
  241. }
  242. // object end
  243. doc_type& oe(const char *key=NULL) {
  244. doc_type *dt = (doc_type*)this;
  245. dt->ObjectEnd(key, NULL);
  246. return *dt;
  247. }
  248. // array begin
  249. doc_type& ab(const char *key) {
  250. doc_type *dt = (doc_type*)this;
  251. dt->ArrayBegin(key, NULL);
  252. return *dt;
  253. }
  254. // array end
  255. doc_type& ae(const char *key=NULL) {
  256. doc_type *dt = (doc_type*)this;
  257. dt->ArrayEnd(key, NULL);
  258. return *dt;
  259. }
  260. };
  261. }
  262. #endif