Pārlūkot izejas kodu

Merge pull request #120 from DaveGamble/typecheck-functions

Typecheck functions
Max Bruckner 8 gadi atpakaļ
vecāks
revīzija
2302f4f0b2
4 mainītis faili ar 182 papildinājumiem un 14 dzēšanām
  1. 100 0
      cJSON.c
  2. 12 0
      cJSON.h
  3. 13 14
      cJSON_Utils.c
  4. 57 0
      tests/misc_tests.c

+ 100 - 0
cJSON.c

@@ -2149,3 +2149,103 @@ void cJSON_Minify(char *json)
     /* and null-terminate. */
     *into = '\0';
 }
+
+extern cjbool cJSON_IsInvalid(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Invalid;
+}
+
+extern cjbool cJSON_IsFalse(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_False;
+}
+
+extern cjbool cJSON_IsTrue(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xff) == cJSON_True;
+}
+
+
+extern cjbool cJSON_IsBool(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & (cJSON_True | cJSON_False)) != 0;
+}
+extern cjbool cJSON_IsNull(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_NULL;
+}
+
+extern cjbool cJSON_IsNumber(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Number;
+}
+
+extern cjbool cJSON_IsString(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_String;
+}
+
+extern cjbool cJSON_IsArray(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Array;
+}
+
+extern cjbool cJSON_IsObject(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Object;
+}
+
+extern cjbool cJSON_IsRaw(const cJSON * const item)
+{
+    if (item == NULL)
+    {
+        return false;
+    }
+
+    return (item->type & 0xFF) == cJSON_Raw;
+}

+ 12 - 0
cJSON.h

@@ -109,6 +109,18 @@ extern int cJSON_HasObjectItem(const cJSON *object, const char *string);
 /* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
 extern const char *cJSON_GetErrorPtr(void);
 
+/* These functions check the type of an item */
+extern int cJSON_IsInvalid(const cJSON * const item);
+extern int cJSON_IsFalse(const cJSON * const item);
+extern int cJSON_IsTrue(const cJSON * const item);
+extern int cJSON_IsBool(const cJSON * const item);
+extern int cJSON_IsNull(const cJSON * const item);
+extern int cJSON_IsNumber(const cJSON * const item);
+extern int cJSON_IsString(const cJSON * const item);
+extern int cJSON_IsArray(const cJSON * const item);
+extern int cJSON_IsObject(const cJSON * const item);
+extern int cJSON_IsRaw(const cJSON * const item);
+
 /* These calls create a cJSON item of the appropriate type. */
 extern cJSON *cJSON_CreateNull(void);
 extern cJSON *cJSON_CreateTrue(void);

+ 13 - 14
cJSON_Utils.c

@@ -117,7 +117,6 @@ static void cJSONUtils_PointerEncodedstrcpy(unsigned char *d, const unsigned cha
 
 char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target)
 {
-    int type = object->type;
     size_t c = 0;
     cJSON *obj = 0;
 
@@ -133,7 +132,7 @@ char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target)
         unsigned char *found = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(obj, target);
         if (found)
         {
-            if ((type & 0xFF) == cJSON_Array)
+            if (cJSON_IsArray(object))
             {
                 /* reserve enough memory for a 64 bit integer + '/' and '\0' */
                 unsigned char *ret = (unsigned char*)malloc(strlen((char*)found) + 23);
@@ -150,7 +149,7 @@ char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target)
 
                 return (char*)ret;
             }
-            else if ((type & 0xFF) == cJSON_Object)
+            else if (cJSON_IsObject(object))
             {
                 unsigned char *ret = (unsigned char*)malloc(strlen((char*)found) + cJSONUtils_PointerEncodedstrlen((unsigned char*)obj->string) + 2);
                 *ret = '/';
@@ -176,7 +175,7 @@ cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer)
     /* follow path of the pointer */
     while ((*pointer++ == '/') && object)
     {
-        if ((object->type & 0xFF) == cJSON_Array)
+        if (cJSON_IsArray(object))
         {
             size_t which = 0;
             /* parse array index */
@@ -195,7 +194,7 @@ cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer)
             }
             object = cJSON_GetArrayItem(object, (int)which);
         }
-        else if ((object->type & 0xFF) == cJSON_Object)
+        else if (cJSON_IsObject(object))
         {
             object = object->child;
             /* GetObjectItem. */
@@ -269,11 +268,11 @@ static cJSON *cJSONUtils_PatchDetach(cJSON *object, const unsigned char *path)
         /* Couldn't find object to remove child from. */
         ret = NULL;
     }
-    else if ((parent->type & 0xFF) == cJSON_Array)
+    else if (cJSON_IsArray(parent))
     {
         ret = cJSON_DetachItemFromArray(parent, atoi((char*)childptr));
     }
-    else if ((parent->type & 0xFF) == cJSON_Object)
+    else if (cJSON_IsObject(parent))
     {
         ret = cJSON_DetachItemFromObject(parent, (char*)childptr);
     }
@@ -474,7 +473,7 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
         cJSON_Delete(value);
         return 9;
     }
-    else if ((parent->type & 0xFF) == cJSON_Array)
+    else if (cJSON_IsArray(parent))
     {
         if (!strcmp((char*)childptr, "-"))
         {
@@ -485,7 +484,7 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
             cJSON_InsertItemInArray(parent, atoi((char*)childptr), value);
         }
     }
-    else if ((parent->type & 0xFF) == cJSON_Object)
+    else if (cJSON_IsObject(parent))
     {
         cJSON_DeleteItemFromObject(parent, (char*)childptr);
         cJSON_AddItemToObject(parent, (char*)childptr, value);
@@ -508,7 +507,7 @@ int cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches)
         return 1;
     }
 
