|
47 | 47 | #endif
|
48 | 48 |
|
49 | 49 | #include <stddef.h>
|
| 50 | +#include <string.h> |
50 | 51 |
|
51 | 52 | #if defined(_MSC_VER)
|
52 | 53 | #define json_weak __inline
|
@@ -143,15 +144,29 @@ enum json_parse_flags_e {
|
143 | 144 | json_weak struct json_value_s *json_parse(const void *src, size_t src_size);
|
144 | 145 |
|
145 | 146 | /* Parse a JSON text file, returning a pointer to the root of the JSON
|
146 |
| - * structure. json_parse performs 1 call to malloc for the entire encoding. |
147 |
| - * Returns 0 if an error occurred (malformed JSON input, or malloc failed). If |
148 |
| - * an error occurred, the result struct (if not NULL) will explain the type of |
149 |
| - * error, and the location in the input it occurred. */ |
| 147 | + * structure. json_parse performs 1 call to alloc_func_ptr for the entire |
| 148 | + * encoding. Returns 0 if an error occurred (malformed JSON input, or malloc |
| 149 | + * failed). If an error occurred, the result struct (if not NULL) will explain |
| 150 | + * the type of error, and the location in the input it occurred. If |
| 151 | + * alloc_func_ptr is null then malloc is used. */ |
150 | 152 | json_weak struct json_value_s *
|
151 | 153 | json_parse_ex(const void *src, size_t src_size, size_t flags_bitset,
|
152 | 154 | void *(*alloc_func_ptr)(void *, size_t), void *user_data,
|
153 | 155 | struct json_parse_result_s *result);
|
154 | 156 |
|
| 157 | +/* Extracts a value and all the data that makes it up into a newly created |
| 158 | + * value. json_extract_value performs 1 call to malloc for the entire encoding. |
| 159 | + */ |
| 160 | +json_weak struct json_value_s * |
| 161 | +json_extract_value(const struct json_value_s *value); |
| 162 | + |
| 163 | +/* Extracts a value and all the data that makes it up into a newly created |
| 164 | + * value. json_extract_value performs 1 call to alloc_func_ptr for the entire |
| 165 | + * encoding. If alloc_func_ptr is null then malloc is used. */ |
| 166 | +json_weak struct json_value_s * |
| 167 | +json_extract_value_ex(const struct json_value_s *value, |
| 168 | + void *(*alloc_func_ptr)(void *, size_t), void *user_data); |
| 169 | + |
155 | 170 | /* Write out a minified JSON utf-8 string. This string is an encoding of the
|
156 | 171 | * minimal string characters required to still encode the same data.
|
157 | 172 | * json_write_minified performs 1 call to malloc for the entire encoding. Return
|
@@ -2101,6 +2116,263 @@ struct json_value_s *json_parse(const void *src, size_t src_size) {
|
2101 | 2116 | json_null, json_null);
|
2102 | 2117 | }
|
2103 | 2118 |
|
| 2119 | +struct json_extract_result_s { |
| 2120 | + size_t dom_size; |
| 2121 | + size_t data_size; |
| 2122 | +}; |
| 2123 | + |
| 2124 | +struct json_value_s *json_extract_value(const struct json_value_s *value) { |
| 2125 | + return json_extract_value_ex(value, json_null, json_null); |
| 2126 | +} |
| 2127 | + |
| 2128 | +json_weak struct json_extract_result_s |
| 2129 | +json_extract_get_number_size(const struct json_number_s *const number); |
| 2130 | +json_weak struct json_extract_result_s |
| 2131 | +json_extract_get_string_size(const struct json_string_s *const string); |
| 2132 | +json_weak struct json_extract_result_s |
| 2133 | +json_extract_get_object_size(const struct json_object_s *const object); |
| 2134 | +json_weak struct json_extract_result_s |
| 2135 | +json_extract_get_array_size(const struct json_array_s *const array); |
| 2136 | +json_weak struct json_extract_result_s |
| 2137 | +json_extract_get_value_size(const struct json_value_s *const value); |
| 2138 | + |
| 2139 | +struct json_extract_result_s |
| 2140 | +json_extract_get_number_size(const struct json_number_s *const number) { |
| 2141 | + struct json_extract_result_s result; |
| 2142 | + result.dom_size = sizeof(struct json_number_s); |
| 2143 | + result.data_size = number->number_size; |
| 2144 | + return result; |
| 2145 | +} |
| 2146 | + |
| 2147 | +struct json_extract_result_s |
| 2148 | +json_extract_get_string_size(const struct json_string_s *const string) { |
| 2149 | + struct json_extract_result_s result; |
| 2150 | + result.dom_size = sizeof(struct json_string_s); |
| 2151 | + result.data_size = string->string_size + 1; |
| 2152 | + return result; |
| 2153 | +} |
| 2154 | + |
| 2155 | +struct json_extract_result_s |
| 2156 | +json_extract_get_object_size(const struct json_object_s *const object) { |
| 2157 | + struct json_extract_result_s result; |
| 2158 | + size_t i; |
| 2159 | + const struct json_object_element_s *element = object->start; |
| 2160 | + |
| 2161 | + result.dom_size = sizeof(struct json_object_s) + |
| 2162 | + (sizeof(struct json_object_element_s) * object->length); |
| 2163 | + result.data_size = 0; |
| 2164 | + |
| 2165 | + for (i = 0; i < object->length; i++) { |
| 2166 | + const struct json_extract_result_s string_result = |
| 2167 | + json_extract_get_string_size(element->name); |
| 2168 | + const struct json_extract_result_s value_result = |
| 2169 | + json_extract_get_value_size(element->value); |
| 2170 | + |
| 2171 | + result.dom_size += string_result.dom_size; |
| 2172 | + result.data_size += string_result.data_size; |
| 2173 | + |
| 2174 | + result.dom_size += value_result.dom_size; |
| 2175 | + result.data_size += value_result.data_size; |
| 2176 | + |
| 2177 | + element = element->next; |
| 2178 | + } |
| 2179 | + |
| 2180 | + return result; |
| 2181 | +} |
| 2182 | + |
| 2183 | +struct json_extract_result_s |
| 2184 | +json_extract_get_array_size(const struct json_array_s *const array) { |
| 2185 | + struct json_extract_result_s result; |
| 2186 | + size_t i; |
| 2187 | + const struct json_array_element_s *element = array->start; |
| 2188 | + |
| 2189 | + result.dom_size = sizeof(struct json_array_s) + |
| 2190 | + (sizeof(struct json_array_element_s) * array->length); |
| 2191 | + result.data_size = 0; |
| 2192 | + |
| 2193 | + for (i = 0; i < array->length; i++) { |
| 2194 | + const struct json_extract_result_s value_result = |
| 2195 | + json_extract_get_value_size(element->value); |
| 2196 | + |
| 2197 | + result.dom_size += value_result.dom_size; |
| 2198 | + result.data_size += value_result.data_size; |
| 2199 | + |
| 2200 | + element = element->next; |
| 2201 | + } |
| 2202 | + |
| 2203 | + return result; |
| 2204 | +} |
| 2205 | + |
| 2206 | +struct json_extract_result_s |
| 2207 | +json_extract_get_value_size(const struct json_value_s *const value) { |
| 2208 | + struct json_extract_result_s result = {0, 0}; |
| 2209 | + |
| 2210 | + switch (value->type) { |
| 2211 | + default: |
| 2212 | + break; |
| 2213 | + case json_type_object: |
| 2214 | + result = json_extract_get_object_size( |
| 2215 | + (const struct json_object_s *)value->payload); |
| 2216 | + break; |
| 2217 | + case json_type_array: |
| 2218 | + result = json_extract_get_array_size( |
| 2219 | + (const struct json_array_s *)value->payload); |
| 2220 | + break; |
| 2221 | + case json_type_number: |
| 2222 | + result = json_extract_get_number_size( |
| 2223 | + (const struct json_number_s *)value->payload); |
| 2224 | + break; |
| 2225 | + case json_type_string: |
| 2226 | + result = json_extract_get_string_size( |
| 2227 | + (const struct json_string_s *)value->payload); |
| 2228 | + break; |
| 2229 | + } |
| 2230 | + |
| 2231 | + result.dom_size += sizeof(struct json_value_s); |
| 2232 | + |
| 2233 | + return result; |
| 2234 | +} |
| 2235 | + |
| 2236 | +struct json_extract_state_s { |
| 2237 | + char *dom; |
| 2238 | + char *data; |
| 2239 | +}; |
| 2240 | + |
| 2241 | +json_weak void json_extract_copy_value(struct json_extract_state_s *const state, |
| 2242 | + const struct json_value_s *const value); |
| 2243 | +void json_extract_copy_value(struct json_extract_state_s *const state, |
| 2244 | + const struct json_value_s *const value) { |
| 2245 | + struct json_string_s *string; |
| 2246 | + struct json_number_s *number; |
| 2247 | + struct json_object_s *object; |
| 2248 | + struct json_array_s *array; |
| 2249 | + struct json_value_s *new_value; |
| 2250 | + |
| 2251 | + memcpy(state->dom, value, sizeof(struct json_value_s)); |
| 2252 | + new_value = (struct json_value_s *)state->dom; |
| 2253 | + state->dom += sizeof(struct json_value_s); |
| 2254 | + new_value->payload = state->dom; |
| 2255 | + |
| 2256 | + if (json_type_string == value->type) { |
| 2257 | + memcpy(state->dom, value->payload, sizeof(struct json_string_s)); |
| 2258 | + string = (struct json_string_s *)state->dom; |
| 2259 | + state->dom += sizeof(struct json_string_s); |
| 2260 | + |
| 2261 | + memcpy(state->data, string->string, string->string_size + 1); |
| 2262 | + string->string = state->data; |
| 2263 | + state->data += string->string_size + 1; |
| 2264 | + } else if (json_type_number == value->type) { |
| 2265 | + memcpy(state->dom, value->payload, sizeof(struct json_number_s)); |
| 2266 | + number = (struct json_number_s *)state->dom; |
| 2267 | + state->dom += sizeof(struct json_number_s); |
| 2268 | + |
| 2269 | + memcpy(state->data, number->number, number->number_size); |
| 2270 | + number->number = state->data; |
| 2271 | + state->data += number->number_size; |
| 2272 | + } else if (json_type_object == value->type) { |
| 2273 | + struct json_object_element_s *element; |
| 2274 | + size_t i; |
| 2275 | + |
| 2276 | + memcpy(state->dom, value->payload, sizeof(struct json_object_s)); |
| 2277 | + object = (struct json_object_s *)state->dom; |
| 2278 | + state->dom += sizeof(struct json_object_s); |
| 2279 | + |
| 2280 | + element = object->start; |
| 2281 | + object->start = (struct json_object_element_s *)state->dom; |
| 2282 | + |
| 2283 | + for (i = 0; i < object->length; i++) { |
| 2284 | + struct json_value_s *previous_value; |
| 2285 | + struct json_object_element_s *previous_element; |
| 2286 | + |
| 2287 | + memcpy(state->dom, element, sizeof(struct json_object_element_s)); |
| 2288 | + element = (struct json_object_element_s *)state->dom; |
| 2289 | + state->dom += sizeof(struct json_object_element_s); |
| 2290 | + |
| 2291 | + string = element->name; |
| 2292 | + memcpy(state->dom, string, sizeof(struct json_string_s)); |
| 2293 | + string = (struct json_string_s *)state->dom; |
| 2294 | + state->dom += sizeof(struct json_string_s); |
| 2295 | + element->name = string; |
| 2296 | + |
| 2297 | + memcpy(state->data, string->string, string->string_size + 1); |
| 2298 | + string->string = state->data; |
| 2299 | + state->data += string->string_size + 1; |
| 2300 | + |
| 2301 | + previous_value = element->value; |
| 2302 | + element->value = (struct json_value_s *)state->dom; |
| 2303 | + json_extract_copy_value(state, previous_value); |
| 2304 | + |
| 2305 | + previous_element = element; |
| 2306 | + element = element->next; |
| 2307 | + |
| 2308 | + if (element) { |
| 2309 | + previous_element->next = (struct json_object_element_s *)state->dom; |
| 2310 | + } |
| 2311 | + } |
| 2312 | + } else if (json_type_array == value->type) { |
| 2313 | + struct json_array_element_s *element; |
| 2314 | + size_t i; |
| 2315 | + |
| 2316 | + memcpy(state->dom, value->payload, sizeof(struct json_array_s)); |
| 2317 | + array = (struct json_array_s *)state->dom; |
| 2318 | + state->dom += sizeof(struct json_array_s); |
| 2319 | + |
| 2320 | + element = array->start; |
| 2321 | + array->start = (struct json_array_element_s *)state->dom; |
| 2322 | + |
| 2323 | + for (i = 0; i < array->length; i++) { |
| 2324 | + struct json_value_s *previous_value; |
| 2325 | + struct json_array_element_s *previous_element; |
| 2326 | + |
| 2327 | + memcpy(state->dom, element, sizeof(struct json_array_element_s)); |
| 2328 | + element = (struct json_array_element_s *)state->dom; |
| 2329 | + state->dom += sizeof(struct json_array_element_s); |
| 2330 | + |
| 2331 | + previous_value = element->value; |
| 2332 | + element->value = (struct json_value_s *)state->dom; |
| 2333 | + json_extract_copy_value(state, previous_value); |
| 2334 | + |
| 2335 | + previous_element = element; |
| 2336 | + element = element->next; |
| 2337 | + |
| 2338 | + if (element) { |
| 2339 | + previous_element->next = (struct json_array_element_s *)state->dom; |
| 2340 | + } |
| 2341 | + } |
| 2342 | + } |
| 2343 | +} |
| 2344 | + |
| 2345 | +struct json_value_s *json_extract_value_ex(const struct json_value_s *value, |
| 2346 | + void *(*alloc_func_ptr)(void *, |
| 2347 | + size_t), |
| 2348 | + void *user_data) { |
| 2349 | + void *allocation; |
| 2350 | + struct json_extract_result_s result; |
| 2351 | + struct json_extract_state_s state; |
| 2352 | + size_t total_size; |
| 2353 | + |
| 2354 | + if (json_null == value) { |
| 2355 | + /* invalid value was null! */ |
| 2356 | + return json_null; |
| 2357 | + } |
| 2358 | + |
| 2359 | + result = json_extract_get_value_size(value); |
| 2360 | + total_size = result.dom_size + result.data_size; |
| 2361 | + |
| 2362 | + if (json_null == alloc_func_ptr) { |
| 2363 | + allocation = malloc(total_size); |
| 2364 | + } else { |
| 2365 | + allocation = alloc_func_ptr(user_data, total_size); |
| 2366 | + } |
| 2367 | + |
| 2368 | + state.dom = (char *)allocation; |
| 2369 | + state.data = state.dom + result.dom_size; |
| 2370 | + |
| 2371 | + json_extract_copy_value(&state, value); |
| 2372 | + |
| 2373 | + return (struct json_value_s *)allocation; |
| 2374 | +} |
| 2375 | + |
2104 | 2376 | struct json_string_s *json_value_as_string(struct json_value_s *const value) {
|
2105 | 2377 | if (value->type != json_type_string) {
|
2106 | 2378 | return json_null;
|
|
0 commit comments