From 0474d4d85fdc418adb56d3bdf1beaca9eac2a554 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Fri, 2 Feb 2018 00:57:00 +0100 Subject: [PATCH] cJSON_ConfigurationChangeParseEnd Add a pointer to an end position of parsing to the cJSON_Configuration object. (Essentially like return_parse_end, but as offset instead of pointer). --- cJSON.c | 33 ++++++++++++++++++++++++++------- cJSON.h | 2 ++ tests/configuration_tests.c | 15 +++++++++++++++ tests/misc_tests.c | 2 +- 4 files changed, 44 insertions(+), 8 deletions(-) diff --git a/cJSON.c b/cJSON.c index 646fe16..4a97030 100644 --- a/cJSON.c +++ b/cJSON.c @@ -130,6 +130,7 @@ typedef struct internal_configuration cJSON_bool case_sensitive; cJSON_Allocators allocators; void *userdata; + size_t *end_position; } internal_configuration; #if defined(_MSC_VER) @@ -194,7 +195,8 @@ static void deallocate(const internal_configuration * const configuration, void global_deallocate_wrapper,\ global_reallocate_wrapper\ },\ - NULL /* no userdata */\ + NULL, /* no userdata */\ + NULL /* no end position */\ } /* this is necessary to assign the default configuration after initialization */ @@ -1060,7 +1062,7 @@ static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) } /* Parse an object - create a new root, and populate. */ -static cJSON *parse(const char * const json, const internal_configuration * const configuration, size_t *end_position) +static cJSON *parse(const char * const json, const internal_configuration * const configuration) { parse_buffer buffer = { 0, 0, 0, 0, default_configuration }; cJSON *item = NULL; @@ -1099,7 +1101,10 @@ static cJSON *parse(const char * const json, const internal_configuration * cons goto fail; } } - *end_position = buffer.offset; + if (configuration->end_position != NULL) + { + *configuration->end_position = buffer.offset; + } return item; @@ -1124,7 +1129,10 @@ fail: local_error.position = buffer.length - 1; } - *end_position = local_error.position; + if (configuration->end_position != NULL) + { + *configuration->end_position = local_error.position; + } global_error = local_error; } @@ -1139,7 +1147,8 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *json, const char **return_ cJSON *item = NULL; configuration.allow_data_after_json = !require_null_terminated; - item = parse(json, &configuration, &end_position); + configuration.end_position = &end_position; + item = parse(json, &configuration); if (return_parse_end != NULL) { @@ -1152,8 +1161,7 @@ CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *json, const char **return_ /* Default options for cJSON_Parse */ CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *json) { - size_t end_position = 0; - return parse(json, &global_configuration, &end_position); + return parse(json, &global_configuration); } #define cjson_min(a, b) ((a < b) ? a : b) @@ -3013,6 +3021,17 @@ CJSON_PUBLIC(cJSON_Configuration) cJSON_ConfigurationChangeUserdata(cJSON_Config return configuration; } +CJSON_PUBLIC(cJSON_Configuration) cJSON_ConfigurationChangeParseEnd(cJSON_Configuration configuration, size_t * const parse_end) +{ + if (configuration == NULL) + { + return NULL; + } + + ((internal_configuration*)configuration)->end_position = parse_end; + return configuration; +} + static cJSON_bool compare(const cJSON * const a, const cJSON * const b, const internal_configuration * const configuration) { if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)) || cJSON_IsInvalid(a)) diff --git a/cJSON.h b/cJSON.h index 20443bb..0528e0e 100644 --- a/cJSON.h +++ b/cJSON.h @@ -179,6 +179,8 @@ CJSON_PUBLIC(cJSON_Configuration) cJSON_CreateConfiguration(const cJSON * const CJSON_PUBLIC(cJSON_Configuration) cJSON_ConfigurationChangeAllocators(cJSON_Configuration configuration, const cJSON_Allocators allocators); /* Change the allocator userdata attached to a cJSON_Configuration */ CJSON_PUBLIC(cJSON_Configuration) cJSON_ConfigurationChangeUserdata(cJSON_Configuration configuration, void *userdata); +/* Change the pointer where the end of parsing is written to */ +CJSON_PUBLIC(cJSON_Configuration) cJSON_ConfigurationChangeParseEnd(cJSON_Configuration configuration, size_t * const parse_end); /* Supply malloc and free functions to cJSON globally */ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); diff --git a/tests/configuration_tests.c b/tests/configuration_tests.c index e4489a9..4319ef6 100644 --- a/tests/configuration_tests.c +++ b/tests/configuration_tests.c @@ -129,6 +129,20 @@ static void configuration_change_userdata_should_change_userdata(void) free(configuration); } +static void configuration_change_parse_end_should_change_parse_end(void) +{ + size_t end_position = 0; + internal_configuration *configuration = (internal_configuration*)cJSON_CreateConfiguration(NULL, NULL, NULL); + TEST_ASSERT_NOT_NULL(configuration); + + configuration = (internal_configuration*)cJSON_ConfigurationChangeParseEnd(configuration, &end_position); + TEST_ASSERT_NOT_NULL(configuration); + + TEST_ASSERT_TRUE_MESSAGE(configuration->end_position == &end_position, "Failed to set parse end."); + + free(configuration); +} + int main(void) { UNITY_BEGIN(); @@ -138,6 +152,7 @@ int main(void) RUN_TEST(create_configuration_should_take_custom_allocators); RUN_TEST(configuration_change_allocators_should_change_allocators); RUN_TEST(configuration_change_userdata_should_change_userdata); + RUN_TEST(configuration_change_parse_end_should_change_parse_end); return UNITY_END(); } diff --git a/tests/misc_tests.c b/tests/misc_tests.c index f4aad6e..e1c54be 100644 --- a/tests/misc_tests.c +++ b/tests/misc_tests.c @@ -420,7 +420,7 @@ static void *failing_realloc(void *pointer, size_t size, void *userdata) static void ensure_should_fail_on_failed_realloc(void) { - printbuffer buffer = {NULL, 10, 0, 0, false, {256, false, true, true, {global_allocate_wrapper, global_deallocate_wrapper, failing_realloc}, NULL } }; + printbuffer buffer = {NULL, 10, 0, 0, false, {256, false, true, true, {global_allocate_wrapper, global_deallocate_wrapper, failing_realloc}, NULL, NULL } }; buffer.configuration.userdata = &buffer; buffer.buffer = (unsigned char*)malloc(100); TEST_ASSERT_NOT_NULL(buffer.buffer);