mirror of
https://github.com/DaveGamble/cJSON
synced 2024-12-24 07:32:05 +00:00
Merge pull request #158 from DaveGamble/case-sensitive
Provide case sensitive versions of all functions
This commit is contained in:
commit
a1a860cd31
@ -138,8 +138,8 @@ This is an object. We're in C. We don't have objects. But we do have structs.
|
||||
What's the framerate?
|
||||
|
||||
```c
|
||||
cJSON *format = cJSON_GetObjectItem(root, "format");
|
||||
cJSON *framerate_item = cJSON_GetObjectItem(format, "frame rate");
|
||||
cJSON *format = cJSON_GetObjectItemCaseSensitive(root, "format");
|
||||
cJSON *framerate_item = cJSON_GetObjectItemCaseSensitive(format, "frame rate");
|
||||
double framerate = 0;
|
||||
if (cJSON_IsNumber(framerate_item))
|
||||
{
|
||||
@ -150,7 +150,7 @@ if (cJSON_IsNumber(framerate_item))
|
||||
Want to change the framerate?
|
||||
|
||||
```c
|
||||
cJSON *framerate_item = cJSON_GetObjectItem(format, "frame rate");
|
||||
cJSON *framerate_item = cJSON_GetObjectItemCaseSensitive(format, "frame rate");
|
||||
cJSON_SetNumberValue(framerate_item, 25);
|
||||
```
|
||||
|
||||
|
175
cJSON.c
175
cJSON.c
@ -1665,16 +1665,33 @@ CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
|
||||
return (int)i;
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int item)
|
||||
static cJSON* get_array_item(const cJSON *array, size_t index)
|
||||
{
|
||||
cJSON *c = array ? array->child : NULL;
|
||||
while (c && item > 0)
|
||||
cJSON *current_child = NULL;
|
||||
|
||||
if (array == NULL)
|
||||
{
|
||||
item--;
|
||||
c = c->next;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return c;
|
||||
current_child = array->child;
|
||||
while ((current_child != NULL) && (index > 0))
|
||||
{
|
||||
index--;
|
||||
current_child = current_child->next;
|
||||
}
|
||||
|
||||
return current_child;
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
|
||||
{
|
||||
if (index < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return get_array_item(array, (size_t)index);
|
||||
}
|
||||
|
||||
static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
|
||||
@ -1814,37 +1831,36 @@ CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *str
|
||||
cJSON_AddItemToObject(object, string, create_reference(item, &global_hooks));
|
||||
}
|
||||
|
||||
static cJSON *DetachItemFromArray(cJSON *array, size_t which)
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
|
||||
{
|
||||
cJSON *c = array->child;
|
||||
while (c && (which > 0))
|
||||
if ((parent == NULL) || (item == NULL))
|
||||
{
|
||||
c = c->next;
|
||||
which--;
|
||||
}
|
||||
if (!c)
|
||||
{
|
||||
/* item doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
if (c->prev)
|
||||
|
||||
if (item->prev != NULL)
|
||||
{
|
||||
/* not the first element */
|
||||
c->prev->next = c->next;
|
||||
item->prev->next = item->next;
|
||||
}
|
||||
if (c->next)
|
||||
if (item->next != NULL)
|
||||
{
|
||||
c->next->prev = c->prev;
|
||||
/* not the last element */
|
||||
item->next->prev = item->prev;
|
||||
}
|
||||
if (c==array->child)
|
||||
|
||||
if (item == parent->child)
|
||||
{
|
||||
array->child = c->next;
|
||||
/* first element */
|
||||
parent->child = item->next;
|
||||
}
|
||||
/* make sure the detached item doesn't point anywhere anymore */
|
||||
c->prev = c->next = NULL;
|
||||
item->prev = NULL;
|
||||
item->next = NULL;
|
||||
|
||||
return c;
|
||||
return item;
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
|
||||
{
|
||||
if (which < 0)
|
||||
@ -1852,7 +1868,7 @@ CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return DetachItemFromArray(array, (size_t)which);
|
||||
return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
|
||||
@ -1862,19 +1878,16 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
|
||||
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
|
||||
{
|
||||
size_t i = 0;
|
||||
cJSON *c = object->child;
|
||||
while (c && (case_insensitive_strcmp((unsigned char*)c->string, (const unsigned char*)string) != 0))
|
||||
{
|
||||
i++;
|
||||
c = c->next;
|
||||
}
|
||||
if (c)
|
||||
{
|
||||
return DetachItemFromArray(object, i);
|
||||
}
|
||||
cJSON *to_detach = cJSON_GetObjectItem(object, string);
|
||||
|
||||
return NULL;
|
||||
return cJSON_DetachItemViaPointer(object, to_detach);
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
|
||||
{
|
||||
cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
|
||||
|
||||
return cJSON_DetachItemViaPointer(object, to_detach);
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
|
||||
@ -1882,24 +1895,32 @@ CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
|
||||
cJSON_Delete(cJSON_DetachItemFromObject(object, string));
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
|
||||
{
|
||||
cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
|
||||
}
|
||||
|
||||
/* Replace array/object items with new ones. */
|
||||
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
|
||||
{
|
||||
cJSON *c = array->child;
|
||||
while (c && (which > 0))
|
||||
cJSON *after_inserted = NULL;
|
||||
|
||||
if (which < 0)
|
||||
{
|
||||
c = c->next;
|
||||
which--;
|
||||
return;
|
||||
}
|
||||
if (!c)
|
||||
|
||||
after_inserted = get_array_item(array, (size_t)which);
|
||||
if (after_inserted == NULL)
|
||||
{
|
||||
cJSON_AddItemToArray(array, newitem);
|
||||
return;
|
||||
}
|
||||
newitem->next = c;
|
||||
newitem->prev = c->prev;
|
||||
c->prev = newitem;
|
||||
if (c == array->child)
|
||||
|
||||
newitem->next = after_inserted;
|
||||
newitem->prev = after_inserted->prev;
|
||||
after_inserted->prev = newitem;
|
||||
if (after_inserted == array->child)
|
||||
{
|
||||
array->child = newitem;
|
||||
}
|
||||
@ -1909,35 +1930,41 @@ CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newit
|
||||
}
|
||||
}
|
||||
|
||||
static void ReplaceItemInArray(cJSON *array, size_t which, cJSON *newitem)
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
|
||||
{
|
||||
cJSON *c = array->child;
|
||||
while (c && (which > 0))
|
||||
if ((parent == NULL) || (replacement == NULL))
|
||||
{
|
||||
c = c->next;
|
||||
which--;
|
||||
return false;
|
||||
}
|
||||
if (!c)
|
||||
|
||||
if (replacement == item)
|
||||
{
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
newitem->next = c->next;
|
||||
newitem->prev = c->prev;
|
||||
if (newitem->next)
|
||||
|
||||
replacement->next = item->next;
|
||||
replacement->prev = item->prev;
|
||||
|
||||
if (replacement->next != NULL)
|
||||
{
|
||||
newitem->next->prev = newitem;
|
||||
replacement->next->prev = replacement;
|
||||
}
|
||||
if (c == array->child)
|
||||
if (replacement->prev != NULL)
|
||||
{
|
||||
array->child = newitem;
|
||||
replacement->prev->next = replacement;
|
||||
}
|
||||
else
|
||||
if (parent->child == item)
|
||||
{
|
||||
newitem->prev->next = newitem;
|
||||
parent->child = replacement;
|
||||
}
|
||||
c->next = c->prev = NULL;
|
||||
cJSON_Delete(c);
|
||||
|
||||
item->next = NULL;
|
||||
item->prev = NULL;
|
||||
cJSON_Delete(item);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
|
||||
{
|
||||
if (which < 0)
|
||||
@ -1945,29 +1972,17 @@ CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newi
|
||||
return;
|
||||
}
|
||||
|
||||
ReplaceItemInArray(array, (size_t)which, newitem);
|
||||
cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
|
||||
{
|
||||
size_t i = 0;
|
||||
cJSON *c = object->child;
|
||||
while(c && (case_insensitive_strcmp((unsigned char*)c->string, (const unsigned char*)string) != 0))
|
||||
{
|
||||
i++;
|
||||
c = c->next;
|
||||
}
|
||||
if(c)
|
||||
{
|
||||
/* free the old string if not const */
|
||||
if (!(newitem->type & cJSON_StringIsConst) && newitem->string)
|
||||
{
|
||||
global_hooks.deallocate(newitem->string);
|
||||
}
|
||||
cJSON_ReplaceItemViaPointer(object, cJSON_GetObjectItem(object, string), newitem);
|
||||
}
|
||||
|
||||
newitem->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
|
||||
ReplaceItemInArray(object, i, newitem);
|
||||
}
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
|
||||
{
|
||||
cJSON_ReplaceItemViaPointer(object, cJSON_GetObjectItemCaseSensitive(object, string), newitem);
|
||||
}
|
||||
|
||||
/* Create basic types: */
|
||||
|
7
cJSON.h
7
cJSON.h
@ -153,7 +153,7 @@ CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
|
||||
/* Returns the number of items in an array (or object). */
|
||||
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
|
||||
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int item);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
|
||||
/* Get item "string" from object. Case insensitive. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON *object, const char *string);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
|
||||
@ -203,15 +203,20 @@ CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||
CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
|
||||
|
||||
/* Remove/Detatch items from Arrays/Objects. */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
|
||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
|
||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
|
||||
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
|
||||
|
||||
/* Update array items. */
|
||||
CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
|
||||
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
||||
CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
|
||||
|
||||
/* Duplicate a cJSON item */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
|
||||
|
@ -218,6 +218,92 @@ static void cjson_set_number_value_should_set_numbers(void)
|
||||
TEST_ASSERT_EQUAL_DOUBLE(-1 + (double)INT_MIN, number->valuedouble);
|
||||
}
|
||||
|
||||
static void cjson_detach_item_via_pointer_should_detach_items(void)
|
||||
{
|
||||
cJSON list[4];
|
||||
cJSON parent[1];
|
||||
|
||||
memset(list, '\0', sizeof(list));
|
||||
|
||||
/* link the list */
|
||||
list[0].next = &(list[1]);
|
||||
list[1].next = &(list[2]);
|
||||
list[2].next = &(list[3]);
|
||||
|
||||
list[3].prev = &(list[2]);
|
||||
list[2].prev = &(list[1]);
|
||||
list[1].prev = &(list[0]);
|
||||
|
||||
parent->child = &list[0];
|
||||
|
||||
/* detach in the middle (list[1]) */
|
||||
TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[1])) == &(list[1]), "Failed to detach in the middle.");
|
||||
TEST_ASSERT_TRUE_MESSAGE((list[1].prev == NULL) && (list[1].next == NULL), "Didn't set pointers of detached item to NULL.");
|
||||
TEST_ASSERT_TRUE((list[0].next == &(list[2])) && (list[2].prev == &(list[0])));
|
||||
|
||||
/* detach beginning (list[0]) */
|
||||
TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[0])) == &(list[0]), "Failed to detach beginning.");
|
||||
TEST_ASSERT_TRUE_MESSAGE((list[0].prev == NULL) && (list[0].next == NULL), "Didn't set pointers of detached item to NULL.");
|
||||
TEST_ASSERT_TRUE_MESSAGE((list[2].prev == NULL) && (parent->child == &(list[2])), "Didn't set the new beginning.");
|
||||
|
||||
/* detach end (list[3])*/
|
||||
TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &(list[3])) == &(list[3]), "Failed to detach end.");
|
||||
TEST_ASSERT_TRUE_MESSAGE((list[3].prev == NULL) && (list[3].next == NULL), "Didn't set pointers of detached item to NULL.");
|
||||
TEST_ASSERT_TRUE_MESSAGE((list[2].next == NULL) && (parent->child == &(list[2])), "Didn't set the new end");
|
||||
|
||||
/* detach single item (list[2]) */
|
||||
TEST_ASSERT_TRUE_MESSAGE(cJSON_DetachItemViaPointer(parent, &list[2]) == &list[2], "Failed to detach single item.");
|
||||
TEST_ASSERT_TRUE_MESSAGE((list[2].prev == NULL) && (list[2].next == NULL), "Didn't set pointers of detached item to NULL.");
|
||||
TEST_ASSERT_NULL_MESSAGE(parent->child, "Child of the parent wasn't set to NULL.");
|
||||
}
|
||||
|
||||
static void cjson_replace_item_via_pointer_should_replace_items(void)
|
||||
{
|
||||
cJSON replacements[3];
|
||||
cJSON *beginning = NULL;
|
||||
cJSON *middle = NULL;
|
||||
cJSON *end = NULL;
|
||||
cJSON *array = NULL;
|
||||
|
||||
beginning = cJSON_CreateNull();
|
||||
TEST_ASSERT_NOT_NULL(beginning);
|
||||
middle = cJSON_CreateNull();
|
||||
TEST_ASSERT_NOT_NULL(middle);
|
||||
end = cJSON_CreateNull();
|
||||
TEST_ASSERT_NOT_NULL(end);
|
||||
|
||||
array = cJSON_CreateArray();
|
||||
TEST_ASSERT_NOT_NULL(array);
|
||||
|
||||
cJSON_AddItemToArray(array, beginning);
|
||||
cJSON_AddItemToArray(array, middle);
|
||||
cJSON_AddItemToArray(array, end);
|
||||
|
||||
|
||||
memset(replacements, '\0', sizeof(replacements));
|
||||
|
||||
/* replace beginning */
|
||||
TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, beginning, &(replacements[0])));
|
||||
TEST_ASSERT_NULL(replacements[0].prev);
|
||||
TEST_ASSERT_TRUE(replacements[0].next == middle);
|
||||
TEST_ASSERT_TRUE(middle->prev == &(replacements[0]));
|
||||
TEST_ASSERT_TRUE(array->child == &(replacements[0]));
|
||||
|
||||
/* replace middle */
|
||||
TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, middle, &(replacements[1])));
|
||||
TEST_ASSERT_TRUE(replacements[1].prev == &(replacements[0]));
|
||||
TEST_ASSERT_TRUE(replacements[1].next == end);
|
||||
TEST_ASSERT_TRUE(end->prev == &(replacements[1]));
|
||||
|
||||
/* replace end */
|
||||
TEST_ASSERT_TRUE(cJSON_ReplaceItemViaPointer(array, end, &(replacements[2])));
|
||||
TEST_ASSERT_TRUE(replacements[2].prev == &(replacements[1]));
|
||||
TEST_ASSERT_NULL(replacements[2].next);
|
||||
TEST_ASSERT_TRUE(replacements[1].next == &(replacements[2]));
|
||||
|
||||
cJSON_free(array);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
@ -229,6 +315,8 @@ int main(void)
|
||||
RUN_TEST(typecheck_functions_should_check_type);
|
||||
RUN_TEST(cjson_should_not_parse_to_deeply_nested_jsons);
|
||||
RUN_TEST(cjson_set_number_value_should_set_numbers);
|
||||
RUN_TEST(cjson_detach_item_via_pointer_should_detach_items);
|
||||
RUN_TEST(cjson_replace_item_via_pointer_should_replace_items);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user