From 2d629511f569e7dfb52071db161d68d0c09f0094 Mon Sep 17 00:00:00 2001 From: WindYu <787738581@qq.com> Date: Wed, 21 Jul 2021 16:44:23 -0400 Subject: [PATCH] json: add the spdk_json_write_uint128 function Add the paired spdk_json_write_named_uint128 function Change-Id: I222f0c5076efe150ab2861c0d915d18476815e37 Signed-off-by: GangCao Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8797 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Tomasz Zawadzki Community-CI: Mellanox Build Bot --- CHANGELOG.md | 5 + include/spdk/json.h | 3 + lib/json/Makefile | 2 +- lib/json/json_write.c | 48 ++++++ lib/json/spdk_json.map | 2 + .../lib/json/json_write.c/json_write_ut.c | 144 ++++++++++++++++++ 6 files changed, 203 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbd66bcb6..97231eae9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## v21.07: (Upcoming Release) +### json + +Added API `spdk_json_write_named_uint128` and `spdk_json_write_uint128` to perform +the uint128 related data. + ### accel_fw Added API `spdk_accel_submit_copy_crc32c` to perform a CRC32C while copying data. diff --git a/include/spdk/json.h b/include/spdk/json.h index 59b5a2fb5..516628b6b 100644 --- a/include/spdk/json.h +++ b/include/spdk/json.h @@ -208,6 +208,7 @@ int spdk_json_write_int32(struct spdk_json_write_ctx *w, int32_t val); int spdk_json_write_uint32(struct spdk_json_write_ctx *w, uint32_t val); int spdk_json_write_int64(struct spdk_json_write_ctx *w, int64_t val); int spdk_json_write_uint64(struct spdk_json_write_ctx *w, uint64_t val); +int spdk_json_write_uint128(struct spdk_json_write_ctx *w, uint64_t low_val, uint64_t high_val); int spdk_json_write_string(struct spdk_json_write_ctx *w, const char *val); int spdk_json_write_string_raw(struct spdk_json_write_ctx *w, const char *val, size_t len); @@ -257,6 +258,8 @@ int spdk_json_write_named_bool(struct spdk_json_write_ctx *w, const char *name, int spdk_json_write_named_int32(struct spdk_json_write_ctx *w, const char *name, int32_t val); int spdk_json_write_named_uint32(struct spdk_json_write_ctx *w, const char *name, uint32_t val); int spdk_json_write_named_uint64(struct spdk_json_write_ctx *w, const char *name, uint64_t val); +int spdk_json_write_named_uint128(struct spdk_json_write_ctx *w, const char *name, + uint64_t low_val, uint64_t high_val); int spdk_json_write_named_int64(struct spdk_json_write_ctx *w, const char *name, int64_t val); int spdk_json_write_named_string(struct spdk_json_write_ctx *w, const char *name, const char *val); int spdk_json_write_named_string_fmt(struct spdk_json_write_ctx *w, const char *name, diff --git a/lib/json/Makefile b/lib/json/Makefile index 80b31981c..801e8d5d9 100644 --- a/lib/json/Makefile +++ b/lib/json/Makefile @@ -35,7 +35,7 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..) include $(SPDK_ROOT_DIR)/mk/spdk.common.mk SO_VER := 3 -SO_MINOR := 0 +SO_MINOR := 1 C_SRCS = json_parse.c json_util.c json_write.c LIBNAME = json diff --git a/lib/json/json_write.c b/lib/json/json_write.c index 7e9fbb5c3..8115cdf78 100644 --- a/lib/json/json_write.c +++ b/lib/json/json_write.c @@ -265,6 +265,54 @@ spdk_json_write_uint64(struct spdk_json_write_ctx *w, uint64_t val) return emit(w, buf, count); } +int +spdk_json_write_uint128(struct spdk_json_write_ctx *w, uint64_t low_val, uint64_t high_val) +{ + char buf[128] = {'\0'}; + uint64_t low = low_val, high = high_val; + int count = 0; + + if (begin_value(w)) { return fail(w); } + + if (high != 0) { + char temp_buf[128] = {'\0'}; + uint64_t seg; + unsigned __int128 total = (unsigned __int128)low + + ((unsigned __int128)high << 64); + + while (total) { + seg = total % 10000000000; + total = total / 10000000000; + if (total) { + count = snprintf(temp_buf, 128, "%010" PRIu64 "%s", seg, buf); + } else { + count = snprintf(temp_buf, 128, "%" PRIu64 "%s", seg, buf); + } + + if (count <= 0 || (size_t)count >= sizeof(temp_buf)) { + return fail(w); + } + + snprintf(buf, 128, "%s", temp_buf); + } + } else { + count = snprintf(buf, sizeof(buf), "%" PRIu64, low); + + if (count <= 0 || (size_t)count >= sizeof(buf)) { return fail(w); } + } + + return emit(w, buf, count); +} + +int +spdk_json_write_named_uint128(struct spdk_json_write_ctx *w, const char *name, + uint64_t low_val, uint64_t high_val) +{ + int rc = spdk_json_write_name(w, name); + + return rc ? rc : spdk_json_write_uint128(w, low_val, high_val); +} + static void write_hex_4(void *dest, uint16_t val) { diff --git a/lib/json/spdk_json.map b/lib/json/spdk_json.map index df86af51d..b0f12d1c6 100644 --- a/lib/json/spdk_json.map +++ b/lib/json/spdk_json.map @@ -32,6 +32,7 @@ spdk_json_write_uint32; spdk_json_write_int64; spdk_json_write_uint64; + spdk_json_write_uint128; spdk_json_write_string; spdk_json_write_string_raw; spdk_json_write_string_utf16le; @@ -53,6 +54,7 @@ spdk_json_write_named_uint32; spdk_json_write_named_uint64; spdk_json_write_named_int64; + spdk_json_write_named_uint128; spdk_json_write_named_string; spdk_json_write_named_string_fmt; spdk_json_write_named_string_fmt_v; diff --git a/test/unit/lib/json/json_write.c/json_write_ut.c b/test/unit/lib/json/json_write.c/json_write_ut.c index d208f650c..28b328f98 100644 --- a/test/unit/lib/json/json_write.c/json_write_ut.c +++ b/test/unit/lib/json/json_write.c/json_write_ut.c @@ -69,6 +69,11 @@ write_cb(void *cb_ctx, const void *data, size_t size) CU_ASSERT(g_write_pos - g_buf == sizeof(json) - 1); \ CU_ASSERT(memcmp(json, g_buf, sizeof(json) - 1) == 0) +#define END_SIZE(val, size) \ + CU_ASSERT(spdk_json_write_end(w) == 0); \ + CU_ASSERT(g_write_pos - g_buf == size); \ + CU_ASSERT(memcmp(val, g_buf, size) == 0) + #define END_NOCMP() \ CU_ASSERT(spdk_json_write_end(w) == 0) @@ -112,6 +117,11 @@ write_cb(void *cb_ctx, const void *data, size_t size) #define VAL_INT64(i) CU_ASSERT(spdk_json_write_int64(w, i) == 0); #define VAL_UINT64(u) CU_ASSERT(spdk_json_write_uint64(w, u) == 0); +#define VAL_UINT128(low, high) \ + CU_ASSERT(spdk_json_write_uint128(w, low, high) == 0); +#define VAL_NAME_UINT128(name, low, high) \ + CU_ASSERT(spdk_json_write_named_uint128(w, name, low, high) == 0); + #define VAL_ARRAY_BEGIN() CU_ASSERT(spdk_json_write_array_begin(w) == 0) #define VAL_ARRAY_END() CU_ASSERT(spdk_json_write_array_end(w) == 0) @@ -351,6 +361,138 @@ test_write_number_uint32(void) END("4294967295"); } +static int +test_generate_string_uint128(char *buf, int buf_size, uint64_t low, uint64_t high) +{ + char tmp_buf[256] = {0}; + unsigned __int128 total; + uint64_t seg; + int count = 0; + + memset(buf, 0, buf_size); + total = ((unsigned __int128)high << 64) + (unsigned __int128)low; + while (total) { + /* Use the different calculation to get the 128bits decimal value in UT */ + seg = total % 1000000000000000; + total = total / 1000000000000000; + if (total) { + snprintf(tmp_buf, buf_size, "%015" PRIu64 "%s", seg, buf); + } else { + snprintf(tmp_buf, buf_size, "%" PRIu64 "%s", seg, buf); + } + + count = snprintf(buf, buf_size, "%s", tmp_buf); + } + + return count; +} + +static int +test_generate_string_name_uint128(char *name, char *buf, int buf_size, uint64_t low, uint64_t high) +{ + char tmp_buf[256] = {0}; + int count = test_generate_string_uint128(buf, buf_size, low, high); + + memcpy(tmp_buf, buf, buf_size); + count = snprintf(buf, 256, "\"%s\":%s", name, tmp_buf); + + return count; +} + +static void +test_write_number_uint128(void) +{ + struct spdk_json_write_ctx *w; + char buf[256] = {0}; + int used_count = 0; + + BEGIN(); + VAL_UINT128(0, 0); + END("0"); + + BEGIN(); + VAL_UINT128(1, 0); + used_count = test_generate_string_uint128(buf, sizeof(buf), 1, 0); + END_SIZE(buf, used_count); + + BEGIN(); + VAL_UINT128(123, 0); + used_count = test_generate_string_uint128(buf, sizeof(buf), 123, 0); + END_SIZE(buf, used_count); + + BEGIN(); + VAL_UINT128(2147483647, 0); + used_count = test_generate_string_uint128(buf, sizeof(buf), 2147483647, 0); + END_SIZE(buf, used_count); + + BEGIN(); + VAL_UINT128(0, 1); + used_count = test_generate_string_uint128(buf, sizeof(buf), 0, 1); + END_SIZE(buf, used_count); + + BEGIN(); + VAL_UINT128(4294967295, 1); + used_count = test_generate_string_uint128(buf, sizeof(buf), 4294967295, 1); + END_SIZE(buf, used_count); + + BEGIN(); + VAL_UINT128(2147483647, 4294967295); + used_count = test_generate_string_uint128(buf, sizeof(buf), 2147483647, 4294967295); + END_SIZE(buf, used_count); + + BEGIN(); + VAL_UINT128(4294967295, 4294967295); + used_count = test_generate_string_uint128(buf, sizeof(buf), 4294967295, 4294967295); + END_SIZE(buf, used_count); +} + +static void +test_write_string_number_uint128(void) +{ + struct spdk_json_write_ctx *w; + char buf[256] = {0}; + int used_count = 0; + + BEGIN(); + VAL_NAME_UINT128("case1", 0, 0); + END("\"case1\":0"); + + BEGIN(); + VAL_NAME_UINT128("case2", 1, 0); + used_count = test_generate_string_name_uint128("case2", buf, sizeof(buf), 1, 0); + END_SIZE(buf, used_count); + + BEGIN(); + VAL_NAME_UINT128("case3", 123, 0); + used_count = test_generate_string_name_uint128("case3", buf, sizeof(buf), 123, 0); + END_SIZE(buf, used_count); + + BEGIN(); + VAL_NAME_UINT128("case4", 2147483647, 0); + used_count = test_generate_string_name_uint128("case4", buf, sizeof(buf), 2147483647, 0); + END_SIZE(buf, used_count); + + BEGIN(); + VAL_NAME_UINT128("case5", 0, 1); + used_count = test_generate_string_name_uint128("case5", buf, sizeof(buf), 0, 1); + END_SIZE(buf, used_count); + + BEGIN(); + VAL_NAME_UINT128("case6", 4294967295, 1); + used_count = test_generate_string_name_uint128("case6", buf, sizeof(buf), 4294967295, 1); + END_SIZE(buf, used_count); + + BEGIN(); + VAL_NAME_UINT128("case7", 2147483647, 4294967295); + used_count = test_generate_string_name_uint128("case7", buf, sizeof(buf), 2147483647, 4294967295); + END_SIZE(buf, used_count); + + BEGIN(); + VAL_NAME_UINT128("case8", 4294967295, 4294967295); + used_count = test_generate_string_name_uint128("case8", buf, sizeof(buf), 4294967295, 4294967295); + END_SIZE(buf, used_count); +} + static void test_write_number_int64(void) { @@ -718,6 +860,8 @@ int main(int argc, char **argv) CU_ADD_TEST(suite, test_write_string_utf16le); CU_ADD_TEST(suite, test_write_number_int32); CU_ADD_TEST(suite, test_write_number_uint32); + CU_ADD_TEST(suite, test_write_number_uint128); + CU_ADD_TEST(suite, test_write_string_number_uint128); CU_ADD_TEST(suite, test_write_number_int64); CU_ADD_TEST(suite, test_write_number_uint64); CU_ADD_TEST(suite, test_write_array);