From c77c655987ea0354a9e38dc5e63fb288fcefd99f Mon Sep 17 00:00:00 2001 From: Darek Stojaczyk Date: Wed, 3 Jun 2020 12:31:23 +0200 Subject: [PATCH] json: add spdk_json_free_object() After decoding a JSON object we had to free the parsed strings one-by-one. Not anymore. Change-Id: I819f1d533e397aa9babca58b5500c38ac01a963d Signed-off-by: Darek Stojaczyk Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/2753 Reviewed-by: Mellanox Build Bot Reviewed-by: Shuhei Matsumoto Reviewed-by: Jim Harris Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins --- CHANGELOG.md | 2 ++ include/spdk/json.h | 3 ++ lib/json/json_util.c | 23 +++++++++++++ lib/json/spdk_json.map | 2 ++ test/unit/lib/json/json_util.c/json_util_ut.c | 32 +++++++++++++++++++ 5 files changed, 62 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc4eacbf7..b1af3e940 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,8 @@ through the JSON context provided via spdk_nvmf_target_opts->transport_specific. ## v20.07: SPDK CSI driver, new accel_fw commands, I/O abort support +spdk_json_free_object() was added to free memory allocated by spdk_json_decode_object(). + ### accel A new API was added `spdk_accel_get_capabilities` that allows applications to diff --git a/include/spdk/json.h b/include/spdk/json.h index 0e81ed1d9..59b5a2fb5 100644 --- a/include/spdk/json.h +++ b/include/spdk/json.h @@ -156,6 +156,9 @@ int spdk_json_decode_uint32(const struct spdk_json_val *val, void *out); int spdk_json_decode_uint64(const struct spdk_json_val *val, void *out); int spdk_json_decode_string(const struct spdk_json_val *val, void *out); +void spdk_json_free_object(const struct spdk_json_object_decoder *decoders, size_t num_decoders, + void *obj); + /** * Get length of a value in number of values. * diff --git a/lib/json/json_util.c b/lib/json/json_util.c index 500952f35..3ef80718c 100644 --- a/lib/json/json_util.c +++ b/lib/json/json_util.c @@ -364,6 +364,29 @@ _json_decode_object(const struct spdk_json_val *values, return invalid ? -1 : 0; } +void +spdk_json_free_object(const struct spdk_json_object_decoder *decoders, size_t num_decoders, + void *obj) +{ + struct spdk_json_val invalid_val = { + .start = "", + .len = 0, + .type = SPDK_JSON_VAL_INVALID + }; + size_t decidx; + + for (decidx = 0; decidx < num_decoders; decidx++) { + const struct spdk_json_object_decoder *dec = &decoders[decidx]; + void *field = (void *)((uintptr_t)obj + dec->offset); + + /* decoding an invalid value will free the + * previous memory without allocating it again. + */ + dec->decode_func(&invalid_val, field); + } +} + + int spdk_json_decode_object(const struct spdk_json_val *values, const struct spdk_json_object_decoder *decoders, size_t num_decoders, void *out) diff --git a/lib/json/spdk_json.map b/lib/json/spdk_json.map index 66b40201a..df86af51d 100644 --- a/lib/json/spdk_json.map +++ b/lib/json/spdk_json.map @@ -13,6 +13,8 @@ spdk_json_decode_uint64; spdk_json_decode_string; + spdk_json_free_object; + spdk_json_val_len; spdk_json_strequal; spdk_json_strdup; diff --git a/test/unit/lib/json/json_util.c/json_util_ut.c b/test/unit/lib/json/json_util.c/json_util_ut.c index 2f883521f..ec8344fff 100644 --- a/test/unit/lib/json/json_util.c/json_util_ut.c +++ b/test/unit/lib/json/json_util.c/json_util_ut.c @@ -251,6 +251,37 @@ test_decode_object(void) free(output.my_name); } +static void +test_free_object(void) +{ + struct my_object { + char *my_name; + uint32_t my_int; + char *my_other_name; + char *empty_string; + }; + struct spdk_json_object_decoder decoders[] = { + {"first", offsetof(struct my_object, my_name), spdk_json_decode_string, false}, + {"second", offsetof(struct my_object, my_int), spdk_json_decode_uint32, false}, + {"third", offsetof(struct my_object, my_other_name), spdk_json_decode_string, true}, + {"fourth", offsetof(struct my_object, empty_string), spdk_json_decode_string, false}, + }; + struct my_object output = { + .my_name = strdup("hello"), + .my_int = 3, + .my_other_name = strdup("world"), + .empty_string = NULL + }; + + SPDK_CU_ASSERT_FATAL(output.my_name != NULL); + SPDK_CU_ASSERT_FATAL(output.my_other_name != NULL); + + spdk_json_free_object(decoders, 4, &output); + CU_ASSERT(output.my_name == NULL); + CU_ASSERT(output.my_other_name == NULL); + CU_ASSERT(output.empty_string == NULL); +} + static void test_decode_array(void) { @@ -942,6 +973,7 @@ int main(int argc, char **argv) CU_ADD_TEST(suite, test_decode_string); CU_ADD_TEST(suite, test_find); CU_ADD_TEST(suite, test_iterating); + CU_ADD_TEST(suite, test_free_object); CU_basic_set_mode(CU_BRM_VERBOSE);