#include <cstdint>
#include <cstring>
#include <iostream>
#include <tuple>
#include <type_traits>
class Serializer
{
public:
explicit Serializer(unsigned int buffer_size=255) : _cursor_end(0),_cursor_begin(0), _buffer_size(buffer_size)
{
_buffer = new unsigned char[buffer_size];
};
~Serializer(){
delete _buffer;
}
Serializer& operator<<(int i){
push(*reinterpret_cast<uint32_t*>(&i));
return *this;
};
Serializer& operator>>(int& i){
pop(*reinterpret_cast<uint32_t*>(&i));
return *this;
};
protected:
unsigned char* _buffer;
unsigned int _cursor_end;
unsigned int _cursor_begin;
unsigned int _buffer_size;
inline void resize(const unsigned int buffer_cursor_end){
unsigned char* buffer = new unsigned char[buffer_cursor_end];
buffer = (unsigned char*)memcpy(buffer,_buffer,_buffer_size);
delete _buffer;
_buffer = buffer;
_buffer_size = buffer_cursor_end;
};
inline void push(uint32_t& a){
if(_buffer_size < _cursor_end + 4)
resize(_buffer_size+128);
uint8_t *d = (uint8_t *)&a;
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
_buffer[_cursor_end++] = d[0];
_buffer[_cursor_end++] = d[1];
_buffer[_cursor_end++] = d[2];
_buffer[_cursor_end++] = d[3];
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
_buffer[_cursor_end++] = d[3];
_buffer[_cursor_end++] = d[2];
_buffer[_cursor_end++] = d[1];
_buffer[_cursor_end++] = d[0];
#else
#error "byte orden not suported (PDP endian)"
#endif
}
inline void pop(uint32_t& a){
if(_cursor_begin +4 <= _cursor_end)
{
uint8_t *d = (uint8_t *)&a;
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
d[0]= _buffer[_cursor_begin++];
d[1]= _buffer[_cursor_begin++];
d[2]= _buffer[_cursor_begin++];
d[3]= _buffer[_cursor_begin++];
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
d[3]= _buffer[_cursor_begin++];
d[2]= _buffer[_cursor_begin++];
d[1]= _buffer[_cursor_begin++];
d[0]= _buffer[_cursor_begin++];
#else
#error "byte orden not suported (PDP endian)"
#endif
}
};
};
template<typename T, T...>
struct integer_sequence
{ };
template<std::size_t... Indices>
struct indices : integer_sequence<std::size_t, Indices...>
{ };
template<std::size_t N, std::size_t... T>
struct build_indices : build_indices<(N - 1), (N - 1), T...>
{ };
template<std::size_t... T>
struct build_indices<0, T...> : indices<T...>
{ };
template<typename Fn, typename... Args, std::size_t... Idx>
auto exec__(Fn fn, Serializer& ser, std::tuple<Args...> args, indices<Idx...>)
-> decltype(fn(ser, std::get<Idx>(args)...))
{
int ctx[] = { ((ser >> std::get<Idx>(args)), void(), 0)... };
(void)ctx;
return fn(ser, std::get<Idx>(args)...);
}
template<typename R, typename... Args>
auto exec(R(*fn)(Serializer&, Args...), Serializer& ser)
-> decltype(fn(ser, Args()...))
{
return exec__(fn, ser, std::tuple<typename std::remove_reference<Args>::type...>(), build_indices<sizeof...(Args)>());
}
int getVersion(Serializer& sock)
{
return 42;
}
int testParamInt(Serializer& sock, int v)
{
std::cout << "param:" << v << std::endl;
return v + 12;
}
int main() {
{
Serializer params;
std::cout << "getVersion : " << exec(&getVersion, params) << std::endl;;
}
{
Serializer params;
params << 35;
/*int p1;
params >> p1;*/
std::cout << "testParamInt: " << exec(&testParamInt, params) << std::endl;
}
return 0;
}