| 1163 | } |
| 1164 | |
| 1165 | static void create_patches(cJSON *const patches, const unsigned char *const path, cJSON *const from, cJSON *const to, |
| 1166 | const cJSON_bool case_sensitive) |
| 1167 | { |
| 1168 | if ((from == NULL) || (to == NULL)) |
| 1169 | { |
| 1170 | return; |
| 1171 | } |
| 1172 | |
| 1173 | if ((from->type & 0xFF) != (to->type & 0xFF)) |
| 1174 | { |
| 1175 | compose_patch(patches, (const unsigned char *)"replace", path, 0, to); |
| 1176 | return; |
| 1177 | } |
| 1178 | |
| 1179 | switch (from->type & 0xFF) |
| 1180 | { |
| 1181 | case cJSON_Number: |
| 1182 | if ((from->valueint != to->valueint) || !compare_double(from->valuedouble, to->valuedouble)) |
| 1183 | { |
| 1184 | compose_patch(patches, (const unsigned char *)"replace", path, NULL, to); |
| 1185 | } |
| 1186 | return; |
| 1187 | |
| 1188 | case cJSON_String: |
| 1189 | if (strcmp(from->valuestring, to->valuestring) != 0) |
| 1190 | { |
| 1191 | compose_patch(patches, (const unsigned char *)"replace", path, NULL, to); |
| 1192 | } |
| 1193 | return; |
| 1194 | |
| 1195 | case cJSON_Array: |
| 1196 | { |
| 1197 | size_t index = 0; |
| 1198 | cJSON *from_child = from->child; |
| 1199 | cJSON *to_child = to->child; |
| 1200 | unsigned char *new_path = (unsigned char *)cJSON_malloc( |
| 1201 | strlen((const char *)path) + 20 + sizeof("/")); /* Allow space for 64bit int. log10(2^64) = 20 */ |
| 1202 | |
| 1203 | /* generate patches for all array elements that exist in both "from" and "to" */ |
| 1204 | for (index = 0; (from_child != NULL) && (to_child != NULL); |
| 1205 | (void)(from_child = from_child->next), (void)(to_child = to_child->next), index++) |
| 1206 | { |
| 1207 | /* check if conversion to unsigned long is valid |
| 1208 | * This should be eliminated at compile time by dead code elimination |
| 1209 | * if size_t is an alias of unsigned long, or if it is bigger */ |
| 1210 | if (index > ULONG_MAX) |
| 1211 | { |
| 1212 | cJSON_free(new_path); |
| 1213 | return; |
| 1214 | } |
| 1215 | sprintf((char *)new_path, "%s/%lu", path, (unsigned long)index); /* path of the current array element */ |
| 1216 | create_patches(patches, new_path, from_child, to_child, case_sensitive); |
| 1217 | } |
| 1218 | |
| 1219 | /* remove leftover elements from 'from' that are not in 'to' */ |
| 1220 | for (; (from_child != NULL); (void)(from_child = from_child->next)) |
| 1221 | { |
| 1222 | /* check if conversion to unsigned long is valid |
no test coverage detected