reformatting: cJSONUtils_ApplyPatch

This commit is contained in:
Max Bruckner 2016-10-17 11:32:47 +07:00
parent 284a8017b7
commit d883f9b9b0

View File

@ -300,73 +300,164 @@ static int cJSONUtils_Compare(cJSON *a, cJSON *b)
return 0; 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"); op = cJSON_GetObjectItem(patch, "op");
path=cJSON_GetObjectItem(patch,"path"); path = cJSON_GetObjectItem(patch, "path");
if (!op || !path) return 2; /* malformed patch. */ if (!op || !path)
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. */
if (opcode==1 || opcode==2) /* Remove/Replace */
{ {
cJSON_Delete(cJSONUtils_PatchDetach(object,path->valuestring)); /* Get rid of old. */ /* malformed patch. */
if (opcode==1) return 0; /* For Remove, this is job done. */ return 2;
} }
if (opcode==3 || opcode==4) /* Copy/Move uses "from". */ /* decode operation */
if (!strcmp(op->valuestring, "add"))
{ {
cJSON *from=cJSON_GetObjectItem(patch,"from"); if (!from) return 4; /* missing "from" for copy/move. */ 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==3) value=cJSONUtils_PatchDetach(object,from->valuestring); /* Remove/Replace */
if (opcode==4) value=cJSONUtils_GetPointer(object,from->valuestring); if ((opcode == 1) || (opcode == 2))
if (!value) return 5; /* missing "from" for copy/move. */ {
if (opcode==4) value=cJSON_Duplicate(value,1); /* Get rid of old. */
if (!value) return 6; /* out of memory for copy/move. */ cJSON_Delete(cJSONUtils_PatchDetach(object, path->valuestring));
if (opcode == 1)
{
/* For Remove, this is job done. */
return 0;
}
}
/* 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)
{
/* 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". */ else /* Add/Replace uses "value". */
{ {
value=cJSON_GetObjectItem(patch,"value"); value = cJSON_GetObjectItem(patch, "value");
if (!value) return 7; /* missing "value" for add/replace. */ if (!value)
value=cJSON_Duplicate(value,1); {
if (!value) return 8; /* out of memory for add/replace. */ /* missing "value" for add/replace. */
return 7;
}
value = cJSON_Duplicate(value, 1);
if (!value)
{
/* out of memory for add/replace. */
return 8;
}
} }
/* Now, just add "value" to "path". */ /* Now, just add "value" to "path". */
parentptr=strdup(path->valuestring); childptr=strrchr(parentptr,'/'); if (childptr) *childptr++=0; /* split pointer in parent and child */
parent=cJSONUtils_GetPointer(object,parentptr); parentptr = strdup(path->valuestring);
childptr = strrchr(parentptr, '/');
if (childptr)
{
*childptr++ = '\0';
}
parent = cJSONUtils_GetPointer(object, parentptr);
cJSONUtils_InplaceDecodePointerString(childptr); cJSONUtils_InplaceDecodePointerString(childptr);
/* add, remove, replace, move, copy, test. */ /* add, remove, replace, move, copy, test. */
if (!parent) {free(parentptr); cJSON_Delete(value); return 9;} /* Couldn't find object to add to. */ if (!parent)
else if (parent->type==cJSON_Array)
{ {
if (!strcmp(childptr,"-")) cJSON_AddItemToArray(parent,value); /* Couldn't find object to add to. */
else cJSON_InsertItemInArray(parent,atoi(childptr),value); free(parentptr);
cJSON_Delete(value);
return 9;
} }
else if (parent->type==cJSON_Object) else if (parent->type == cJSON_Array)
{ {
cJSON_DeleteItemFromObject(parent,childptr); if (!strcmp(childptr, "-"))
cJSON_AddItemToObject(parent,childptr,value); {
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 else
{ {
cJSON_Delete(value); cJSON_Delete(value);
} }
free(parentptr); free(parentptr);
return 0; return 0;
} }
int cJSONUtils_ApplyPatches(cJSON *object,cJSON *patches) int cJSONUtils_ApplyPatches(cJSON *object,cJSON *patches)
{ {
int err; int err;