From 03f2ca28442f31a97321e02dac09fa7f0dd3923f Mon Sep 17 00:00:00 2001 From: hzcheng Date: Thu, 7 May 2020 05:45:05 +0000 Subject: [PATCH] add encoding functions --- src/common/inc/tdataformat.h | 2 +- src/util/inc/tcoding.h | 57 +++++++++++++--- src/util/tests/codingTests.cpp | 116 +++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 9 deletions(-) create mode 100644 src/util/tests/codingTests.cpp diff --git a/src/common/inc/tdataformat.h b/src/common/inc/tdataformat.h index ba37db519e..794d45da6f 100644 --- a/src/common/inc/tdataformat.h +++ b/src/common/inc/tdataformat.h @@ -97,7 +97,7 @@ typedef void *SDataRow; #define TD_DATA_ROW_HEAD_SIZE sizeof(int32_t) #define dataRowLen(r) (*(int32_t *)(r)) -#define dataRowTuple(r) POINTER_DRIFT(r, TD_DATA_ROW_HEAD_SIZE) +#define dataRowTuple(r) POINTER_SHIFT(r, TD_DATA_ROW_HEAD_SIZE) #define dataRowKey(r) (*(TSKEY *)(dataRowTuple(r))) #define dataRowSetLen(r, l) (dataRowLen(r) = (l)) #define dataRowCpy(dst, r) memcpy((dst), (r), dataRowLen(r)) diff --git a/src/util/inc/tcoding.h b/src/util/inc/tcoding.h index e74222cb9b..9f64f127e1 100644 --- a/src/util/inc/tcoding.h +++ b/src/util/inc/tcoding.h @@ -24,8 +24,9 @@ extern "C" { #include "tutil.h" -const int32_t TNUMBER = 1; -const uint8_t ENCODE_LIMIT = (1 << 7); +// TODO: move this to a platform file +#define ENCODE_LIMIT (((uint8_t)1) << 7) +static const int32_t TNUMBER = 1; #define IS_LITTLE_ENDIAN() (*(uint8_t *)(&TNUMBER) != 0) static FORCE_INLINE void *taosEncodeFixed16(void *buf, uint16_t value) { @@ -154,17 +155,57 @@ static FORCE_INLINE void *taosEncodeVariant64(void *buf, uint64_t value) { static FORCE_INLINE void *taosDecodeVariant16(void *buf, uint16_t *value) { int i = 0; + uint16_t tval = 0; *value = 0; - while (i < 3 && ) { - (*value) |= (((uint8_t *)buf)[i] << (7 * i)); - i++; + while (i < 3) { + tval = (uint16_t)(((uint8_t *)buf)[i]); + if (tval < ENCODE_LIMIT) { + (*value) |= (tval << (7 * i)); + return POINTER_SHIFT(buf, i + 1); + } else { + (*value) |= ((tval & (ENCODE_LIMIT - 1)) << (7 * i)); + i++; + } + } + + return NULL; // error happened +} + +static FORCE_INLINE void *taosDecodeVariant32(void *buf, uint32_t *value) { + int i = 0; + uint32_t tval = 0; + *value = 0; + while (i < 5) { + tval = (uint32_t)(((uint8_t *)buf)[i]); + if (tval < ENCODE_LIMIT) { + (*value) |= (tval << (7 * i)); + return POINTER_SHIFT(buf, i + 1); + } else { + (*value) |= ((tval & (ENCODE_LIMIT - 1)) << (7 * i)); + i++; + } } - return NULL; // error happened + return NULL; // error happened } -static FORCE_INLINE void *taosDecodeVariant32(void *buf, uint32_t *value) {} -static FORCE_INLINE void *taosDecodeVariant64(void *buf, uint64_t *value) {} +static FORCE_INLINE void *taosDecodeVariant64(void *buf, uint64_t *value) { + int i = 0; + uint64_t tval = 0; + *value = 0; + while (i < 10) { + tval = (uint64_t)(((uint8_t *)buf)[i]); + if (tval < ENCODE_LIMIT) { + (*value) |= (tval << (7 * i)); + return POINTER_SHIFT(buf, i + 1); + } else { + (*value) |= ((tval & (ENCODE_LIMIT - 1)) << (7 * i)); + i++; + } + } + + return NULL; // error happened +} #ifdef __cplusplus } diff --git a/src/util/tests/codingTests.cpp b/src/util/tests/codingTests.cpp new file mode 100644 index 0000000000..a72c7ef291 --- /dev/null +++ b/src/util/tests/codingTests.cpp @@ -0,0 +1,116 @@ +#include +#include +#include +#include + +#include "tcoding.h" + +static bool test_fixed_uint16(uint16_t value) { + char buf[20] = "\0"; + uint16_t value_check = 0; + + void *ptr1 = taosEncodeFixed16(static_cast(buf), value); + void *ptr2 = taosDecodeFixed16(static_cast(buf), &value_check); + + return ((ptr2 != NULL) && (value == value_check) && (ptr1 == ptr2)); +} + +static bool test_fixed_uint32(uint32_t value) { + char buf[20] = "\0"; + uint32_t value_check = 0; + + void *ptr1 = taosEncodeFixed32(static_cast(buf), value); + void *ptr2 = taosDecodeFixed32(static_cast(buf), &value_check); + + return ((ptr2 != NULL) && (value == value_check) && (ptr1 == ptr2)); +} + +static bool test_fixed_uint64(uint64_t value) { + char buf[20] = "\0"; + uint64_t value_check = 0; + + void *ptr1 = taosEncodeFixed64(static_cast(buf), value); + void *ptr2 = taosDecodeFixed64(static_cast(buf), &value_check); + + return ((ptr2 != NULL) && (value == value_check) && (ptr1 == ptr2)); +} + +static bool test_variant_uint16(uint16_t value) { + char buf[20] = "\0"; + uint16_t value_check = 0; + + void *ptr1 = taosEncodeVariant16(static_cast(buf), value); + void *ptr2 = taosDecodeVariant16(static_cast(buf), &value_check); + + return ((ptr2 != NULL) && (value == value_check) && (ptr1 == ptr2)); +} + +static bool test_variant_uint32(uint32_t value) { + char buf[20] = "\0"; + uint32_t value_check = 0; + + void *ptr1 = taosEncodeVariant32(static_cast(buf), value); + void *ptr2 = taosDecodeVariant32(static_cast(buf), &value_check); + + return ((ptr2 != NULL) && (value == value_check) && (ptr1 == ptr2)); +} + +static bool test_variant_uint64(uint64_t value) { + char buf[20] = "\0"; + uint64_t value_check = 0; + + void *ptr1 = taosEncodeVariant64(static_cast(buf), value); + void *ptr2 = taosDecodeVariant64(static_cast(buf), &value_check); + + return ((ptr2 != NULL) && (value == value_check) && (ptr1 == ptr2)); +} + +TEST(codingTest, fixed_encode_decode) { + srand(time(0)); + + for (uint16_t value = 0; value <= UINT16_MAX; value++) { + ASSERT_TRUE(test_fixed_uint16(value)); + if (value == UINT16_MAX) break; + } + + ASSERT_TRUE(test_fixed_uint32(0)); + ASSERT_TRUE(test_fixed_uint32(UINT32_MAX)); + + for (int i = 0; i < 1000000; i++) { + ASSERT_TRUE(test_fixed_uint32(rand())); + } + + std::mt19937_64 gen (std::random_device{}()); + + ASSERT_TRUE(test_fixed_uint64(0)); + ASSERT_TRUE(test_fixed_uint64(UINT64_MAX)); + for (int i = 0; i < 1000000; i++) { + ASSERT_TRUE(test_fixed_uint64(gen())); + } +} + +TEST(codingTest, variant_encode_decode) { + srand(time(0)); + + for (uint16_t value = 0; value <= UINT16_MAX; value++) { + ASSERT_TRUE(test_variant_uint16(value)); + if (value == UINT16_MAX) break; + } + + ASSERT_TRUE(test_variant_uint32(0)); + ASSERT_TRUE(test_variant_uint32(UINT32_MAX)); + + for (int i = 0; i < 5000000; i++) { + ASSERT_TRUE(test_variant_uint32(rand())); + } + + std::mt19937_64 gen (std::random_device{}()); + + ASSERT_TRUE(test_variant_uint64(0)); + ASSERT_TRUE(test_variant_uint64(UINT64_MAX)); + for (int i = 0; i < 5000000; i++) { + uint64_t value = gen(); + // printf("%ull\n", value); + ASSERT_TRUE(test_variant_uint64(value)); + } +} \ No newline at end of file -- GitLab