Files
obconnector-c/libmariadb/ob_serialize.c
2022-10-17 16:49:00 +08:00

510 lines
13 KiB
C

#include "ob_serialize.h"
inline int64_t encoded_length_vi64(int64_t val)
{
uint64_t __v = (uint64_t)(val);
int64_t need_bytes = 0;
if (__v <= OB_MAX_V1B) {
need_bytes = 1;
} else if (__v <= OB_MAX_V2B) {
need_bytes = 2;
} else if (__v <= OB_MAX_V3B) {
need_bytes = 3;
} else if (__v <= OB_MAX_V4B) {
need_bytes = 4;
} else if (__v <= OB_MAX_V5B) {
need_bytes = 5;
} else if (__v <= OB_MAX_V6B) {
need_bytes = 6;
} else if (__v <= OB_MAX_V7B) {
need_bytes = 7;
} else if (__v <= OB_MAX_V8B) {
need_bytes = 8;
} else if (__v <= OB_MAX_V9B) {
need_bytes = 9;
} else {
need_bytes = 10;
}
return need_bytes;
}
/**
* @brief Encode a integer (up to 64bit) in variable length encoding
*
* @param buf pointer to the destination buffer
* @param end the end pointer to the destination buffer
* @param val value to encode
*
* @return true - success, false - failed
*/
inline int encode_vi64(char *buf, const int64_t buf_len, int64_t *ppos, int64_t val)
{
int64_t pos = *ppos;
uint64_t __v = (uint64_t)(val);
int ret = ((NULL != buf) &&
((buf_len - pos) >= encoded_length_vi64(__v))) ? OB_SUCCESS : OB_SIZE_OVERFLOW;
if (OB_SUCC(ret)) {
while (__v > OB_MAX_V1B) {
*(buf + pos++) = (int8_t)((__v) | 0x80);
__v >>= 7;
}
if (__v <= OB_MAX_V1B) {
*(buf + pos++) = (int8_t)((__v) & 0x7f);
}
*ppos = pos;
}
return ret;
}
inline int decode_vi64(const char *buf, const int64_t data_len, int64_t *ppos, int64_t *val)
{
uint64_t __v = 0;
uint32_t shift = 0;
int64_t pos = *ppos;
int64_t tmp_pos = pos;
int ret = OB_SUCCESS;
while (OB_SUCC(ret) && ((*(buf + tmp_pos)) & 0x80)) {
if (data_len - tmp_pos < 1) {
ret = OB_DESERIALIZE_ERROR;
break;
}
__v |= ((uint64_t)(*(buf + tmp_pos++)) & 0x7f) << shift;
shift += 7;
}
if (OB_SUCC(ret)) {
if (data_len - tmp_pos < 1) {
ret = OB_DESERIALIZE_ERROR;
} else {
__v |= (((uint64_t)(*(buf + tmp_pos++)) & 0x7f) << shift);
*val = (int64_t)(__v);
pos = tmp_pos;
}
*ppos = pos;
}
return ret;
}
inline int64_t encoded_length_vi32(int32_t val)
{
uint32_t __v = (uint64_t)(val);
int64_t need_bytes = 0;
if (__v <= OB_MAX_V1B) {
need_bytes = 1;
} else if (__v <= OB_MAX_V2B) {
need_bytes = 2;
} else if (__v <= OB_MAX_V3B) {
need_bytes = 3;
} else if (__v <= OB_MAX_V4B) {
need_bytes = 4;
} else {
need_bytes = 5;
}
return need_bytes;
}
/**
* @brief Encode a integer (up to 32bit) in variable length encoding
*
* @param buf pointer to the destination buffer
* @param end the end pointer to the destination buffer
* @param val value to encode
*
* @return true - success, false - failed
*/
inline int encode_vi32(char *buf, const int64_t buf_len, int64_t *ppos, int32_t val)
{
int64_t pos = *ppos;
uint32_t __v = (uint32_t)(val);
int ret = ((NULL != buf) &&
((buf_len - pos) >= encoded_length_vi32(val))) ? OB_SUCCESS : OB_SIZE_OVERFLOW;
if (OB_SUCC(ret)) {
while (__v > OB_MAX_V1B) {
*(buf + pos++) = (int8_t)((__v) | 0x80);
__v >>= 7;
}
if (__v <= OB_MAX_V1B) {
*(buf + pos++) = (int8_t)((__v) & 0x7f);
}
*ppos = pos;
}
return ret;
}
inline int decode_vi32(const char *buf, const int64_t data_len, int64_t *ppos, int32_t *val)
{
uint32_t __v = 0;
uint32_t shift = 0;
int ret = OB_SUCCESS;
int64_t pos = *ppos;
int64_t tmp_pos = pos;
while (OB_SUCC(ret) && ((*(buf + tmp_pos)) & 0x80)) {
if (data_len - tmp_pos < 1) {
ret = OB_DESERIALIZE_ERROR;
break;
}
__v |= ((uint32_t)(*(buf + tmp_pos++)) & 0x7f) << shift;
shift += 7;
}
if (OB_SUCC(ret)) {
if (data_len - tmp_pos < 1) {
ret = OB_DESERIALIZE_ERROR;
} else {
__v |= ((uint32_t)(*(buf + tmp_pos++)) & 0x7f) << shift;
*val = (int32_t)(__v);
pos = tmp_pos;
}
*ppos = pos;
}
return ret;
}
inline int64_t encoded_length_i8(int8_t val)
{
return (int64_t)(sizeof(val));
}
inline int encode_i8(char *buf, const int64_t buf_len, int64_t *ppos, int8_t val)
{
int64_t pos = *ppos;
int ret = ((NULL != buf) &&
((buf_len - pos) >= (int64_t)(sizeof(val)))) ? OB_SUCCESS : OB_SIZE_OVERFLOW;
if (OB_SUCC(ret)) {
*(buf + pos++) = val;
*ppos = pos;
}
return ret;
}
inline int decode_i8(const char *buf, const int64_t data_len, int64_t *ppos, int8_t *val)
{
int pos = *ppos;
int ret = (NULL != buf && data_len - pos >= 1) ? OB_SUCCESS : OB_DESERIALIZE_ERROR;
if (OB_SUCC(ret)) {
*val = *(buf + pos++);
*ppos = pos;
}
return ret;
}
inline int encode_i64(char *buf, const int64_t buf_len, int64_t *ppos, int64_t val)
{
int pos = *ppos;
int ret = ((NULL != buf) &&
((buf_len - pos) >= (int64_t)(sizeof(val)))) ? OB_SUCCESS : OB_ERROR;
if (OB_SUCC(ret)) {
*(buf + pos++) = (char)(((val) >> 56) & 0xff);
*(buf + pos++) = (char)(((val) >> 48) & 0xff);
*(buf + pos++) = (char)(((val) >> 40) & 0xff);
*(buf + pos++) = (char)(((val) >> 32) & 0xff);
*(buf + pos++) = (char)(((val) >> 24) & 0xff);
*(buf + pos++) = (char)(((val) >> 16) & 0xff);
*(buf + pos++) = (char)(((val) >> 8) & 0xff);
*(buf + pos++) = (char)((val) & 0xff);
*ppos = pos;
}
return ret;
}
inline int decode_i64(const char *buf, const int64_t data_len, int64_t *ppos, int64_t *val)
{
int pos = *ppos;
int ret = (NULL != buf && data_len - pos >= 8) ? OB_SUCCESS : OB_ERROR;
if (OB_SUCC(ret)) {
*val = (((int64_t)((*(buf + pos++))) & 0xff)) << 56;
*val |= (((int64_t)((*(buf + pos++))) & 0xff)) << 48;
*val |= (((int64_t)((*(buf + pos++))) & 0xff)) << 40;
*val |= (((int64_t)((*(buf + pos++))) & 0xff)) << 32;
*val |= (((int64_t)((*(buf + pos++))) & 0xff)) << 24;
*val |= (((int64_t)((*(buf + pos++))) & 0xff)) << 16;
*val |= (((int64_t)((*(buf + pos++))) & 0xff)) << 8;
*val |= (((int64_t)((*(buf + pos++))) & 0xff));
}
return ret;
}
inline int encode_int64_t(char *buf, const int64_t buf_len, int64_t *pos, int64_t val)
{
return encode_vi64(buf, buf_len, pos, val);
}
inline int encode_uint64_t(char *buf, const int64_t buf_len, int64_t *pos, uint64_t val)
{
return encode_vi64(buf, buf_len, pos, (int64_t)(val));
}
inline int encode_int32_t(char *buf, const int64_t buf_len, int64_t *pos, int32_t val)
{
return encode_vi32(buf, buf_len, pos, val);
}
inline int encode_uint32_t(char *buf, const int64_t buf_len, int64_t *pos, uint32_t val)
{
return encode_vi32(buf, buf_len, pos, (int32_t)(val));
}
inline int encode_int16_t(char *buf, const int64_t buf_len, int64_t *pos, int16_t val)
{
return encode_vi32(buf, buf_len, pos, (int32_t)(val));
}
inline int encode_uint16_t(char *buf, const int64_t buf_len, int64_t *pos, uint16_t val)
{
return encode_vi32(buf, buf_len, pos, (int32_t)(val));
}
inline int encode_int8_t(char *buf, const int64_t buf_len, int64_t *pos, int8_t val)
{
return encode_i8(buf, buf_len, pos, val);
}
inline int encode_uint8_t(char *buf, const int64_t buf_len, int64_t *pos, uint8_t val)
{
return encode_i8(buf, buf_len, pos, (int8_t)(val));
}
inline int decode_int8_t(const char *buf, const int64_t data_len, int64_t *pos, int8_t *val)
{
*val = 0;
return decode_i8(buf, data_len, pos, val);
}
inline int decode_uint8_t(const char *buf, const int64_t data_len, int64_t *pos, uint8_t *val)
{
*val = 0;
return decode_i8(buf, data_len, pos, (int8_t*)val);
}
inline int decode_int16_t(const char *buf, const int64_t data_len, int64_t *pos, int16_t *val)
{
int32_t v = 0;
int ret = decode_vi32(buf, data_len, pos, &v);
*val = (int16_t)(v);
return ret;
}
inline int decode_uint16_t(const char *buf, const int64_t data_len, int64_t *pos, uint16_t *val)
{
int32_t v = 0;
int ret = decode_vi32(buf, data_len, pos, &v);
*val = (uint16_t)(v);
return ret;
}
inline int decode_int32_t(const char *buf, const int64_t data_len, int64_t *pos, int32_t *val)
{
*val = 0;
return decode_vi32(buf, data_len, pos, val);
}
inline int decode_uint32_t(const char *buf, const int64_t data_len, int64_t *pos, uint32_t *val)
{
*val = 0;
return decode_vi32(buf, data_len, pos, (int32_t *)val);
}
inline int decode_int64_t(const char *buf, const int64_t data_len, int64_t *pos, int64_t *val)
{
*val = 0;
return decode_vi64(buf, data_len, pos, val);
}
inline int decode_uint64_t(const char *buf, const int64_t data_len, int64_t *pos, uint64_t *val)
{
*val = 0;
return decode_vi64(buf, data_len, pos, (int64_t *)val);
}
inline int64_t encoded_length_int64_t(int64_t val)
{
return encoded_length_vi64(val);
}
inline int64_t encoded_length_uint64_t(uint64_t val)
{
return encoded_length_vi64((int64_t)val);
}
inline int64_t encoded_length_int32_t(int32_t val)
{
return encoded_length_vi32(val);
}
inline int64_t encoded_length_uint32_t(uint32_t val)
{
return encoded_length_vi32((int32_t)val);
}
inline int64_t encoded_length_int16_t(int16_t val)
{
return encoded_length_vi32(val);
}
inline int64_t encoded_length_uint16_t(uint16_t val)
{
return encoded_length_vi32((int32_t)val);
}
inline int64_t encoded_length_int8_t(int8_t unused)
{
UNUSED(unused);
return 1;
}
inline int64_t encoded_length_uint8_t(uint8_t unused)
{
UNUSED(unused);
return 1;
}
inline int64_t encoded_length_float(float val)
{
int32_t tmp = 0;
memcpy(&tmp, &val, sizeof(tmp));
return encoded_length_vi32(tmp);
}
inline int encode_float(char *buf, const int64_t buf_len, int64_t *pos, float val)
{
int32_t tmp = 0;
memcpy(&tmp, &val, sizeof(tmp));
return encode_vi32(buf, buf_len, pos, tmp);
}
inline int decode_float(const char *buf, const int64_t data_len, int64_t *pos, float *val)
{
int32_t tmp = 0;
int ret = OB_SUCCESS;
if ((ret = decode_vi32(buf, data_len, pos, &tmp)) == 0) {
memcpy(val, &tmp, sizeof(*val));
}
return ret;
}
inline int64_t encoded_length_double(double val)
{
int64_t tmp = 0;
memcpy(&tmp, &val, sizeof(tmp));
return encoded_length_vi64(tmp);
}
inline int encode_double(char *buf, const int64_t buf_len, int64_t *pos, double val)
{
int64_t tmp = 0;
memcpy(&tmp, &val, sizeof(tmp));
return encode_vi64(buf, buf_len, pos, tmp);
}
inline int decode_double(const char *buf, const int64_t data_len, int64_t *pos, double *val)
{
int64_t tmp = 0;
int ret = OB_SUCCESS;
if ((ret = decode_vi64(buf, data_len, pos, &tmp)) == 0) {
memcpy(val, &tmp, sizeof(*val));
}
return ret;
}
/**
* @brief Computes the encoded length of vstr(int64,data,null)
*
* @param len string length
*
* @return the encoded length of str
*/
inline int64_t encoded_length_vstr_with_len(int64_t len)
{
return encoded_length_vi64(len) + len + 1;
}
inline int64_t encoded_length_vstr(const char *str)
{
return encoded_length_vstr_with_len(str ? (int64_t)(strlen(str) + 1) : 0);
}
/**
* @brief get the decoded length of data len of vstr
* won't change the pos
* @return the length of data
*/
inline int64_t decoded_length_vstr(const char *buf, const int64_t data_len, int64_t pos)
{
int64_t len = -1;
int64_t tmp_pos = pos;
if (NULL == buf || data_len < 0 || pos < 0) {
len = -1;
} else if (decode_vi64(buf, data_len, &tmp_pos, &len) != 0) {
len = -1;
}
return len;
}
/**
* @brief Encode a buf as vstr(int64,data,null)
*
* @param buf 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_vstr_with_len(char *buf, const int64_t buf_len, int64_t *ppos, const void *vbuf,
int64_t len)
{
int64_t pos = *ppos;
int ret = ((NULL != buf) && (len >= 0)
&& ((buf_len - pos) >= (int32_t)(encoded_length_vstr_with_len(len))))
? OB_SUCCESS : OB_SIZE_OVERFLOW;
if (OB_SUCC(ret)) {
/**
* even through it's a null string, we can serialize it with
* lenght 0, and following a '\0'
*/
ret = encode_vi64(buf, buf_len, &pos, len);
if (OB_SUCCESS == ret && len > 0 && NULL != vbuf) {
memcpy(buf + pos, vbuf, len);
pos += len;
}
*(buf + pos++) = 0;
*ppos = pos;
}
return ret;
}
inline int encode_vstr(char *buf, const int64_t buf_len, int64_t *ppos, const char *s)
{
return encode_vstr_with_len(buf, buf_len, ppos, s, s ? strlen(s) + 1 : 0);
}
inline const char *decode_vstr_nocopy(const char *buf, const int64_t data_len, int64_t *ppos, int64_t *lenp)
{
int64_t pos = *ppos;
const char *str = 0;
int64_t tmp_len = 0;
int64_t tmp_pos = pos;
if ((NULL == buf) || (data_len < 0) || (pos < 0) || (NULL == lenp)) {
//just _return_;
} else if (decode_vi64(buf, data_len, &tmp_pos, &tmp_len) != OB_SUCCESS) {
*lenp = -1;
} else if (tmp_len >= 0) {
if (data_len - tmp_pos >= tmp_len) {
str = buf + tmp_pos;
*lenp = tmp_len++;
tmp_pos += tmp_len;
pos = tmp_pos;
} else {
*lenp = -1;
}
}
*ppos = pos;
return str;
}
inline const char *decode_vstr(const char *buf, const int64_t data_len, int64_t *ppos,
char *dest, int64_t buf_len, int64_t *lenp)
{
int64_t pos = *ppos;
const char *str = 0;
int64_t tmp_len = 0;
int64_t tmp_pos = pos;
if ((NULL == buf) || (data_len < 0) || (pos < 0) || (0 == dest) || buf_len < 0 || (NULL == lenp)) {
//just _return_;
} else if (decode_vi64(buf, data_len, &tmp_pos, &tmp_len) != 0 || tmp_len > buf_len) {
*lenp = -1;
} else if (tmp_len >= 0) {
if (data_len - tmp_pos >= tmp_len) {
str = buf + tmp_pos;
*lenp = tmp_len++;
memcpy(dest, str, *lenp);
tmp_pos += tmp_len;
pos = tmp_pos;
} else {
*lenp = -1;
}
}
*ppos = pos;
return str;
}