|
@@ -2,15 +2,17 @@
|
|
|
#include <string.h>
|
|
|
#include <stdlib.h>
|
|
|
#include <stdio.h>
|
|
|
+#include <limits.h>
|
|
|
+
|
|
|
#include "cJSON_Utils.h"
|
|
|
|
|
|
-static char* cJSONUtils_strdup(const char* str)
|
|
|
+static unsigned char* cJSONUtils_strdup(const unsigned char* str)
|
|
|
{
|
|
|
size_t len = 0;
|
|
|
- char *copy = NULL;
|
|
|
+ unsigned char *copy = NULL;
|
|
|
|
|
|
- len = strlen(str) + 1;
|
|
|
- if (!(copy = (char*)malloc(len)))
|
|
|
+ len = strlen((const char*)str) + 1;
|
|
|
+ if (!(copy = (unsigned char*)malloc(len)))
|
|
|
{
|
|
|
return NULL;
|
|
|
}
|
|
@@ -19,7 +21,7 @@ static char* cJSONUtils_strdup(const char* str)
|
|
|
return copy;
|
|
|
}
|
|
|
|
|
|
-static int cJSONUtils_strcasecmp(const char *s1, const char *s2)
|
|
|
+static int cJSONUtils_strcasecmp(const unsigned char *s1, const unsigned char *s2)
|
|
|
{
|
|
|
if (!s1)
|
|
|
{
|
|
@@ -37,11 +39,11 @@ static int cJSONUtils_strcasecmp(const char *s1, const char *s2)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
|
|
|
+ return tolower(*s1) - tolower(*s2);
|
|
|
}
|
|
|
|
|
|
/* JSON Pointer implementation: */
|
|
|
-static int cJSONUtils_Pstrcasecmp(const char *a, const char *e)
|
|
|
+static int cJSONUtils_Pstrcasecmp(const unsigned char *a, const unsigned char *e)
|
|
|
{
|
|
|
if (!a || !e)
|
|
|
{
|
|
@@ -76,9 +78,9 @@ static int cJSONUtils_Pstrcasecmp(const char *a, const char *e)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int cJSONUtils_PointerEncodedstrlen(const char *s)
|
|
|
+static size_t cJSONUtils_PointerEncodedstrlen(const unsigned char *s)
|
|
|
{
|
|
|
- int l = 0;
|
|
|
+ size_t l = 0;
|
|
|
for (; *s; s++, l++)
|
|
|
{
|
|
|
if ((*s == '~') || (*s == '/'))
|
|
@@ -90,7 +92,7 @@ static int cJSONUtils_PointerEncodedstrlen(const char *s)
|
|
|
return l;
|
|
|
}
|
|
|
|
|
|
-static void cJSONUtils_PointerEncodedstrcpy(char *d, const char *s)
|
|
|
+static void cJSONUtils_PointerEncodedstrcpy(unsigned char *d, const unsigned char *s)
|
|
|
{
|
|
|
for (; *s; s++)
|
|
|
{
|
|
@@ -116,39 +118,39 @@ static void cJSONUtils_PointerEncodedstrcpy(char *d, const char *s)
|
|
|
char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target)
|
|
|
{
|
|
|
int type = object->type;
|
|
|
- int c = 0;
|
|
|
+ size_t c = 0;
|
|
|
cJSON *obj = 0;
|
|
|
|
|
|
if (object == target)
|
|
|
{
|
|
|
/* found */
|
|
|
- return cJSONUtils_strdup("");
|
|
|
+ return (char*)cJSONUtils_strdup((const unsigned char*)"");
|
|
|
}
|
|
|
|
|
|
/* recursively search all children of the object */
|
|
|
for (obj = object->child; obj; obj = obj->next, c++)
|
|
|
{
|
|
|
- char *found = cJSONUtils_FindPointerFromObjectTo(obj, target);
|
|
|
+ unsigned char *found = (unsigned char*)cJSONUtils_FindPointerFromObjectTo(obj, target);
|
|
|
if (found)
|
|
|
{
|
|
|
if ((type & 0xFF) == cJSON_Array)
|
|
|
{
|
|
|
/* reserve enough memory for a 64 bit integer + '/' and '\0' */
|
|
|
- char *ret = (char*)malloc(strlen(found) + 23);
|
|
|
- sprintf(ret, "/%d%s", c, found); /* /<array_index><path> */
|
|
|
+ unsigned char *ret = (unsigned char*)malloc(strlen((char*)found) + 23);
|
|
|
+ sprintf((char*)ret, "/%lu%s", c, found); /* /<array_index><path> */
|
|
|
free(found);
|
|
|
|
|
|
- return ret;
|
|
|
+ return (char*)ret;
|
|
|
}
|
|
|
else if ((type & 0xFF) == cJSON_Object)
|
|
|
{
|
|
|
- char *ret = (char*)malloc(strlen(found) + cJSONUtils_PointerEncodedstrlen(obj->string) + 2);
|
|
|
+ unsigned char *ret = (unsigned char*)malloc(strlen((char*)found) + cJSONUtils_PointerEncodedstrlen((unsigned char*)obj->string) + 2);
|
|
|
*ret = '/';
|
|
|
- cJSONUtils_PointerEncodedstrcpy(ret + 1, obj->string);
|
|
|
- strcat(ret, found);
|
|
|
+ cJSONUtils_PointerEncodedstrcpy(ret + 1, (unsigned char*)obj->string);
|
|
|
+ strcat((char*)ret, (char*)found);
|
|
|
free(found);
|
|
|
|
|
|
- return ret;
|
|
|
+ return (char*)ret;
|
|
|
}
|
|
|
|
|
|
/* reached leaf of the tree, found nothing */
|
|
@@ -168,24 +170,28 @@ cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer)
|
|
|
{
|
|
|
if ((object->type & 0xFF) == cJSON_Array)
|
|
|
{
|
|
|
- int which = 0;
|
|
|
+ size_t which = 0;
|
|
|
/* parse array index */
|
|
|
while ((*pointer >= '0') && (*pointer <= '9'))
|
|
|
{
|
|
|
- which = (10 * which) + (*pointer++ - '0');
|
|
|
+ which = (10 * which) + (size_t)(*pointer++ - '0');
|
|
|
}
|
|
|
if (*pointer && (*pointer != '/'))
|
|
|
{
|
|
|
/* not end of string or new path token */
|
|
|
return NULL;
|
|
|
}
|
|
|
- object = cJSON_GetArrayItem(object, which);
|
|
|
+ if (which > INT_MAX)
|
|
|
+ {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ object = cJSON_GetArrayItem(object, (int)which);
|
|
|
}
|
|
|
else if ((object->type & 0xFF) == cJSON_Object)
|
|
|
{
|
|
|
object = object->child;
|
|
|
/* GetObjectItem. */
|
|
|
- while (object && cJSONUtils_Pstrcasecmp(object->string, pointer))
|
|
|
+ while (object && cJSONUtils_Pstrcasecmp((unsigned char*)object->string, (const unsigned char*)pointer))
|
|
|
{
|
|
|
object = object->next;
|
|
|
}
|
|
@@ -205,9 +211,9 @@ cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer)
|
|
|
}
|
|
|
|
|
|
/* JSON Patch implementation. */
|
|
|
-static void cJSONUtils_InplaceDecodePointerString(char *string)
|
|
|
+static void cJSONUtils_InplaceDecodePointerString(unsigned char *string)
|
|
|
{
|
|
|
- char *s2 = string;
|
|
|
+ unsigned char *s2 = string;
|
|
|
|
|
|
if (string == NULL) {
|
|
|
return;
|
|
@@ -225,10 +231,10 @@ static void cJSONUtils_InplaceDecodePointerString(char *string)
|
|
|
*s2 = '\0';
|
|
|
}
|
|
|
|
|
|
-static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path)
|
|
|
+static cJSON *cJSONUtils_PatchDetach(cJSON *object, const unsigned char *path)
|
|
|
{
|
|
|
- char *parentptr = NULL;
|
|
|
- char *childptr = NULL;
|
|
|
+ unsigned char *parentptr = NULL;
|
|
|
+ unsigned char *childptr = NULL;
|
|
|
cJSON *parent = NULL;
|
|
|
cJSON *ret = NULL;
|
|
|
|
|
@@ -238,7 +244,7 @@ static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
- childptr = strrchr(parentptr, '/'); /* last '/' */
|
|
|
+ childptr = (unsigned char*)strrchr((char*)parentptr, '/'); /* last '/' */
|
|
|
if (childptr == NULL)
|
|
|
{
|
|
|
free(parentptr);
|
|
@@ -247,7 +253,7 @@ static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path)
|
|
|
/* split strings */
|
|
|
*childptr++ = '\0';
|
|
|
|
|
|
- parent = cJSONUtils_GetPointer(object, parentptr);
|
|
|
+ parent = cJSONUtils_GetPointer(object, (char*)parentptr);
|
|
|
cJSONUtils_InplaceDecodePointerString(childptr);
|
|
|
|
|
|
if (!parent)
|
|
@@ -257,11 +263,11 @@ static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path)
|
|
|
}
|
|
|
else if ((parent->type & 0xFF) == cJSON_Array)
|
|
|
{
|
|
|
- ret = cJSON_DetachItemFromArray(parent, atoi(childptr));
|
|
|
+ ret = cJSON_DetachItemFromArray(parent, atoi((char*)childptr));
|
|
|
}
|
|
|
else if ((parent->type & 0xFF) == cJSON_Object)
|
|
|
{
|
|
|
- ret = cJSON_DetachItemFromObject(parent, childptr);
|
|
|
+ ret = cJSON_DetachItemFromObject(parent, (char*)childptr);
|
|
|
}
|
|
|
free(parentptr);
|
|
|
|
|
@@ -304,7 +310,7 @@ static int cJSONUtils_Compare(cJSON *a, cJSON *b)
|
|
|
{
|
|
|
int err = 0;
|
|
|
/* compare object keys */
|
|
|
- if (cJSONUtils_strcasecmp(a->string, b->string))
|
|
|
+ if (cJSONUtils_strcasecmp((unsigned char*)a->string, (unsigned char*)b->string))
|
|
|
{
|
|
|
/* missing member */
|
|
|
return -6;
|
|
@@ -334,8 +340,8 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
|
|
|
cJSON *value = NULL;
|
|
|
cJSON *parent = NULL;
|
|
|
int opcode = 0;
|
|
|
- char *parentptr = NULL;
|
|
|
- char *childptr = NULL;
|
|
|
+ unsigned char *parentptr = NULL;
|
|
|
+ unsigned char *childptr = NULL;
|
|
|
|
|
|
op = cJSON_GetObjectItem(patch, "op");
|
|
|
path = cJSON_GetObjectItem(patch, "path");
|
|
@@ -381,7 +387,7 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
|
|
|
if ((opcode == 1) || (opcode == 2))
|
|
|
{
|
|
|
/* Get rid of old. */
|
|
|
- cJSON_Delete(cJSONUtils_PatchDetach(object, path->valuestring));
|
|
|
+ cJSON_Delete(cJSONUtils_PatchDetach(object, (unsigned char*)path->valuestring));
|
|
|
if (opcode == 1)
|
|
|
{
|
|
|
/* For Remove, this is job done. */
|
|
@@ -402,7 +408,7 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
|
|
|
if (opcode == 3)
|
|
|
{
|
|
|
/* move */
|
|
|
- value = cJSONUtils_PatchDetach(object, from->valuestring);
|
|
|
+ value = cJSONUtils_PatchDetach(object, (unsigned char*)from->valuestring);
|
|
|
}
|
|
|
if (opcode == 4)
|
|
|
{
|
|
@@ -443,13 +449,13 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
|
|
|
/* Now, just add "value" to "path". */
|
|
|
|
|
|
/* split pointer in parent and child */
|
|
|
- parentptr = cJSONUtils_strdup(path->valuestring);
|
|
|
- childptr = strrchr(parentptr, '/');
|
|
|
+ parentptr = cJSONUtils_strdup((unsigned char*)path->valuestring);
|
|
|
+ childptr = (unsigned char*)strrchr((char*)parentptr, '/');
|
|
|
if (childptr)
|
|
|
{
|
|
|
*childptr++ = '\0';
|
|
|
}
|
|
|
- parent = cJSONUtils_GetPointer(object, parentptr);
|
|
|
+ parent = cJSONUtils_GetPointer(object, (char*)parentptr);
|
|
|
cJSONUtils_InplaceDecodePointerString(childptr);
|
|
|
|
|
|
/* add, remove, replace, move, copy, test. */
|
|
@@ -462,19 +468,19 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch)
|
|
|
}
|
|
|
else if ((parent->type & 0xFF) == cJSON_Array)
|
|
|
{
|
|
|
- if (!strcmp(childptr, "-"))
|
|
|
+ if (!strcmp((char*)childptr, "-"))
|
|
|
{
|
|
|
cJSON_AddItemToArray(parent, value);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- cJSON_InsertItemInArray(parent, atoi(childptr), value);
|
|
|
+ cJSON_InsertItemInArray(parent, atoi((char*)childptr), value);
|
|
|
}
|
|
|
}
|
|
|
else if ((parent->type & 0xFF) == cJSON_Object)
|
|
|
{
|
|
|
- cJSON_DeleteItemFromObject(parent, childptr);
|
|
|
- cJSON_AddItemToObject(parent, childptr, value);
|
|
|
+ cJSON_DeleteItemFromObject(parent, (char*)childptr);
|
|
|
+ cJSON_AddItemToObject(parent, (char*)childptr, value);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -509,20 +515,20 @@ int cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void cJSONUtils_GeneratePatch(cJSON *patches, const char *op, const char *path, const char *suffix, cJSON *val)
|
|
|
+static void cJSONUtils_GeneratePatch(cJSON *patches, const unsigned char *op, const unsigned char *path, const unsigned char *suffix, cJSON *val)
|
|
|
{
|
|
|
cJSON *patch = cJSON_CreateObject();
|
|
|
- cJSON_AddItemToObject(patch, "op", cJSON_CreateString(op));
|
|
|
+ cJSON_AddItemToObject(patch, "op", cJSON_CreateString((const char*)op));
|
|
|
if (suffix)
|
|
|
{
|
|
|
- char *newpath = (char*)malloc(strlen(path) + cJSONUtils_PointerEncodedstrlen(suffix) + 2);
|
|
|
- cJSONUtils_PointerEncodedstrcpy(newpath + sprintf(newpath, "%s/", path), suffix);
|
|
|
- cJSON_AddItemToObject(patch, "path", cJSON_CreateString(newpath));
|
|
|
+ unsigned char *newpath = (unsigned char*)malloc(strlen((const char*)path) + cJSONUtils_PointerEncodedstrlen(suffix) + 2);
|
|
|
+ cJSONUtils_PointerEncodedstrcpy(newpath + sprintf((char*)newpath, "%s/", (const char*)path), suffix);
|
|
|
+ cJSON_AddItemToObject(patch, "path", cJSON_CreateString((const char*)newpath));
|
|
|
free(newpath);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- cJSON_AddItemToObject(patch, "path", cJSON_CreateString(path));
|
|
|
+ cJSON_AddItemToObject(patch, "path", cJSON_CreateString((const char*)path));
|
|
|
}
|
|
|
if (val)
|
|
|
{
|
|
@@ -533,14 +539,14 @@ static void cJSONUtils_GeneratePatch(cJSON *patches, const char *op, const char
|
|
|
|
|
|
void cJSONUtils_AddPatchToArray(cJSON *array, const char *op, const char *path, cJSON *val)
|
|
|
{
|
|
|
- cJSONUtils_GeneratePatch(array, op, path, 0, val);
|
|
|
+ cJSONUtils_GeneratePatch(array, (const unsigned char*)op, (const unsigned char*)path, 0, val);
|
|
|
}
|
|
|
|
|
|
-static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *from, cJSON *to)
|
|
|
+static void cJSONUtils_CompareToPatch(cJSON *patches, const unsigned char *path, cJSON *from, cJSON *to)
|
|
|
{
|
|
|
if ((from->type & 0xFF) != (to->type & 0xFF))
|
|
|
{
|
|
|
- cJSONUtils_GeneratePatch(patches, "replace", path, 0, to);
|
|
|
+ cJSONUtils_GeneratePatch(patches, (const unsigned char*)"replace", path, 0, to);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -549,37 +555,37 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *f
|
|
|
case cJSON_Number:
|
|
|
if ((from->valueint != to->valueint) || (from->valuedouble != to->valuedouble))
|
|
|
{
|
|
|
- cJSONUtils_GeneratePatch(patches, "replace", path, 0, to);
|
|
|
+ cJSONUtils_GeneratePatch(patches, (const unsigned char*)"replace", path, 0, to);
|
|
|
}
|
|
|
return;
|
|
|
|
|
|
case cJSON_String:
|
|
|
if (strcmp(from->valuestring, to->valuestring) != 0)
|
|
|
{
|
|
|
- cJSONUtils_GeneratePatch(patches, "replace", path, 0, to);
|
|
|
+ cJSONUtils_GeneratePatch(patches, (const unsigned char*)"replace", path, 0, to);
|
|
|
}
|
|
|
return;
|
|
|
|
|
|
case cJSON_Array:
|
|
|
{
|
|
|
- int c = 0;
|
|
|
- char *newpath = (char*)malloc(strlen(path) + 23); /* Allow space for 64bit int. */
|
|
|
+ size_t c = 0;
|
|
|
+ unsigned char *newpath = (unsigned char*)malloc(strlen((const char*)path) + 23); /* Allow space for 64bit int. */
|
|
|
/* generate patches for all array elements that exist in "from" and "to" */
|
|
|
for (c = 0, from = from->child, to = to->child; from && to; from = from->next, to = to->next, c++)
|
|
|
{
|
|
|
- sprintf(newpath, "%s/%d", path, c); /* path of the current array element */
|
|
|
+ sprintf((char*)newpath, "%s/%lu", path, c); /* path of the current array element */
|
|
|
cJSONUtils_CompareToPatch(patches, newpath, from, to);
|
|
|
}
|
|
|
/* remove leftover elements from 'from' that are not in 'to' */
|
|
|
for (; from; from = from->next, c++)
|
|
|
{
|
|
|
- sprintf(newpath, "%d", c);
|
|
|
- cJSONUtils_GeneratePatch(patches, "remove", path, newpath, 0);
|
|
|
+ sprintf((char*)newpath, "%lu", c);
|
|
|
+ cJSONUtils_GeneratePatch(patches, (const unsigned char*)"remove", path, newpath, 0);
|
|
|
}
|
|
|
/* add new elements in 'to' that were not in 'from' */
|
|
|
for (; to; to = to->next, c++)
|
|
|
{
|
|
|
- cJSONUtils_GeneratePatch(patches, "add", path, "-", to);
|
|
|
+ cJSONUtils_GeneratePatch(patches, (const unsigned char*)"add", path, (const unsigned char*)"-", to);
|
|
|
}
|
|
|
free(newpath);
|
|
|
return;
|
|
@@ -597,12 +603,12 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *f
|
|
|
/* for all object values in the object with more of them */
|
|
|
while (a || b)
|
|
|
{
|
|
|
- int diff = (!a) ? 1 : ((!b) ? -1 : cJSONUtils_strcasecmp(a->string, b->string));
|
|
|
+ int diff = (!a) ? 1 : ((!b) ? -1 : cJSONUtils_strcasecmp((unsigned char*)a->string, (unsigned char*)b->string));
|
|
|
if (!diff)
|
|
|
{
|
|
|
/* both object keys are the same */
|
|
|
- char *newpath = (char*)malloc(strlen(path) + cJSONUtils_PointerEncodedstrlen(a->string) + 2);
|
|
|
- cJSONUtils_PointerEncodedstrcpy(newpath + sprintf(newpath, "%s/", path), a->string);
|
|
|
+ unsigned char *newpath = (unsigned char*)malloc(strlen((const char*)path) + cJSONUtils_PointerEncodedstrlen((unsigned char*)a->string) + 2);
|
|
|
+ cJSONUtils_PointerEncodedstrcpy(newpath + sprintf((char*)newpath, "%s/", path), (unsigned char*)a->string);
|
|
|
/* create a patch for the element */
|
|
|
cJSONUtils_CompareToPatch(patches, newpath, a, b);
|
|
|
free(newpath);
|
|
@@ -612,13 +618,13 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *f
|
|
|
else if (diff < 0)
|
|
|
{
|
|
|
/* object element doesn't exist in 'to' --> remove it */
|
|
|
- cJSONUtils_GeneratePatch(patches, "remove", path, a->string, 0);
|
|
|
+ cJSONUtils_GeneratePatch(patches, (const unsigned char*)"remove", path, (unsigned char*)a->string, 0);
|
|
|
a = a->next;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
/* object element doesn't exist in 'from' --> add it */
|
|
|
- cJSONUtils_GeneratePatch(patches, "add", path, b->string, b);
|
|
|
+ cJSONUtils_GeneratePatch(patches, (const unsigned char*)"add", path, (unsigned char*)b->string, b);
|
|
|
b = b->next;
|
|
|
}
|
|
|
}
|
|
@@ -633,7 +639,7 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *f
|
|
|
cJSON* cJSONUtils_GeneratePatches(cJSON *from, cJSON *to)
|
|
|
{
|
|
|
cJSON *patches = cJSON_CreateArray();
|
|
|
- cJSONUtils_CompareToPatch(patches, "", from, to);
|
|
|
+ cJSONUtils_CompareToPatch(patches, (const unsigned char*)"", from, to);
|
|
|
|
|
|
return patches;
|
|
|
}
|
|
@@ -651,7 +657,7 @@ static cJSON *cJSONUtils_SortList(cJSON *list)
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
- while (ptr && ptr->next && (cJSONUtils_strcasecmp(ptr->string, ptr->next->string) < 0))
|
|
|
+ while (ptr && ptr->next && (cJSONUtils_strcasecmp((unsigned char*)ptr->string, (unsigned char*)ptr->next->string) < 0))
|
|
|
{
|
|
|
/* Test for list sorted. */
|
|
|
ptr = ptr->next;
|
|
@@ -688,7 +694,7 @@ static cJSON *cJSONUtils_SortList(cJSON *list)
|
|
|
|
|
|
while (first && second) /* Merge the sub-lists */
|
|
|
{
|
|
|
- if (cJSONUtils_strcasecmp(first->string, second->string) < 0)
|
|
|
+ if (cJSONUtils_strcasecmp((unsigned char*)first->string, (unsigned char*)second->string) < 0)
|
|
|
{
|
|
|
if (!list)
|
|
|
{
|