From fcbeb1c36bbd4885a615d9b61f2b9e4ed5d45667 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Tue, 11 Oct 2016 00:34:19 +0700 Subject: [PATCH 01/23] reformatting: test.c --- test.c | 348 ++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 246 insertions(+), 102 deletions(-) diff --git a/test.c b/test.c index a9124a6..97fa01f 100644 --- a/test.c +++ b/test.c @@ -27,125 +27,269 @@ /* Parse text to JSON, then render back to text, and print! */ void doit(char *text) { - char *out;cJSON *json; + char *out; + cJSON *json; - json=cJSON_Parse(text); - if (!json) {printf("Error before: [%s]\n",cJSON_GetErrorPtr());} - else - { - out=cJSON_Print(json); - cJSON_Delete(json); - printf("%s\n",out); - free(out); - } + json = cJSON_Parse(text); + if (!json) + { + printf("Error before: [%s]\n", cJSON_GetErrorPtr()); + } + else + { + out = cJSON_Print(json); + cJSON_Delete(json); + printf("%s\n", out); + free(out); + } } /* Read a file, parse, render back, etc. */ void dofile(char *filename) { - FILE *f;long len;char *data; + FILE *f; + long len; + char *data; - f=fopen(filename,"rb");fseek(f,0,SEEK_END);len=ftell(f);fseek(f,0,SEEK_SET); - data=(char*)malloc(len+1);fread(data,1,len,f);data[len]='\0';fclose(f); - doit(data); - free(data); + /* open in read binary mode */ + f = fopen(filename,"rb"); + /* get the length */ + fseek(f, 0, SEEK_END); + len = ftell(f); + fseek(f, 0, SEEK_SET); + + data = (char*)malloc(len + 1); + + fread(data, 1, len, f); + data[len] = '\0'; + fclose(f); + + doit(data); + free(data); } /* Used by some code below as an example datatype. */ -struct record {const char *precision;double lat,lon;const char *address,*city,*state,*zip,*country; }; +struct record +{ + const char *precision; + double lat; + double lon; + const char *address; + const char *city; + const char *state; + const char *zip; + const char *country; +}; /* Create a bunch of objects as demonstration. */ void create_objects() { - cJSON *root,*fmt,*img,*thm,*fld;char *out;int i; /* declare a few. */ - /* Our "days of the week" array: */ - const char *strings[7]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"}; - /* Our matrix: */ - int numbers[3][3]={{0,-1,0},{1,0,0},{0,0,1}}; - /* Our "gallery" item: */ - int ids[4]={116,943,234,38793}; - /* Our array of "records": */ - struct record fields[2]={ - {"zip",37.7668,-1.223959e+2,"","SAN FRANCISCO","CA","94107","US"}, - {"zip",37.371991,-1.22026e+2,"","SUNNYVALE","CA","94085","US"}}; - volatile double zero = 0.0; + /* declare a few. */ + cJSON *root; + cJSON *fmt; + cJSON *img; + cJSON *thm; + cJSON *fld; + char *out; + int i; - /* Here we construct some JSON standards, from the JSON site. */ + /* Our "days of the week" array: */ + const char *strings[7] = + { + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday" + }; + /* Our matrix: */ + int numbers[3][3] = + { + {0, -1, 0}, + {1, 0, 0}, + {0 ,0, 1} + }; + /* Our "gallery" item: */ + int ids[4] = { 116, 943, 234, 38793 }; + /* Our array of "records": */ + struct record fields[2] = + { + { + "zip", + 37.7668, + -1.223959e+2, + "", + "SAN FRANCISCO", + "CA", + "94107", + "US" + }, + { + "zip", + 37.371991, + -1.22026e+2, + "", + "SUNNYVALE", + "CA", + "94085", + "US" + } + }; + volatile double zero = 0.0; - /* Our "Video" datatype: */ - root=cJSON_CreateObject(); - cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble")); - cJSON_AddItemToObject(root, "format", fmt=cJSON_CreateObject()); - cJSON_AddStringToObject(fmt,"type", "rect"); - cJSON_AddNumberToObject(fmt,"width", 1920); - cJSON_AddNumberToObject(fmt,"height", 1080); - cJSON_AddFalseToObject (fmt,"interlace"); - cJSON_AddNumberToObject(fmt,"frame rate", 24); + /* Here we construct some JSON standards, from the JSON site. */ - out=cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); free(out); /* Print to text, Delete the cJSON, print it, release the string. */ + /* Our "Video" datatype: */ + root = cJSON_CreateObject(); + cJSON_AddItemToObject(root, "name", cJSON_CreateString("Jack (\"Bee\") Nimble")); + cJSON_AddItemToObject(root, "format", fmt = cJSON_CreateObject()); + cJSON_AddStringToObject(fmt, "type", "rect"); + cJSON_AddNumberToObject(fmt, "width", 1920); + cJSON_AddNumberToObject(fmt, "height", 1080); + cJSON_AddFalseToObject (fmt, "interlace"); + cJSON_AddNumberToObject(fmt, "frame rate", 24); - /* Our "days of the week" array: */ - root=cJSON_CreateStringArray(strings,7); + /* Print to text */ + out = cJSON_Print(root); + /* Delete the cJSON */ + cJSON_Delete(root); + /* print it */ + printf("%s\n",out); + /* release the string */ + free(out); - out=cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); free(out); + /* Our "days of the week" array: */ + root = cJSON_CreateStringArray(strings, 7); - /* Our matrix: */ - root=cJSON_CreateArray(); - for (i=0;i<3;i++) cJSON_AddItemToArray(root,cJSON_CreateIntArray(numbers[i],3)); + out = cJSON_Print(root); + cJSON_Delete(root); + printf("%s\n", out); + free(out); -/* cJSON_ReplaceItemInArray(root,1,cJSON_CreateString("Replacement")); */ + /* Our matrix: */ + root = cJSON_CreateArray(); + for (i = 0; i < 3; i++) + { + cJSON_AddItemToArray(root, cJSON_CreateIntArray(numbers[i], 3)); + } - out=cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); free(out); + /* cJSON_ReplaceItemInArray(root, 1, cJSON_CreateString("Replacement")); */ + + out = cJSON_Print(root); + cJSON_Delete(root); + printf("%s\n", out); + free(out); - /* Our "gallery" item: */ - root=cJSON_CreateObject(); - cJSON_AddItemToObject(root, "Image", img=cJSON_CreateObject()); - cJSON_AddNumberToObject(img,"Width",800); - cJSON_AddNumberToObject(img,"Height",600); - cJSON_AddStringToObject(img,"Title","View from 15th Floor"); - cJSON_AddItemToObject(img, "Thumbnail", thm=cJSON_CreateObject()); - cJSON_AddStringToObject(thm, "Url", "http:/*www.example.com/image/481989943"); - cJSON_AddNumberToObject(thm,"Height",125); - cJSON_AddStringToObject(thm,"Width","100"); - cJSON_AddItemToObject(img,"IDs", cJSON_CreateIntArray(ids,4)); + /* Our "gallery" item: */ + root = cJSON_CreateObject(); + cJSON_AddItemToObject(root, "Image", img = cJSON_CreateObject()); + cJSON_AddNumberToObject(img, "Width", 800); + cJSON_AddNumberToObject(img, "Height", 600); + cJSON_AddStringToObject(img, "Title", "View from 15th Floor"); + cJSON_AddItemToObject(img, "Thumbnail", thm = cJSON_CreateObject()); + cJSON_AddStringToObject(thm, "Url", "http:/*www.example.com/image/481989943"); + cJSON_AddNumberToObject(thm, "Height", 125); + cJSON_AddStringToObject(thm, "Width", "100"); + cJSON_AddItemToObject(img, "IDs", cJSON_CreateIntArray(ids, 4)); - out=cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); free(out); + out = cJSON_Print(root); + cJSON_Delete(root); + printf("%s\n", out); + free(out); - /* Our array of "records": */ + /* Our array of "records": */ - root=cJSON_CreateArray(); - for (i=0;i<2;i++) - { - cJSON_AddItemToArray(root,fld=cJSON_CreateObject()); - cJSON_AddStringToObject(fld, "precision", fields[i].precision); - cJSON_AddNumberToObject(fld, "Latitude", fields[i].lat); - cJSON_AddNumberToObject(fld, "Longitude", fields[i].lon); - cJSON_AddStringToObject(fld, "Address", fields[i].address); - cJSON_AddStringToObject(fld, "City", fields[i].city); - cJSON_AddStringToObject(fld, "State", fields[i].state); - cJSON_AddStringToObject(fld, "Zip", fields[i].zip); - cJSON_AddStringToObject(fld, "Country", fields[i].country); - } + root = cJSON_CreateArray(); + for (i = 0; i < 2; i++) + { + cJSON_AddItemToArray(root, fld = cJSON_CreateObject()); + cJSON_AddStringToObject(fld, "precision", fields[i].precision); + cJSON_AddNumberToObject(fld, "Latitude", fields[i].lat); + cJSON_AddNumberToObject(fld, "Longitude", fields[i].lon); + cJSON_AddStringToObject(fld, "Address", fields[i].address); + cJSON_AddStringToObject(fld, "City", fields[i].city); + cJSON_AddStringToObject(fld, "State", fields[i].state); + cJSON_AddStringToObject(fld, "Zip", fields[i].zip); + cJSON_AddStringToObject(fld, "Country", fields[i].country); + } -/* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root,1),"City",cJSON_CreateIntArray(ids,4)); */ + /* cJSON_ReplaceItemInObject(cJSON_GetArrayItem(root, 1), "City", cJSON_CreateIntArray(ids, 4)); */ - out=cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); free(out); + out = cJSON_Print(root); + cJSON_Delete(root); + printf("%s\n", out); + free(out); - root=cJSON_CreateObject(); - cJSON_AddNumberToObject(root,"number", 1.0/zero); - out=cJSON_Print(root); cJSON_Delete(root); printf("%s\n",out); free(out); + root = cJSON_CreateObject(); + cJSON_AddNumberToObject(root, "number", 1.0 / zero); + out = cJSON_Print(root); + cJSON_Delete(root); + printf("%s\n", out); + free(out); } -int main (int argc, const char * argv[]) { - /* a bunch of json: */ - char text1[]="{\n\"name\": \"Jack (\\\"Bee\\\") Nimble\", \n\"format\": {\"type\": \"rect\", \n\"width\": 1920, \n\"height\": 1080, \n\"interlace\": false,\"frame rate\": 24\n}\n}"; - char text2[]="[\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]"; - char text3[]="[\n [0, -1, 0],\n [1, 0, 0],\n [0, 0, 1]\n ]\n"; - char text4[]="{\n \"Image\": {\n \"Width\": 800,\n \"Height\": 600,\n \"Title\": \"View from 15th Floor\",\n \"Thumbnail\": {\n \"Url\": \"http:/*www.example.com/image/481989943\",\n \"Height\": 125,\n \"Width\": \"100\"\n },\n \"IDs\": [116, 943, 234, 38793]\n }\n }"; - char text5[]="[\n {\n \"precision\": \"zip\",\n \"Latitude\": 37.7668,\n \"Longitude\": -122.3959,\n \"Address\": \"\",\n \"City\": \"SAN FRANCISCO\",\n \"State\": \"CA\",\n \"Zip\": \"94107\",\n \"Country\": \"US\"\n },\n {\n \"precision\": \"zip\",\n \"Latitude\": 37.371991,\n \"Longitude\": -122.026020,\n \"Address\": \"\",\n \"City\": \"SUNNYVALE\",\n \"State\": \"CA\",\n \"Zip\": \"94085\",\n \"Country\": \"US\"\n }\n ]"; +int main (int argc, const char *argv[]) +{ + /* a bunch of json: */ + char text1[] = + "{\n" + "\"name\": \"Jack (\\\"Bee\\\") Nimble\", \n" + "\"format\": {\"type\": \"rect\", \n" + "\"width\": 1920, \n" + "\"height\": 1080, \n" + "\"interlace\": false,\"frame rate\": 24\n" + "}\n" + "}"; + char text2[] = "[\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]"; + char text3[] = + "[\n" + " [0, -1, 0],\n" + " [1, 0, 0],\n" + " [0, 0, 1]\n" + "\t]\n"; + char text4[] = + "{\n" + "\t\t\"Image\": {\n" + "\t\t\t\"Width\": 800,\n" + "\t\t\t\"Height\": 600,\n" + "\t\t\t\"Title\": \"View from 15th Floor\",\n" + "\t\t\t\"Thumbnail\": {\n" + "\t\t\t\t\"Url\": \"http:/*www.example.com/image/481989943\",\n" + "\t\t\t\t\"Height\": 125,\n" + "\t\t\t\t\"Width\": \"100\"\n" + "\t\t\t},\n" + "\t\t\t\"IDs\": [116, 943, 234, 38793]\n" + "\t\t}\n" + "\t}"; + char text5[] = + "[\n" + "\t {\n" + "\t \"precision\": \"zip\",\n" + "\t \"Latitude\": 37.7668,\n" + "\t \"Longitude\": -122.3959,\n" + "\t \"Address\": \"\",\n" + "\t \"City\": \"SAN FRANCISCO\",\n" + "\t \"State\": \"CA\",\n" + "\t \"Zip\": \"94107\",\n" + "\t \"Country\": \"US\"\n" + "\t },\n" + "\t {\n" + "\t \"precision\": \"zip\",\n" + "\t \"Latitude\": 37.371991,\n" + "\t \"Longitude\": -122.026020,\n" + "\t \"Address\": \"\",\n" + "\t \"City\": \"SUNNYVALE\",\n" + "\t \"State\": \"CA\",\n" + "\t \"Zip\": \"94085\",\n" + "\t \"Country\": \"US\"\n" + "\t }\n" + "\t ]"; - char text6[] = "" + char text6[] = + "" "\n" "\n" " \n" @@ -162,24 +306,24 @@ int main (int argc, const char * argv[]) { "\n" "\n"; - /* Process each json textblock by parsing, then rebuilding: */ - doit(text1); - doit(text2); - doit(text3); - doit(text4); - doit(text5); + /* Process each json textblock by parsing, then rebuilding: */ + doit(text1); + doit(text2); + doit(text3); + doit(text4); + doit(text5); doit(text6); - /* Parse standard testfiles: */ -/* dofile("../../tests/test1"); */ -/* dofile("../../tests/test2"); */ -/* dofile("../../tests/test3"); */ -/* dofile("../../tests/test4"); */ -/* dofile("../../tests/test5"); */ -/* dofile("../../tests/test6"); */ + /* Parse standard testfiles: */ + /* dofile("../../tests/test1"); */ + /* dofile("../../tests/test2"); */ + /* dofile("../../tests/test3"); */ + /* dofile("../../tests/test4"); */ + /* dofile("../../tests/test5"); */ + /* dofile("../../tests/test6"); */ - /* Now some samplecode for building objects concisely: */ - create_objects(); + /* Now some samplecode for building objects concisely: */ + create_objects(); - return 0; + return 0; } From 526d6b13128392b267a7fa84d6822bc5815fb1e3 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Thu, 13 Oct 2016 00:18:44 +0700 Subject: [PATCH 02/23] reformatting: cJSON_Utils.h --- cJSON_Utils.h | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/cJSON_Utils.h b/cJSON_Utils.h index b129b06..cefda08 100644 --- a/cJSON_Utils.h +++ b/cJSON_Utils.h @@ -1,30 +1,44 @@ #include "cJSON.h" -/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */ -cJSON *cJSONUtils_GetPointer(cJSON *object,const char *pointer); +/* Implement RFC6901 (https://tools.ietf.org/html/rfc6901) JSON Pointer spec. */ +cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer); -/* Implement RFC6902 (https://tools.ietf.org/html/rfc6902) JSON Patch spec. */ -cJSON* cJSONUtils_GeneratePatches(cJSON *from,cJSON *to); -void cJSONUtils_AddPatchToArray(cJSON *array,const char *op,const char *path,cJSON *val); /* Utility for generating patch array entries. */ -int cJSONUtils_ApplyPatches(cJSON *object,cJSON *patches); /* Returns 0 for success. */ +/* Implement RFC6902 (https://tools.ietf.org/html/rfc6902) JSON Patch spec. */ +cJSON* cJSONUtils_GeneratePatches(cJSON *from, cJSON *to); +/* Utility for generating patch array entries. */ +void cJSONUtils_AddPatchToArray(cJSON *array, const char *op, const char *path, cJSON *val); +/* Returns 0 for success. */ +int cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches); /* // Note that ApplyPatches is NOT atomic on failure. To implement an atomic ApplyPatches, use: //int cJSONUtils_AtomicApplyPatches(cJSON **object, cJSON *patches) //{ -// cJSON *modme=cJSON_Duplicate(*object,1); -// int error=cJSONUtils_ApplyPatches(modme,patches); -// if (!error) {cJSON_Delete(*object);*object=modme;} -// else cJSON_Delete(modme); -// return error; +// cJSON *modme = cJSON_Duplicate(*object, 1); +// int error = cJSONUtils_ApplyPatches(modme, patches); +// if (!error) +// { +// cJSON_Delete(*object); +// *object = modme; +// } +// else +// { +// cJSON_Delete(modme); +// } +// +// return error; //} // Code not added to library since this strategy is a LOT slower. */ /* Implement RFC7386 (https://tools.ietf.org/html/rfc7396) JSON Merge Patch spec. */ -cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch); /* target will be modified by patch. return value is new ptr for target. */ -cJSON *cJSONUtils_GenerateMergePatch(cJSON *from,cJSON *to); /* generates a patch to move from -> to */ +/* target will be modified by patch. return value is new ptr for target. */ +cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch); +/* generates a patch to move from -> to */ +cJSON *cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to); -char *cJSONUtils_FindPointerFromObjectTo(cJSON *object,cJSON *target); /* Given a root object and a target object, construct a pointer from one to the other. */ +/* Given a root object and a target object, construct a pointer from one to the other. */ +char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target); -void cJSONUtils_SortObject(cJSON *object); /* Sorts the members of the object into alphabetical order. */ +/* Sorts the members of the object into alphabetical order. */ +void cJSONUtils_SortObject(cJSON *object); From cb6445f47b9e38405601f012e2c1458c30c51cc0 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Thu, 13 Oct 2016 23:26:53 +0700 Subject: [PATCH 03/23] reformatting: cJSON_strcasecmp --- cJSON_Utils.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index 82aafee..d421161 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -4,11 +4,25 @@ #include #include "cJSON_Utils.h" -static int cJSONUtils_strcasecmp(const char *s1,const char *s2) +static int cJSONUtils_strcasecmp(const char *s1, const char *s2) { - if (!s1) return (s1==s2)?0:1;if (!s2) return 1; - for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; - return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); + if (!s1) + { + return (s1 == s2) ? 0 : 1; /* both NULL? */ + } + if (!s2) + { + return 1; + } + for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) + { + if(*s1 == 0) + { + return 0; + } + } + + return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); } /* JSON Pointer implementation: */ @@ -392,4 +406,4 @@ cJSON *cJSONUtils_GenerateMergePatch(cJSON *from,cJSON *to) } if (!patch->child) {cJSON_Delete(patch);return 0;} return patch; -} \ No newline at end of file +} From 2f002879c0b8e47bedcec7d778f8ab07ae472121 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Thu, 13 Oct 2016 23:40:02 +0700 Subject: [PATCH 04/23] reformatting: cJSONUtils_Pstrcasecmp --- cJSON_Utils.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index d421161..8015b7a 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -26,15 +26,39 @@ static int cJSONUtils_strcasecmp(const char *s1, const char *s2) } /* JSON Pointer implementation: */ -static int cJSONUtils_Pstrcasecmp(const char *a,const char *e) +static int cJSONUtils_Pstrcasecmp(const char *a, const char *e) { - if (!a || !e) return (a==e)?0:1; - for (;*a && *e && *e!='/';a++,e++) { - if (*e=='~') {if (!(e[1]=='0' && *a=='~') && !(e[1]=='1' && *a=='/')) return 1; else e++;} - else if (tolower(*a)!=tolower(*e)) return 1; - } - if ((*e!=0 && *e!='/') != (*a!=0)) return 1; - return 0; + if (!a || !e) + { + return (a == e) ? 0 : 1; /* both NULL? */ + } + for (; *a && *e && (*e != '/'); a++, e++) /* compare until next '/' */ + { + if (*e == '~') + { + /* check for escaped '~' (~0) and '/' (~1) */ + if (!((e[1] == '0') && (*a == '~')) && !((e[1] == '1') && (*a == '/'))) + { + /* invalid escape sequence or wrong character in *a */ + return 1; + } + else + { + e++; + } + } + else if (tolower(*a) != tolower(*e)) + { + return 1; + } + } + if (((*e != 0) && (*e != '/')) != (*a != 0)) + { + /* one string has ended, the other not */ + return 1; + } + + return 0; } static int cJSONUtils_PointerEncodedstrlen(const char *s) {int l=0;for (;*s;s++,l++) if (*s=='~' || *s=='/') l++;return l;} From 3f6716e63a489fe3d5967297cc504774e1f9a4b0 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Thu, 13 Oct 2016 23:42:34 +0700 Subject: [PATCH 05/23] reformatting: cJSONUtils_PointerEncodedstrlen --- cJSON_Utils.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index 8015b7a..f816948 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -61,7 +61,19 @@ static int cJSONUtils_Pstrcasecmp(const char *a, const char *e) return 0; } -static int cJSONUtils_PointerEncodedstrlen(const char *s) {int l=0;for (;*s;s++,l++) if (*s=='~' || *s=='/') l++;return l;} +static int cJSONUtils_PointerEncodedstrlen(const char *s) +{ + int l = 0; + for (; *s; s++, l++) + { + if ((*s == '~') || (*s == '/')) + { + l++; + } + } + + return l; +} static void cJSONUtils_PointerEncodedstrcpy(char *d,const char *s) { From 7771225e35370f0e208f8cc2de2a9b9d0c9d5060 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Thu, 13 Oct 2016 23:47:40 +0700 Subject: [PATCH 06/23] reformatting: cJSONUtils_PointerEncodedstrcpy --- cJSON_Utils.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index f816948..13bd463 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -75,15 +75,27 @@ static int cJSONUtils_PointerEncodedstrlen(const char *s) return l; } -static void cJSONUtils_PointerEncodedstrcpy(char *d,const char *s) +static void cJSONUtils_PointerEncodedstrcpy(char *d, const char *s) { - for (;*s;s++) - { - if (*s=='/') {*d++='~';*d++='1';} - else if (*s=='~') {*d++='~';*d++='0';} - else *d++=*s; - } - *d=0; + for (; *s; s++) + { + if (*s == '/') + { + *d++ = '~'; + *d++ = '1'; + } + else if (*s == '~') + { + *d++ = '~'; + *d++ = '0'; + } + else + { + *d++ = *s; + } + } + + *d = '\0'; } char *cJSONUtils_FindPointerFromObjectTo(cJSON *object,cJSON *target) From c6cb991e3f833f91811416530b73aa5872049544 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Thu, 13 Oct 2016 23:48:53 +0700 Subject: [PATCH 07/23] reformatting: cJSON.h: remove trailing spaces --- cJSON.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cJSON.h b/cJSON.h index 6b535a1..c2b8d57 100644 --- a/cJSON.h +++ b/cJSON.h @@ -1,16 +1,16 @@ /* Copyright (c) 2009 Dave Gamble - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -36,7 +36,7 @@ extern "C" #define cJSON_String (1 << 4) #define cJSON_Array (1 << 5) #define cJSON_Object (1 << 6) - + #define cJSON_IsReference 256 #define cJSON_StringIsConst 512 @@ -93,7 +93,7 @@ extern cJSON *cJSON_GetObjectItem(const cJSON *object, const char *string); 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 calls create a cJSON item of the appropriate type. */ extern cJSON *cJSON_CreateNull(void); extern cJSON *cJSON_CreateTrue(void); From 158ddceab3071130941099aeb9a74f53aa554368 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Fri, 14 Oct 2016 00:05:58 +0700 Subject: [PATCH 08/23] reformatting: cJSONUtils_FindPointerFromObjectTo --- cJSON_Utils.c | 71 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index 13bd463..ac5df2c 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -98,37 +98,52 @@ static void cJSONUtils_PointerEncodedstrcpy(char *d, const char *s) *d = '\0'; } -char *cJSONUtils_FindPointerFromObjectTo(cJSON *object,cJSON *target) +char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target) { - int type=object->type,c=0;cJSON *obj=0; + int type = object->type; + int c = 0; + cJSON *obj = 0; - if (object==target) return strdup(""); + if (object == target) + { + /* found */ + return strdup(""); + } - for (obj=object->child;obj;obj=obj->next,c++) - { - char *found=cJSONUtils_FindPointerFromObjectTo(obj,target); - if (found) - { - if (type==cJSON_Array) - { - char *ret=(char*)malloc(strlen(found)+23); - sprintf(ret,"/%d%s",c,found); - free(found); - return ret; - } - else if (type==cJSON_Object) - { - char *ret=(char*)malloc(strlen(found)+cJSONUtils_PointerEncodedstrlen(obj->string)+2); - *ret='/';cJSONUtils_PointerEncodedstrcpy(ret+1,obj->string); - strcat(ret,found); - free(found); - return ret; - } - free(found); - return 0; - } - } - return 0; + /* recursively search all children of the object */ + for (obj = object->child; obj; obj = obj->next, c++) + { + char *found = cJSONUtils_FindPointerFromObjectTo(obj, target); + if (found) + { + if (type == 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); /* / */ + free(found); + + return ret; + } + else if (type == cJSON_Object) + { + char *ret = (char*)malloc(strlen(found) + cJSONUtils_PointerEncodedstrlen(obj->string) + 2); + *ret = '/'; + cJSONUtils_PointerEncodedstrcpy(ret + 1, obj->string); + strcat(ret, found); + free(found); + + return ret; + } + + /* reached leaf of the tree, found nothing */ + free(found); + return 0; + } + } + + /* not found */ + return 0; } cJSON *cJSONUtils_GetPointer(cJSON *object,const char *pointer) From 5713edb71081dcc02e772468c3b24e68dfb724fc Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Fri, 14 Oct 2016 00:18:15 +0700 Subject: [PATCH 09/23] reformatting: cJSON_Utils_GetPointer NOTE: This can change the assembly slightly, in my case it reordered two instructions. This is due to the change from: which = (10 * which) + *pointer++ - '0'; to which = (10 * which) + (*pointer++ - '0'); This means that after the change, the subtraction runs before the addition instead of after that. That shouldn't change the behavior though. --- cJSON_Utils.c | 57 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index ac5df2c..afbb593 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -146,24 +146,47 @@ char *cJSONUtils_FindPointerFromObjectTo(cJSON *object, cJSON *target) return 0; } -cJSON *cJSONUtils_GetPointer(cJSON *object,const char *pointer) +cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer) { - while (*pointer++=='/' && object) - { - if (object->type==cJSON_Array) - { - int which=0; while (*pointer>='0' && *pointer<='9') which=(10*which) + *pointer++ - '0'; - if (*pointer && *pointer!='/') return 0; - object=cJSON_GetArrayItem(object,which); - } - else if (object->type==cJSON_Object) - { - object=object->child; while (object && cJSONUtils_Pstrcasecmp(object->string,pointer)) object=object->next; /* GetObjectItem. */ - while (*pointer && *pointer!='/') pointer++; - } - else return 0; - } - return object; + /* follow path of the pointer */ + while ((*pointer++ == '/') && object) + { + if (object->type == cJSON_Array) + { + int which = 0; + /* parse array index */ + while ((*pointer >= '0') && (*pointer <= '9')) + { + which = (10 * which) + (*pointer++ - '0'); + } + if (*pointer && (*pointer != '/')) + { + /* not end of string or new path token */ + return 0; + } + object = cJSON_GetArrayItem(object, which); + } + else if (object->type == cJSON_Object) + { + object = object->child; + /* GetObjectItem. */ + while (object && cJSONUtils_Pstrcasecmp(object->string, pointer)) + { + object = object->next; + } + /* skip to the next path token or end of string */ + while (*pointer && (*pointer != '/')) + { + pointer++; + } + } + else + { + return 0; + } + } + + return object; } /* JSON Patch implementation. */ From a21a124d404ec8727f4d7663febec65951831b51 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Sat, 15 Oct 2016 12:20:47 +0700 Subject: [PATCH 10/23] reformatting: cJSONUtils_InplaceDecodePointerString --- cJSON_Utils.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index afbb593..5658563 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -192,9 +192,17 @@ cJSON *cJSONUtils_GetPointer(cJSON *object, const char *pointer) /* JSON Patch implementation. */ static void cJSONUtils_InplaceDecodePointerString(char *string) { - char *s2=string; - for (;*string;s2++,string++) *s2=(*string!='~')?(*string):((*(++string)=='0')?'~':'/'); - *s2=0; + char *s2 = string; + for (; *string; s2++, string++) + { + *s2 = (*string != '~') + ? (*string) + : ((*(++string) == '0') + ? '~' + : '/'); + } + + *s2 = '\0'; } static cJSON *cJSONUtils_PatchDetach(cJSON *object,const char *path) From 1235c622355b7247ab2f4800b0a7f05191cfe4f0 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Mon, 17 Oct 2016 01:17:31 +0700 Subject: [PATCH 11/23] reformatting: cJSONUtils_PatchDetach --- cJSON_Utils.c | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index 5658563..c717285 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -205,19 +205,41 @@ static void cJSONUtils_InplaceDecodePointerString(char *string) *s2 = '\0'; } -static cJSON *cJSONUtils_PatchDetach(cJSON *object,const char *path) +static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path) { - char *parentptr=0,*childptr=0;cJSON *parent=0,*ret=0; + char *parentptr = 0; + char *childptr = 0; + cJSON *parent = 0; + cJSON *ret = 0; - parentptr=strdup(path); childptr=strrchr(parentptr,'/'); if (childptr) *childptr++=0; - parent=cJSONUtils_GetPointer(object,parentptr); - cJSONUtils_InplaceDecodePointerString(childptr); + /* copy path and split it in parent and child */ + parentptr = strdup(path); + childptr = strrchr(parentptr, '/'); /* last '/' */ + if (childptr) + { + /* split strings */ + *childptr++ = '\0'; + } + parent = cJSONUtils_GetPointer(object, parentptr); + cJSONUtils_InplaceDecodePointerString(childptr); - if (!parent) ret=0; /* Couldn't find object to remove child from. */ - else if (parent->type==cJSON_Array) ret=cJSON_DetachItemFromArray(parent,atoi(childptr)); - else if (parent->type==cJSON_Object) ret=cJSON_DetachItemFromObject(parent,childptr); - free(parentptr); - return ret; + if (!parent) + { + /* Couldn't find object to remove child from. */ + ret = 0; + } + else if (parent->type == cJSON_Array) + { + ret = cJSON_DetachItemFromArray(parent, atoi(childptr)); + } + else if (parent->type == cJSON_Object) + { + ret = cJSON_DetachItemFromObject(parent, childptr); + } + free(parentptr); + + /* return the detachted item */ + return ret; } static int cJSONUtils_Compare(cJSON *a,cJSON *b) From 284a8017b76ce5c4fd82188439e288debf463046 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Mon, 17 Oct 2016 01:23:37 +0700 Subject: [PATCH 12/23] reformatting: cJSONUtils_Compare --- cJSON_Utils.c | 77 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index c717285..f1a2bea 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -242,31 +242,62 @@ static cJSON *cJSONUtils_PatchDetach(cJSON *object, const char *path) return ret; } -static int cJSONUtils_Compare(cJSON *a,cJSON *b) +static int cJSONUtils_Compare(cJSON *a, cJSON *b) { - if (a->type!=b->type) return -1; /* mismatched type. */ - switch (a->type) - { - case cJSON_Number: return (a->valueint!=b->valueint || a->valuedouble!=b->valuedouble)?-2:0; /* numeric mismatch. */ - case cJSON_String: return (strcmp(a->valuestring,b->valuestring)!=0)?-3:0; /* string mismatch. */ - case cJSON_Array: for (a=a->child,b=b->child;a && b;a=a->next,b=b->next) {int err=cJSONUtils_Compare(a,b);if (err) return err;} - return (a || b)?-4:0; /* array size mismatch. */ - case cJSON_Object: - cJSONUtils_SortObject(a); - cJSONUtils_SortObject(b); - a=a->child,b=b->child; - while (a && b) - { - int err; - if (cJSONUtils_strcasecmp(a->string,b->string)) return -6; /* missing member */ - err=cJSONUtils_Compare(a,b);if (err) return err; - a=a->next,b=b->next; - } - return (a || b)?-5:0; /* object length mismatch */ + if (a->type != b->type) + { + /* mismatched type. */ + return -1; + } + switch (a->type) + { + case cJSON_Number: + /* numeric mismatch. */ + return ((a->valueint != b->valueint) || (a->valuedouble != b->valuedouble)) ? -2 : 0; + case cJSON_String: + /* string mismatch. */ + return (strcmp(a->valuestring, b->valuestring) != 0) ? -3 : 0; + case cJSON_Array: + for (a = a->child, b = b->child; a && b; a = a->next, b = b->next) + { + int err = cJSONUtils_Compare(a, b); + if (err) + { + return err; + } + } + /* array size mismatch? (one of both children is not NULL) */ + return (a || b) ? -4 : 0; + case cJSON_Object: + cJSONUtils_SortObject(a); + cJSONUtils_SortObject(b); + a = a->child; + b = b->child; + while (a && b) + { + int err; + /* compare object keys */ + if (cJSONUtils_strcasecmp(a->string, b->string)) + { + /* missing member */ + return -6; + } + err = cJSONUtils_Compare(a, b); + if (err) + { + return err; + } + a = a->next; + b = b->next; + } + /* object length mismatch (one of both children is not null) */ + return (a || b) ? -5 : 0; - default: break; - } - return 0; + default: + break; + } + /* null, true or false */ + return 0; } static int cJSONUtils_ApplyPatch(cJSON *object,cJSON *patch) From d883f9b9b06b13a7c4f8e81cade77cfaf1c5954c Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Mon, 17 Oct 2016 11:32:47 +0700 Subject: [PATCH 13/23] reformatting: cJSONUtils_ApplyPatch --- cJSON_Utils.c | 205 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 148 insertions(+), 57 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index f1a2bea..969ca5c 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -300,73 +300,164 @@ static int cJSONUtils_Compare(cJSON *a, cJSON *b) return 0; } -static int cJSONUtils_ApplyPatch(cJSON *object,cJSON *patch) +static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch) { - cJSON *op=0,*path=0,*value=0,*parent=0;int opcode=0;char *parentptr=0,*childptr=0; + cJSON *op = 0; + cJSON *path = 0; + cJSON *value = 0; + cJSON *parent = 0; + int opcode = 0; + char *parentptr = 0; + char *childptr = 0; - op=cJSON_GetObjectItem(patch,"op"); - path=cJSON_GetObjectItem(patch,"path"); - if (!op || !path) return 2; /* malformed patch. */ + op = cJSON_GetObjectItem(patch, "op"); + path = cJSON_GetObjectItem(patch, "path"); + if (!op || !path) + { + /* malformed patch. */ + return 2; + } - if (!strcmp(op->valuestring,"add")) opcode=0; - else if (!strcmp(op->valuestring,"remove")) opcode=1; - else if (!strcmp(op->valuestring,"replace"))opcode=2; - else if (!strcmp(op->valuestring,"move")) opcode=3; - else if (!strcmp(op->valuestring,"copy")) opcode=4; - else if (!strcmp(op->valuestring,"test")) return cJSONUtils_Compare(cJSONUtils_GetPointer(object,path->valuestring),cJSON_GetObjectItem(patch,"value")); - else return 3; /* unknown opcode. */ + /* decode operation */ + if (!strcmp(op->valuestring, "add")) + { + opcode = 0; + } + else if (!strcmp(op->valuestring, "remove")) + { + opcode = 1; + } + else if (!strcmp(op->valuestring, "replace")) + { + opcode = 2; + } + else if (!strcmp(op->valuestring, "move")) + { + opcode = 3; + } + else if (!strcmp(op->valuestring, "copy")) + { + opcode = 4; + } + else if (!strcmp(op->valuestring, "test")) + { + /* compare value: {...} with the given path */ + return cJSONUtils_Compare(cJSONUtils_GetPointer(object, path->valuestring), cJSON_GetObjectItem(patch, "value")); + } + else + { + /* unknown opcode. */ + return 3; + } - if (opcode==1 || opcode==2) /* Remove/Replace */ - { - cJSON_Delete(cJSONUtils_PatchDetach(object,path->valuestring)); /* Get rid of old. */ - if (opcode==1) return 0; /* For Remove, this is job done. */ - } + /* Remove/Replace */ + if ((opcode == 1) || (opcode == 2)) + { + /* Get rid of old. */ + cJSON_Delete(cJSONUtils_PatchDetach(object, path->valuestring)); + if (opcode == 1) + { + /* For Remove, this is job done. */ + return 0; + } + } - if (opcode==3 || opcode==4) /* Copy/Move uses "from". */ - { - cJSON *from=cJSON_GetObjectItem(patch,"from"); if (!from) return 4; /* missing "from" for copy/move. */ + /* Copy/Move uses "from". */ + if ((opcode == 3) || (opcode == 4)) + { + cJSON *from = cJSON_GetObjectItem(patch, "from"); + if (!from) + { + /* missing "from" for copy/move. */ + return 4; + } - if (opcode==3) value=cJSONUtils_PatchDetach(object,from->valuestring); - if (opcode==4) value=cJSONUtils_GetPointer(object,from->valuestring); - if (!value) return 5; /* missing "from" for copy/move. */ - if (opcode==4) value=cJSON_Duplicate(value,1); - if (!value) return 6; /* out of memory for copy/move. */ - } - else /* Add/Replace uses "value". */ - { - value=cJSON_GetObjectItem(patch,"value"); - if (!value) return 7; /* missing "value" for add/replace. */ - value=cJSON_Duplicate(value,1); - if (!value) return 8; /* out of memory for add/replace. */ - } - - /* Now, just add "value" to "path". */ + if (opcode == 3) + { + /* move */ + value = cJSONUtils_PatchDetach(object, from->valuestring); + } + if (opcode == 4) + { + /* copy */ + value = cJSONUtils_GetPointer(object, from->valuestring); + } + if (!value) + { + /* missing "from" for copy/move. */ + return 5; + } + if (opcode == 4) + { + value = cJSON_Duplicate(value, 1); + } + if (!value) + { + /* out of memory for copy/move. */ + return 6; + } + } + else /* Add/Replace uses "value". */ + { + value = cJSON_GetObjectItem(patch, "value"); + if (!value) + { + /* missing "value" for add/replace. */ + return 7; + } + value = cJSON_Duplicate(value, 1); + if (!value) + { + /* out of memory for add/replace. */ + return 8; + } + } - parentptr=strdup(path->valuestring); childptr=strrchr(parentptr,'/'); if (childptr) *childptr++=0; - parent=cJSONUtils_GetPointer(object,parentptr); - cJSONUtils_InplaceDecodePointerString(childptr); + /* Now, just add "value" to "path". */ - /* add, remove, replace, move, copy, test. */ - if (!parent) {free(parentptr); cJSON_Delete(value); return 9;} /* Couldn't find object to add to. */ - else if (parent->type==cJSON_Array) - { - if (!strcmp(childptr,"-")) cJSON_AddItemToArray(parent,value); - else cJSON_InsertItemInArray(parent,atoi(childptr),value); - } - else if (parent->type==cJSON_Object) - { - cJSON_DeleteItemFromObject(parent,childptr); - cJSON_AddItemToObject(parent,childptr,value); - } - else - { - cJSON_Delete(value); - } - free(parentptr); - return 0; + /* split pointer in parent and child */ + parentptr = strdup(path->valuestring); + childptr = strrchr(parentptr, '/'); + if (childptr) + { + *childptr++ = '\0'; + } + parent = cJSONUtils_GetPointer(object, parentptr); + cJSONUtils_InplaceDecodePointerString(childptr); + + /* add, remove, replace, move, copy, test. */ + if (!parent) + { + /* Couldn't find object to add to. */ + free(parentptr); + cJSON_Delete(value); + return 9; + } + else if (parent->type == cJSON_Array) + { + if (!strcmp(childptr, "-")) + { + cJSON_AddItemToArray(parent, value); + } + else + { + cJSON_InsertItemInArray(parent, atoi(childptr), value); + } + } + else if (parent->type == cJSON_Object) + { + cJSON_DeleteItemFromObject(parent, childptr); + cJSON_AddItemToObject(parent, childptr, value); + } + else + { + cJSON_Delete(value); + } + free(parentptr); + + return 0; } - int cJSONUtils_ApplyPatches(cJSON *object,cJSON *patches) { int err; From e8a67f0e4b9617fd4a4ce3c12e891c9c35227585 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Mon, 17 Oct 2016 11:34:33 +0700 Subject: [PATCH 14/23] reformatting: cJSONUtils_ApplyPatches --- cJSON_Utils.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index 969ca5c..8d9d741 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -458,17 +458,28 @@ static int cJSONUtils_ApplyPatch(cJSON *object, cJSON *patch) return 0; } -int cJSONUtils_ApplyPatches(cJSON *object,cJSON *patches) +int cJSONUtils_ApplyPatches(cJSON *object, cJSON *patches) { - int err; - if (patches->type!=cJSON_Array) return 1; /* malformed patches. */ - if (patches) patches=patches->child; - while (patches) - { - if ((err=cJSONUtils_ApplyPatch(object,patches))) return err; - patches=patches->next; - } - return 0; + int err; + if (patches->type != cJSON_Array) + { + /* malformed patches. */ + return 1; + } + if (patches) + { + patches = patches->child; + } + while (patches) + { + if ((err = cJSONUtils_ApplyPatch(object, patches))) + { + return err; + } + patches = patches->next; + } + + return 0; } static void cJSONUtils_GeneratePatch(cJSON *patches,const char *op,const char *path,const char *suffix,cJSON *val) From d6a6abeca0758bc43a2ded4e2133459c5f384ab3 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Mon, 17 Oct 2016 17:00:46 +0700 Subject: [PATCH 15/23] reformatting: cJSONUtils_GeneratePatch --- cJSON_Utils.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index 8d9d741..6f40c0d 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -482,20 +482,26 @@ 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 char *op, const char *path, const char *suffix, cJSON *val) { - cJSON *patch=cJSON_CreateObject(); - cJSON_AddItemToObject(patch,"op",cJSON_CreateString(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)); - free(newpath); - } - else cJSON_AddItemToObject(patch,"path",cJSON_CreateString(path)); - if (val) cJSON_AddItemToObject(patch,"value",cJSON_Duplicate(val,1)); - cJSON_AddItemToArray(patches,patch); + cJSON *patch = cJSON_CreateObject(); + cJSON_AddItemToObject(patch, "op", cJSON_CreateString(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)); + free(newpath); + } + else + { + cJSON_AddItemToObject(patch, "path", cJSON_CreateString(path)); + } + if (val) + { + cJSON_AddItemToObject(patch, "value", cJSON_Duplicate(val, 1)); + } + cJSON_AddItemToArray(patches, patch); } void cJSONUtils_AddPatchToArray(cJSON *array,const char *op,const char *path,cJSON *val) {cJSONUtils_GeneratePatch(array,op,path,0,val);} From 52e53acfc38796c3046f7fed46995c451537d957 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Mon, 17 Oct 2016 17:01:52 +0700 Subject: [PATCH 16/23] reformatting: cJSON_AddPatchToArray --- cJSON_Utils.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index 6f40c0d..9b7e85a 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -504,7 +504,10 @@ static void cJSONUtils_GeneratePatch(cJSON *patches, const char *op, const char cJSON_AddItemToArray(patches, patch); } -void cJSONUtils_AddPatchToArray(cJSON *array,const char *op,const char *path,cJSON *val) {cJSONUtils_GeneratePatch(array,op,path,0,val);} +void cJSONUtils_AddPatchToArray(cJSON *array, const char *op, const char *path, cJSON *val) +{ + cJSONUtils_GeneratePatch(array, op, path, 0, val); +} static void cJSONUtils_CompareToPatch(cJSON *patches,const char *path,cJSON *from,cJSON *to) { From 8879ed5dbcc362507cd29d7b2fd42b4faa572502 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Mon, 17 Oct 2016 17:35:49 +0700 Subject: [PATCH 17/23] reformatting: cJSONUtils_CompareToPatch --- cJSON_Utils.c | 140 +++++++++++++++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 52 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index 9b7e85a..eb3f6d8 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -509,64 +509,100 @@ void cJSONUtils_AddPatchToArray(cJSON *array, const char *op, const char *path, cJSONUtils_GeneratePatch(array, op, path, 0, val); } -static void cJSONUtils_CompareToPatch(cJSON *patches,const char *path,cJSON *from,cJSON *to) +static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *from, cJSON *to) { - if (from->type!=to->type) {cJSONUtils_GeneratePatch(patches,"replace",path,0,to); return; } - - switch (from->type) - { - case cJSON_Number: - if (from->valueint!=to->valueint || from->valuedouble!=to->valuedouble) - cJSONUtils_GeneratePatch(patches,"replace",path,0,to); - return; - - case cJSON_String: - if (strcmp(from->valuestring,to->valuestring)!=0) - cJSONUtils_GeneratePatch(patches,"replace",path,0,to); - return; + if (from->type != to->type) + { + cJSONUtils_GeneratePatch(patches, "replace", path, 0, to); + return; + } - case cJSON_Array: - { - int c;char *newpath=(char*)malloc(strlen(path)+23); /* Allow space for 64bit int. */ - for (c=0,from=from->child,to=to->child;from && to;from=from->next,to=to->next,c++){ - sprintf(newpath,"%s/%d",path,c); cJSONUtils_CompareToPatch(patches,newpath,from,to); - } - for (;from;from=from->next,c++) {sprintf(newpath,"%d",c); cJSONUtils_GeneratePatch(patches,"remove",path,newpath,0); } - for (;to;to=to->next,c++) cJSONUtils_GeneratePatch(patches,"add",path,"-",to); - free(newpath); - return; - } + switch (from->type) + { + case cJSON_Number: + if ((from->valueint != to->valueint) || (from->valuedouble != to->valuedouble)) + { + cJSONUtils_GeneratePatch(patches, "replace", path, 0, to); + } + return; - case cJSON_Object: - { - cJSON *a,*b; - cJSONUtils_SortObject(from); - cJSONUtils_SortObject(to); - - a=from->child,b=to->child; - while (a || b) - { - int diff=(!a)?1:(!b)?-1:cJSONUtils_strcasecmp(a->string,b->string); - if (!diff) - { - char *newpath=(char*)malloc(strlen(path)+cJSONUtils_PointerEncodedstrlen(a->string)+2); - cJSONUtils_PointerEncodedstrcpy(newpath+sprintf(newpath,"%s/",path),a->string); - cJSONUtils_CompareToPatch(patches,newpath,a,b); - free(newpath); - a=a->next; - b=b->next; - } - else if (diff<0) {cJSONUtils_GeneratePatch(patches,"remove",path,a->string,0); a=a->next;} - else {cJSONUtils_GeneratePatch(patches,"add",path,b->string,b); b=b->next;} - } - return; - } + case cJSON_String: + if (strcmp(from->valuestring, to->valuestring) != 0) + { + cJSONUtils_GeneratePatch(patches, "replace", path, 0, to); + } + return; - default: break; - } + case cJSON_Array: + { + int c; + char *newpath = (char*)malloc(strlen(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 */ + 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); + } + /* add new elements in 'to' that were not in 'from' */ + for (; to; to = to->next, c++) + { + cJSONUtils_GeneratePatch(patches, "add", path, "-", to); + } + free(newpath); + return; + } + + case cJSON_Object: + { + cJSON *a; + cJSON *b; + cJSONUtils_SortObject(from); + cJSONUtils_SortObject(to); + + a = from->child; + b = to->child; + /* 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)); + 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); + /* create a patch for the element */ + cJSONUtils_CompareToPatch(patches, newpath, a, b); + free(newpath); + a = a->next; + b = b->next; + } + else if (diff < 0) + { + /* object element doesn't exist in 'to' --> remove it */ + cJSONUtils_GeneratePatch(patches, "remove", path, a->string, 0); + a = a->next; + } + else + { + /* object element doesn't exist in 'from' --> add it */ + cJSONUtils_GeneratePatch(patches, "add", path, b->string, b); + b = b->next; + } + } + return; + } + + default: + break; + } } - cJSON* cJSONUtils_GeneratePatches(cJSON *from,cJSON *to) { cJSON *patches=cJSON_CreateArray(); From ec9d1cfedba24a7fc33fee445da75fdd1923f79f Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Mon, 17 Oct 2016 17:41:50 +0700 Subject: [PATCH 18/23] reformatting: cJSONUtils_GeneratePatches --- cJSON_Utils.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index eb3f6d8..db7fb7e 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -603,13 +603,13 @@ static void cJSONUtils_CompareToPatch(cJSON *patches, const char *path, cJSON *f } } -cJSON* cJSONUtils_GeneratePatches(cJSON *from,cJSON *to) +cJSON* cJSONUtils_GeneratePatches(cJSON *from, cJSON *to) { - cJSON *patches=cJSON_CreateArray(); - cJSONUtils_CompareToPatch(patches,"",from,to); - return patches; -} + cJSON *patches = cJSON_CreateArray(); + cJSONUtils_CompareToPatch(patches, "", from, to); + return patches; +} static cJSON *cJSONUtils_SortList(cJSON *list) { From 8964287ec44d754aff11d9e251e7bf5fbe9ae24c Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Fri, 28 Oct 2016 23:27:15 +0700 Subject: [PATCH 19/23] reformatting: cJSONUtils_SortList --- cJSON_Utils.c | 128 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 99 insertions(+), 29 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index db7fb7e..b59510f 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -611,44 +611,114 @@ cJSON* cJSONUtils_GeneratePatches(cJSON *from, cJSON *to) return patches; } +/* sort lists using mergesort */ static cJSON *cJSONUtils_SortList(cJSON *list) { - cJSON *first=list,*second=list,*ptr=list; + cJSON *first = list; + cJSON *second = list; + cJSON *ptr = list; - if (!list || !list->next) return list; /* One entry is sorted already. */ - - while (ptr && ptr->next && cJSONUtils_strcasecmp(ptr->string,ptr->next->string)<0) ptr=ptr->next; /* Test for list sorted. */ - if (!ptr || !ptr->next) return list; /* Leave sorted lists unmodified. */ - ptr=list; + if (!list || !list->next) + { + /* One entry is sorted already. */ + return list; + } - while (ptr) {second=second->next;ptr=ptr->next;if (ptr) ptr=ptr->next;} /* Walk two pointers to find the middle. */ - if (second && second->prev) second->prev->next=0; /* Split the lists */ + while (ptr && ptr->next && (cJSONUtils_strcasecmp(ptr->string, ptr->next->string) < 0)) + { + /* Test for list sorted. */ + ptr = ptr->next; + } + if (!ptr || !ptr->next) + { + /* Leave sorted lists unmodified. */ + return list; + } - first=cJSONUtils_SortList(first); /* Recursively sort the sub-lists. */ - second=cJSONUtils_SortList(second); - list=ptr=0; + /* reset ptr to the beginning */ + ptr = list; + while (ptr) + { + /* Walk two pointers to find the middle. */ + second = second->next; + ptr = ptr->next; + /* advances ptr two steps at a time */ + if (ptr) + { + ptr = ptr->next; + } + } + if (second && second->prev) + { + /* Split the lists */ + second->prev->next = 0; + } - while (first && second) /* Merge the sub-lists */ - { - if (cJSONUtils_strcasecmp(first->string,second->string)<0) - { - if (!list) list=ptr=first; - else {ptr->next=first;first->prev=ptr;ptr=first;} - first=first->next; - } - else - { - if (!list) list=ptr=second; - else {ptr->next=second;second->prev=ptr;ptr=second;} - second=second->next; - } - } - if (first) { if (!list) return first; ptr->next=first; first->prev=ptr; } /* Append any tails. */ - if (second) { if (!list) return second; ptr->next=second; second->prev=ptr; } + /* Recursively sort the sub-lists. */ + first = cJSONUtils_SortList(first); + second = cJSONUtils_SortList(second); + list = ptr = 0; - return list; + while (first && second) /* Merge the sub-lists */ + { + if (cJSONUtils_strcasecmp(first->string, second->string) < 0) + { + if (!list) + { + /* start merged list with the first element of the first list */ + list = ptr = first; + } + else + { + /* add first element of first list to merged list */ + ptr->next = first; + first->prev = ptr; + ptr = first; + } + first = first->next; + } + else + { + if (!list) + { + /* start merged list with the first element of the second list */ + list = ptr = second; + } + else + { + /* add first element of second list to merged list */ + ptr->next = second; + second->prev = ptr; + ptr = second; + } + second = second->next; + } + } + if (first) + { + /* Append rest of first list. */ + if (!list) + { + return first; + } + ptr->next = first; + first->prev = ptr; + } + if (second) + { + /* Append rest of second list */ + if (!list) + { + return second; + } + ptr->next = second; + second->prev = ptr; + } + + return list; } + void cJSONUtils_SortObject(cJSON *object) {object->child=cJSONUtils_SortList(object->child);} cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch) From c65514fcb430f2c5380d9264807c137d7c86b8d8 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Fri, 28 Oct 2016 23:37:21 +0700 Subject: [PATCH 20/23] reformatting: cJSONUtils_SortObject --- cJSON_Utils.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index b59510f..903e2da 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -718,8 +718,10 @@ static cJSON *cJSONUtils_SortList(cJSON *list) return list; } - -void cJSONUtils_SortObject(cJSON *object) {object->child=cJSONUtils_SortList(object->child);} +void cJSONUtils_SortObject(cJSON *object) +{ + object->child = cJSONUtils_SortList(object->child); +} cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch) { From 01a813f642b2606c5fd84444690c4681cd85b4d0 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Sat, 29 Oct 2016 12:40:41 +0700 Subject: [PATCH 21/23] reformatting: cJSONUtils_MergePatch --- cJSON_Utils.c | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index 903e2da..50dc9a3 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -725,21 +725,35 @@ void cJSONUtils_SortObject(cJSON *object) cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch) { - if (!patch || patch->type != cJSON_Object) {cJSON_Delete(target);return cJSON_Duplicate(patch,1);} - if (!target || target->type != cJSON_Object) {cJSON_Delete(target);target=cJSON_CreateObject();} + if (!patch || (patch->type != cJSON_Object)) + { + /* scalar value, array or NULL, just duplicate */ + cJSON_Delete(target); + return cJSON_Duplicate(patch, 1); + } - patch=patch->child; - while (patch) - { - if (patch->type == cJSON_NULL) cJSON_DeleteItemFromObject(target,patch->string); - else - { - cJSON *replaceme=cJSON_DetachItemFromObject(target,patch->string); - cJSON_AddItemToObject(target,patch->string,cJSONUtils_MergePatch(replaceme,patch)); - } - patch=patch->next; - } - return target; + if (!target || (target->type != cJSON_Object)) + { + cJSON_Delete(target); + target = cJSON_CreateObject(); + } + + patch = patch->child; + while (patch) + { + if (patch->type == cJSON_NULL) + { + /* NULL is the indicator to remove a value, see RFC7396 */ + cJSON_DeleteItemFromObject(target, patch->string); + } + else + { + cJSON *replaceme = cJSON_DetachItemFromObject(target, patch->string); + cJSON_AddItemToObject(target, patch->string, cJSONUtils_MergePatch(replaceme, patch)); + } + patch = patch->next; + } + return target; } cJSON *cJSONUtils_GenerateMergePatch(cJSON *from,cJSON *to) From c0b17dc65125ebc419b80a720c4b4ef53c1d13c8 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Sat, 29 Oct 2016 22:15:49 +0700 Subject: [PATCH 22/23] reformatting: cJSONUtils_GenerateMergePatch --- cJSON_Utils.c | 82 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 29 deletions(-) diff --git a/cJSON_Utils.c b/cJSON_Utils.c index 50dc9a3..618b89f 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -756,34 +756,58 @@ cJSON* cJSONUtils_MergePatch(cJSON *target, cJSON *patch) return target; } -cJSON *cJSONUtils_GenerateMergePatch(cJSON *from,cJSON *to) +cJSON *cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to) { - cJSON *patch=0; - if (!to) return cJSON_CreateNull(); - if (to->type!=cJSON_Object || !from || from->type!=cJSON_Object) return cJSON_Duplicate(to,1); - cJSONUtils_SortObject(from); - cJSONUtils_SortObject(to); - from=from->child;to=to->child; - patch=cJSON_CreateObject(); - while (from || to) - { - int compare=from?(to?strcmp(from->string,to->string):-1):1; - if (compare<0) - { - cJSON_AddItemToObject(patch,from->string,cJSON_CreateNull()); - from=from->next; - } - else if (compare>0) - { - cJSON_AddItemToObject(patch,to->string,cJSON_Duplicate(to,1)); - to=to->next; - } - else - { - if (cJSONUtils_Compare(from,to)) cJSON_AddItemToObject(patch,to->string,cJSONUtils_GenerateMergePatch(from,to)); - from=from->next;to=to->next; - } - } - if (!patch->child) {cJSON_Delete(patch);return 0;} - return patch; + cJSON *patch = 0; + if (!to) + { + /* patch to delete everything */ + return cJSON_CreateNull(); + } + if ((to->type != cJSON_Object) || !from || (from->type != cJSON_Object)) + { + return cJSON_Duplicate(to, 1); + } + + cJSONUtils_SortObject(from); + cJSONUtils_SortObject(to); + + from = from->child; + to = to->child; + patch = cJSON_CreateObject(); + while (from || to) + { + int compare = from ? (to ? strcmp(from->string, to->string) : -1) : 1; + if (compare < 0) + { + /* from has a value that to doesn't have -> remove */ + cJSON_AddItemToObject(patch, from->string, cJSON_CreateNull()); + from = from->next; + } + else if (compare > 0) + { + /* to has a value that from doesn't have -> add to patch */ + cJSON_AddItemToObject(patch, to->string, cJSON_Duplicate(to, 1)); + to = to->next; + } + else + { + /* object key exists in both objects */ + if (cJSONUtils_Compare(from, to)) + { + /* not identical --> generate a patch */ + cJSON_AddItemToObject(patch, to->string, cJSONUtils_GenerateMergePatch(from, to)); + } + /* next key in the object */ + from = from->next; + to = to->next; + } + } + if (!patch->child) + { + cJSON_Delete(patch); + return 0; + } + + return patch; } From ddeca827180f777ad0cedbb8818c430aea482c66 Mon Sep 17 00:00:00 2001 From: Max Bruckner Date: Sat, 29 Oct 2016 22:17:59 +0700 Subject: [PATCH 23/23] reformatting: cJSON.c: fix indentation --- cJSON.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cJSON.c b/cJSON.c index 36d9233..a3a3466 100644 --- a/cJSON.c +++ b/cJSON.c @@ -1722,7 +1722,7 @@ cJSON *cJSON_DetachItemFromArray(cJSON *array, int which) /* item doesn't exist */ return 0; } - if (c->prev) + if (c->prev) { /* not the first element */ c->prev->next = c->next;