#if !defined(_LIBPOMP_HPP_) || !defined(POMP_CXX11)
# error "This file shall not be included directly, use libpomp.hpp"
#endif
#ifndef _LIBPOMP_CXX11_HPP_
#define _LIBPOMP_CXX11_HPP_
namespace pomp {
enum ArgType {
ArgI8,
ArgU8,
ArgI16,
ArgU16,
ArgI32,
ArgU32,
ArgI64,
ArgU64,
ArgStr,
ArgBuf,
ArgF32,
ArgF64,
ArgFd,
};
namespace internal {
template<ArgType T> struct traits {
enum {valid = false};
typedef void *type;
static int encode(struct pomp_encoder *enc, const type &v);
static int decode(struct pomp_decoder *dec, type &v);
};
template<> struct traits<ArgI8> {
enum {valid = true};
typedef int8_t type;
inline static int encode(struct pomp_encoder *enc, const type &v) {
return pomp_encoder_write_i8(enc, v);
}
inline static int decode(struct pomp_decoder *dec, type &v) {
return pomp_decoder_read_i8(dec, &v);
}
};
template<> struct traits<ArgU8> {
enum {valid = true};
typedef uint8_t type;
inline static int encode(struct pomp_encoder *enc, const type &v) {
return pomp_encoder_write_u8(enc, v);
}
inline static int decode(struct pomp_decoder *dec, type &v) {
return pomp_decoder_read_u8(dec, &v);
}
};
template<> struct traits<ArgI16> {
enum {valid = true};
typedef int16_t type;
inline static int encode(struct pomp_encoder *enc, const type &v) {
return pomp_encoder_write_i16(enc, v);
}
inline static int decode(struct pomp_decoder *dec, type &v) {
return pomp_decoder_read_i16(dec, &v);
}
};
template<> struct traits<ArgU16> {
enum {valid = true};
typedef uint16_t type;
inline static int encode(struct pomp_encoder *enc, const type &v) {
return pomp_encoder_write_u16(enc, v);
}
inline static int decode(struct pomp_decoder *dec, type &v) {
return pomp_decoder_read_u16(dec, &v);
}
};
template<> struct traits<ArgI32> {
enum {valid = true};
typedef int32_t type;
inline static int encode(struct pomp_encoder *enc, const type &v) {
return pomp_encoder_write_i32(enc, v);
}
inline static int decode(struct pomp_decoder *dec, type &v) {
return pomp_decoder_read_i32(dec, &v);
}
};
template<> struct traits<ArgU32> {
enum {valid = true};
typedef uint32_t type;
inline static int encode(struct pomp_encoder *enc, const type &v) {
return pomp_encoder_write_u32(enc, v);
}
inline static int decode(struct pomp_decoder *dec, type &v) {
return pomp_decoder_read_u32(dec, &v);
}
};
template<> struct traits<ArgI64> {
enum {valid = true};
typedef int64_t type;
inline static int encode(struct pomp_encoder *enc, const type &v) {
return pomp_encoder_write_i64(enc, v);
}
inline static int decode(struct pomp_decoder *dec, type &v) {
return pomp_decoder_read_i64(dec, &v);
}
};
template<> struct traits<ArgU64> {
enum {valid = true};
typedef uint64_t type;
inline static int encode(struct pomp_encoder *enc, const type &v) {
return pomp_encoder_write_u64(enc, v);
}
inline static int decode(struct pomp_decoder *dec, type &v) {
return pomp_decoder_read_u64(dec, &v);
}
};
template<> struct traits<ArgStr> {
enum {valid = true};
typedef std::string type;
inline static int encode(struct pomp_encoder *enc, const type &v) {
return pomp_encoder_write_str(enc, v.c_str());
}
inline static int decode(struct pomp_decoder *dec, type &v) {
const char *s = NULL;
int res = pomp_decoder_read_cstr(dec, &s);
if (res == 0)
v.assign(s);
return res;
}
};
template<> struct traits<ArgBuf> {
enum {valid = true};
typedef std::vector<uint8_t> type;
inline static int encode(struct pomp_encoder *enc, const type &v) {
const uint8_t *p = v.data();
uint32_t n = static_cast<uint32_t>(v.size());
return pomp_encoder_write_buf(enc, p, n);
}
inline static int decode(struct pomp_decoder *dec, type &v) {
const void *p = NULL;
uint32_t n = 0;
int res = pomp_decoder_read_cbuf(dec, &p, &n);
if (res == 0) {
const uint8_t *start = reinterpret_cast<const uint8_t *>(p);
const uint8_t *end = start + n;
v.assign(start, end);
}
return res;
}
};
template<> struct traits<ArgF32> {
enum {valid = true};
typedef float type;
inline static int encode(struct pomp_encoder *enc, const type &v) {
return pomp_encoder_write_f32(enc, v);
}
inline static int decode(struct pomp_decoder *dec, type &v) {
return pomp_decoder_read_f32(dec, &v);
}
};
template<> struct traits<ArgF64> {
enum {valid = true};
typedef double type;
inline static int encode(struct pomp_encoder *enc, const type &v) {
return pomp_encoder_write_f64(enc, v);
}
inline static int decode(struct pomp_decoder *dec, type &v) {
return pomp_decoder_read_f64(dec, &v);
}
};
template<> struct traits<ArgFd> {
enum {valid = true};
typedef int type;
inline static int encode(struct pomp_encoder *enc, const type &v) {
return pomp_encoder_write_fd(enc, v);
}
inline static int decode(struct pomp_decoder *dec, type &v) {
return pomp_decoder_read_fd(dec, &v);
}
};
}
template<uint32_t Id, ArgType... Args>
struct MessageFormat {
enum {id = Id};
static int encode(struct pomp_encoder *enc,
const typename pomp::internal::traits<Args>::type&... args);
static int decode(struct pomp_decoder *dec,
typename pomp::internal::traits<Args>::type&... args);
};
template<uint32_t Id>
struct MessageFormat<Id> {
enum {id = Id};
inline static int encode(struct pomp_encoder *enc) { (void)enc; return 0;}
inline static int decode(struct pomp_decoder *dec) { (void)dec; return 0;}
};
template<uint32_t Id, ArgType Arg1, ArgType... Args>
struct MessageFormat<Id, Arg1, Args...> {
enum {id = Id};
typedef MessageFormat<Id, Args...> _Base;
inline static int encode(struct pomp_encoder *enc,
const typename pomp::internal::traits<Arg1>::type& arg1,
const typename pomp::internal::traits<Args>::type&... args) {
static_assert(pomp::internal::traits<Arg1>::valid, "Invalid type");
int res = pomp::internal::traits<Arg1>::encode(enc, arg1);
return res !=0 ? res : _Base::encode(enc, std::forward<
const typename pomp::internal::traits<Args>::type&>(args)...);
}
inline static int decode(struct pomp_decoder *dec,
typename pomp::internal::traits<Arg1>::type& arg1,
typename pomp::internal::traits<Args>::type&... args) {
static_assert(pomp::internal::traits<Arg1>::valid, "Invalid type");
int res = pomp::internal::traits<Arg1>::decode(dec, arg1);
return res !=0 ? res : _Base::decode(dec, std::forward<
typename pomp::internal::traits<Args>::type&>(args)...);
}
};
}
#endif