xpack.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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_H
  17. #define __X_PACK_H
  18. #include "extend.h"
  19. #include "l1l2_expand.h"
  20. /*
  21. work with X_PACK_N to expand macro
  22. struct MyX {
  23. int a;
  24. std::string b;
  25. double c;
  26. XPACK(A(a,"_id"), O(b,c));
  27. };
  28. macro expand order:
  29. XPACK(A(a,"_id"), O(b,c))
  30. --> X_PACK_N(X_PACK_L1, X_PACK_L1_DECODE, , A(a, "_id"), O(b,c))
  31. --> X_PACK_L1_2(X_PACK_L1_DECODE, A(a, "_id"), O(b,c))
  32. --> X_PACK_L1_DECODE(A(a, "_id")) X_PACK_L1_DECODE(O(b,c))
  33. --> X_PACK_L1_DECODE_A(a, "_id") X_PACK_L1_DECODE_O(b,c)
  34. --> X_PACK_ACT_DECODE_A(a, "_id") X_PACK_N2(X_PACK_L2, X_PACK_ACT_DECODE_O, b, c) // https://gcc.gnu.org/onlinedocs/cpp/Self-Referential-Macros.html so we need define X_PACK_N2. if use X_PACK_N preprocessor will treat is as Self-Referential-Macros
  35. --> X_PACK_ACT_DECODE_A(a, "_id") X_PACK_L2_2(X_PACK_ACT_DECODE_O, b, c)
  36. --> X_PACK_ACT_DECODE_A(a, "_id") X_PACK_ACT_DECODE_O(b) X_PACK_ACT_DECODE_O(c)
  37. --> // expand to convert code
  38. */
  39. // flag only work for this member
  40. #define X_EXPAND_FLAG_F(...) int __x_pack_flag = 0 X_PACK_N2(X_PACK_L2, X_PACK_ACT_FLAG, __VA_ARGS__) ;
  41. #define X_PACK_ACT_FLAG(F) | X_PACK_FLAG_##F
  42. /*
  43. X(F(x,y,z), member1, member2, ....)
  44. O same as X(F(0), member1, member2, ...)
  45. M same as X(F(M), member1, member2, ...)
  46. A Alias. A(member1, alias1, member2, alias2, ...)
  47. AF Alias with Flag. A(F(x,y,z), member1, alias1, member2, alias2 ...)
  48. I Inherit
  49. B bitfield
  50. */
  51. /////////////////////////// XPACK /////////////////////////////
  52. //=======DECODE
  53. #define X_PACK_L1_DECODE(x) { X_PACK_L1_DECODE_##x }
  54. //----
  55. #define X_PACK_L1_DECODE_X(FLAG, ...) X_EXPAND_FLAG_##FLAG xpack::Extend __x_pack_ext(__x_pack_flag, NULL); X_PACK_N2(X_PACK_L2, X_PACK_DECODE_ACT_O, __VA_ARGS__)
  56. #define X_PACK_L1_DECODE_E(FLAG, ...) X_EXPAND_FLAG_##FLAG xpack::Extend __x_pack_ext(__x_pack_flag, NULL); X_PACK_N2(X_PACK_L2, X_PACK_DECODE_ACT_E, __VA_ARGS__)
  57. #define X_PACK_L1_DECODE_B(FLAG, ...) X_EXPAND_FLAG_##FLAG xpack::Extend __x_pack_ext(__x_pack_flag, NULL); X_PACK_N2(X_PACK_L2, X_PACK_DECODE_ACT_B, __VA_ARGS__)
  58. #define X_PACK_L1_DECODE_AF(FLAG, ...) X_EXPAND_FLAG_##FLAG X_PACK_N2(X_PACK_L2_2, X_PACK_DECODE_ACT_A, __VA_ARGS__) // extend define in ACTION
  59. #define X_PACK_L1_DECODE_O(...) X_PACK_L1_DECODE_X(F(0), __VA_ARGS__)
  60. #define X_PACK_L1_DECODE_M(...) X_PACK_L1_DECODE_X(F(M), __VA_ARGS__)
  61. #define X_PACK_L1_DECODE_A(...) X_PACK_L1_DECODE_AF(F(0), __VA_ARGS__)
  62. #define X_PACK_L1_DECODE_I(...) X_PACK_N2(X_PACK_L2, X_PACK_DECODE_ACT_I, __VA_ARGS__)
  63. //=======ENCODE
  64. #define X_PACK_L1_ENCODE(x) { X_PACK_L1_ENCODE_##x }
  65. //-----
  66. #define X_PACK_L1_ENCODE_X(FLAG, ...) X_EXPAND_FLAG_##FLAG xpack::Extend __x_pack_ext(__x_pack_flag, NULL); X_PACK_N2(X_PACK_L2, X_PACK_ENCODE_ACT_O, __VA_ARGS__)
  67. #define X_PACK_L1_ENCODE_E(FLAG, ...) X_EXPAND_FLAG_##FLAG xpack::Extend __x_pack_ext(__x_pack_flag, NULL); X_PACK_N2(X_PACK_L2, X_PACK_ENCODE_ACT_E, __VA_ARGS__)
  68. #define X_PACK_L1_ENCODE_B(FLAG, ...) X_EXPAND_FLAG_##FLAG xpack::Extend __x_pack_ext(__x_pack_flag, NULL); X_PACK_N2(X_PACK_L2, X_PACK_ENCODE_ACT_B, __VA_ARGS__)
  69. #define X_PACK_L1_ENCODE_AF(FLAG, ...) X_EXPAND_FLAG_##FLAG X_PACK_N2(X_PACK_L2_2, X_PACK_ENCODE_ACT_A, __VA_ARGS__) // extend define in ACTION
  70. #define X_PACK_L1_ENCODE_O(...) X_PACK_L1_ENCODE_X(F(0), __VA_ARGS__)
  71. #define X_PACK_L1_ENCODE_M(...) X_PACK_L1_ENCODE_X(F(M), __VA_ARGS__)
  72. #define X_PACK_L1_ENCODE_A(...) X_PACK_L1_ENCODE_AF(F(0), __VA_ARGS__)
  73. //-----
  74. #define X_PACK_L1_ENCODE_I(...) X_PACK_N2(X_PACK_L2, X_PACK_ENCODE_ACT_I, __VA_ARGS__)
  75. // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ decode act ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  76. #define X_PACK_DECODE_ACT_O(M) \
  77. __x_pack_obj.decode(#M, __x_pack_self.M, &__x_pack_ext);
  78. // enum for not support c++11
  79. #define X_PACK_DECODE_ACT_E(M) \
  80. __x_pack_obj.decode(#M, *((int*)&__x_pack_self.M), &__x_pack_ext);
  81. #define X_PACK_DECODE_ACT_A(M, NAME) \
  82. { \
  83. static xpack::Alias __x_pack_alias(#M, NAME); \
  84. xpack::Extend __x_pack_ext(__x_pack_flag, &__x_pack_alias); \
  85. const char *__new_name = __x_pack_alias.Name(__x_pack_obj.Type());\
  86. __x_pack_obj.decode(__new_name, __x_pack_self.M, &__x_pack_ext); \
  87. }
  88. // Inheritance B::__x_pack_decode(__x_pack_obj)
  89. #define X_PACK_DECODE_ACT_I(P) __x_pack_obj.decode(NULL, static_cast<P&>(__x_pack_self), NULL);
  90. // bitfield, not support alias
  91. #define X_PACK_DECODE_ACT_B(B) \
  92. { \
  93. x_pack_decltype(__x_pack_self.B) __x_pack_tmp = 0; \
  94. __x_pack_obj.decode(#B, __x_pack_tmp, &__x_pack_ext); \
  95. __x_pack_self.B = __x_pack_tmp;\
  96. }
  97. // ~~~~~~~~~~~~~~~~~~~~~~~ encode act ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  98. #define X_PACK_ENCODE_ACT_O(M) \
  99. __x_pack_obj.encode(#M, __x_pack_self.M, &__x_pack_ext);
  100. #define X_PACK_ENCODE_ACT_E(M) \
  101. __x_pack_obj.encode(#M, (const int&)__x_pack_self.M, &__x_pack_ext);
  102. #define X_PACK_ENCODE_ACT_A(M, NAME) \
  103. { \
  104. static xpack::Alias __x_pack_alias(#M, NAME); \
  105. xpack::Extend __x_pack_ext(__x_pack_flag, &__x_pack_alias); \
  106. const char *__new_name = __x_pack_alias.Name(__x_pack_obj.Type());\
  107. __x_pack_obj.encode(__new_name, __x_pack_self.M, &__x_pack_ext); \
  108. }
  109. #define X_PACK_ENCODE_ACT_B(M) \
  110. __x_pack_obj.encode(#M, __x_pack_self.M, &__x_pack_ext);
  111. #define X_PACK_ENCODE_ACT_I(P) \
  112. { \
  113. xpack::Extend __x_pack_tmp_ext(0,NULL); __x_pack_tmp_ext.ctrl_flag |= X_PACK_CTRL_FLAG_INHERIT;\
  114. __x_pack_obj.encode(NULL, static_cast<const P&>(__x_pack_self), &__x_pack_tmp_ext); \
  115. }
  116. // for mark defined XPACK
  117. #define X_PACK_COMMON \
  118. public: \
  119. static bool const __x_pack_value = true;
  120. // decode function
  121. #define X_PACK_DECODE_BEGIN \
  122. template<class __X_PACK_DOC, class __X_PACK_ME> \
  123. void __x_pack_decode(__X_PACK_DOC& __x_pack_obj, __X_PACK_ME &__x_pack_self, const xpack::Extend *__x_pack_extp) {(void)__x_pack_extp;
  124. // encode function
  125. #define X_PACK_ENCODE_BEGIN \
  126. template <class __X_PACK_DOC, class __X_PACK_ME> \
  127. void __x_pack_encode(__X_PACK_DOC& __x_pack_obj, const __X_PACK_ME &__x_pack_self, const xpack::Extend *__x_pack_extp) const {(void)__x_pack_extp;
  128. // out decode function
  129. #define X_PACK_DECODE_BEGIN_OUT(NAME) \
  130. template<typename __X_PACK_DOC> \
  131. void __x_pack_decode_out(__X_PACK_DOC& __x_pack_obj, NAME & __x_pack_self, const xpack::Extend *__x_pack_extp) {(void)__x_pack_extp;
  132. // out encode function
  133. #define X_PACK_ENCODE_BEGIN_OUT(NAME) \
  134. template <class __X_PACK_DOC> \
  135. void __x_pack_encode_out(__X_PACK_DOC& __x_pack_obj, const NAME &__x_pack_self, const xpack::Extend *__x_pack_extp) {(void)__x_pack_extp;
  136. #define XPACK(...) \
  137. X_PACK_COMMON \
  138. X_PACK_DECODE_BEGIN X_PACK_N(X_PACK_L1, X_PACK_L1_DECODE, __VA_ARGS__) } \
  139. X_PACK_ENCODE_BEGIN X_PACK_N(X_PACK_L1, X_PACK_L1_ENCODE, __VA_ARGS__) }
  140. #define XPACK_OUT(NAME, ...) \
  141. namespace xpack { \
  142. template<> struct is_xpack_out<NAME> {static bool const value = true;}; \
  143. X_PACK_DECODE_BEGIN_OUT(NAME) X_PACK_N(X_PACK_L1, X_PACK_L1_DECODE, __VA_ARGS__) } \
  144. X_PACK_ENCODE_BEGIN_OUT(NAME) X_PACK_N(X_PACK_L1, X_PACK_L1_ENCODE, __VA_ARGS__) } \
  145. }
  146. #endif