fork download
  1. #include <cstdint>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <tuple>
  5. #include <type_traits>
  6.  
  7. class Serializer
  8. {
  9. public:
  10. explicit Serializer(unsigned int buffer_size=255) : _cursor_end(0),_cursor_begin(0), _buffer_size(buffer_size)
  11. {
  12. _buffer = new unsigned char[buffer_size];
  13. };
  14. ~Serializer(){
  15. delete _buffer;
  16. }
  17.  
  18. Serializer& operator<<(int i){
  19. push(*reinterpret_cast<uint32_t*>(&i));
  20. return *this;
  21.  
  22. };
  23.  
  24. Serializer& operator>>(int& i){
  25. pop(*reinterpret_cast<uint32_t*>(&i));
  26. return *this;
  27. };
  28.  
  29. protected:
  30.  
  31. unsigned char* _buffer;
  32. unsigned int _cursor_end;
  33. unsigned int _cursor_begin;
  34. unsigned int _buffer_size;
  35.  
  36. inline void resize(const unsigned int buffer_cursor_end){
  37. unsigned char* buffer = new unsigned char[buffer_cursor_end];
  38. buffer = (unsigned char*)memcpy(buffer,_buffer,_buffer_size);
  39.  
  40. delete _buffer;
  41. _buffer = buffer;
  42. _buffer_size = buffer_cursor_end;
  43. };
  44.  
  45. inline void push(uint32_t& a){
  46. if(_buffer_size < _cursor_end + 4)
  47. resize(_buffer_size+128);
  48.  
  49. uint8_t *d = (uint8_t *)&a;
  50.  
  51. #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  52. _buffer[_cursor_end++] = d[0];
  53. _buffer[_cursor_end++] = d[1];
  54. _buffer[_cursor_end++] = d[2];
  55. _buffer[_cursor_end++] = d[3];
  56. #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  57. _buffer[_cursor_end++] = d[3];
  58. _buffer[_cursor_end++] = d[2];
  59. _buffer[_cursor_end++] = d[1];
  60. _buffer[_cursor_end++] = d[0];
  61. #else
  62. #error "byte orden not suported (PDP endian)"
  63. #endif
  64.  
  65. }
  66.  
  67. inline void pop(uint32_t& a){
  68. if(_cursor_begin +4 <= _cursor_end)
  69. {
  70. uint8_t *d = (uint8_t *)&a;
  71. #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
  72. d[0]= _buffer[_cursor_begin++];
  73. d[1]= _buffer[_cursor_begin++];
  74. d[2]= _buffer[_cursor_begin++];
  75. d[3]= _buffer[_cursor_begin++];
  76. #elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
  77. d[3]= _buffer[_cursor_begin++];
  78. d[2]= _buffer[_cursor_begin++];
  79. d[1]= _buffer[_cursor_begin++];
  80. d[0]= _buffer[_cursor_begin++];
  81. #else
  82. #error "byte orden not suported (PDP endian)"
  83. #endif
  84. }
  85. };
  86. };
  87.  
  88. template<typename T, T...>
  89. struct integer_sequence
  90. { };
  91.  
  92. template<std::size_t... Indices>
  93. struct indices : integer_sequence<std::size_t, Indices...>
  94. { };
  95.  
  96. template<std::size_t N, std::size_t... T>
  97. struct build_indices : build_indices<(N - 1), (N - 1), T...>
  98. { };
  99.  
  100. template<std::size_t... T>
  101. struct build_indices<0, T...> : indices<T...>
  102. { };
  103.  
  104. template<typename Fn, typename... Args, std::size_t... Idx>
  105. auto exec__(Fn fn, Serializer& ser, std::tuple<Args...> args, indices<Idx...>)
  106. -> decltype(fn(ser, std::get<Idx>(args)...))
  107. {
  108. int ctx[] = { ((ser >> std::get<Idx>(args)), void(), 0)... };
  109. (void)ctx;
  110. return fn(ser, std::get<Idx>(args)...);
  111. }
  112.  
  113. template<typename R, typename... Args>
  114. auto exec(R(*fn)(Serializer&, Args...), Serializer& ser)
  115. -> decltype(fn(ser, Args()...))
  116. {
  117. return exec__(fn, ser, std::tuple<typename std::remove_reference<Args>::type...>(), build_indices<sizeof...(Args)>());
  118. }
  119.  
  120. int getVersion(Serializer& sock)
  121. {
  122. return 42;
  123. }
  124.  
  125. int testParamInt(Serializer& sock, int v)
  126. {
  127. std::cout << "param:" << v << std::endl;
  128. return v + 12;
  129. }
  130.  
  131. int main() {
  132. {
  133. Serializer params;
  134. std::cout << "getVersion : " << exec(&getVersion, params) << std::endl;;
  135. }
  136.  
  137. {
  138. Serializer params;
  139. params << 35;
  140. /*int p1;
  141.   params >> p1;*/
  142. std::cout << "testParamInt: " << exec(&testParamInt, params) << std::endl;
  143. }
  144. return 0;
  145. }
  146.  
Success #stdin #stdout 0s 3428KB
stdin
Standard input is empty
stdout
getVersion : 42
param:35
testParamInt: 47