1199 lines
38 KiB
C++
1199 lines
38 KiB
C++
/*
|
|
* Copyright (c) 2020, Alibaba Group Holding Limited
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
* serialization.h is for packing all of integral types data into buffer stream.
|
|
*/
|
|
|
|
#ifndef XENGINE_INCLUDE_SERIALIZATION_H_
|
|
#define XENGINE_INCLUDE_SERIALIZATION_H_
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unordered_set>
|
|
#include <unordered_map>
|
|
//#include "autovector.h"
|
|
#include "template_util.h"
|
|
#include "xengine/slice.h"
|
|
#include "xengine/status.h"
|
|
|
|
#ifndef UNUSED
|
|
#define UNUSED(x) ((void)x)
|
|
#endif
|
|
|
|
#define ASSERT_BUFFER(length) \
|
|
assert(nullptr != buffer && bufsiz - pos >= length)
|
|
|
|
#define ASSERT_FIXED_LENGTH_BUFFER(type) \
|
|
assert(nullptr != buffer && bufsiz - pos >= (int64_t)sizeof(type))
|
|
|
|
#define DECLARE_SERIALIZATION() \
|
|
public: \
|
|
int serialize(char *buffer, int64_t bufsiz, int64_t &pos) const; \
|
|
int deserialize(const char *buffer, int64_t bufsiz, int64_t &pos); \
|
|
int64_t get_serialize_size() const;
|
|
|
|
#define DEFINE_SERIALIZATION(clz, ...) \
|
|
int clz::serialize(char *buffer, int64_t bufsiz, int64_t &pos) const { \
|
|
return util::serialize(buffer, bufsiz, pos, __VA_ARGS__); \
|
|
} \
|
|
int clz::deserialize(const char *buffer, int64_t bufsiz, int64_t &pos) { \
|
|
return util::deserialize(buffer, bufsiz, pos, __VA_ARGS__); \
|
|
} \
|
|
int64_t clz::get_serialize_size() const { \
|
|
return util::get_serialize_size(__VA_ARGS__); \
|
|
}
|
|
|
|
/*-----------------macros for compactiple serialize and deserialize---------------------*/
|
|
//macros for declare compactiple serialize and deserialize
|
|
#define DECLARE_COMPACTIPLE_SERIALIZATION(VERSION) \
|
|
public: \
|
|
DECLARE_COMPACTIPLE_SERIALIZATION_; \
|
|
private: \
|
|
const static int64_t VERSION_ = VERSION
|
|
|
|
#define DECLARE_COMPACTIPLE_SERIALIZATION_ \
|
|
int serialize(char *buf, int64_t buf_len, int64_t &pos) const; \
|
|
int serialize_(char *buf, int64_t buf_len, int64_t &pos) const; \
|
|
int deserialize(const char *buf, int64_t buf_len, int64_t &pos); \
|
|
int deserialize_(const char *buf, int64_t buf_len, int64_t &pos); \
|
|
int64_t get_serialize_size() const; \
|
|
int64_t get_serialize_size_() const
|
|
|
|
//macros for serialize and deserialize header
|
|
#define SERIALIZE_HEADER(VERSION, LEN) \
|
|
if (common::Status::kOk == ret) { \
|
|
ret = util::serialize(buf, buf_len, pos, VERSION); \
|
|
} \
|
|
if (common::Status::kOk == ret) { \
|
|
ret = util::serialize(buf, buf_len, pos, LEN); \
|
|
}
|
|
|
|
#define CHECK_HEADER(VERSION, LEN) \
|
|
if (common::Status::kOk == ret) { \
|
|
if (VERSION_ != VERSION) { \
|
|
ret = common::Status::kNotSupported; \
|
|
} else if (LEN < 0) { \
|
|
ret = common::Status::kCorruption; \
|
|
} else if (buf_len < (pos + LEN)) { \
|
|
ret = common::Status::kCorruption; \
|
|
} \
|
|
}
|
|
|
|
#define DESERIALIZE_HEADER(VERSION, LEN) \
|
|
if (common::Status::kOk == ret) { \
|
|
ret = util::deserialize(buf, buf_len, pos, VERSION); \
|
|
} \
|
|
if (common::Status::kOk == ret) { \
|
|
ret = util::deserialize(buf, buf_len, pos, LEN); \
|
|
}
|
|
|
|
#define HEADER_SERIALIZE_SIZE(VERSION, LEN) \
|
|
LEN += util::get_serialize_size(LEN); \
|
|
LEN += util::get_serialize_size(VERSION)
|
|
|
|
#define DEFINE_COMPACTIPLE_SERIALIZATION(CLZ, ...) \
|
|
int CLZ::serialize(char *buf, int64_t buf_len, int64_t &pos) const \
|
|
{ \
|
|
int ret = common::Status::kOk; \
|
|
int64_t serialize_size = get_serialize_size_(); \
|
|
SERIALIZE_HEADER(VERSION_, serialize_size); \
|
|
if (common::Status::kOk == ret) { \
|
|
ret = serialize_(buf, buf_len, pos); \
|
|
} \
|
|
return ret; \
|
|
} \
|
|
int CLZ::serialize_(char *buf, int64_t buf_len, int64_t &pos) const \
|
|
{ \
|
|
return util::serialize_x(buf, buf_len, pos, ##__VA_ARGS__); \
|
|
} \
|
|
int CLZ::deserialize(const char *buf, int64_t buf_len, int64_t &pos) \
|
|
{ \
|
|
int ret = common::Status::kOk; \
|
|
int64_t version = 0; \
|
|
int64_t deserialize_size = 0; \
|
|
int64_t orig_pos = 0; \
|
|
DESERIALIZE_HEADER(version, deserialize_size);\
|
|
CHECK_HEADER(version, deserialize_size); \
|
|
if (common::Status::kOk == ret) { \
|
|
orig_pos = pos; \
|
|
pos = 0; \
|
|
ret = deserialize_(buf + orig_pos, deserialize_size, pos); \
|
|
pos = orig_pos + deserialize_size; \
|
|
} \
|
|
return ret; \
|
|
} \
|
|
int CLZ::deserialize_(const char *buf, int64_t buf_len, int64_t &pos) \
|
|
{ \
|
|
return util::deserialize_x(buf, buf_len, pos, ##__VA_ARGS__); \
|
|
} \
|
|
int64_t CLZ::get_serialize_size() const \
|
|
{ \
|
|
int64_t serialize_size = get_serialize_size_(); \
|
|
HEADER_SERIALIZE_SIZE(VERSION_, serialize_size); \
|
|
return serialize_size; \
|
|
} \
|
|
int64_t CLZ::get_serialize_size_() const \
|
|
{ \
|
|
return util::get_serialize_size_x(__VA_ARGS__); \
|
|
}
|
|
|
|
// macros for declare pure virtual serialize and deserialize
|
|
#define DECLARE_PURE_VIRTUAL_SERIALIZATION() \
|
|
virtual int serialize(char *buf, int64_t buf_len, int64_t &pos) const = 0; \
|
|
virtual int deserialize(const char *buf, int64_t buf_len, int64_t &pos) = 0; \
|
|
virtual int64_t get_serialize_size() const = 0
|
|
|
|
namespace xengine {
|
|
namespace common {
|
|
class Status;
|
|
class Slice;
|
|
} // namespace common
|
|
|
|
namespace util {
|
|
|
|
const uint64_t XE_MAX_V1B = (__UINT64_C(1) << 7) - 1;
|
|
const uint64_t XE_MAX_V2B = (__UINT64_C(1) << 14) - 1;
|
|
const uint64_t XE_MAX_V3B = (__UINT64_C(1) << 21) - 1;
|
|
const uint64_t XE_MAX_V4B = (__UINT64_C(1) << 28) - 1;
|
|
const uint64_t XE_MAX_V5B = (__UINT64_C(1) << 35) - 1;
|
|
const uint64_t XE_MAX_V6B = (__UINT64_C(1) << 42) - 1;
|
|
const uint64_t XE_MAX_V7B = (__UINT64_C(1) << 49) - 1;
|
|
const uint64_t XE_MAX_V8B = (__UINT64_C(1) << 56) - 1;
|
|
const uint64_t XE_MAX_V9B = (__UINT64_C(1) << 63) - 1;
|
|
|
|
const uint64_t XE_MAX_1B = (__UINT64_C(1) << 8) - 1;
|
|
const uint64_t XE_MAX_2B = (__UINT64_C(1) << 16) - 1;
|
|
const uint64_t XE_MAX_3B = (__UINT64_C(1) << 24) - 1;
|
|
const uint64_t XE_MAX_4B = (__UINT64_C(1) << 32) - 1;
|
|
const uint64_t XE_MAX_5B = (__UINT64_C(1) << 40) - 1;
|
|
const uint64_t XE_MAX_6B = (__UINT64_C(1) << 48) - 1;
|
|
const uint64_t XE_MAX_7B = (__UINT64_C(1) << 56) - 1;
|
|
const uint64_t XE_MAX_8B = UINT64_MAX;
|
|
|
|
const uint64_t XE_MAX_INT_1B = (__UINT64_C(23));
|
|
const uint64_t XE_MAX_INT_2B = (__UINT64_C(1) << 8) - 1;
|
|
const uint64_t XE_MAX_INT_3B = (__UINT64_C(1) << 16) - 1;
|
|
const uint64_t XE_MAX_INT_4B = (__UINT64_C(1) << 24) - 1;
|
|
const uint64_t XE_MAX_INT_5B = (__UINT64_C(1) << 32) - 1;
|
|
const uint64_t XE_MAX_INT_7B = (__UINT64_C(1) << 48) - 1;
|
|
const uint64_t XE_MAX_INT_9B = UINT64_MAX;
|
|
|
|
const int64_t XE_MAX_1B_STR_LEN = (__INT64_C(55));
|
|
const int64_t XE_MAX_2B_STR_LEN = (__INT64_C(1) << 8) - 1;
|
|
const int64_t XE_MAX_3B_STR_LEN = (__INT64_C(1) << 16) - 1;
|
|
const int64_t XE_MAX_4B_STR_LEN = (__INT64_C(1) << 24) - 1;
|
|
const int64_t XE_MAX_5B_STR_LEN = (__INT64_C(1) << 32) - 1;
|
|
|
|
const int8_t XE_INT_TYPE_BIT_POS = 7;
|
|
const int8_t XE_INT_OPERATION_BIT_POS = 6;
|
|
const int8_t XE_INT_SIGN_BIT_POS = 5;
|
|
const int8_t XE_DATETIME_OPERATION_BIT = 3;
|
|
const int8_t XE_DATETIME_SIGN_BIT = 2;
|
|
const int8_t XE_FLOAT_OPERATION_BIT_POS = 0;
|
|
const int8_t XE_DECIMAL_OPERATION_BIT_POS = 7;
|
|
|
|
const int8_t XE_INT_VALUE_MASK = 0x1f;
|
|
const int8_t XE_VARCHAR_LEN_MASK = 0x3f;
|
|
const int8_t XE_DATETIME_LEN_MASK = 0x3;
|
|
|
|
const int8_t XE_VARCHAR_TYPE = static_cast<int8_t>((0x1 << 7));
|
|
const int8_t XE_SEQ_TYPE = static_cast<int8_t>(0xc0);
|
|
const int8_t XE_DATETIME_TYPE = static_cast<int8_t>(0xd0);
|
|
const int8_t XE_PRECISE_DATETIME_TYPE = static_cast<int8_t>(0xe0);
|
|
const int8_t XE_MODIFYTIME_TYPE = static_cast<int8_t>(0xf0);
|
|
const int8_t XE_CREATETIME_TYPE = static_cast<int8_t>(0xf4);
|
|
const int8_t XE_FLOAT_TYPE = static_cast<int8_t>(0xf8);
|
|
const int8_t XE_DOUBLE_TYPE = static_cast<int8_t>(0xfa);
|
|
const int8_t XE_nullptr_TYPE = static_cast<int8_t>(0xfc);
|
|
const int8_t XE_BOOL_TYPE = static_cast<int8_t>(0xfd);
|
|
const int8_t XE_EXTEND_TYPE = static_cast<int8_t>(0xfe);
|
|
const int8_t XE_DECIMAL_TYPE = static_cast<int8_t>(0xff);
|
|
const int8_t XE_NUMBER_TYPE = XE_DECIMAL_TYPE; // 2014number
|
|
|
|
/**
|
|
* @brief Encode a byte into given buffer.
|
|
*
|
|
* @param buffer address of destination buffer
|
|
* @param value the byte
|
|
*
|
|
*/
|
|
|
|
inline int encode_fixed_int8(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
int8_t value) {
|
|
ASSERT_FIXED_LENGTH_BUFFER(int8_t);
|
|
*(buffer + pos++) = value;
|
|
return common::Status::kOk;
|
|
}
|
|
|
|
inline int decode_fixed_int8(const char *buffer, const int64_t bufsiz,
|
|
int64_t &pos, int8_t &value) {
|
|
ASSERT_FIXED_LENGTH_BUFFER(int8_t);
|
|
value = *(buffer + pos++);
|
|
return common::Status::kOk;
|
|
}
|
|
|
|
/**
|
|
* @brief Enocde a 16-bit integer in big-endian order
|
|
*
|
|
* @param buffer address of destination buffer
|
|
* @param value value to encode
|
|
*/
|
|
inline int encode_fixed_int16(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
int16_t value) {
|
|
ASSERT_FIXED_LENGTH_BUFFER(int16_t);
|
|
*(buffer + pos++) = static_cast<char>((((value) >> 8)) & 0xff);
|
|
*(buffer + pos++) = static_cast<char>((value)&0xff);
|
|
return common::Status::kOk;
|
|
}
|
|
|
|
inline int decode_fixed_int16(const char *buffer, const int64_t bufsiz,
|
|
int64_t &pos, int16_t &value) {
|
|
ASSERT_FIXED_LENGTH_BUFFER(int16_t);
|
|
value = static_cast<int16_t>(((*(buffer + pos++)) & 0xff) << 8);
|
|
value = static_cast<int16_t>(value | (*(buffer + pos++) & 0xff));
|
|
return common::Status::kOk;
|
|
}
|
|
|
|
inline int encode_fixed_int32(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
int32_t value) {
|
|
ASSERT_FIXED_LENGTH_BUFFER(int32_t);
|
|
*(buffer + pos++) = static_cast<char>(((value) >> 24) & 0xff);
|
|
*(buffer + pos++) = static_cast<char>(((value) >> 16) & 0xff);
|
|
*(buffer + pos++) = static_cast<char>(((value) >> 8) & 0xff);
|
|
*(buffer + pos++) = static_cast<char>((value)&0xff);
|
|
return common::Status::kOk;
|
|
}
|
|
|
|
inline int decode_fixed_int32(const char *buffer, const int64_t bufsiz,
|
|
int64_t &pos, int32_t &value) {
|
|
ASSERT_FIXED_LENGTH_BUFFER(int32_t);
|
|
value = ((static_cast<int32_t>(*(buffer + pos++))) & 0xff) << 24;
|
|
value |= ((static_cast<int32_t>(*(buffer + pos++))) & 0xff) << 16;
|
|
value |= ((static_cast<int32_t>(*(buffer + pos++))) & 0xff) << 8;
|
|
value |= ((static_cast<int32_t>(*(buffer + pos++))) & 0xff);
|
|
return common::Status::kOk;
|
|
}
|
|
|
|
inline int encode_fixed_int64(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
int64_t value) {
|
|
ASSERT_FIXED_LENGTH_BUFFER(int64_t);
|
|
*(buffer + pos++) = static_cast<char>(((value) >> 56) & 0xff);
|
|
*(buffer + pos++) = static_cast<char>(((value) >> 48) & 0xff);
|
|
*(buffer + pos++) = static_cast<char>(((value) >> 40) & 0xff);
|
|
*(buffer + pos++) = static_cast<char>(((value) >> 32) & 0xff);
|
|
*(buffer + pos++) = static_cast<char>(((value) >> 24) & 0xff);
|
|
*(buffer + pos++) = static_cast<char>(((value) >> 16) & 0xff);
|
|
*(buffer + pos++) = static_cast<char>(((value) >> 8) & 0xff);
|
|
*(buffer + pos++) = static_cast<char>((value)&0xff);
|
|
return common::Status::kOk;
|
|
}
|
|
|
|
inline int decode_fixed_int64(const char *buffer, const int64_t bufsiz,
|
|
int64_t &pos, int64_t &value) {
|
|
ASSERT_FIXED_LENGTH_BUFFER(int64_t);
|
|
value = ((static_cast<int64_t>((*(buffer + pos++))) & 0xff)) << 56;
|
|
value |= ((static_cast<int64_t>((*(buffer + pos++))) & 0xff)) << 48;
|
|
value |= ((static_cast<int64_t>((*(buffer + pos++))) & 0xff)) << 40;
|
|
value |= ((static_cast<int64_t>((*(buffer + pos++))) & 0xff)) << 32;
|
|
value |= ((static_cast<int64_t>((*(buffer + pos++))) & 0xff)) << 24;
|
|
value |= ((static_cast<int64_t>((*(buffer + pos++))) & 0xff)) << 16;
|
|
value |= ((static_cast<int64_t>((*(buffer + pos++))) & 0xff)) << 8;
|
|
value |= ((static_cast<int64_t>((*(buffer + pos++))) & 0xff));
|
|
return common::Status::kOk;
|
|
}
|
|
|
|
inline int encode_boolean(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
bool value) {
|
|
ASSERT_FIXED_LENGTH_BUFFER(int8_t);
|
|
*(buffer + pos++) = (value) ? 1 : 0;
|
|
return common::Status::kOk;
|
|
}
|
|
|
|
inline int decode_boolean(const char *buffer, const int64_t bufsiz,
|
|
int64_t &pos, bool &value) {
|
|
ASSERT_FIXED_LENGTH_BUFFER(char);
|
|
int8_t v = 0;
|
|
int ret = 0;
|
|
if ((ret = decode_fixed_int8(buffer, bufsiz, pos, v)) ==
|
|
common::Status::kOk) {
|
|
value = (v != 0);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
inline int64_t encoded_length_var_int64(int64_t value) {
|
|
uint64_t uv = static_cast<uint64_t>(value);
|
|
int64_t need_bytes = 0;
|
|
if (uv <= XE_MAX_V1B)
|
|
need_bytes = 1;
|
|
else if (uv <= XE_MAX_V2B)
|
|
need_bytes = 2;
|
|
else if (uv <= XE_MAX_V3B)
|
|
need_bytes = 3;
|
|
else if (uv <= XE_MAX_V4B)
|
|
need_bytes = 4;
|
|
else if (uv <= XE_MAX_V5B)
|
|
need_bytes = 5;
|
|
else if (uv <= XE_MAX_V6B)
|
|
need_bytes = 6;
|
|
else if (uv <= XE_MAX_V7B)
|
|
need_bytes = 7;
|
|
else if (uv <= XE_MAX_V8B)
|
|
need_bytes = 8;
|
|
else if (uv <= XE_MAX_V9B)
|
|
need_bytes = 9;
|
|
else
|
|
need_bytes = 10;
|
|
return need_bytes;
|
|
}
|
|
|
|
/**
|
|
* @brief Encode a integer (up to 64bit) in variable length encoding
|
|
*
|
|
* @param buffer pointer to the destination buffer
|
|
* @param end the end pointer to the destination buffer
|
|
* @param value value to encode
|
|
*
|
|
* @return true - success, false - failed
|
|
*/
|
|
inline int encode_var_int64(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
int64_t value) {
|
|
uint64_t uv = static_cast<uint64_t>(value);
|
|
ASSERT_BUFFER(encoded_length_var_int64(uv));
|
|
while (uv > XE_MAX_V1B) {
|
|
*(buffer + pos++) = static_cast<int8_t>((uv) | 0x80);
|
|
uv >>= 7;
|
|
}
|
|
if (uv <= XE_MAX_V1B) {
|
|
*(buffer + pos++) = static_cast<int8_t>((uv)&0x7f);
|
|
}
|
|
return common::Status::kOk;
|
|
}
|
|
|
|
inline int decode_var_int64(const char *buffer, const int64_t bufsiz,
|
|
int64_t &pos, int64_t &value) {
|
|
uint64_t uv = 0;
|
|
uint32_t shift = 0;
|
|
int64_t tmp_pos = pos;
|
|
int ret = common::Status::kOk;
|
|
while ((*(buffer + tmp_pos)) & 0x80) {
|
|
if (bufsiz - tmp_pos < 1) {
|
|
ret = common::Status::kNoSpace;
|
|
break;
|
|
}
|
|
uv |= (static_cast<uint64_t>(*(buffer + tmp_pos++)) & 0x7f) << shift;
|
|
shift += 7;
|
|
}
|
|
if (common::Status::kOk == ret) {
|
|
if (bufsiz - tmp_pos < 1) {
|
|
ret = common::Status::kNoSpace;
|
|
} else {
|
|
uv |= ((static_cast<uint64_t>(*(buffer + tmp_pos++)) & 0x7f) << shift);
|
|
value = static_cast<int64_t>(uv);
|
|
pos = tmp_pos;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
inline int64_t encoded_length_var_int32(int32_t value) {
|
|
uint32_t uv = static_cast<uint64_t>(value);
|
|
int64_t need_bytes = 0;
|
|
if (uv <= XE_MAX_V1B)
|
|
need_bytes = 1;
|
|
else if (uv <= XE_MAX_V2B)
|
|
need_bytes = 2;
|
|
else if (uv <= XE_MAX_V3B)
|
|
need_bytes = 3;
|
|
else if (uv <= XE_MAX_V4B)
|
|
need_bytes = 4;
|
|
else
|
|
need_bytes = 5;
|
|
return need_bytes;
|
|
}
|
|
|
|
/**
|
|
* @brief Encode a integer (up to 32bit) in variable length encoding
|
|
*
|
|
* @param buffer pointer to the destination buffer
|
|
* @param end the end pointer to the destination buffer
|
|
* @param value value to encode
|
|
*
|
|
* @return true - success, false - failed
|
|
*/
|
|
|
|
inline int encode_var_int32(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
int32_t value) {
|
|
uint32_t uv = static_cast<uint32_t>(value);
|
|
ASSERT_BUFFER(encoded_length_var_int32(value));
|
|
while (uv > XE_MAX_V1B) {
|
|
*(buffer + pos++) = static_cast<int8_t>((uv) | 0x80);
|
|
uv >>= 7;
|
|
}
|
|
if (uv <= XE_MAX_V1B) {
|
|
*(buffer + pos++) = static_cast<int8_t>((uv)&0x7f);
|
|
}
|
|
return common::Status::kOk;
|
|
}
|
|
|
|
inline int decode_var_int32(const char *buffer, const int64_t bufsiz,
|
|
int64_t &pos, int32_t &value) {
|
|
uint32_t uv = 0;
|
|
uint32_t shift = 0;
|
|
int ret = common::Status::kOk;
|
|
int64_t tmp_pos = pos;
|
|
while ((*(buffer + tmp_pos)) & 0x80) {
|
|
if (bufsiz - tmp_pos < 1) {
|
|
ret = common::Status::kNoSpace;
|
|
break;
|
|
}
|
|
uv |= (static_cast<uint32_t>(*(buffer + tmp_pos++)) & 0x7f) << shift;
|
|
shift += 7;
|
|
}
|
|
if (common::Status::kOk == ret) {
|
|
if (bufsiz - tmp_pos < 1)
|
|
ret = common::Status::kNoSpace;
|
|
else {
|
|
uv |= (static_cast<uint32_t>(*(buffer + tmp_pos++)) & 0x7f) << shift;
|
|
value = static_cast<int32_t>(uv);
|
|
pos = tmp_pos;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
inline int64_t encoded_length_var_str(int64_t len) {
|
|
return encoded_length_var_int64(len) + len;
|
|
}
|
|
|
|
/**
|
|
* @brief Encode a buffer as vstr(int64,data,null)
|
|
*
|
|
* @param buffer pointer to the destination buffer
|
|
* @param vbuf pointer to the start of the input buffer
|
|
* @param len length of the input buffer
|
|
*/
|
|
inline int encode_var_str(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
const void *str, int64_t len) {
|
|
int ret = 0;
|
|
ASSERT_BUFFER(encoded_length_var_str(len));
|
|
if (common::Status::kOk == ret) {
|
|
/**
|
|
* even through it's a null string, we can serialize it with
|
|
* lenght 0, and following a '\0'
|
|
*/
|
|
ret = encode_var_int64(buffer, bufsiz, pos, len);
|
|
if (common::Status::kOk == ret && len > 0 && nullptr != str) {
|
|
memcpy(buffer + pos, str, len);
|
|
pos += len;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
inline int encode_var_str(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
const common::Slice &slice) {
|
|
return encode_var_str(buffer, bufsiz, pos, slice.data(), slice.size());
|
|
}
|
|
|
|
// return deserialized string pointer to input buffer;
|
|
// return nullptr if error occurs;
|
|
inline const char *decode_var_str(const char *buffer, const int64_t bufsiz,
|
|
int64_t &pos, int64_t &length) {
|
|
const char *str = 0;
|
|
int64_t tmp_pos = pos;
|
|
|
|
length = -1;
|
|
if ((nullptr == buffer) || (bufsiz < 0) || (pos < 0)) {
|
|
} else if (decode_var_int64(buffer, bufsiz, tmp_pos, length) !=
|
|
common::Status::kOk) {
|
|
} else if (length >= 0) {
|
|
if (bufsiz - tmp_pos >= length) {
|
|
str = buffer + tmp_pos;
|
|
tmp_pos += length;
|
|
pos = tmp_pos;
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
|
|
// copy deserialized string into @dest[@length]
|
|
inline int decode_var_str(const char *buffer, const int64_t bufsiz,
|
|
int64_t &pos, char *dest, int64_t &length) {
|
|
int ret = 0;
|
|
int64_t tmp_len = 0;
|
|
int64_t tmp_pos = pos;
|
|
if ((nullptr == buffer) || (bufsiz < 0) || (pos < 0) || (nullptr == dest) ||
|
|
length < 0) {
|
|
ret = common::Status::kNoSpace;
|
|
} else if (decode_var_int64(buffer, bufsiz, tmp_pos, tmp_len) != 0 ||
|
|
tmp_len > bufsiz || tmp_len > length) {
|
|
ret = common::Status::kNoSpace;
|
|
} else if (tmp_len >= 0) {
|
|
if (bufsiz - tmp_pos >= tmp_len) {
|
|
length = tmp_len;
|
|
memcpy(dest, buffer + tmp_pos, tmp_len);
|
|
tmp_pos += tmp_len;
|
|
pos = tmp_pos;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// setup @slice's data point to serialized buffer;
|
|
// WARNING : @slice does not own the buffer, it will be unavialable
|
|
// when @buffer is no longer live.
|
|
inline int decode_var_str(const char *buffer, const int64_t bufsiz,
|
|
int64_t &pos, common::Slice &slice) {
|
|
int64_t length = 0;
|
|
slice.data_ = decode_var_str(buffer, bufsiz, pos, length);
|
|
slice.size_ = static_cast<size_t>(length);
|
|
if (nullptr == slice.data_ || length < 0) {
|
|
return common::Status::kNoSpace;
|
|
}
|
|
return common::Status::kOk;
|
|
}
|
|
|
|
inline int decode_var_str(const char *buffer, const int64_t bufsiz,
|
|
int64_t &pos, std::string &value) {
|
|
int64_t length = 0;
|
|
const char *data = decode_var_str(buffer, bufsiz, pos, length);
|
|
if (nullptr == data || length < 0) {
|
|
return common::Status::kNoSpace;
|
|
}
|
|
value.assign(data, length);
|
|
return common::Status::kOk;
|
|
}
|
|
|
|
// -----------------------------------------------------------------
|
|
// serialize & deserialize template functions;
|
|
// -----------------------------------------------------------------
|
|
|
|
inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
int64_t value) {
|
|
return encode_var_int64(buffer, bufsiz, pos, value);
|
|
}
|
|
inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
uint64_t value) {
|
|
return encode_var_int64(buffer, bufsiz, pos, static_cast<int64_t>(value));
|
|
}
|
|
inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
int32_t value) {
|
|
return encode_var_int32(buffer, bufsiz, pos, value);
|
|
}
|
|
inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
uint32_t value) {
|
|
return encode_var_int32(buffer, bufsiz, pos, static_cast<int32_t>(value));
|
|
}
|
|
inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
int16_t value) {
|
|
return encode_fixed_int16(buffer, bufsiz, pos, value);
|
|
}
|
|
inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
uint16_t value) {
|
|
return encode_fixed_int16(buffer, bufsiz, pos, static_cast<int16_t>(value));
|
|
}
|
|
inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
int8_t value) {
|
|
return encode_fixed_int8(buffer, bufsiz, pos, value);
|
|
}
|
|
inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
uint8_t value) {
|
|
return encode_fixed_int8(buffer, bufsiz, pos, static_cast<int8_t>(value));
|
|
}
|
|
inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
const char *value) {
|
|
return encode_var_str(buffer, bufsiz, pos, value, strlen(value));
|
|
}
|
|
inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
const common::Slice &value) {
|
|
return encode_var_str(buffer, bufsiz, pos, value);
|
|
}
|
|
inline int serialize(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
const std::string &value) {
|
|
return encode_var_str(buffer, bufsiz, pos, value.data(), value.size());
|
|
}
|
|
|
|
template <typename T>
|
|
int serialize(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
const T &value) {
|
|
return value.serialize(buffer, bufsiz, pos);
|
|
}
|
|
|
|
template <typename T>
|
|
int serialize_x(char *buf, const int64_t buf_len, int64_t &pos, const T &value);
|
|
|
|
template <typename T, typename... Args>
|
|
int serialize_x(char *buf, const int64_t buf_len, int64_t &pos, const T &head, const Args &... rest);
|
|
|
|
template <typename T>
|
|
int deserialize_x(const char *buf, int64_t buf_len, int64_t &pos, T &value);
|
|
|
|
template <typename T, typename... Args>
|
|
int deserialize_x(const char *buf, int64_t buf_len, int64_t &pos, T &head, Args &... rest);
|
|
|
|
template <typename T>
|
|
int get_serialize_size_x(const T &value);
|
|
|
|
template <typename T, typename... Args>
|
|
int get_serialize_size_x(const T &head, const Args &... rest);
|
|
|
|
template <typename T>
|
|
int serialize_v(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
const autovector<T> &values) {
|
|
int ret = 0;
|
|
if (common::Status::kOk !=
|
|
(ret = encode_var_int64(buffer, bufsiz, pos, values.size()))) {
|
|
} else {
|
|
for (auto &value : values) {
|
|
if (common::Status::kOk !=
|
|
(ret = serialize(buffer, bufsiz, pos, value))) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T>
|
|
int serialize_v(char *buf, const int64_t buf_len, int64_t &pos, const std::vector<T> &values)
|
|
{
|
|
int ret = common::Status::kOk;
|
|
if (common::Status::kOk != (ret = encode_var_int64(buf, buf_len, pos, values.size()))) {
|
|
} else {
|
|
for (auto &value : values) {
|
|
if (common::Status::kOk != (ret = serialize_x(buf, buf_len, pos, value))) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T>
|
|
int serialize_v(char *buf, const int64_t buf_len, int64_t &pos, const std::unordered_set<T> &values)
|
|
{
|
|
int ret = common::Status::kOk;
|
|
if (common::Status::kOk != (ret = encode_var_int64(buf, buf_len, pos, values.size()))) {
|
|
} else {
|
|
for (auto &value : values) {
|
|
if (common::Status::kOk != (ret = serialize(buf, buf_len, pos, value))) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T>
|
|
int serialize_x(char *buf, const int64_t buf_len, int64_t &pos, const T &value);
|
|
|
|
template <typename T,typename E>
|
|
int serialize_v(char *buf, const int64_t buf_len, int64_t &pos, const std::unordered_map<T,E> &values)
|
|
{
|
|
int ret = common::Status::kOk;
|
|
if (common::Status::kOk != (ret = encode_var_int64(buf, buf_len, pos, values.size()))) {
|
|
} else {
|
|
for (auto &value : values) {
|
|
if (common::Status::kOk != (ret = serialize_x(buf, buf_len, pos, value.first))) {
|
|
break;
|
|
}
|
|
if(common::Status::kOk != (ret = serialize_x(buf, buf_len, pos, value.second)) ) {
|
|
break;
|
|
}
|
|
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename E, template <typename, typename...> class Container,
|
|
typename... Args>
|
|
int serialize_v(char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
const Container<E, Args...> &values) {
|
|
int ret = 0;
|
|
if (common::Status::kOk !=
|
|
(ret = encode_var_int64(buffer, bufsiz, pos, values.size()))) {
|
|
} else {
|
|
for (auto &value : values) {
|
|
if (common::Status::kOk !=
|
|
(ret = serialize(buffer, bufsiz, pos, value))) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
int64_t &value) {
|
|
return decode_var_int64(buffer, bufsiz, pos, value);
|
|
}
|
|
inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
uint64_t &value) {
|
|
return decode_var_int64(buffer, bufsiz, pos,
|
|
reinterpret_cast<int64_t &>(value));
|
|
}
|
|
inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
int32_t &value) {
|
|
return decode_var_int32(buffer, bufsiz, pos, value);
|
|
}
|
|
inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
uint32_t &value) {
|
|
return decode_var_int32(buffer, bufsiz, pos,
|
|
reinterpret_cast<int32_t &>(value));
|
|
}
|
|
inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
int16_t &value) {
|
|
return decode_fixed_int16(buffer, bufsiz, pos, value);
|
|
}
|
|
inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
uint16_t &value) {
|
|
return decode_fixed_int16(buffer, bufsiz, pos,
|
|
reinterpret_cast<int16_t &>(value));
|
|
}
|
|
inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
int8_t &value) {
|
|
return decode_fixed_int8(buffer, bufsiz, pos, value);
|
|
}
|
|
inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
uint8_t &value) {
|
|
return decode_fixed_int8(buffer, bufsiz, pos,
|
|
reinterpret_cast<int8_t &>(value));
|
|
}
|
|
// make sure @value has enough space, otherwise it will be segment fault.
|
|
inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
char *value) {
|
|
int64_t length = bufsiz;
|
|
int ret = decode_var_str(buffer, bufsiz, pos, value, length);
|
|
if (common::Status::kOk == ret) {
|
|
value[length] = 0;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
common::Slice &value) {
|
|
return decode_var_str(buffer, bufsiz, pos, value);
|
|
}
|
|
|
|
inline int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
std::string &value) {
|
|
return decode_var_str(buffer, bufsiz, pos, value);
|
|
}
|
|
|
|
template <typename T>
|
|
int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
T &value) {
|
|
return value.deserialize(buffer, bufsiz, pos);
|
|
}
|
|
|
|
template <typename E, template <typename, typename...> class Container,
|
|
typename... Args>
|
|
int deserialize_v(const char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
Container<E, Args...> &values) {
|
|
int ret = 0;
|
|
int64_t size = 0;
|
|
if (common::Status::kOk !=
|
|
(ret = decode_var_int64(buffer, bufsiz, pos, size))) {
|
|
} else {
|
|
E value;
|
|
for (int64_t i = 0; i < size; ++i) {
|
|
if (common::Status::kOk !=
|
|
(ret = deserialize(buffer, bufsiz, pos, value))) {
|
|
break;
|
|
} else {
|
|
values.push_back(value);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename E>
|
|
int deserialize_v(const char *buffer, const int64_t bufsiz, int64_t &pos,
|
|
autovector<E> &values) {
|
|
int ret = 0;
|
|
int64_t size = 0;
|
|
if (common::Status::kOk !=
|
|
(ret = decode_var_int64(buffer, bufsiz, pos, size))) {
|
|
} else {
|
|
E value;
|
|
for (int64_t i = 0; i < size; ++i) {
|
|
if (common::Status::kOk !=
|
|
(ret = deserialize(buffer, bufsiz, pos, value))) {
|
|
break;
|
|
} else {
|
|
values.emplace_back(value);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T>
|
|
int deserialize_v(const char *buf, const int64_t buf_len, int64_t &pos, std::vector<T> &values)
|
|
{
|
|
int ret = common::Status::kOk;
|
|
int64_t size = 0;
|
|
if (common::Status::kOk != (ret = decode_var_int64(buf, buf_len, pos, size))) {
|
|
} else {
|
|
T value;
|
|
for (int64_t i = 0; i < size; ++i) {
|
|
if (common::Status::kOk != (ret = deserialize_x(buf, buf_len, pos, value))) {
|
|
break;
|
|
} else {
|
|
values.emplace_back(value);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T>
|
|
int deserialize_v(const char *buf, const int64_t buf_len, int64_t &pos, std::unordered_set<T> &values)
|
|
{
|
|
int ret = common::Status::kOk;
|
|
int64_t size = 0;
|
|
T value;
|
|
if (common::Status::kOk != (ret = decode_var_int64(buf, buf_len, pos, size))) {
|
|
} else {
|
|
for (int64_t i = 0; i < size; ++i) {
|
|
if (common::Status::kOk != (ret = deserialize(buf, buf_len, pos, value))) {
|
|
break;
|
|
} else {
|
|
values.emplace(value);
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T>
|
|
int deserialize_x(const char *buf, int64_t buf_len, int64_t &pos, T &value);
|
|
|
|
template <typename T, typename E>
|
|
int deserialize_v(const char *buf, const int64_t buf_len, int64_t &pos, std::unordered_map<T,E> &values)
|
|
{
|
|
int ret = common::Status::kOk;
|
|
int64_t size = 0;
|
|
if (common::Status::kOk != (ret = decode_var_int64(buf, buf_len, pos, size))) {
|
|
} else {
|
|
for (int64_t i = 0; i < size; ++i) {
|
|
T first;
|
|
E second;
|
|
if (common::Status::kOk != (ret = deserialize_x(buf, buf_len, pos, first))) {
|
|
break;
|
|
} else if (common::Status::kOk != (ret = deserialize_x(buf, buf_len, pos, second))) {
|
|
break;
|
|
} else {
|
|
values[first] = second;
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
inline int64_t get_serialize_size(int64_t value) {
|
|
return encoded_length_var_int64(value);
|
|
}
|
|
inline int64_t get_serialize_size(uint64_t value) {
|
|
return encoded_length_var_int64(static_cast<int64_t>(value));
|
|
}
|
|
inline int64_t get_serialize_size(int32_t value) {
|
|
return encoded_length_var_int32(value);
|
|
}
|
|
inline int64_t get_serialize_size(uint32_t value) {
|
|
return encoded_length_var_int32(static_cast<int32_t>(value));
|
|
}
|
|
inline int64_t get_serialize_size(int16_t value) { return sizeof(value); }
|
|
inline int64_t get_serialize_size(uint16_t value) { return sizeof(value); }
|
|
inline int64_t get_serialize_size(int8_t value) { return sizeof(value); }
|
|
inline int64_t get_serialize_size(uint8_t value) { return sizeof(value); }
|
|
inline int64_t get_serialize_size(const char *value) {
|
|
return encoded_length_var_str(nullptr == value ? 0 : strlen(value));
|
|
}
|
|
inline int64_t get_serialize_size(const common::Slice &value) {
|
|
return encoded_length_var_str(value.size());
|
|
}
|
|
inline int64_t get_serialize_size(const std::string &value) {
|
|
return encoded_length_var_str(value.size());
|
|
}
|
|
|
|
template <typename T>
|
|
int64_t get_serialize_size(const T &value) {
|
|
return value.get_serialize_size();
|
|
}
|
|
|
|
template <typename E>
|
|
int get_serialize_v_size(const autovector<E> &values) {
|
|
int64_t ret = get_serialize_size(values.size());
|
|
for (auto &value : values) {
|
|
ret += get_serialize_size(value);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T>
|
|
int get_serialize_v_size(const std::vector<T> &values)
|
|
{
|
|
int64_t value_size = values.size();
|
|
int64_t ret_size = get_serialize_size(value_size);
|
|
for (auto &value : values) {
|
|
ret_size += get_serialize_size_x(value);
|
|
}
|
|
return ret_size;
|
|
}
|
|
|
|
template <typename T>
|
|
int get_serialize_v_size(const std::unordered_set<T> &values)
|
|
{
|
|
int64_t size = get_serialize_size(values.size());
|
|
for (auto &value : values) {
|
|
size += get_serialize_size(value);
|
|
}
|
|
return size;
|
|
}
|
|
|
|
template <typename T>
|
|
int get_serialize_size_x(const T &value);
|
|
|
|
template <typename T, typename E>
|
|
int get_serialize_v_size(const std::unordered_map<T,E> &values)
|
|
{
|
|
int64_t size = get_serialize_size(values.size());
|
|
for (auto &value : values) {
|
|
size += get_serialize_size_x(value.first);
|
|
size += get_serialize_size_x(value.second);
|
|
}
|
|
return size;
|
|
}
|
|
|
|
template <typename E, template <typename, typename...> class Container,
|
|
typename... Args>
|
|
int get_serialize_v_size(const Container<E, Args...> &values) {
|
|
int64_t ret = get_serialize_size(values.size());
|
|
for (auto &value : values) {
|
|
ret += get_serialize_size(value);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
// generic template (variant arguments)
|
|
template <typename T, typename... Args>
|
|
int serialize(char *buffer, const int64_t bufsiz, int64_t &pos, const T &head,
|
|
const Args &... rest) {
|
|
int ret = 0;
|
|
if (common::Status::kOk != (ret = serialize(buffer, bufsiz, pos, head))) {
|
|
} else if (common::Status::kOk !=
|
|
(ret = serialize(buffer, bufsiz, pos, rest...))) {
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T, typename... Args>
|
|
int deserialize(const char *buffer, const int64_t bufsiz, int64_t &pos, T &head,
|
|
Args &... rest) {
|
|
int ret = 0;
|
|
if (common::Status::kOk != (ret = deserialize(buffer, bufsiz, pos, head))) {
|
|
} else if (common::Status::kOk !=
|
|
(ret = deserialize(buffer, bufsiz, pos, rest...))) {
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T, typename... Args>
|
|
int64_t get_serialize_size(const T &head, const Args &... rest) {
|
|
return get_serialize_size(head) + get_serialize_size(rest...);
|
|
}
|
|
|
|
// generic template (variant arguments), for compactiple serialize and deserialize
|
|
template <bool> struct ContainerSerializeWrap;
|
|
template <>
|
|
struct ContainerSerializeWrap<true>
|
|
{
|
|
template <typename T>
|
|
int operator()(char *buf, int64_t buf_len, int64_t &pos, const T &t)
|
|
{
|
|
return util::serialize_v(buf, buf_len, pos, t);
|
|
}
|
|
};
|
|
template <>
|
|
struct ContainerSerializeWrap<false>
|
|
{
|
|
template <typename T>
|
|
int operator()(char *buf, int64_t buf_len, int64_t &pos, const T &t)
|
|
{
|
|
return util::serialize(buf, buf_len, pos, t);
|
|
}
|
|
};
|
|
|
|
template <bool> struct ContainerDeserializeWrap;
|
|
template <>
|
|
struct ContainerDeserializeWrap<true>
|
|
{
|
|
template <typename T>
|
|
int operator()(const char *buf, int64_t buf_len, int64_t &pos, T &t)
|
|
{
|
|
return util::deserialize_v(buf, buf_len, pos, t);
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct ContainerDeserializeWrap<false>
|
|
{
|
|
template <typename T>
|
|
int operator()(const char *buf, int64_t buf_len, int64_t &pos, T &t)
|
|
{
|
|
return util::deserialize(buf, buf_len, pos, t);
|
|
}
|
|
};
|
|
|
|
template <bool> struct ContainerGetSerializeSizeWrap;
|
|
template <>
|
|
struct ContainerGetSerializeSizeWrap<true>
|
|
{
|
|
template <typename T>
|
|
int operator()(const T &t)
|
|
{
|
|
return util::get_serialize_v_size(t);
|
|
}
|
|
};
|
|
template <>
|
|
struct ContainerGetSerializeSizeWrap<false>
|
|
{
|
|
template <typename T>
|
|
int operator()(const T &t)
|
|
{
|
|
return util::get_serialize_size(t);
|
|
}
|
|
};
|
|
|
|
template <bool> struct SerializeWrap;
|
|
template <>
|
|
struct SerializeWrap<true>
|
|
{
|
|
template <typename T>
|
|
int operator()(char *buf, int64_t buf_len, int64_t &pos, const T &t)
|
|
{
|
|
return t.serialize(buf, buf_len, pos);
|
|
}
|
|
};
|
|
template <>
|
|
struct SerializeWrap<false>
|
|
{
|
|
template <typename T>
|
|
int operator()(char *buf, int64_t buf_len, int64_t &pos, const T &t)
|
|
{
|
|
typedef ContainerSerializeWrap<IS_CONTAINER(T)> Wrap;
|
|
return Wrap()(buf, buf_len, pos, t);
|
|
}
|
|
};
|
|
|
|
template <bool> struct DeserializeWrap;
|
|
template <>
|
|
struct DeserializeWrap<true>
|
|
{
|
|
template <typename T>
|
|
int operator()(const char *buf, int64_t buf_len, int64_t &pos, T &t)
|
|
{
|
|
return t.deserialize(buf, buf_len, pos);
|
|
}
|
|
};
|
|
template <>
|
|
struct DeserializeWrap<false>
|
|
{
|
|
template <typename T>
|
|
int operator()(const char *buf, int64_t buf_len, int64_t &pos, T &t)
|
|
{
|
|
typedef ContainerDeserializeWrap<IS_CONTAINER(T)> Wrap;
|
|
return Wrap()(buf, buf_len, pos, t);
|
|
}
|
|
};
|
|
|
|
template <bool> struct GetSerializeSizeWrap;
|
|
template <>
|
|
struct GetSerializeSizeWrap<true>
|
|
{
|
|
template <typename T>
|
|
int64_t operator()(const T &t)
|
|
{
|
|
return t.get_serialize_size();
|
|
}
|
|
};
|
|
template <>
|
|
struct GetSerializeSizeWrap<false>
|
|
{
|
|
template <typename T>
|
|
int64_t operator()(const T &t)
|
|
{
|
|
typedef ContainerGetSerializeSizeWrap<IS_CONTAINER(T)> Wrap;
|
|
return Wrap()(t);
|
|
//return util::get_serialize_size(t);
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
int serialize_x(char *buf, const int64_t buf_len, int64_t &pos, const T &value)
|
|
{
|
|
typedef SerializeWrap<HAS_MEMBER(T, serialize)> Wrap;
|
|
return Wrap()(buf, buf_len, pos, value);
|
|
}
|
|
|
|
template <typename T, typename... Args>
|
|
int serialize_x(char *buf, const int64_t buf_len, int64_t &pos, const T &head, const Args &... rest)
|
|
{
|
|
int ret = common::Status::kOk;
|
|
typedef SerializeWrap<HAS_MEMBER(T, serialize)> Wrap;
|
|
if (common::Status::kOk != (ret = Wrap()(buf, buf_len, pos, head))) {
|
|
} else if (common::Status::kOk != (ret = serialize_x(buf, buf_len, pos, rest...))) {
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T>
|
|
int deserialize_x(const char *buf, int64_t buf_len, int64_t &pos, T &value)
|
|
{
|
|
typedef DeserializeWrap<HAS_MEMBER(T, deserialize)> Wrap;
|
|
return Wrap()(buf, buf_len, pos, value);
|
|
}
|
|
template <typename T, typename... Args>
|
|
int deserialize_x(const char *buf, int64_t buf_len, int64_t &pos, T &head, Args &... rest)
|
|
{
|
|
int ret = common::Status::kOk;
|
|
typedef DeserializeWrap<HAS_MEMBER(T, deserialize)> Wrap;
|
|
if ((pos < buf_len) && common::Status::kOk != (ret = Wrap()(buf, buf_len, pos, head))) {
|
|
} else if ((pos < buf_len) && common::Status::kOk != (ret = deserialize_x(buf, buf_len, pos, rest...))) {
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template <typename T>
|
|
int get_serialize_size_x(const T &value)
|
|
{
|
|
typedef GetSerializeSizeWrap<HAS_MEMBER(T, get_serialize_size)> Wrap;
|
|
return Wrap()(value);
|
|
}
|
|
template <typename T, typename... Args>
|
|
int get_serialize_size_x(const T &head, const Args &... rest)
|
|
{
|
|
typedef GetSerializeSizeWrap<HAS_MEMBER(T, get_serialize_size)> Wrap;
|
|
return Wrap()(head) + get_serialize_size_x(rest...);
|
|
}
|
|
} /* util */
|
|
} /* xengine*/
|
|
|
|
#endif // XENGINE_SERIALIZATION_H_
|