From 050f982608f41f65eec2556f6a8093c9182cc206 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Sat, 3 Feb 2018 05:02:05 +0100 Subject: [PATCH] cJSON_DuplicateConfiguration --- cJSON.c | 30 +++++++++++++--------------- cJSON.h | 2 ++ tests/configuration_tests.c | 39 +++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 17 deletions(-) diff --git a/cJSON.c b/cJSON.c index 343620c..3c147a3 100644 --- a/cJSON.c +++ b/cJSON.c @@ -206,7 +206,7 @@ static void deallocate(const internal_configuration * const configuration, void } /* this is necessary to assign the default configuration after initialization */ -static const internal_configuration global_default_configuration = default_configuration; +static internal_configuration global_default_configuration = default_configuration; static internal_configuration global_configuration = default_configuration; @@ -2887,10 +2887,10 @@ CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) return (item->type & 0xFF) == cJSON_Raw; } -CJSON_PUBLIC(cJSON_Configuration) cJSON_CreateConfiguration(const cJSON_Allocators * const allocators, void *allocator_userdata) +CJSON_PUBLIC(cJSON_Configuration) cJSON_DuplicateConfiguration(const cJSON_Configuration configuration, const cJSON_Allocators * const allocators, void *allocator_userdata) { - internal_configuration *configuration = NULL; - const cJSON_Allocators *local_allocators = &global_configuration.allocators; + internal_configuration *duplicate = NULL; + const cJSON_Allocators *local_allocators = &global_default_configuration.allocators; if (allocators != NULL) { @@ -2902,24 +2902,20 @@ CJSON_PUBLIC(cJSON_Configuration) cJSON_CreateConfiguration(const cJSON_Allocato local_allocators = allocators; } - configuration = (internal_configuration*)local_allocators->allocate(sizeof(internal_configuration), allocator_userdata); - if (configuration == NULL) + duplicate = (internal_configuration*)local_allocators->allocate(sizeof(internal_configuration), allocator_userdata); + if (duplicate == NULL) { - goto fail; + return NULL; } - /* initialize with the default */ - *configuration = global_default_configuration; + memcpy(duplicate, configuration, sizeof(internal_configuration)); - return (cJSON_Configuration)configuration; + return duplicate; +} -fail: - if (configuration != NULL) - { - local_allocators->deallocate(configuration, allocator_userdata); - } - - return NULL; +CJSON_PUBLIC(cJSON_Configuration) cJSON_CreateConfiguration(const cJSON_Allocators * const allocators, void *allocator_userdata) +{ + return cJSON_DuplicateConfiguration((cJSON_Configuration)&global_default_configuration, allocators, allocator_userdata); } CJSON_PUBLIC(cJSON_Configuration) cJSON_ConfigurationChangeAllocators(cJSON_Configuration configuration, const cJSON_Allocators allocators) diff --git a/cJSON.h b/cJSON.h index 729c04a..b7036a2 100644 --- a/cJSON.h +++ b/cJSON.h @@ -154,6 +154,8 @@ CJSON_PUBLIC(const char*) cJSON_Version(void); * allocator_userdata can be used to pass custom data to your allocator (e.g. for pool allocators). * */ CJSON_PUBLIC(cJSON_Configuration) cJSON_CreateConfiguration(const cJSON_Allocators * const allocators, void *allocator_userdata); +/* Create a copy of an existing configuration */ +CJSON_PUBLIC(cJSON_Configuration) cJSON_DuplicateConfiguration(const cJSON_Configuration, const cJSON_Allocators * const allocators, void *allocator_userdata); /* Change the allocators of a cJSON_Configuration and reset the userdata */ CJSON_PUBLIC(cJSON_Configuration) cJSON_ConfigurationChangeAllocators(cJSON_Configuration configuration, const cJSON_Allocators allocators); /* Change the allocator userdata attached to a cJSON_Configuration */ diff --git a/tests/configuration_tests.c b/tests/configuration_tests.c index 9902136..04d9a37 100644 --- a/tests/configuration_tests.c +++ b/tests/configuration_tests.c @@ -83,6 +83,42 @@ static void create_configuration_should_not_take_incomplete_allocators(void) TEST_ASSERT_NULL(cJSON_CreateConfiguration(&allocators2, &userdata)); } +static void duplicate_configuration_should_duplicate_a_configuration(void) +{ + internal_configuration *configuration = NULL; + + configuration = (internal_configuration*)cJSON_DuplicateConfiguration(&global_configuration, NULL, NULL); + TEST_ASSERT_NOT_NULL(configuration); + + TEST_ASSERT_EQUAL_MEMORY(&global_configuration, configuration, sizeof(internal_configuration)); + + free(configuration); +} + +static void duplicate_configuration_should_take_custom_allocators(void) +{ + internal_configuration *configuration = NULL; + cJSON_Allocators allocators = {custom_allocator, custom_deallocator, NULL}; + size_t userdata = 0; + + configuration = (internal_configuration*)cJSON_DuplicateConfiguration(&global_configuration, &allocators, &userdata); + TEST_ASSERT_NOT_NULL(configuration); + TEST_ASSERT_EQUAL_MESSAGE(userdata, sizeof(internal_configuration), "custom allocator wasn't run properly"); + + TEST_ASSERT_EQUAL_MEMORY(&global_configuration, configuration, sizeof(internal_configuration)); + free(configuration); +} + +static void duplicate_configuration_should_not_take_incomplete_allocators(void) +{ + cJSON_Allocators allocators1 = {custom_allocator, NULL, NULL}; + cJSON_Allocators allocators2 = {NULL, custom_deallocator, NULL}; + size_t userdata = 0; + + TEST_ASSERT_NULL(cJSON_DuplicateConfiguration(&global_configuration, &allocators1, &userdata)); + TEST_ASSERT_NULL(cJSON_DuplicateConfiguration(&global_configuration, &allocators2, &userdata)); +} + static void configuration_change_allocators_should_change_allocators(void) { internal_configuration *configuration = NULL; @@ -211,6 +247,9 @@ int main(void) RUN_TEST(create_configuration_should_create_a_configuration); RUN_TEST(create_configuration_should_take_custom_allocators); RUN_TEST(create_configuration_should_not_take_incomplete_allocators); + RUN_TEST(duplicate_configuration_should_duplicate_a_configuration); + RUN_TEST(duplicate_configuration_should_take_custom_allocators); + RUN_TEST(duplicate_configuration_should_not_take_incomplete_allocators); RUN_TEST(configuration_change_allocators_should_change_allocators); RUN_TEST(configuration_change_allocators_should_not_change_incomplete_allocators); RUN_TEST(configuration_change_userdata_should_change_userdata);