-    if ((patches->type & 0xFF) != cJSON_Array)
+    if (cJSON_IsArray(patches))
     {
         /* malformed patches. */
         return 1;
@@ -793,14 +792,14 @@ void cJSONUtils_SortObject(cJSON *object)
 
 cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch)
 {
-    if (!patch || ((patch->type & 0xFF) != cJSON_Object))
+    if (!cJSON_IsObject(patch))
     {
         /* scalar value, array or NULL, just duplicate */
         cJSON_Delete(target);
         return cJSON_Duplicate(patch, 1);
     }
 
-    if (!target || ((target->type & 0xFF) != cJSON_Object))
+    if (!cJSON_IsObject(target))
     {
         cJSON_Delete(target);
         target = cJSON_CreateObject();
@@ -809,7 +808,7 @@ cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch)
     patch = patch->child;
     while (patch)
     {
-        if ((patch->type & 0xFF) == cJSON_NULL)
+        if (cJSON_IsNull(patch))
         {
             /* NULL is the indicator to remove a value, see RFC7396 */
             cJSON_DeleteItemFromObject(target, patch->string);
@@ -832,7 +831,7 @@ cJSON *cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to)
         /* patch to delete everything */
         return cJSON_CreateNull();
     }
-    if (((to->type & 0xFF) != cJSON_Object) || !from || ((from->type & 0xFF) != cJSON_Object))
+    if (!cJSON_IsObject(to) || !cJSON_IsObject(from))
     {
         return cJSON_Duplicate(to, 1);
     }

+ 57 - 0
tests/misc_tests.c

@@ -127,6 +127,62 @@ static void cjson_get_object_item_case_sensitive_should_get_object_items(void)
     cJSON_Delete(item);
 }
 
+static void typecheck_functions_should_check_type(void)
+{
+    cJSON invalid[1];
+    cJSON item[1];
+    invalid->type = cJSON_Invalid;
+    invalid->type |= cJSON_StringIsConst;
+    item->type = cJSON_False;
+    item->type |= cJSON_StringIsConst;
+
+    TEST_ASSERT_FALSE(cJSON_IsInvalid(NULL));
+    TEST_ASSERT_FALSE(cJSON_IsInvalid(item));
+    TEST_ASSERT_TRUE(cJSON_IsInvalid(invalid));
+
+    item->type = cJSON_False | cJSON_StringIsConst;
+    TEST_ASSERT_FALSE(cJSON_IsFalse(NULL));
+    TEST_ASSERT_FALSE(cJSON_IsFalse(invalid));
+    TEST_ASSERT_TRUE(cJSON_IsFalse(item));
+    TEST_ASSERT_TRUE(cJSON_IsBool(item));
+
+    item->type = cJSON_True | cJSON_StringIsConst;
+    TEST_ASSERT_FALSE(cJSON_IsTrue(NULL));
+    TEST_ASSERT_FALSE(cJSON_IsTrue(invalid));
+    TEST_ASSERT_TRUE(cJSON_IsTrue(item));
+    TEST_ASSERT_TRUE(cJSON_IsBool(item));
+
+    item->type = cJSON_NULL | cJSON_StringIsConst;
+    TEST_ASSERT_FALSE(cJSON_IsNull(NULL));
+    TEST_ASSERT_FALSE(cJSON_IsNull(invalid));
+    TEST_ASSERT_TRUE(cJSON_IsNull(item));
+
+    item->type = cJSON_Number | cJSON_StringIsConst;
+    TEST_ASSERT_FALSE(cJSON_IsNumber(NULL));
+    TEST_ASSERT_FALSE(cJSON_IsNumber(invalid));
+    TEST_ASSERT_TRUE(cJSON_IsNumber(item));
+
+    item->type = cJSON_String | cJSON_StringIsConst;
+    TEST_ASSERT_FALSE(cJSON_IsString(NULL));
+    TEST_ASSERT_FALSE(cJSON_IsString(invalid));
+    TEST_ASSERT_TRUE(cJSON_IsString(item));
+
+    item->type = cJSON_Array | cJSON_StringIsConst;
+    TEST_ASSERT_FALSE(cJSON_IsArray(NULL));
+    TEST_ASSERT_FALSE(cJSON_IsArray(invalid));
+    TEST_ASSERT_TRUE(cJSON_IsArray(item));
+
+    item->type = cJSON_Object | cJSON_StringIsConst;
+    TEST_ASSERT_FALSE(cJSON_IsObject(NULL));
+    TEST_ASSERT_FALSE(cJSON_IsObject(invalid));
+    TEST_ASSERT_TRUE(cJSON_IsObject(item));
+
+    item->type = cJSON_Raw | cJSON_StringIsConst;
+    TEST_ASSERT_FALSE(cJSON_IsRaw(NULL));
+    TEST_ASSERT_FALSE(cJSON_IsRaw(invalid));
+    TEST_ASSERT_TRUE(cJSON_IsRaw(item));
+}
+
 int main(void)
 {
     UNITY_BEGIN();
@@ -135,6 +191,7 @@ int main(void)
     RUN_TEST(cjson_array_foreach_should_not_dereference_null_pointer);
     RUN_TEST(cjson_get_object_item_should_get_object_items);
     RUN_TEST(cjson_get_object_item_case_sensitive_should_get_object_items);
+    RUN_TEST(typecheck_functions_should_check_type);
 
     return UNITY_END();
 }