Merge pull request #158 from DaveGamble/case-sensitive

Provide case sensitive versions of all functions
This commit is contained in:
Max Bruckner 2017-05-02 01:27:49 +02:00 committed by GitHub
commit a1a860cd31
4 changed files with 192 additions and 84 deletions

View File

@ -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
View File

@ -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: */

View File

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

View File

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