// // MessagePack for C++ serializing routine // // Copyright (C) 2008-2016 FURUHASHI Sadayuki and KONDO Takatoshi // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // #ifndef MSGPACK_V1_PACK_HPP #define MSGPACK_V1_PACK_HPP #include "rpc/msgpack/v1/pack_decl.hpp" #include #include #include #include namespace clmdep_msgpack { /// @cond MSGPACK_API_VERSION_NAMESPACE(v1) { /// @endcond /// The class template that supports continuous packing. /** * @tparam Stream Any type that have a member function `Stream write(const char*, size_t s)` * */ template class packer { public: /// Constructor /** * This constructor is left for compatibility. * Use `packer(Stream& s)` instead of the constructor. * * @param s A pointer to packing destination stream object. */ packer(Stream* s); /// Constructor /** * @param s Packing destination stream object. */ packer(Stream& s); public: /// Packing function template /** * @tparam T The type of packing object. * * @param v a packing object. * * @return The reference of `*this`. */ template packer& pack(const T& v); /// Packing uint8 /** * The byte size of the packed data depends on `d`. * The packed type is positive fixnum or uint8. * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_uint8(uint8_t d); /// Packing uint16 /** * The byte size of the packed data depends on `d`. * The packed type is positive fixnum, uint8 or uint16. * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_uint16(uint16_t d); /// Packing uint32 /** * The byte size of the packed data depends on `d`. * The packed type is positive fixnum, uint8, uint16 or uint32. * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_uint32(uint32_t d); /// Packing uint16 /** * The byte size of the packed data depends on `d`. * The packed type is positive fixnum, uint8, uint16, uint32 or uint64. * The minimum byte size expression is used. * positive fixnum, uint8, uint16, or uint32 is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_uint64(uint64_t d); /// Packing int8 /** * The byte size of the packed data depends on `d`. * If `d` is zero or positive, the packed type is positive fixnum, or uint8, * else the packed type is negative fixnum, or int8 * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_int8(int8_t d); /// Packing int16 /** * The byte size of the packed data depends on `d`. * If `d` is zero or positive, the packed type is positive fixnum, uint8, or uint16, * else the packed type is negative fixnum, int8, or int16. * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_int16(int16_t d); /// Packing int32 /** * The byte size of the packed data depends on `d`. * If `d` is zero or positive, the packed type is positive fixnum, uint8, uint16, or uint32, * else the packed type is negative fixnum, int8, int16, or int32. * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_int32(int32_t d); /// Packing int32 /** * The byte size of the packed data depends on `d`. * If `d` is zero or positive, the packed type is positive fixnum, uint8, uint16, uint32, or uint64, * else the packed type is negative fixnum, int8, int16, int32, or int64. * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_int64(int64_t d); /// Packing uint8 (fixed packed type). /** * The packed type is always uint8. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_fix_uint8(uint8_t d); /// Packing uint8 (fixed packed type). /** * The packed type is always uint16. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_fix_uint16(uint16_t d); /// Packing uint8 (fixed packed type). /** * The packed type is always uint32. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_fix_uint32(uint32_t d); /// Packing uint8 (fixed packed type). /** * The packed type is always uint64. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_fix_uint64(uint64_t d); /// Packing uint8 (fixed packed type). /** * The packed type is always int8. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_fix_int8(int8_t d); /// Packing uint8 (fixed packed type). /** * The packed type is always int16. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_fix_int16(int16_t d); /// Packing uint8 (fixed packed type). /** * The packed type is always int32. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_fix_int32(int32_t d); /// Packing uint8 (fixed packed type). /** * The packed type is always int64. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_fix_int64(int64_t d); /// Packing char /** * The byte size of the packed data depends on `d`. * If `d` is zero or positive, the packed type is positive fixnum, or uint*, * else the packed type is negative fixnum, or int* * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_char(char d); /// Packing signed char /** * The byte size of the packed data depends on `d`. * If `d` is zero or positive, the packed type is positive fixnum, or uint*, * else the packed type is negative fixnum, or int* * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_signed_char(signed char d); /// Packing short /** * The byte size of the packed data depends on `d`. * If `d` is zero or positive, the packed type is positive fixnum, or uint*, * else the packed type is negative fixnum, or int* * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_short(short d); /// Packing int /** * The byte size of the packed data depends on `d`. * If `d` is zero or positive, the packed type is positive fixnum, or uint*, * else the packed type is negative fixnum, or int* * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_int(int d); /// Packing long /** * The byte size of the packed data depends on `d`. * If `d` is zero or positive, the packed type is positive fixnum, or uint*, * else the packed type is negative fixnum, or int* * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_long(long d); /// Packing long long /** * The byte size of the packed data depends on `d`. * If `d` is zero or positive, the packed type is positive fixnum, or uint*, * else the packed type is negative fixnum, or int* * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_long_long(long long d); /// Packing unsigned char /** * The byte size of the packed data depends on `d`. * The packed type is positive fixnum, or uint*. * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_unsigned_char(unsigned char d); /// Packing unsigned short /** * The byte size of the packed data depends on `d`. * The packed type is positive fixnum, or uint*. * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_unsigned_short(unsigned short d); /// Packing unsigned int /** * The byte size of the packed data depends on `d`. * The packed type is positive fixnum, or uint*. * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_unsigned_int(unsigned int d); /// Packing unsigned long /** * The byte size of the packed data depends on `d`. * The packed type is positive fixnum, or uint*. * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_unsigned_long(unsigned long d); /// Packing unsigned long long /** * The byte size of the packed data depends on `d`. * The packed type is positive fixnum, or uint*. * The minimum byte size expression is used. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-int * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_unsigned_long_long(unsigned long long d); /// Packing float /** * The packed type is float32. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-float * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_float(float d); /// Packing double /** * The packed type is float64. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-float * * @param d a packing object. * * @return The reference of `*this`. */ packer& pack_double(double d); /// Packing nil /** * The packed type is nil. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-nil * * @return The reference of `*this`. */ packer& pack_nil(); /// Packing true /** * The packed type is bool, value is true. * See https://github.com/msgpack/msgpack/blob/master/spec.md#bool-format-family * * @return The reference of `*this`. */ packer& pack_true(); /// Packing false /** * The packed type is bool, value is false. * See https://github.com/msgpack/msgpack/blob/master/spec.md#bool-format-family * * @return The reference of `*this`. */ packer& pack_false(); /// Packing array header and size /** * The packed type is array header and array size. * You need to pack `n` msgpack objects following this header and size. * See https://github.com/msgpack/msgpack/blob/master/spec.md#array-format-family * * @param n The number of array elements (array size). * * @return The reference of `*this`. */ packer& pack_array(uint32_t n); /// Packing map header and size /** * The packed type is map header and map size. * You need to pack `n` pairs of msgpack objects following this header and size. * See https://github.com/msgpack/msgpack/blob/master/spec.md#map-format-family * * @param n The number of array elements (array size). * * @return The reference of `*this`. */ packer& pack_map(uint32_t n); /// Packing str header and length /** * The packed type is str header and length. * The minimum byte size length expression is used. * You need to call `pack_str_body(const char* b, uint32_t l)` after this function calling with the same `l` value. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-str * * @param l The length of string. * * @return The reference of `*this`. */ packer& pack_str(uint32_t l); /// Packing str body /** * You need to call this function just after `pack_str(uint32_t l)` calling. * The value `l` should be the same as `pack_str(uint32_t l)` argument `l`. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-str * * @param l The length of string. * * @return The reference of `*this`. */ packer& pack_str_body(const char* b, uint32_t l); /// Packing raw (v4) header and length /** * The packed type is raw header and length. * The minimum byte size length expression is used. * The format raw (v4) is old MessagePack version4 format. * You need to call `pack_v4raw_body(const char* b, uint32_t l)` after this function calling with the same `l` value. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-str * * @param l The length of string. * * @return The reference of `*this`. */ packer& pack_v4raw(uint32_t l); /// Packing raw (v4) body /** * The format raw (v4) is old MessagePack version4 format. * You need to call this function just after `pack_v4raw(uint32_t l)` calling. * The value `l` should be the same as `pack_v4raw(uint32_t l)` argument `l`. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-str * * @param l The length of string. * * @return The reference of `*this`. */ packer& pack_v4raw_body(const char* b, uint32_t l); /// Packing bin header and length /** * The packed type is bin header and length. * The minimum byte size length expression is used. * You need to call `pack_bin_body(const char* b, uint32_t l)` after this function calling with the same `l` value. * See https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family * * @param l The length of string. * * @return The reference of `*this`. */ packer& pack_bin(uint32_t l); /// Packing bin body /** * You need to call this function just after `pack_bin(uint32_t l)` calling. * The value `l` should be the same as `pack_bin(uint32_t l)` argument `l`. * See https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family * * @param l The length of string. * * @return The reference of `*this`. */ packer& pack_bin_body(const char* b, uint32_t l); /// Packing ext header, type, and length /** * The packed type is ext. * The minimum byte size length expression is used. * The length 1, 2, 4, 8, and 16 can be encoded in the header. * You need to call `pack_ext_body(const char* b, uint32_t l)` after this function calling with the same `l` value. * See https://github.com/msgpack/msgpack/blob/master/spec.md#formats-ext * * @param l The length of string. * * @return The reference of `*this`. */ packer& pack_ext(size_t l, int8_t type); /// Packing ext body /** * You need to call this function just after `pack_ext(size_t l, int8_t type)` calling. * The value `l` should be the same as `pack_ext(size_t l, int8_t type)` argument `l`. * See https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family * * @param l The length of string. * * @return The reference of `*this`. */ packer& pack_ext_body(const char* b, uint32_t l); private: template void pack_imp_uint8(T d); template void pack_imp_uint16(T d); template void pack_imp_uint32(T d); template void pack_imp_uint64(T d); template void pack_imp_int8(T d); template void pack_imp_int16(T d); template void pack_imp_int32(T d); template void pack_imp_int64(T d); void append_buffer(const char* buf, size_t len) { m_stream.write(buf, len); } private: Stream& m_stream; #if defined(MSGPACK_USE_CPP03) private: packer(const packer&); packer& operator=(const packer&); packer(); #else // defined(MSGPACK_USE_CPP03) public: packer(const packer&) = delete; packer& operator=(const packer&) = delete; packer() = delete; #endif // defined(MSGPACK_USE_CPP03) }; /// Pack the value as MessagePack format into the stream /** * This function template is left for compatibility. * Use `void pack(Stream& s, const T& v)` instead of the function template. * * @tparam Stream Any type that have a member function `Stream write(const char*, size_t s)` * @tparam T Any type that is adapted to MessagePack * @param s The pointer to packing destination stream * @param v Packing value */ template inline void pack(Stream* s, const T& v) { packer(*s).pack(v); } /// Pack the value as MessagePack format into the stream /** * @tparam Stream Any type that have a member function `Stream write(const char*, size_t s)` * @tparam T Any type that is adapted to MessagePack * @param s Packing destination stream * @param v Packing value */ template inline void pack(Stream& s, const T& v) { packer(s).pack(v); } #if MSGPACK_ENDIAN_LITTLE_BYTE template inline char take8_8(T d) { return static_cast(reinterpret_cast(&d)[0]); } template inline char take8_16(T d) { return static_cast(reinterpret_cast(&d)[0]); } template inline char take8_32(T d) { return static_cast(reinterpret_cast(&d)[0]); } template inline char take8_64(T d) { return static_cast(reinterpret_cast(&d)[0]); } #elif MSGPACK_ENDIAN_BIG_BYTE template inline char take8_8(T d) { return static_cast(reinterpret_cast(&d)[0]); } template inline char take8_16(T d) { return static_cast(reinterpret_cast(&d)[1]); } template inline char take8_32(T d) { return static_cast(reinterpret_cast(&d)[3]); } template inline char take8_64(T d) { return static_cast(reinterpret_cast(&d)[7]); } #else #error msgpack-c supports only big endian and little endian #endif template inline packer::packer(Stream* s) : m_stream(*s) { } template inline packer::packer(Stream& s) : m_stream(s) { } template inline packer& packer::pack_uint8(uint8_t d) { pack_imp_uint8(d); return *this; } template inline packer& packer::pack_uint16(uint16_t d) { pack_imp_uint16(d); return *this; } template inline packer& packer::pack_uint32(uint32_t d) { pack_imp_uint32(d); return *this; } template inline packer& packer::pack_uint64(uint64_t d) { pack_imp_uint64(d); return *this; } template inline packer& packer::pack_int8(int8_t d) { pack_imp_int8(d); return *this; } template inline packer& packer::pack_int16(int16_t d) { pack_imp_int16(d); return *this; } template inline packer& packer::pack_int32(int32_t d) { pack_imp_int32(d); return *this; } template inline packer& packer::pack_int64(int64_t d) { pack_imp_int64(d); return *this;} template inline packer& packer::pack_fix_uint8(uint8_t d) { char buf[2] = {static_cast(0xccu), take8_8(d)}; append_buffer(buf, 2); return *this; } template inline packer& packer::pack_fix_uint16(uint16_t d) { char buf[3]; buf[0] = static_cast(0xcdu); _msgpack_store16(&buf[1], d); append_buffer(buf, 3); return *this; } template inline packer& packer::pack_fix_uint32(uint32_t d) { char buf[5]; buf[0] = static_cast(0xceu); _msgpack_store32(&buf[1], d); append_buffer(buf, 5); return *this; } template inline packer& packer::pack_fix_uint64(uint64_t d) { char buf[9]; buf[0] = static_cast(0xcfu); _msgpack_store64(&buf[1], d); append_buffer(buf, 9); return *this; } template inline packer& packer::pack_fix_int8(int8_t d) { char buf[2] = {static_cast(0xd0u), take8_8(d)}; append_buffer(buf, 2); return *this; } template inline packer& packer::pack_fix_int16(int16_t d) { char buf[3]; buf[0] = static_cast(0xd1u); _msgpack_store16(&buf[1], d); append_buffer(buf, 3); return *this; } template inline packer& packer::pack_fix_int32(int32_t d) { char buf[5]; buf[0] = static_cast(0xd2u); _msgpack_store32(&buf[1], d); append_buffer(buf, 5); return *this; } template inline packer& packer::pack_fix_int64(int64_t d) { char buf[9]; buf[0] = static_cast(0xd3u); _msgpack_store64(&buf[1], d); append_buffer(buf, 9); return *this; } template inline packer& packer::pack_char(char d) { #if defined(CHAR_MIN) #if CHAR_MIN < 0 pack_imp_int8(d); #else pack_imp_uint8(d); #endif #else #error CHAR_MIN is not defined #endif return *this; } template inline packer& packer::pack_signed_char(signed char d) { pack_imp_int8(d); return *this; } template inline packer& packer::pack_short(short d) { #if defined(SIZEOF_SHORT) #if SIZEOF_SHORT == 2 pack_imp_int16(d); #elif SIZEOF_SHORT == 4 pack_imp_int32(d); #else pack_imp_int64(d); #endif #elif defined(SHRT_MAX) #if SHRT_MAX == 0x7fff pack_imp_int16(d); #elif SHRT_MAX == 0x7fffffff pack_imp_int32(d); #else pack_imp_int64(d); #endif #else if(sizeof(short) == 2) { pack_imp_int16(d); } else if(sizeof(short) == 4) { pack_imp_int32(d); } else { pack_imp_int64(d); } #endif return *this; } template inline packer& packer::pack_int(int d) { #if defined(SIZEOF_INT) #if SIZEOF_INT == 2 pack_imp_int16(d); #elif SIZEOF_INT == 4 pack_imp_int32(d); #else pack_imp_int64(d); #endif #elif defined(INT_MAX) #if INT_MAX == 0x7fff pack_imp_int16(d); #elif INT_MAX == 0x7fffffff pack_imp_int32(d); #else pack_imp_int64(d); #endif #else if(sizeof(int) == 2) { pack_imp_int16(d); } else if(sizeof(int) == 4) { pack_imp_int32(d); } else { pack_imp_int64(d); } #endif return *this; } template inline packer& packer::pack_long(long d) { #if defined(SIZEOF_LONG) #if SIZEOF_LONG == 2 pack_imp_int16(d); #elif SIZEOF_LONG == 4 pack_imp_int32(d); #else pack_imp_int64(d); #endif #elif defined(LONG_MAX) #if LONG_MAX == 0x7fffL pack_imp_int16(d); #elif LONG_MAX == 0x7fffffffL pack_imp_int32(d); #else pack_imp_int64(d); #endif #else if(sizeof(long) == 2) { pack_imp_int16(d); } else if(sizeof(long) == 4) { pack_imp_int32(d); } else { pack_imp_int64(d); } #endif return *this; } template inline packer& packer::pack_long_long(long long d) { #if defined(SIZEOF_LONG_LONG) #if SIZEOF_LONG_LONG == 2 pack_imp_int16(d); #elif SIZEOF_LONG_LONG == 4 pack_imp_int32(d); #else pack_imp_int64(d); #endif #elif defined(LLONG_MAX) #if LLONG_MAX == 0x7fffL pack_imp_int16(d); #elif LLONG_MAX == 0x7fffffffL pack_imp_int32(d); #else pack_imp_int64(d); #endif #else if(sizeof(long long) == 2) { pack_imp_int16(d); } else if(sizeof(long long) == 4) { pack_imp_int32(d); } else { pack_imp_int64(d); } #endif return *this; } template inline packer& packer::pack_unsigned_char(unsigned char d) { pack_imp_uint8(d); return *this; } template inline packer& packer::pack_unsigned_short(unsigned short d) { #if defined(SIZEOF_SHORT) #if SIZEOF_SHORT == 2 pack_imp_uint16(d); #elif SIZEOF_SHORT == 4 pack_imp_uint32(d); #else pack_imp_uint64(d); #endif #elif defined(USHRT_MAX) #if USHRT_MAX == 0xffffU pack_imp_uint16(d); #elif USHRT_MAX == 0xffffffffU pack_imp_uint32(d); #else pack_imp_uint64(d); #endif #else if(sizeof(unsigned short) == 2) { pack_imp_uint16(d); } else if(sizeof(unsigned short) == 4) { pack_imp_uint32(d); } else { pack_imp_uint64(d); } #endif return *this; } template inline packer& packer::pack_unsigned_int(unsigned int d) { #if defined(SIZEOF_INT) #if SIZEOF_INT == 2 pack_imp_uint16(d); #elif SIZEOF_INT == 4 pack_imp_uint32(d); #else pack_imp_uint64(d); #endif #elif defined(UINT_MAX) #if UINT_MAX == 0xffffU pack_imp_uint16(d); #elif UINT_MAX == 0xffffffffU pack_imp_uint32(d); #else pack_imp_uint64(d); #endif #else if(sizeof(unsigned int) == 2) { pack_imp_uint16(d); } else if(sizeof(unsigned int) == 4) { pack_imp_uint32(d); } else { pack_imp_uint64(d); } #endif return *this; } template inline packer& packer::pack_unsigned_long(unsigned long d) { #if defined(SIZEOF_LONG) #if SIZEOF_LONG == 2 pack_imp_uint16(d); #elif SIZEOF_LONG == 4 pack_imp_uint32(d); #else pack_imp_uint64(d); #endif #elif defined(ULONG_MAX) #if ULONG_MAX == 0xffffUL pack_imp_uint16(d); #elif ULONG_MAX == 0xffffffffUL pack_imp_uint32(d); #else pack_imp_uint64(d); #endif #else if(sizeof(unsigned long) == 2) { pack_imp_uint16(d); } else if(sizeof(unsigned long) == 4) { pack_imp_uint32(d); } else { pack_imp_uint64(d); } #endif return *this; } template inline packer& packer::pack_unsigned_long_long(unsigned long long d) { #if defined(SIZEOF_LONG_LONG) #if SIZEOF_LONG_LONG == 2 pack_imp_uint16(d); #elif SIZEOF_LONG_LONG == 4 pack_imp_uint32(d); #else pack_imp_uint64(d); #endif #elif defined(ULLONG_MAX) #if ULLONG_MAX == 0xffffUL pack_imp_uint16(d); #elif ULLONG_MAX == 0xffffffffUL pack_imp_uint32(d); #else pack_imp_uint64(d); #endif #else if(sizeof(unsigned long long) == 2) { pack_imp_uint16(d); } else if(sizeof(unsigned long long) == 4) { pack_imp_uint32(d); } else { pack_imp_uint64(d); } #endif return *this; } template inline packer& packer::pack_float(float d) { union { float f; uint32_t i; } mem; mem.f = d; char buf[5]; buf[0] = static_cast(0xcau); _msgpack_store32(&buf[1], mem.i); append_buffer(buf, 5); return *this; } template inline packer& packer::pack_double(double d) { union { double f; uint64_t i; } mem; mem.f = d; char buf[9]; buf[0] = static_cast(0xcbu); #if defined(TARGET_OS_IPHONE) // ok #elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi // https://github.com/msgpack/msgpack-perl/pull/1 mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL); #endif _msgpack_store64(&buf[1], mem.i); append_buffer(buf, 9); return *this; } template inline packer& packer::pack_nil() { const char d = static_cast(0xc0u); append_buffer(&d, 1); return *this; } template inline packer& packer::pack_true() { const char d = static_cast(0xc3u); append_buffer(&d, 1); return *this; } template inline packer& packer::pack_false() { const char d = static_cast(0xc2u); append_buffer(&d, 1); return *this; } template inline packer& packer::pack_array(uint32_t n) { if(n < 16) { char d = static_cast(0x90u | n); append_buffer(&d, 1); } else if(n < 65536) { char buf[3]; buf[0] = static_cast(0xdcu); _msgpack_store16(&buf[1], static_cast(n)); append_buffer(buf, 3); } else { char buf[5]; buf[0] = static_cast(0xddu); _msgpack_store32(&buf[1], static_cast(n)); append_buffer(buf, 5); } return *this; } template inline packer& packer::pack_map(uint32_t n) { if(n < 16) { unsigned char d = static_cast(0x80u | n); char buf = take8_8(d); append_buffer(&buf, 1); } else if(n < 65536) { char buf[3]; buf[0] = static_cast(0xdeu); _msgpack_store16(&buf[1], static_cast(n)); append_buffer(buf, 3); } else { char buf[5]; buf[0] = static_cast(0xdfu); _msgpack_store32(&buf[1], static_cast(n)); append_buffer(buf, 5); } return *this; } template inline packer& packer::pack_str(uint32_t l) { if(l < 32) { unsigned char d = static_cast(0xa0u | l); char buf = take8_8(d); append_buffer(&buf, 1); } else if(l < 256) { char buf[2]; buf[0] = static_cast(0xd9u); buf[1] = static_cast(l); append_buffer(buf, 2); } else if(l < 65536) { char buf[3]; buf[0] = static_cast(0xdau); _msgpack_store16(&buf[1], static_cast(l)); append_buffer(buf, 3); } else { char buf[5]; buf[0] = static_cast(0xdbu); _msgpack_store32(&buf[1], static_cast(l)); append_buffer(buf, 5); } return *this; } template inline packer& packer::pack_str_body(const char* b, uint32_t l) { append_buffer(b, l); return *this; } // Raw (V4) template inline packer& packer::pack_v4raw(uint32_t l) { if(l < 32) { unsigned char d = static_cast(0xa0u | l); char buf = take8_8(d); append_buffer(&buf, 1); } else if(l < 65536) { char buf[3]; buf[0] = static_cast(0xdau); _msgpack_store16(&buf[1], static_cast(l)); append_buffer(buf, 3); } else { char buf[5]; buf[0] = static_cast(0xdbu); _msgpack_store32(&buf[1], static_cast(l)); append_buffer(buf, 5); } return *this; } template inline packer& packer::pack_v4raw_body(const char* b, uint32_t l) { append_buffer(b, l); return *this; } template inline packer& packer::pack_bin(uint32_t l) { if(l < 256) { char buf[2]; buf[0] = static_cast(0xc4u); buf[1] = static_cast(l); append_buffer(buf, 2); } else if(l < 65536) { char buf[3]; buf[0] = static_cast(0xc5u); _msgpack_store16(&buf[1], static_cast(l)); append_buffer(buf, 3); } else { char buf[5]; buf[0] = static_cast(0xc6u); _msgpack_store32(&buf[1], static_cast(l)); append_buffer(buf, 5); } return *this; } template inline packer& packer::pack_bin_body(const char* b, uint32_t l) { append_buffer(b, l); return *this; } template inline packer& packer::pack_ext(size_t l, int8_t type) { switch(l) { case 1: { char buf[2]; buf[0] = static_cast(0xd4u); buf[1] = static_cast(type); append_buffer(buf, 2); } break; case 2: { char buf[2]; buf[0] = static_cast(0xd5u); buf[1] = static_cast(type); append_buffer(buf, 2); } break; case 4: { char buf[2]; buf[0] = static_cast(0xd6u); buf[1] = static_cast(type); append_buffer(buf, 2); } break; case 8: { char buf[2]; buf[0] = static_cast(0xd7u); buf[1] = static_cast(type); append_buffer(buf, 2); } break; case 16: { char buf[2]; buf[0] = static_cast(0xd8u); buf[1] = static_cast(type); append_buffer(buf, 2); } break; default: if(l < 256) { char buf[3]; buf[0] = static_cast(0xc7u); buf[1] = static_cast(l); buf[2] = static_cast(type); append_buffer(buf, 3); } else if(l < 65536) { char buf[4]; buf[0] = static_cast(0xc8u); _msgpack_store16(&buf[1], static_cast(l)); buf[3] = static_cast(type); append_buffer(buf, 4); } else { char buf[6]; buf[0] = static_cast(0xc9u); _msgpack_store32(&buf[1], static_cast(l)); buf[5] = static_cast(type); append_buffer(buf, 6); } break; } return *this; } template inline packer& packer::pack_ext_body(const char* b, uint32_t l) { append_buffer(b, l); return *this; } template template inline void packer::pack_imp_uint8(T d) { if(d < (1<<7)) { /* fixnum */ char buf = take8_8(d); append_buffer(&buf, 1); } else { /* unsigned 8 */ char buf[2] = {static_cast(0xccu), take8_8(d)}; append_buffer(buf, 2); } } template template inline void packer::pack_imp_uint16(T d) { if(d < (1<<7)) { /* fixnum */ char buf = take8_16(d); append_buffer(&buf, 1); } else if(d < (1<<8)) { /* unsigned 8 */ char buf[2] = {static_cast(0xccu), take8_16(d)}; append_buffer(buf, 2); } else { /* unsigned 16 */ char buf[3]; buf[0] = static_cast(0xcdu); _msgpack_store16(&buf[1], static_cast(d)); append_buffer(buf, 3); } } template template inline void packer::pack_imp_uint32(T d) { if(d < (1<<8)) { if(d < (1<<7)) { /* fixnum */ char buf = take8_32(d); append_buffer(&buf, 1); } else { /* unsigned 8 */ char buf[2] = {static_cast(0xccu), take8_32(d)}; append_buffer(buf, 2); } } else { if(d < (1<<16)) { /* unsigned 16 */ char buf[3]; buf[0] = static_cast(0xcdu); _msgpack_store16(&buf[1], static_cast(d)); append_buffer(buf, 3); } else { /* unsigned 32 */ char buf[5]; buf[0] = static_cast(0xceu); _msgpack_store32(&buf[1], static_cast(d)); append_buffer(buf, 5); } } } template template inline void packer::pack_imp_uint64(T d) { if(d < (1ULL<<8)) { if(d < (1ULL<<7)) { /* fixnum */ char buf = take8_64(d); append_buffer(&buf, 1); } else { /* unsigned 8 */ char buf[2] = {static_cast(0xccu), take8_64(d)}; append_buffer(buf, 2); } } else { if(d < (1ULL<<16)) { /* unsigned 16 */ char buf[3]; buf[0] = static_cast(0xcdu); _msgpack_store16(&buf[1], static_cast(d)); append_buffer(buf, 3); } else if(d < (1ULL<<32)) { /* unsigned 32 */ char buf[5]; buf[0] = static_cast(0xceu); _msgpack_store32(&buf[1], static_cast(d)); append_buffer(buf, 5); } else { /* unsigned 64 */ char buf[9]; buf[0] = static_cast(0xcfu); _msgpack_store64(&buf[1], d); append_buffer(buf, 9); } } } template template inline void packer::pack_imp_int8(T d) { if(d < -(1<<5)) { /* signed 8 */ char buf[2] = {static_cast(0xd0u), take8_8(d)}; append_buffer(buf, 2); } else { /* fixnum */ char buf = take8_8(d); append_buffer(&buf, 1); } } template template inline void packer::pack_imp_int16(T d) { if(d < -(1<<5)) { if(d < -(1<<7)) { /* signed 16 */ char buf[3]; buf[0] = static_cast(0xd1u); _msgpack_store16(&buf[1], static_cast(d)); append_buffer(buf, 3); } else { /* signed 8 */ char buf[2] = {static_cast(0xd0u), take8_16(d)}; append_buffer(buf, 2); } } else if(d < (1<<7)) { /* fixnum */ char buf = take8_16(d); append_buffer(&buf, 1); } else { if(d < (1<<8)) { /* unsigned 8 */ char buf[2] = {static_cast(0xccu), take8_16(d)}; append_buffer(buf, 2); } else { /* unsigned 16 */ char buf[3]; buf[0] = static_cast(0xcdu); _msgpack_store16(&buf[1], static_cast(d)); append_buffer(buf, 3); } } } template template inline void packer::pack_imp_int32(T d) { if(d < -(1<<5)) { if(d < -(1<<15)) { /* signed 32 */ char buf[5]; buf[0] = static_cast(0xd2u); _msgpack_store32(&buf[1], static_cast(d)); append_buffer(buf, 5); } else if(d < -(1<<7)) { /* signed 16 */ char buf[3]; buf[0] = static_cast(0xd1u); _msgpack_store16(&buf[1], static_cast(d)); append_buffer(buf, 3); } else { /* signed 8 */ char buf[2] = { static_cast(0xd0u), take8_32(d)}; append_buffer(buf, 2); } } else if(d < (1<<7)) { /* fixnum */ char buf = take8_32(d); append_buffer(&buf, 1); } else { if(d < (1<<8)) { /* unsigned 8 */ char buf[2] = { static_cast(0xccu), take8_32(d)}; append_buffer(buf, 2); } else if(d < (1<<16)) { /* unsigned 16 */ char buf[3]; buf[0] = static_cast(0xcdu); _msgpack_store16(&buf[1], static_cast(d)); append_buffer(buf, 3); } else { /* unsigned 32 */ char buf[5]; buf[0] = static_cast(0xceu); _msgpack_store32(&buf[1], static_cast(d)); append_buffer(buf, 5); } } } template template inline void packer::pack_imp_int64(T d) { if(d < -(1LL<<5)) { if(d < -(1LL<<15)) { if(d < -(1LL<<31)) { /* signed 64 */ char buf[9]; buf[0] = static_cast(0xd3u); _msgpack_store64(&buf[1], d); append_buffer(buf, 9); } else { /* signed 32 */ char buf[5]; buf[0] = static_cast(0xd2u); _msgpack_store32(&buf[1], static_cast(d)); append_buffer(buf, 5); } } else { if(d < -(1<<7)) { /* signed 16 */ char buf[3]; buf[0] = static_cast(0xd1u); _msgpack_store16(&buf[1], static_cast(d)); append_buffer(buf, 3); } else { /* signed 8 */ char buf[2] = {static_cast(0xd0u), take8_64(d)}; append_buffer(buf, 2); } } } else if(d < (1<<7)) { /* fixnum */ char buf = take8_64(d); append_buffer(&buf, 1); } else { if(d < (1LL<<16)) { if(d < (1<<8)) { /* unsigned 8 */ char buf[2] = {static_cast(0xccu), take8_64(d)}; append_buffer(buf, 2); } else { /* unsigned 16 */ char buf[3]; buf[0] = static_cast(0xcdu); _msgpack_store16(&buf[1], static_cast(d)); append_buffer(buf, 3); } } else { if(d < (1LL<<32)) { /* unsigned 32 */ char buf[5]; buf[0] = static_cast(0xceu); _msgpack_store32(&buf[1], static_cast(d)); append_buffer(buf, 5); } else { /* unsigned 64 */ char buf[9]; buf[0] = static_cast(0xcfu); _msgpack_store64(&buf[1], d); append_buffer(buf, 9); } } } } /// @cond } // MSGPACK_API_VERSION_NAMESPACE(v1) /// @endcond } // namespace clmdep_msgpack #endif // MSGPACK_V1_PACK_HPP