From e82f32b35940a39f7c6a137f0ae410d8274e12cd Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Sat, 3 Feb 2018 15:54:47 +0100 Subject: [PATCH] cJSON_Compare: Performance improvement for objects Check the size to prevent comparing objects equal if they are prefixes of each other. --- cJSON.c | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/cJSON.c b/cJSON.c index 125bea4..13ccfd9 100644 --- a/cJSON.c +++ b/cJSON.c @@ -1743,8 +1743,7 @@ static cJSON_bool print_object(const cJSON * const item, printbuffer * const out return true; } -/* Get Array size/item / object item. */ -CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +static size_t get_array_size(const cJSON * const array) { cJSON *child = NULL; size_t size = 0; @@ -1756,13 +1755,25 @@ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) child = array->child; - while(child != NULL) + while (child != NULL) { size++; child = child->next; } - /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ + return size; +} + +/* Get Array size/item / object item. */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +{ + size_t size = get_array_size(array); + + if (size > INT_MAX) + { + /* This is incorrect but can't be fixed without breaking the API */ + return INT_MAX; + } return (int)size; } @@ -2891,6 +2902,14 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons { cJSON *a_element = NULL; cJSON *b_element = NULL; + size_t a_size = get_array_size(a); + size_t b_size = get_array_size(b); + + if (a_size != b_size) + { + return false; + } + cJSON_ArrayForEach(a_element, a) { /* TODO This has O(n^2) runtime, which is horrible! */ @@ -2906,22 +2925,6 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons } } - /* doing this twice, once on a and b to prevent true comparison if a subset of b - * TODO: Do this the proper way, this is just a fix for now */ - cJSON_ArrayForEach(b_element, b) - { - a_element = get_object_item(a, b_element->string, case_sensitive); - if (a_element == NULL) - { - return false; - } - - if (!cJSON_Compare(b_element, a_element, case_sensitive)) - { - return false; - } - } - return true; }