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;