/* * Copyright (c) 2019 TAOS Data, Inc. * * This program is free software: you can use, redistribute, and/or modify * it under the terms of the GNU Affero General Public License, version 3 * or later ("AGPL"), as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ #ifndef _TD_UTIL_ENCODE_H_ #define _TD_UTIL_ENCODE_H_ #include "tcoding.h" #include "tfreelist.h" #ifdef __cplusplus extern "C" { #endif #define tPut(TYPE, BUF, VAL) ((TYPE*)(BUF))[0] = (VAL) #define tGet(TYPE, BUF, VAL) (VAL) = ((TYPE*)(BUF))[0] #define tRPut16(PDEST, PSRC) \ ((uint8_t*)(PDEST))[0] = ((uint8_t*)(PSRC))[1]; \ ((uint8_t*)(PDEST))[1] = ((uint8_t*)(PSRC))[0]; #define tRPut32(PDEST, PSRC) \ ((uint8_t*)(PDEST))[0] = ((uint8_t*)(PSRC))[3]; \ ((uint8_t*)(PDEST))[1] = ((uint8_t*)(PSRC))[2]; \ ((uint8_t*)(PDEST))[2] = ((uint8_t*)(PSRC))[1]; \ ((uint8_t*)(PDEST))[3] = ((uint8_t*)(PSRC))[0]; #define tRPut64(PDEST, PSRC) \ ((uint8_t*)(PDEST))[0] = ((uint8_t*)(PSRC))[7]; \ ((uint8_t*)(PDEST))[1] = ((uint8_t*)(PSRC))[6]; \ ((uint8_t*)(PDEST))[2] = ((uint8_t*)(PSRC))[5]; \ ((uint8_t*)(PDEST))[3] = ((uint8_t*)(PSRC))[4]; \ ((uint8_t*)(PDEST))[4] = ((uint8_t*)(PSRC))[3]; \ ((uint8_t*)(PDEST))[5] = ((uint8_t*)(PSRC))[2]; \ ((uint8_t*)(PDEST))[6] = ((uint8_t*)(PSRC))[1]; \ ((uint8_t*)(PDEST))[7] = ((uint8_t*)(PSRC))[0]; #define tRGet16 tRPut16 #define tRGet32 tRPut32 #define tRGet64 tRPut64 typedef enum { TD_ENCODER, TD_DECODER } td_coder_t; #define CODER_NODE_FIELDS \ uint8_t* data; \ int32_t size; \ int32_t pos; struct SCoderNode { TD_SLIST_NODE(SCoderNode); CODER_NODE_FIELDS }; typedef struct { td_coder_t type; td_endian_t endian; SFreeList fl; CODER_NODE_FIELDS TD_SLIST(SCoderNode) stack; } SCoder; #define TD_CODER_POS(CODER) ((CODER)->pos) #define TD_CODER_CURRENT(CODER) ((CODER)->data + (CODER)->pos) #define TD_CODER_MOVE_POS(CODER, MOVE) ((CODER)->pos += (MOVE)) #define TD_CODER_CHECK_CAPACITY_FAILED(CODER, EXPSIZE) (((CODER)->size - (CODER)->pos) < (EXPSIZE)) #define TCODER_MALLOC(PTR, TYPE, SIZE, CODER) TFL_MALLOC(PTR, TYPE, SIZE, &((CODER)->fl)) void tCoderInit(SCoder* pCoder, td_endian_t endian, uint8_t* data, int32_t size, td_coder_t type); void tCoderClear(SCoder* pCoder); /* ------------------------ ENCODE ------------------------ */ int32_t tStartEncode(SCoder* pEncoder); void tEndEncode(SCoder* pEncoder); static int32_t tEncodeU8(SCoder* pEncoder, uint8_t val); static int32_t tEncodeI8(SCoder* pEncoder, int8_t val); static int32_t tEncodeU16(SCoder* pEncoder, uint16_t val); static int32_t tEncodeI16(SCoder* pEncoder, int16_t val); static int32_t tEncodeU32(SCoder* pEncoder, uint32_t val); static int32_t tEncodeI32(SCoder* pEncoder, int32_t val); static int32_t tEncodeU64(SCoder* pEncoder, uint64_t val); static int32_t tEncodeI64(SCoder* pEncoder, int64_t val); static int32_t tEncodeU16v(SCoder* pEncoder, uint16_t val); static int32_t tEncodeI16v(SCoder* pEncoder, int16_t val); static int32_t tEncodeU32v(SCoder* pEncoder, uint32_t val); static int32_t tEncodeI32v(SCoder* pEncoder, int32_t val); static int32_t tEncodeU64v(SCoder* pEncoder, uint64_t val); static int32_t tEncodeI64v(SCoder* pEncoder, int64_t val); static int32_t tEncodeFloat(SCoder* pEncoder, float val); static int32_t tEncodeDouble(SCoder* pEncoder, double val); static int32_t tEncodeBinary(SCoder* pEncoder, const void* val, uint64_t len); static int32_t tEncodeCStrWithLen(SCoder* pEncoder, const char* val, uint64_t len); static int32_t tEncodeCStr(SCoder* pEncoder, const char* val); /* ------------------------ DECODE ------------------------ */ int32_t tStartDecode(SCoder* pDecoder); void tEndDecode(SCoder* pDecoder); static bool tDecodeIsEnd(SCoder* pCoder); static int32_t tDecodeU8(SCoder* pDecoder, uint8_t* val); static int32_t tDecodeI8(SCoder* pDecoder, int8_t* val); static int32_t tDecodeU16(SCoder* pDecoder, uint16_t* val); static int32_t tDecodeI16(SCoder* pDecoder, int16_t* val); static int32_t tDecodeU32(SCoder* pDecoder, uint32_t* val); static int32_t tDecodeI32(SCoder* pDecoder, int32_t* val); static int32_t tDecodeU64(SCoder* pDecoder, uint64_t* val); static int32_t tDecodeI64(SCoder* pDecoder, int64_t* val); static int32_t tDecodeU16v(SCoder* pDecoder, uint16_t* val); static int32_t tDecodeI16v(SCoder* pDecoder, int16_t* val); static int32_t tDecodeU32v(SCoder* pDecoder, uint32_t* val); static int32_t tDecodeI32v(SCoder* pDecoder, int32_t* val); static int32_t tDecodeU64v(SCoder* pDecoder, uint64_t* val); static int32_t tDecodeI64v(SCoder* pDecoder, int64_t* val); static int32_t tDecodeFloat(SCoder* pDecoder, float* val); static int32_t tDecodeDouble(SCoder* pDecoder, double* val); static int32_t tDecodeBinary(SCoder* pDecoder, const void** val, uint64_t* len); static int32_t tDecodeCStrAndLen(SCoder* pDecoder, const char** val, uint64_t* len); static int32_t tDecodeCStr(SCoder* pDecoder, const char** val); static int32_t tDecodeCStrTo(SCoder* pDecoder, char* val); /* ------------------------ IMPL ------------------------ */ #define TD_ENCODE_MACRO(CODER, VAL, TYPE, BITS) \ if ((CODER)->data) { \ if (TD_CODER_CHECK_CAPACITY_FAILED(CODER, sizeof(VAL))) return -1; \ if (TD_RT_ENDIAN() == (CODER)->endian) { \ tPut(TYPE, TD_CODER_CURRENT(CODER), (VAL)); \ } else { \ tRPut##BITS(TD_CODER_CURRENT(CODER), &(VAL)); \ } \ } \ TD_CODER_MOVE_POS(CODER, sizeof(VAL)); \ return 0; #define TD_ENCODE_VARIANT_MACRO(CODER, VAL) \ while ((VAL) >= ENCODE_LIMIT) { \ if ((CODER)->data) { \ if (TD_CODER_CHECK_CAPACITY_FAILED(CODER, 1)) return -1; \ TD_CODER_CURRENT(CODER)[0] = ((VAL) | ENCODE_LIMIT) & 0xff; \ } \ \ (VAL) >>= 7; \ TD_CODER_MOVE_POS(CODER, 1); \ } \ \ if ((CODER)->data) { \ if (TD_CODER_CHECK_CAPACITY_FAILED(CODER, 1)) return -1; \ TD_CODER_CURRENT(CODER)[0] = (uint8_t)(VAL); \ } \ TD_CODER_MOVE_POS(CODER, 1); \ return 0; #define TD_DECODE_MACRO(CODER, PVAL, TYPE, BITS) \ if (TD_CODER_CHECK_CAPACITY_FAILED(CODER, sizeof(*(PVAL)))) return -1; \ if (TD_RT_ENDIAN() == (CODER)->endian) { \ tGet(TYPE, TD_CODER_CURRENT(CODER), *(PVAL)); \ } else { \ tRGet##BITS(PVAL, TD_CODER_CURRENT(CODER)); \ } \ \ TD_CODER_MOVE_POS(CODER, sizeof(*(PVAL))); \ return 0; #define TD_DECODE_VARIANT_MACRO(CODER, PVAL, TYPE) \ int32_t i = 0; \ *(PVAL) = 0; \ for (;;) { \ if (TD_CODER_CHECK_CAPACITY_FAILED(CODER, 1)) return -1; \ TYPE tval = TD_CODER_CURRENT(CODER)[0]; \ if (tval < ENCODE_LIMIT) { \ *(PVAL) |= (tval << (7 * i)); \ TD_CODER_MOVE_POS(pDecoder, 1); \ break; \ } else { \ *(PVAL) |= (((tval) & (ENCODE_LIMIT - 1)) << (7 * i)); \ i++; \ TD_CODER_MOVE_POS(pDecoder, 1); \ } \ } \ \ return 0; // 8 static FORCE_INLINE int32_t tEncodeU8(SCoder* pEncoder, uint8_t val) { if (pEncoder->data) { if (TD_CODER_CHECK_CAPACITY_FAILED(pEncoder, sizeof(val))) return -1; tPut(uint8_t, TD_CODER_CURRENT(pEncoder), val); } TD_CODER_MOVE_POS(pEncoder, sizeof(val)); return 0; } static FORCE_INLINE int32_t tEncodeI8(SCoder* pEncoder, int8_t val) { if (pEncoder->data) { if (TD_CODER_CHECK_CAPACITY_FAILED(pEncoder, sizeof(val))) return -1; tPut(int8_t, TD_CODER_CURRENT(pEncoder), val); } TD_CODER_MOVE_POS(pEncoder, sizeof(val)); return 0; } // 16 static FORCE_INLINE int32_t tEncodeU16(SCoder* pEncoder, uint16_t val) { TD_ENCODE_MACRO(pEncoder, val, uint16_t, 16); } static FORCE_INLINE int32_t tEncodeI16(SCoder* pEncoder, int16_t val) { TD_ENCODE_MACRO(pEncoder, val, int16_t, 16); } // 32 static FORCE_INLINE int32_t tEncodeU32(SCoder* pEncoder, uint32_t val) { TD_ENCODE_MACRO(pEncoder, val, uint32_t, 32); } static FORCE_INLINE int32_t tEncodeI32(SCoder* pEncoder, int32_t val) { TD_ENCODE_MACRO(pEncoder, val, int32_t, 32); } // 64 static FORCE_INLINE int32_t tEncodeU64(SCoder* pEncoder, uint64_t val) { TD_ENCODE_MACRO(pEncoder, val, uint64_t, 64); } static FORCE_INLINE int32_t tEncodeI64(SCoder* pEncoder, int64_t val) { TD_ENCODE_MACRO(pEncoder, val, int64_t, 64); } // 16v static FORCE_INLINE int32_t tEncodeU16v(SCoder* pEncoder, uint16_t val) { TD_ENCODE_VARIANT_MACRO(pEncoder, val); } static FORCE_INLINE int32_t tEncodeI16v(SCoder* pEncoder, int16_t val) { return tEncodeU16v(pEncoder, ZIGZAGE(int16_t, val)); } // 32v static FORCE_INLINE int32_t tEncodeU32v(SCoder* pEncoder, uint32_t val) { TD_ENCODE_VARIANT_MACRO(pEncoder, val); } static FORCE_INLINE int32_t tEncodeI32v(SCoder* pEncoder, int32_t val) { return tEncodeU32v(pEncoder, ZIGZAGE(int32_t, val)); } // 64v static FORCE_INLINE int32_t tEncodeU64v(SCoder* pEncoder, uint64_t val) { TD_ENCODE_VARIANT_MACRO(pEncoder, val); } static FORCE_INLINE int32_t tEncodeI64v(SCoder* pEncoder, int64_t val) { return tEncodeU64v(pEncoder, ZIGZAGE(int64_t, val)); } static FORCE_INLINE int32_t tEncodeFloat(SCoder* pEncoder, float val) { union { uint32_t ui; float f; } v = {.f = val}; return tEncodeU32(pEncoder, v.ui); } static FORCE_INLINE int32_t tEncodeDouble(SCoder* pEncoder, double val) { union { uint64_t ui; double d; } v = {.d = val}; return tEncodeU64(pEncoder, v.ui); } static FORCE_INLINE int32_t tEncodeBinary(SCoder* pEncoder, const void* val, uint64_t len) { if (tEncodeU64v(pEncoder, len) < 0) return -1; if (pEncoder->data) { if (TD_CODER_CHECK_CAPACITY_FAILED(pEncoder, len)) return -1; memcpy(TD_CODER_CURRENT(pEncoder), val, len); } TD_CODER_MOVE_POS(pEncoder, len); return 0; } static FORCE_INLINE int32_t tEncodeCStrWithLen(SCoder* pEncoder, const char* val, uint64_t len) { return tEncodeBinary(pEncoder, (void*)val, len + 1); } static FORCE_INLINE int32_t tEncodeCStr(SCoder* pEncoder, const char* val) { return tEncodeCStrWithLen(pEncoder, val, (uint64_t)strlen(val)); } /* ------------------------ FOR DECODER ------------------------ */ // 8 static FORCE_INLINE int32_t tDecodeU8(SCoder* pDecoder, uint8_t* val) { if (TD_CODER_CHECK_CAPACITY_FAILED(pDecoder, sizeof(*val))) return -1; tGet(uint8_t, TD_CODER_CURRENT(pDecoder), *val); TD_CODER_MOVE_POS(pDecoder, sizeof(*val)); return 0; } static FORCE_INLINE int32_t tDecodeI8(SCoder* pDecoder, int8_t* val) { if (TD_CODER_CHECK_CAPACITY_FAILED(pDecoder, sizeof(*val))) return -1; tGet(int8_t, TD_CODER_CURRENT(pDecoder), *val); TD_CODER_MOVE_POS(pDecoder, sizeof(*val)); return 0; } // 16 static FORCE_INLINE int32_t tDecodeU16(SCoder* pDecoder, uint16_t* val) { TD_DECODE_MACRO(pDecoder, val, uint16_t, 16); } static FORCE_INLINE int32_t tDecodeI16(SCoder* pDecoder, int16_t* val) { TD_DECODE_MACRO(pDecoder, val, int16_t, 16); } // 32 static FORCE_INLINE int32_t tDecodeU32(SCoder* pDecoder, uint32_t* val) { TD_DECODE_MACRO(pDecoder, val, uint32_t, 32); } static FORCE_INLINE int32_t tDecodeI32(SCoder* pDecoder, int32_t* val) { TD_DECODE_MACRO(pDecoder, val, int32_t, 32); } // 64 static FORCE_INLINE int32_t tDecodeU64(SCoder* pDecoder, uint64_t* val) { TD_DECODE_MACRO(pDecoder, val, uint64_t, 64); } static FORCE_INLINE int32_t tDecodeI64(SCoder* pDecoder, int64_t* val) { TD_DECODE_MACRO(pDecoder, val, int64_t, 64); } // 16v static FORCE_INLINE int32_t tDecodeU16v(SCoder* pDecoder, uint16_t* val) { TD_DECODE_VARIANT_MACRO(pDecoder, val, uint16_t); } static FORCE_INLINE int32_t tDecodeI16v(SCoder* pDecoder, int16_t* val) { uint16_t tval; if (tDecodeU16v(pDecoder, &tval) < 0) { return -1; } *val = ZIGZAGD(int16_t, tval); return 0; } // 32v static FORCE_INLINE int32_t tDecodeU32v(SCoder* pDecoder, uint32_t* val) { TD_DECODE_VARIANT_MACRO(pDecoder, val, uint32_t); } static FORCE_INLINE int32_t tDecodeI32v(SCoder* pDecoder, int32_t* val) { uint32_t tval; if (tDecodeU32v(pDecoder, &tval) < 0) { return -1; } *val = ZIGZAGD(int32_t, tval); return 0; } // 64v static FORCE_INLINE int32_t tDecodeU64v(SCoder* pDecoder, uint64_t* val) { TD_DECODE_VARIANT_MACRO(pDecoder, val, uint64_t); } static FORCE_INLINE int32_t tDecodeI64v(SCoder* pDecoder, int64_t* val) { uint64_t tval; if (tDecodeU64v(pDecoder, &tval) < 0) { return -1; } *val = ZIGZAGD(int64_t, tval); return 0; } static FORCE_INLINE int32_t tDecodeFloat(SCoder* pDecoder, float* val) { union { uint32_t ui; float f; } v; if (tDecodeU32(pDecoder, &(v.ui)) < 0) { return -1; } *val = v.f; return 0; } static FORCE_INLINE int32_t tDecodeDouble(SCoder* pDecoder, double* val) { union { uint64_t ui; double d; } v; if (tDecodeU64(pDecoder, &(v.ui)) < 0) { return -1; } *val = v.d; return 0; } static FORCE_INLINE int32_t tDecodeBinary(SCoder* pDecoder, const void** val, uint64_t* len) { if (tDecodeU64v(pDecoder, len) < 0) return -1; if (TD_CODER_CHECK_CAPACITY_FAILED(pDecoder, *len)) return -1; *val = (void*)TD_CODER_CURRENT(pDecoder); TD_CODER_MOVE_POS(pDecoder, *len); return 0; } static FORCE_INLINE int32_t tDecodeCStrAndLen(SCoder* pDecoder, const char** val, uint64_t* len) { if (tDecodeBinary(pDecoder, (const void**)val, len) < 0) return -1; (*len) -= 1; return 0; } static FORCE_INLINE int32_t tDecodeCStr(SCoder* pDecoder, const char** val) { uint64_t len; return tDecodeCStrAndLen(pDecoder, val, &len); } static int32_t tDecodeCStrTo(SCoder* pDecoder, char* val) { const char* pStr; uint64_t len; if (tDecodeCStrAndLen(pDecoder, &pStr, &len) < 0) return -1; memcpy(val, pStr, len + 1); return 0; } static FORCE_INLINE int32_t tDecodeBinaryAlloc(SCoder* pDecoder, void** val, uint64_t* len) { if (tDecodeU64v(pDecoder, len) < 0) return -1; if (TD_CODER_CHECK_CAPACITY_FAILED(pDecoder, *len)) return -1; *val = taosMemoryMalloc(*len); if (*val == NULL) return -1; memcpy(*val, TD_CODER_CURRENT(pDecoder), *len); TD_CODER_MOVE_POS(pDecoder, *len); return 0; } static FORCE_INLINE int32_t tDecodeCStrAndLenAlloc(SCoder* pDecoder, char** val, uint64_t* len) { if (tDecodeBinaryAlloc(pDecoder, (void**)val, len) < 0) return -1; (*len) -= 1; return 0; } static FORCE_INLINE int32_t tDecodeCStrAlloc(SCoder* pDecoder, char** val) { uint64_t len; return tDecodeCStrAndLenAlloc(pDecoder, val, &len); } static FORCE_INLINE bool tDecodeIsEnd(SCoder* pCoder) { return (pCoder->size == pCoder->pos); } #ifdef __cplusplus } #endif #endif /*_TD_UTIL_ENCODE_H_*/