|
@@ -300,72 +300,163 @@ 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)
|
|
|
{
|