From e8077d01500279a7b45b8cd7a0ae94ea7ad5748a Mon Sep 17 00:00:00 2001
From: xiaomianhehe <hongshaokai@hotmail.com>
Date: Tue, 18 Feb 2020 11:54:23 +0800
Subject: [PATCH] use prev pointer when array do adding (#430)

* use prev pointer when array do adding
---
 cJSON.c            | 37 ++++++++++++++++++++++++++++---------
 tests/misc_tests.c |  2 +-
 2 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/cJSON.c b/cJSON.c
index bc95cde..a198d66 100644
--- a/cJSON.c
+++ b/cJSON.c
@@ -1871,22 +1871,34 @@ static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
     }
 
     child = array->child;
-
+    /*
+     * To find the last item int array quickly, we use prev in array
+     */
     if (child == NULL)
     {
         /* list is empty, start new one */
         array->child = item;
+        item->prev = item;
+        item->next = NULL;
     }
     else
     {
         /* append to the end */
-        while (child->next)
+        if (child->prev)
         {
-            child = child->next;
+            suffix_object(child->prev, item);
+            array->child->prev = item;
+        }
+        else
+        {
+            while (child->next)
+            {
+                child = child->next;
+            }
+            suffix_object(child, item);
+            array->child->prev = item;
         }
-        suffix_object(child, item);
     }
-
     return true;
 }
 
@@ -2206,14 +2218,21 @@ CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON
     {
         replacement->next->prev = replacement;
     }
-    if (replacement->prev != NULL)
-    {
-        replacement->prev->next = replacement;
-    }
+
     if (parent->child == item)
     {
         parent->child = replacement;
     }
+    else
+    {   /*
+         * To find the last item int array quickly, we use prev in array.
+         * We can't modify the last item's next pointer where this item was the parent's child
+         */
+        if (replacement->prev != NULL)
+        {
+            replacement->prev->next = replacement;
+        }
+    }
 
     item->next = NULL;
     item->prev = NULL;
diff --git a/tests/misc_tests.c b/tests/misc_tests.c
index 1635fa3..9551683 100644
--- a/tests/misc_tests.c
+++ b/tests/misc_tests.c
@@ -306,7 +306,7 @@ static void cjson_replace_item_via_pointer_should_replace_items(void)
 
     /* replace beginning */
     TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, beginning, &(replacements[0])));
-    TEST_ASSERT_NULL(replacements[0].prev);
+    TEST_ASSERT_TRUE(replacements[0].prev == end);
     TEST_ASSERT_TRUE(replacements[0].next == middle);
     TEST_ASSERT_TRUE(middle->prev == &(replacements[0]));
     TEST_ASSERT_TRUE(array->child == &(replacements[0]));