refactor cJSONUtils_GenerateMergePatch

This commit is contained in:
Max Bruckner 2017-04-30 13:18:25 +02:00
parent 11b8a8cd76
commit bb2f868126
2 changed files with 41 additions and 18 deletions

View File

@ -1180,10 +1180,12 @@ CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const p
return target; return target;
} }
CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to) CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, cJSON * const to)
{ {
cJSON *from_child = NULL;
cJSON *to_child = NULL;
cJSON *patch = NULL; cJSON *patch = NULL;
if (!to) if (to == NULL)
{ {
/* patch to delete everything */ /* patch to delete everything */
return cJSON_CreateNull(); return cJSON_CreateNull();
@ -1196,39 +1198,59 @@ CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to)
cJSONUtils_SortObject(from); cJSONUtils_SortObject(from);
cJSONUtils_SortObject(to); cJSONUtils_SortObject(to);
from = from->child; from_child = from->child;
to = to->child; to_child = to->child;
patch = cJSON_CreateObject(); patch = cJSON_CreateObject();
while (from || to) while (from_child || to_child)
{ {
int compare = from ? (to ? strcmp(from->string, to->string) : -1) : 1; int diff;
if (compare < 0) if (from_child != NULL)
{
if (to_child != NULL)
{
diff = strcmp(from_child->string, to_child->string);
}
else
{
diff = -1;
}
}
else
{
diff = 1;
}
if (diff < 0)
{ {
/* from has a value that to doesn't have -> remove */ /* from has a value that to doesn't have -> remove */
cJSON_AddItemToObject(patch, from->string, cJSON_CreateNull()); cJSON_AddItemToObject(patch, from_child->string, cJSON_CreateNull());
from = from->next;
from_child = from_child->next;
} }
else if (compare > 0) else if (diff > 0)
{ {
/* to has a value that from doesn't have -> add to patch */ /* to has a value that from doesn't have -> add to patch */
cJSON_AddItemToObject(patch, to->string, cJSON_Duplicate(to, 1)); cJSON_AddItemToObject(patch, to_child->string, cJSON_Duplicate(to_child, 1));
to = to->next;
to_child = to_child->next;
} }
else else
{ {
/* object key exists in both objects */ /* object key exists in both objects */
if (cJSONUtils_Compare(from, to)) if (cJSONUtils_Compare(from_child, to_child))
{ {
/* not identical --> generate a patch */ /* not identical --> generate a patch */
cJSON_AddItemToObject(patch, to->string, cJSONUtils_GenerateMergePatch(from, to)); cJSON_AddItemToObject(patch, to_child->string, cJSONUtils_GenerateMergePatch(from_child, to_child));
} }
/* next key in the object */ /* next key in the object */
from = from->next; from_child = from_child->next;
to = to->next; to_child = to_child->next;
} }
} }
if (!patch->child) if (patch->child == NULL)
{ {
/* no patch generated */
cJSON_Delete(patch); cJSON_Delete(patch);
return NULL; return NULL;
} }

View File

@ -58,7 +58,8 @@ CJSON_PUBLIC(int) cJSONUtils_ApplyPatches(cJSON * const object, const cJSON * co
/* target will be modified by patch. return value is new ptr for target. */ /* target will be modified by patch. return value is new ptr for target. */
CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch); CJSON_PUBLIC(cJSON *) cJSONUtils_MergePatch(cJSON *target, const cJSON * const patch);
/* generates a patch to move from -> to */ /* generates a patch to move from -> to */
CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to); /* NOTE: This modifies objects in 'from' and 'to' by sorting the elements by their key */
CJSON_PUBLIC(cJSON *) cJSONUtils_GenerateMergePatch(cJSON * const from, cJSON * const to);
/* 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. */
CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target); CJSON_PUBLIC(char *) cJSONUtils_FindPointerFromObjectTo(const cJSON * const object, const cJSON * const target);