cJSON_Compare: Performance improvement for objects

Check the size to prevent comparing objects equal if they are prefixes
of each other.
This commit is contained in:
Max Bruckner 2018-02-03 15:54:47 +01:00
parent afc246f1d5
commit e82f32b359

43
cJSON.c
View File

@ -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;
}