| 1139 | } |
| 1140 | |
| 1141 | static void create_patches(cJSON * const patches, const unsigned char * const path, cJSON * const from, cJSON * const to, const cJSON_bool case_sensitive) |
| 1142 | { |
| 1143 | if ((from == NULL) || (to == NULL)) |
| 1144 | { |
| 1145 | return; |
| 1146 | } |
| 1147 | |
| 1148 | if ((from->type & 0xFF) != (to->type & 0xFF)) |
| 1149 | { |
| 1150 | compose_patch(patches, (const unsigned char*)"replace", path, 0, to); |
| 1151 | return; |
| 1152 | } |
| 1153 | |
| 1154 | switch (from->type & 0xFF) |
| 1155 | { |
| 1156 | case cJSON_Number: |
| 1157 | if ((from->valueint != to->valueint) || !compare_double(from->valuedouble, to->valuedouble)) |
| 1158 | { |
| 1159 | compose_patch(patches, (const unsigned char*)"replace", path, NULL, to); |
| 1160 | } |
| 1161 | return; |
| 1162 | |
| 1163 | case cJSON_String: |
| 1164 | if (strcmp(from->valuestring, to->valuestring) != 0) |
| 1165 | { |
| 1166 | compose_patch(patches, (const unsigned char*)"replace", path, NULL, to); |
| 1167 | } |
| 1168 | return; |
| 1169 | |
| 1170 | case cJSON_Array: |
| 1171 | { |
| 1172 | size_t index = 0; |
| 1173 | cJSON *from_child = from->child; |
| 1174 | cJSON *to_child = to->child; |
| 1175 | unsigned char *new_path = (unsigned char*)cJSON_malloc(strlen((const char*)path) + 20 + sizeof("/")); /* Allow space for 64bit int. log10(2^64) = 20 */ |
| 1176 | |
| 1177 | /* generate patches for all array elements that exist in both "from" and "to" */ |
| 1178 | for (index = 0; (from_child != NULL) && (to_child != NULL); (void)(from_child = from_child->next), (void)(to_child = to_child->next), index++) |
| 1179 | { |
| 1180 | /* check if conversion to unsigned long is valid |
| 1181 | * This should be eliminated at compile time by dead code elimination |
| 1182 | * if size_t is an alias of unsigned long, or if it is bigger */ |
| 1183 | if (index > ULONG_MAX) |
| 1184 | { |
| 1185 | cJSON_free(new_path); |
| 1186 | return; |
| 1187 | } |
| 1188 | sprintf((char*)new_path, "%s/%lu", path, (unsigned long)index); /* path of the current array element */ |
| 1189 | create_patches(patches, new_path, from_child, to_child, case_sensitive); |
| 1190 | } |
| 1191 | |
| 1192 | /* remove leftover elements from 'from' that are not in 'to' */ |
| 1193 | for (; (from_child != NULL); (void)(from_child = from_child->next)) |
| 1194 | { |
| 1195 | /* check if conversion to unsigned long is valid |
| 1196 | * This should be eliminated at compile time by dead code elimination |
| 1197 | * if size_t is an alias of unsigned long, or if it is bigger */ |
| 1198 | if (index > ULONG_MAX) |
no test coverage detected
searching dependent graphs…