Explorar el Código

cJSON_Compare: Performance improvement for objects

Check the size to prevent comparing objects equal if they are prefixes
of each other.
Max Bruckner hace 7 años
padre
commit
e82f32b359
Se han modificado 1 ficheros con 23 adiciones y 20 borrados
  1. 23 20
      cJSON.c

+ 23 - 20
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;
         }