| 2076 | } |
| 2077 | |
| 2078 | static int jl_upsert_entry(const char *file_path, const char *const *object_path, size_t path_len, |
| 2079 | const char *entry_key, const char *entry_json, bool enforce_expected, |
| 2080 | const char *expected_content, size_t expected_length) { |
| 2081 | if (jl_validate_arguments(file_path, object_path, path_len, entry_key) != 0 || !entry_json) { |
| 2082 | return -1; |
| 2083 | } |
| 2084 | size_t entry_start = 0; |
| 2085 | size_t entry_length = 0; |
| 2086 | if (jl_validate_entry(entry_json, &entry_start, &entry_length) != 0) { |
| 2087 | return -1; |
| 2088 | } |
| 2089 | const char *entry_value = entry_json + entry_start; |
| 2090 | |
| 2091 | char *source = NULL; |
| 2092 | size_t source_length = 0; |
| 2093 | bool missing = false; |
| 2094 | jl_file_snapshot_t snapshot; |
| 2095 | if (jl_read_file(file_path, &source, &source_length, &missing, &snapshot) != 0) { |
| 2096 | return -1; |
| 2097 | } |
| 2098 | if (enforce_expected) { |
| 2099 | bool expected_missing = expected_content == NULL; |
| 2100 | bool content_matches = expected_missing |
| 2101 | ? missing |
| 2102 | : !missing && source_length == expected_length && |
| 2103 | (expected_length == 0U || |
| 2104 | memcmp(source, expected_content, expected_length) == 0); |
| 2105 | if (!content_matches) { |
| 2106 | free(source); |
| 2107 | return -1; |
| 2108 | } |
| 2109 | } |
| 2110 | if (missing || source_length == 0U) { |
| 2111 | char *fresh = NULL; |
| 2112 | size_t fresh_length = 0; |
| 2113 | int result = jl_build_fresh(object_path, path_len, entry_key, entry_value, entry_length, |
| 2114 | &fresh, &fresh_length); |
| 2115 | if (result == 0) { |
| 2116 | result = |
| 2117 | jl_write_document(file_path, fresh, fresh_length, source, source_length, &snapshot); |
| 2118 | } |
| 2119 | free(fresh); |
| 2120 | free(source); |
| 2121 | return result; |
| 2122 | } |
| 2123 | |
| 2124 | size_t object_start = 0; |
| 2125 | if (jl_validate_document(source, source_length, &object_start) != 0) { |
| 2126 | free(source); |
| 2127 | return -1; |
| 2128 | } |
| 2129 | for (size_t i = 0; i < path_len; i++) { |
| 2130 | jl_object_t object; |
| 2131 | if (jl_scan_object(source, source_length, object_start, object_path[i], &object) != 0 || |
| 2132 | object.match_count > 1U) { |
| 2133 | free(source); |
| 2134 | return -1; |
| 2135 | } |
no test coverage detected