| 824 | } |
| 825 | |
| 826 | static int apply_patch(cJSON *object, const cJSON *patch, const cJSON_bool case_sensitive) |
| 827 | { |
| 828 | cJSON *path = NULL; |
| 829 | cJSON *value = NULL; |
| 830 | cJSON *parent = NULL; |
| 831 | enum patch_operation opcode = INVALID; |
| 832 | unsigned char *parent_pointer = NULL; |
| 833 | unsigned char *child_pointer = NULL; |
| 834 | int status = 0; |
| 835 | |
| 836 | path = get_object_item(patch, "path", case_sensitive); |
| 837 | if (!cJSON_IsString(path)) |
| 838 | { |
| 839 | /* malformed patch. */ |
| 840 | status = 2; |
| 841 | goto cleanup; |
| 842 | } |
| 843 | |
| 844 | opcode = decode_patch_operation(patch, case_sensitive); |
| 845 | if (opcode == INVALID) |
| 846 | { |
| 847 | status = 3; |
| 848 | goto cleanup; |
| 849 | } |
| 850 | else if (opcode == TEST) |
| 851 | { |
| 852 | /* compare value: {...} with the given path */ |
| 853 | status = !compare_json(get_item_from_pointer(object, path->valuestring, case_sensitive), |
| 854 | get_object_item(patch, "value", case_sensitive), case_sensitive); |
| 855 | goto cleanup; |
| 856 | } |
| 857 | |
| 858 | /* special case for replacing the root */ |
| 859 | if (path->valuestring[0] == '\0') |
| 860 | { |
| 861 | if (opcode == REMOVE) |
| 862 | { |
| 863 | static const cJSON invalid = {NULL, NULL, NULL, cJSON_Invalid, NULL, 0, 0, NULL}; |
| 864 | |
| 865 | overwrite_item(object, invalid); |
| 866 | |
| 867 | status = 0; |
| 868 | goto cleanup; |
| 869 | } |
| 870 | |
| 871 | if ((opcode == REPLACE) || (opcode == ADD)) |
| 872 | { |
| 873 | value = get_object_item(patch, "value", case_sensitive); |
| 874 | if (value == NULL) |
| 875 | { |
| 876 | /* missing "value" for add/replace. */ |
| 877 | status = 7; |
| 878 | goto cleanup; |
| 879 | } |
| 880 | |
| 881 | value = cJSON_Duplicate(value, 1); |
| 882 | if (value == NULL) |
| 883 | { |
no test coverage detected