cJSON *cJSONUtils_GenerateMergePatch(cJSON *from, cJSON *to) { 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; }
static cJSON *generate_merge_patch(cJSON * const from, cJSON * const to, const cJSON_bool case_sensitive) { cJSON *from_child = NULL; cJSON *to_child = NULL; cJSON *patch = NULL; if (to == NULL) { /* patch to delete everything */ return cJSON_CreateNull(); } if (!cJSON_IsObject(to) || !cJSON_IsObject(from)) { return cJSON_Duplicate(to, 1); } sort_object(from, case_sensitive); sort_object(to, case_sensitive); from_child = from->child; to_child = to->child; patch = cJSON_CreateObject(); while (from_child || to_child) { int diff; 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 */ cJSON_AddItemToObject(patch, from_child->string, cJSON_CreateNull()); from_child = from_child->next; } else if (diff > 0) { /* to has a value that from doesn't have -> add to patch */ cJSON_AddItemToObject(patch, to_child->string, cJSON_Duplicate(to_child, 1)); to_child = to_child->next; } else { /* object key exists in both objects */ if (!compare_json(from_child, to_child, case_sensitive)) { /* not identical --> generate a patch */ cJSON_AddItemToObject(patch, to_child->string, cJSONUtils_GenerateMergePatch(from_child, to_child)); } /* next key in the object */ from_child = from_child->next; to_child = to_child->next; } } if (patch->child == NULL) { /* no patch generated */ cJSON_Delete(patch); return NULL; } return patch; }