/src/openvswitch/lib/json.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2009-2012, 2014-2017 Nicira, Inc. |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at: |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | |
17 | | #include <config.h> |
18 | | |
19 | | #include "openvswitch/json.h" |
20 | | |
21 | | #include <ctype.h> |
22 | | #include <errno.h> |
23 | | #include <float.h> |
24 | | #include <limits.h> |
25 | | #include <string.h> |
26 | | |
27 | | #include "cooperative-multitasking.h" |
28 | | #include "openvswitch/dynamic-string.h" |
29 | | #include "hash.h" |
30 | | #include "json.h" |
31 | | #include "openvswitch/shash.h" |
32 | | #include "unicode.h" |
33 | | #include "util.h" |
34 | | #include "uuid.h" |
35 | | |
36 | | /* Non-public JSSF_* flags. Must not overlap with public ones defined |
37 | | * in include/openvswitch/json.h. */ |
38 | | enum { |
39 | | JSSF_YIELD = 1 << 7, |
40 | | }; |
41 | | |
42 | | /* The type of a JSON token. */ |
43 | | enum json_token_type { |
44 | | T_EOF = 0, |
45 | | T_BEGIN_ARRAY = '[', |
46 | | T_END_ARRAY = ']', |
47 | | T_BEGIN_OBJECT = '{', |
48 | | T_END_OBJECT = '}', |
49 | | T_NAME_SEPARATOR = ':', |
50 | | T_VALUE_SEPARATOR = ',', |
51 | | T_FALSE = UCHAR_MAX + 1, |
52 | | T_NULL, |
53 | | T_TRUE, |
54 | | T_INTEGER, |
55 | | T_REAL, |
56 | | T_STRING |
57 | | }; |
58 | | |
59 | | /* A JSON token. |
60 | | * |
61 | | * RFC 4627 doesn't define a lexical structure for JSON but I believe this to |
62 | | * be compliant with the standard. |
63 | | */ |
64 | | struct json_token { |
65 | | enum json_token_type type; |
66 | | union { |
67 | | double real; |
68 | | long long int integer; |
69 | | const char *string; |
70 | | }; |
71 | | }; |
72 | | |
73 | | enum json_lex_state { |
74 | | JSON_LEX_START, /* Not inside a token. */ |
75 | | JSON_LEX_NUMBER, /* Reading a number. */ |
76 | | JSON_LEX_KEYWORD, /* Reading a keyword. */ |
77 | | JSON_LEX_STRING, /* Reading a quoted string. */ |
78 | | JSON_LEX_ESCAPE /* In a quoted string just after a "\". */ |
79 | | }; |
80 | | |
81 | | enum json_parse_state { |
82 | | JSON_PARSE_START, /* Beginning of input. */ |
83 | | JSON_PARSE_END, /* End of input. */ |
84 | | |
85 | | /* Objects. */ |
86 | | JSON_PARSE_OBJECT_INIT, /* Expecting '}' or an object name. */ |
87 | | JSON_PARSE_OBJECT_NAME, /* Expecting an object name. */ |
88 | | JSON_PARSE_OBJECT_COLON, /* Expecting ':'. */ |
89 | | JSON_PARSE_OBJECT_VALUE, /* Expecting an object value. */ |
90 | | JSON_PARSE_OBJECT_NEXT, /* Expecting ',' or '}'. */ |
91 | | |
92 | | /* Arrays. */ |
93 | | JSON_PARSE_ARRAY_INIT, /* Expecting ']' or a value. */ |
94 | | JSON_PARSE_ARRAY_VALUE, /* Expecting a value. */ |
95 | | JSON_PARSE_ARRAY_NEXT /* Expecting ',' or ']'. */ |
96 | | }; |
97 | | |
98 | | struct json_parser_node { |
99 | | struct json *json; |
100 | | }; |
101 | | |
102 | | /* A JSON parser. */ |
103 | | struct json_parser { |
104 | | int flags; |
105 | | |
106 | | /* Lexical analysis. */ |
107 | | enum json_lex_state lex_state; |
108 | | struct ds buffer; /* Buffer for accumulating token text. */ |
109 | | int line_number; |
110 | | int column_number; |
111 | | int byte_number; |
112 | | |
113 | | /* Parsing. */ |
114 | | enum json_parse_state parse_state; |
115 | 0 | #define JSON_MAX_HEIGHT 1000 |
116 | | struct json_parser_node *stack; |
117 | | size_t height, allocated_height; |
118 | | char *member_name; |
119 | | |
120 | | /* Parse status. */ |
121 | | bool done; |
122 | | char *error; /* Error message, if any, null if none yet. */ |
123 | | }; |
124 | | |
125 | | static struct json *json_create(enum json_type type); |
126 | | static void json_parser_input(struct json_parser *, struct json_token *); |
127 | | |
128 | | static void json_error(struct json_parser *p, const char *format, ...) |
129 | | OVS_PRINTF_FORMAT(2, 3); |
130 | | |
131 | | const char * |
132 | | json_type_to_string(enum json_type type) |
133 | 0 | { |
134 | 0 | switch (type) { |
135 | 0 | case JSON_NULL: |
136 | 0 | return "null"; |
137 | | |
138 | 0 | case JSON_FALSE: |
139 | 0 | return "false"; |
140 | | |
141 | 0 | case JSON_TRUE: |
142 | 0 | return "true"; |
143 | | |
144 | 0 | case JSON_OBJECT: |
145 | 0 | return "object"; |
146 | | |
147 | 0 | case JSON_ARRAY: |
148 | 0 | return "array"; |
149 | | |
150 | 0 | case JSON_INTEGER: |
151 | 0 | case JSON_REAL: |
152 | 0 | return "number"; |
153 | | |
154 | 0 | case JSON_STRING: |
155 | 0 | return "string"; |
156 | | |
157 | 0 | case JSON_SERIALIZED_OBJECT: |
158 | 0 | case JSON_N_TYPES: |
159 | 0 | default: |
160 | 0 | return "<invalid>"; |
161 | 0 | } |
162 | 0 | } |
163 | | |
164 | | /* Functions for manipulating struct json. */ |
165 | | |
166 | | struct json * |
167 | | json_null_create(void) |
168 | 0 | { |
169 | 0 | return json_create(JSON_NULL); |
170 | 0 | } |
171 | | |
172 | | struct json * |
173 | | json_boolean_create(bool b) |
174 | 0 | { |
175 | 0 | return json_create(b ? JSON_TRUE : JSON_FALSE); |
176 | 0 | } |
177 | | |
178 | | struct json * |
179 | | json_string_create_nocopy(char *s) |
180 | 0 | { |
181 | 0 | struct json *json = json_create(JSON_STRING); |
182 | 0 | json->storage_type = JSON_STRING_DYNAMIC; |
183 | 0 | json->str_ptr = s; |
184 | 0 | return json; |
185 | 0 | } |
186 | | |
187 | | struct json * |
188 | | json_string_create(const char *s) |
189 | 0 | { |
190 | 0 | struct json *json = json_create(JSON_STRING); |
191 | 0 | size_t length = strlen(s); |
192 | |
|
193 | 0 | if (length <= JSON_STRING_INLINE_LEN) { |
194 | 0 | json->storage_type = JSON_STRING_INLINE; |
195 | 0 | memcpy(json->str, s, length); |
196 | 0 | json->str[length] = '\0'; |
197 | 0 | } else { |
198 | 0 | json->storage_type = JSON_STRING_DYNAMIC; |
199 | 0 | json->str_ptr = xmemdup0(s, length); |
200 | 0 | } |
201 | 0 | return json; |
202 | 0 | } |
203 | | |
204 | | struct json *json_string_create_uuid(const struct uuid *uuid) |
205 | 0 | { |
206 | 0 | return json_string_create_nocopy(uuid_to_string(uuid)); |
207 | 0 | } |
208 | | |
209 | | struct json * |
210 | | json_serialized_object_create(const struct json *src) |
211 | 0 | { |
212 | 0 | struct json *json = json_create(JSON_SERIALIZED_OBJECT); |
213 | 0 | json->str_ptr = json_to_string(src, JSSF_SORT); |
214 | 0 | return json; |
215 | 0 | } |
216 | | |
217 | | struct json * |
218 | | json_serialized_object_create_with_yield(const struct json *src) |
219 | 0 | { |
220 | 0 | struct json *json = json_create(JSON_SERIALIZED_OBJECT); |
221 | 0 | json->str_ptr = json_to_string(src, JSSF_SORT | JSSF_YIELD); |
222 | 0 | return json; |
223 | 0 | } |
224 | | |
225 | | struct json * |
226 | | json_array_create_empty(void) |
227 | 0 | { |
228 | 0 | struct json *json = json_create(JSON_ARRAY); |
229 | 0 | json->storage_type = JSON_ARRAY_DYNAMIC; |
230 | 0 | json->array.elements = NULL; |
231 | 0 | json->array.size = 0; |
232 | 0 | json->array.allocated = 0; |
233 | 0 | return json; |
234 | 0 | } |
235 | | |
236 | | void |
237 | | json_array_add(struct json *array_, struct json *element) |
238 | 0 | { |
239 | 0 | switch (array_->storage_type) { |
240 | 0 | case JSON_ARRAY_DYNAMIC: |
241 | 0 | if (!array_->array.size) { |
242 | 0 | array_->storage_type = JSON_ARRAY_INLINE_1; |
243 | 0 | array_->elements[0] = element; |
244 | 0 | return; |
245 | 0 | } |
246 | 0 | break; |
247 | | |
248 | 0 | case JSON_ARRAY_INLINE_1: |
249 | 0 | case JSON_ARRAY_INLINE_2: |
250 | 0 | array_->elements[array_->storage_type - JSON_ARRAY_DYNAMIC] = element; |
251 | 0 | array_->storage_type++; |
252 | 0 | return; |
253 | | |
254 | 0 | case JSON_ARRAY_INLINE_3: { |
255 | 0 | struct json **elements = xmalloc(4 * sizeof *elements); |
256 | |
|
257 | 0 | memcpy(elements, array_->elements, 3 * sizeof array_->elements[0]); |
258 | 0 | array_->array.elements = elements; |
259 | 0 | array_->array.elements[3] = element; |
260 | 0 | array_->array.size = 4; |
261 | 0 | array_->array.allocated = 4; |
262 | 0 | array_->storage_type = JSON_ARRAY_DYNAMIC; |
263 | 0 | return; |
264 | 0 | } |
265 | | |
266 | 0 | case JSON_STRING_DYNAMIC: |
267 | 0 | case JSON_STRING_INLINE: |
268 | 0 | default: |
269 | 0 | OVS_NOT_REACHED(); |
270 | 0 | } |
271 | | |
272 | 0 | struct json_array *array = &array_->array; |
273 | 0 | if (array->size >= array->allocated) { |
274 | 0 | array->elements = x2nrealloc(array->elements, &array->allocated, |
275 | 0 | sizeof *array->elements); |
276 | 0 | } |
277 | 0 | array->elements[array->size++] = element; |
278 | 0 | } |
279 | | |
280 | | void |
281 | | json_array_set(struct json *json, size_t index, struct json *element) |
282 | 0 | { |
283 | 0 | ovs_assert(json_array_size(json) > index); |
284 | 0 | if (json->storage_type == JSON_ARRAY_DYNAMIC) { |
285 | 0 | json->array.elements[index] = element; |
286 | 0 | } else { |
287 | 0 | json->elements[index] = element; |
288 | 0 | } |
289 | 0 | } |
290 | | |
291 | | struct json * |
292 | | json_array_pop(struct json *json) |
293 | 0 | { |
294 | 0 | if (!json_array_size(json)) { |
295 | 0 | return NULL; |
296 | 0 | } |
297 | 0 | if (json->storage_type == JSON_ARRAY_DYNAMIC) { |
298 | 0 | return json->array.elements[--json->array.size]; |
299 | 0 | } |
300 | 0 | if (json->storage_type > JSON_ARRAY_INLINE_1) { |
301 | 0 | return json->elements[--json->storage_type - JSON_ARRAY_DYNAMIC]; |
302 | 0 | } |
303 | | |
304 | | /* Need to fall back to an empty array in case it's the last |
305 | | * inline element. */ |
306 | 0 | struct json *element = json->elements[0]; |
307 | 0 | json->storage_type = JSON_ARRAY_DYNAMIC; |
308 | 0 | json->array.elements = NULL; |
309 | 0 | json->array.size = 0; |
310 | 0 | json->array.allocated = 0; |
311 | 0 | return element; |
312 | 0 | } |
313 | | |
314 | | void |
315 | | json_array_trim(struct json *array_) |
316 | 0 | { |
317 | 0 | if (array_->storage_type != JSON_ARRAY_DYNAMIC) { |
318 | 0 | return; |
319 | 0 | } |
320 | | |
321 | 0 | struct json_array *array = &array_->array; |
322 | 0 | if (array->size < array->allocated) { |
323 | 0 | array->allocated = array->size; |
324 | 0 | array->elements = xrealloc(array->elements, |
325 | 0 | array->size * sizeof *array->elements); |
326 | 0 | } |
327 | 0 | } |
328 | | |
329 | | struct json * |
330 | | json_array_create(struct json **elements, size_t n) |
331 | 0 | { |
332 | 0 | struct json *json = json_create(JSON_ARRAY); |
333 | 0 | json->storage_type = JSON_ARRAY_DYNAMIC; |
334 | 0 | json->array.elements = elements; |
335 | 0 | json->array.size = n; |
336 | 0 | json->array.allocated = n; |
337 | 0 | return json; |
338 | 0 | } |
339 | | |
340 | | struct json * |
341 | | json_array_create_1(struct json *elem0) |
342 | 0 | { |
343 | 0 | struct json *json = json_create(JSON_ARRAY); |
344 | |
|
345 | 0 | json->storage_type = JSON_ARRAY_INLINE_1; |
346 | 0 | json->elements[0] = elem0; |
347 | |
|
348 | 0 | return json; |
349 | 0 | } |
350 | | |
351 | | struct json * |
352 | | json_array_create_2(struct json *elem0, struct json *elem1) |
353 | 0 | { |
354 | 0 | struct json *json = json_create(JSON_ARRAY); |
355 | |
|
356 | 0 | json->storage_type = JSON_ARRAY_INLINE_2; |
357 | 0 | json->elements[0] = elem0; |
358 | 0 | json->elements[1] = elem1; |
359 | |
|
360 | 0 | return json; |
361 | 0 | } |
362 | | |
363 | | struct json * |
364 | | json_array_create_3(struct json *elem0, struct json *elem1, struct json *elem2) |
365 | 0 | { |
366 | 0 | struct json *json = json_create(JSON_ARRAY); |
367 | |
|
368 | 0 | json->storage_type = JSON_ARRAY_INLINE_3; |
369 | 0 | json->elements[0] = elem0; |
370 | 0 | json->elements[1] = elem1; |
371 | 0 | json->elements[2] = elem2; |
372 | |
|
373 | 0 | return json; |
374 | 0 | } |
375 | | |
376 | | bool |
377 | | json_array_contains_string(const struct json *json, const char *str) |
378 | 0 | { |
379 | 0 | size_t n = json_array_size(json); |
380 | |
|
381 | 0 | for (size_t i = 0; i < n; i++) { |
382 | 0 | const struct json *elem = json_array_at(json, i); |
383 | |
|
384 | 0 | if (elem->type == JSON_STRING && !strcmp(json_string(elem), str)) { |
385 | 0 | return true; |
386 | 0 | } |
387 | 0 | } |
388 | 0 | return false; |
389 | 0 | } |
390 | | |
391 | | struct json * |
392 | | json_object_create(void) |
393 | 0 | { |
394 | 0 | struct json *json = json_create(JSON_OBJECT); |
395 | 0 | json->object = xmalloc(sizeof *json->object); |
396 | 0 | shash_init(json->object); |
397 | 0 | return json; |
398 | 0 | } |
399 | | |
400 | | struct json * |
401 | | json_integer_create(long long int integer) |
402 | 0 | { |
403 | 0 | struct json *json = json_create(JSON_INTEGER); |
404 | 0 | json->integer = integer; |
405 | 0 | return json; |
406 | 0 | } |
407 | | |
408 | | struct json * |
409 | | json_real_create(double real) |
410 | 0 | { |
411 | 0 | struct json *json = json_create(JSON_REAL); |
412 | 0 | json->real = real; |
413 | 0 | return json; |
414 | 0 | } |
415 | | |
416 | | void |
417 | | json_object_put(struct json *json, const char *name, struct json *value) |
418 | 0 | { |
419 | 0 | json_destroy(shash_replace(json->object, name, value)); |
420 | 0 | } |
421 | | |
422 | | void |
423 | | json_object_put_nocopy(struct json *json, char *name, struct json *value) |
424 | 0 | { |
425 | 0 | json_destroy(shash_replace_nocopy(json->object, name, value)); |
426 | 0 | } |
427 | | |
428 | | void |
429 | | json_object_put_string(struct json *json, const char *name, const char *value) |
430 | 0 | { |
431 | 0 | json_object_put(json, name, json_string_create(value)); |
432 | 0 | } |
433 | | |
434 | | void OVS_PRINTF_FORMAT(3, 4) |
435 | | json_object_put_format(struct json *json, |
436 | | const char *name, const char *format, ...) |
437 | 0 | { |
438 | 0 | va_list args; |
439 | 0 | va_start(args, format); |
440 | 0 | json_object_put(json, name, |
441 | 0 | json_string_create_nocopy(xvasprintf(format, args))); |
442 | 0 | va_end(args); |
443 | 0 | } |
444 | | |
445 | | void json_object_put_uuid(struct json *json, |
446 | | const char *name, const struct uuid *uuid) |
447 | 0 | { |
448 | 0 | json_object_put(json, name, json_string_create_uuid(uuid)); |
449 | 0 | } |
450 | | |
451 | | const char * |
452 | | json_string(const struct json *json) |
453 | 0 | { |
454 | 0 | ovs_assert(json->type == JSON_STRING); |
455 | 0 | return json->storage_type == JSON_STRING_DYNAMIC |
456 | 0 | ? json->str_ptr : json->str; |
457 | 0 | } |
458 | | |
459 | | const char * |
460 | | json_serialized_object(const struct json *json) |
461 | 0 | { |
462 | 0 | ovs_assert(json->type == JSON_SERIALIZED_OBJECT); |
463 | 0 | return json->str_ptr; |
464 | 0 | } |
465 | | |
466 | | size_t |
467 | | json_array_size(const struct json *json) |
468 | 0 | { |
469 | 0 | ovs_assert(json->type == JSON_ARRAY); |
470 | 0 | if (json->storage_type == JSON_ARRAY_DYNAMIC) { |
471 | 0 | return json->array.size; |
472 | 0 | } |
473 | 0 | return json->storage_type - JSON_ARRAY_DYNAMIC; |
474 | 0 | } |
475 | | |
476 | | const struct json * |
477 | | json_array_at(const struct json *json, size_t index) |
478 | 0 | { |
479 | 0 | ovs_assert(json->type == JSON_ARRAY); |
480 | |
|
481 | 0 | if (json->storage_type == JSON_ARRAY_DYNAMIC) { |
482 | 0 | if (json->array.size <= index) { |
483 | 0 | return NULL; |
484 | 0 | } |
485 | 0 | return json->array.elements[index]; |
486 | 0 | } |
487 | | |
488 | 0 | if (json->storage_type - JSON_ARRAY_DYNAMIC <= index) { |
489 | 0 | return NULL; |
490 | 0 | } |
491 | 0 | return json->elements[index]; |
492 | 0 | } |
493 | | |
494 | | struct shash * |
495 | | json_object(const struct json *json) |
496 | 0 | { |
497 | 0 | ovs_assert(json->type == JSON_OBJECT); |
498 | 0 | return CONST_CAST(struct shash *, json->object); |
499 | 0 | } |
500 | | |
501 | | bool |
502 | | json_boolean(const struct json *json) |
503 | 0 | { |
504 | 0 | ovs_assert(json->type == JSON_TRUE || json->type == JSON_FALSE); |
505 | 0 | return json->type == JSON_TRUE; |
506 | 0 | } |
507 | | |
508 | | double |
509 | | json_real(const struct json *json) |
510 | 0 | { |
511 | 0 | ovs_assert(json->type == JSON_REAL || json->type == JSON_INTEGER); |
512 | 0 | return json->type == JSON_REAL ? json->real : json->integer; |
513 | 0 | } |
514 | | |
515 | | int64_t |
516 | | json_integer(const struct json *json) |
517 | 0 | { |
518 | 0 | ovs_assert(json->type == JSON_INTEGER); |
519 | 0 | return json->integer; |
520 | 0 | } |
521 | | |
522 | | static void json_destroy_object(struct shash *object, bool yield); |
523 | | static void json_destroy_array(struct json *json, bool yield); |
524 | | |
525 | | /* Frees 'json' and everything it points to, recursively. */ |
526 | | void |
527 | | json_destroy__(struct json *json, bool yield) |
528 | 0 | { |
529 | 0 | switch (json->type) { |
530 | 0 | case JSON_OBJECT: |
531 | 0 | json_destroy_object(json->object, yield); |
532 | 0 | break; |
533 | | |
534 | 0 | case JSON_ARRAY: |
535 | 0 | json_destroy_array(json, yield); |
536 | 0 | break; |
537 | | |
538 | 0 | case JSON_STRING: |
539 | 0 | if (json->storage_type == JSON_STRING_DYNAMIC) { |
540 | 0 | free(json->str_ptr); |
541 | 0 | } |
542 | 0 | break; |
543 | | |
544 | 0 | case JSON_SERIALIZED_OBJECT: |
545 | 0 | free(json->str_ptr); |
546 | 0 | break; |
547 | | |
548 | 0 | case JSON_NULL: |
549 | 0 | case JSON_FALSE: |
550 | 0 | case JSON_TRUE: |
551 | 0 | case JSON_INTEGER: |
552 | 0 | case JSON_REAL: |
553 | 0 | break; |
554 | | |
555 | 0 | case JSON_N_TYPES: |
556 | 0 | OVS_NOT_REACHED(); |
557 | 0 | } |
558 | 0 | free(json); |
559 | 0 | } |
560 | | |
561 | | static void |
562 | | json_destroy_object(struct shash *object, bool yield) |
563 | 0 | { |
564 | 0 | struct shash_node *node; |
565 | |
|
566 | 0 | if (yield) { |
567 | 0 | cooperative_multitasking_yield(); |
568 | 0 | } |
569 | |
|
570 | 0 | SHASH_FOR_EACH_SAFE (node, object) { |
571 | 0 | struct json *value = node->data; |
572 | |
|
573 | 0 | if (yield) { |
574 | 0 | json_destroy_with_yield(value); |
575 | 0 | } else { |
576 | 0 | json_destroy(value); |
577 | 0 | } |
578 | 0 | shash_delete(object, node); |
579 | 0 | } |
580 | 0 | shash_destroy(object); |
581 | 0 | free(object); |
582 | 0 | } |
583 | | |
584 | | static void |
585 | | json_destroy_array(struct json *json, bool yield) |
586 | 0 | { |
587 | 0 | size_t i, n = json_array_size(json); |
588 | |
|
589 | 0 | if (yield) { |
590 | 0 | cooperative_multitasking_yield(); |
591 | 0 | } |
592 | |
|
593 | 0 | for (i = 0; i < n; i++) { |
594 | 0 | if (yield) { |
595 | 0 | json_destroy_with_yield( |
596 | 0 | CONST_CAST(struct json *, json_array_at(json, i))); |
597 | 0 | } else { |
598 | 0 | json_destroy(CONST_CAST(struct json *, json_array_at(json, i))); |
599 | 0 | } |
600 | 0 | } |
601 | 0 | if (json->storage_type == JSON_ARRAY_DYNAMIC) { |
602 | 0 | free(json->array.elements); |
603 | 0 | } |
604 | 0 | } |
605 | | |
606 | | static struct json *json_deep_clone_object(const struct shash *object); |
607 | | static struct json *json_deep_clone_array(const struct json *); |
608 | | |
609 | | /* Returns a deep copy of 'json'. */ |
610 | | struct json * |
611 | | json_deep_clone(const struct json *json) |
612 | 0 | { |
613 | 0 | switch (json->type) { |
614 | 0 | case JSON_OBJECT: |
615 | 0 | return json_deep_clone_object(json->object); |
616 | | |
617 | 0 | case JSON_ARRAY: |
618 | 0 | return json_deep_clone_array(json); |
619 | | |
620 | 0 | case JSON_STRING: |
621 | 0 | return json_string_create(json_string(json)); |
622 | | |
623 | 0 | case JSON_SERIALIZED_OBJECT: |
624 | 0 | return json_serialized_object_create(json); |
625 | | |
626 | 0 | case JSON_NULL: |
627 | 0 | case JSON_FALSE: |
628 | 0 | case JSON_TRUE: |
629 | 0 | return json_create(json->type); |
630 | | |
631 | 0 | case JSON_INTEGER: |
632 | 0 | return json_integer_create(json->integer); |
633 | | |
634 | 0 | case JSON_REAL: |
635 | 0 | return json_real_create(json->real); |
636 | | |
637 | 0 | case JSON_N_TYPES: |
638 | 0 | default: |
639 | 0 | OVS_NOT_REACHED(); |
640 | 0 | } |
641 | 0 | } |
642 | | |
643 | | struct json * |
644 | | json_nullable_clone(const struct json *json) |
645 | 0 | { |
646 | 0 | return json ? json_clone(json) : NULL; |
647 | 0 | } |
648 | | |
649 | | static struct json * |
650 | | json_deep_clone_object(const struct shash *object) |
651 | 0 | { |
652 | 0 | struct shash_node *node; |
653 | 0 | struct json *json; |
654 | |
|
655 | 0 | json = json_object_create(); |
656 | 0 | SHASH_FOR_EACH (node, object) { |
657 | 0 | struct json *value = node->data; |
658 | 0 | json_object_put(json, node->name, json_deep_clone(value)); |
659 | 0 | } |
660 | 0 | return json; |
661 | 0 | } |
662 | | |
663 | | static struct json * |
664 | | json_deep_clone_array(const struct json *json) |
665 | 0 | { |
666 | 0 | struct json **elements; |
667 | 0 | size_t i, n; |
668 | |
|
669 | 0 | n = json_array_size(json); |
670 | 0 | switch (n) { |
671 | 0 | case 0: |
672 | 0 | return json_array_create_empty(); |
673 | 0 | case 1: |
674 | 0 | return json_array_create_1(json_deep_clone(json_array_at(json, 0))); |
675 | 0 | case 2: |
676 | 0 | return json_array_create_2(json_deep_clone(json_array_at(json, 0)), |
677 | 0 | json_deep_clone(json_array_at(json, 1))); |
678 | 0 | case 3: |
679 | 0 | return json_array_create_3(json_deep_clone(json_array_at(json, 0)), |
680 | 0 | json_deep_clone(json_array_at(json, 1)), |
681 | 0 | json_deep_clone(json_array_at(json, 2))); |
682 | 0 | default: |
683 | 0 | break; |
684 | 0 | } |
685 | | |
686 | 0 | elements = xmalloc(n * sizeof *elements); |
687 | 0 | for (i = 0; i < n; i++) { |
688 | 0 | elements[i] = json_deep_clone(json_array_at(json, i)); |
689 | 0 | } |
690 | 0 | return json_array_create(elements, n); |
691 | 0 | } |
692 | | |
693 | | static size_t |
694 | | json_hash_object(const struct shash *object, size_t basis) |
695 | 0 | { |
696 | 0 | const struct shash_node **nodes; |
697 | 0 | size_t n, i; |
698 | |
|
699 | 0 | nodes = shash_sort(object); |
700 | 0 | n = shash_count(object); |
701 | 0 | for (i = 0; i < n; i++) { |
702 | 0 | const struct shash_node *node = nodes[i]; |
703 | 0 | basis = hash_string(node->name, basis); |
704 | 0 | basis = json_hash(node->data, basis); |
705 | 0 | } |
706 | 0 | free(nodes); |
707 | 0 | return basis; |
708 | 0 | } |
709 | | |
710 | | static size_t |
711 | | json_hash_array(const struct json *json, size_t basis) |
712 | 0 | { |
713 | 0 | size_t i, n = json_array_size(json); |
714 | |
|
715 | 0 | basis = hash_int(n, basis); |
716 | 0 | for (i = 0; i < n; i++) { |
717 | 0 | basis = json_hash(json_array_at(json, i), basis); |
718 | 0 | } |
719 | 0 | return basis; |
720 | 0 | } |
721 | | |
722 | | size_t |
723 | | json_hash(const struct json *json, size_t basis) |
724 | 0 | { |
725 | 0 | switch (json->type) { |
726 | 0 | case JSON_OBJECT: |
727 | 0 | return json_hash_object(json->object, basis); |
728 | | |
729 | 0 | case JSON_ARRAY: |
730 | 0 | return json_hash_array(json, basis); |
731 | | |
732 | 0 | case JSON_STRING: |
733 | 0 | return hash_string(json_string(json), basis); |
734 | | |
735 | 0 | case JSON_SERIALIZED_OBJECT: |
736 | 0 | return hash_string(json_serialized_object(json), basis); |
737 | | |
738 | 0 | case JSON_NULL: |
739 | 0 | case JSON_FALSE: |
740 | 0 | case JSON_TRUE: |
741 | 0 | return hash_int(json->type << 8, basis); |
742 | | |
743 | 0 | case JSON_INTEGER: |
744 | 0 | return hash_int(json->integer, basis); |
745 | | |
746 | 0 | case JSON_REAL: |
747 | 0 | return hash_double(json->real, basis); |
748 | | |
749 | 0 | case JSON_N_TYPES: |
750 | 0 | default: |
751 | 0 | OVS_NOT_REACHED(); |
752 | 0 | } |
753 | 0 | } |
754 | | |
755 | | static bool |
756 | | json_equal_object(const struct shash *a, const struct shash *b) |
757 | 0 | { |
758 | 0 | struct shash_node *a_node; |
759 | |
|
760 | 0 | if (shash_count(a) != shash_count(b)) { |
761 | 0 | return false; |
762 | 0 | } |
763 | | |
764 | 0 | SHASH_FOR_EACH (a_node, a) { |
765 | 0 | struct shash_node *b_node = shash_find(b, a_node->name); |
766 | 0 | if (!b_node || !json_equal(a_node->data, b_node->data)) { |
767 | 0 | return false; |
768 | 0 | } |
769 | 0 | } |
770 | | |
771 | 0 | return true; |
772 | 0 | } |
773 | | |
774 | | static bool |
775 | | json_equal_array(const struct json *a, const struct json *b) |
776 | 0 | { |
777 | 0 | size_t i, n = json_array_size(a); |
778 | |
|
779 | 0 | if (n != json_array_size(b)) { |
780 | 0 | return false; |
781 | 0 | } |
782 | | |
783 | 0 | for (i = 0; i < n; i++) { |
784 | 0 | if (!json_equal(json_array_at(a, i), json_array_at(b, i))) { |
785 | 0 | return false; |
786 | 0 | } |
787 | 0 | } |
788 | | |
789 | 0 | return true; |
790 | 0 | } |
791 | | |
792 | | bool |
793 | | json_equal(const struct json *a, const struct json *b) |
794 | 0 | { |
795 | 0 | if (a == b) { |
796 | 0 | return true; |
797 | 0 | } else if (!a || !b) { |
798 | 0 | return false; |
799 | 0 | } else if (a->type != b->type) { |
800 | 0 | return false; |
801 | 0 | } |
802 | | |
803 | 0 | switch (a->type) { |
804 | 0 | case JSON_OBJECT: |
805 | 0 | return json_equal_object(a->object, b->object); |
806 | | |
807 | 0 | case JSON_ARRAY: |
808 | 0 | return json_equal_array(a, b); |
809 | | |
810 | 0 | case JSON_STRING: |
811 | 0 | return !strcmp(json_string(a), json_string(b)); |
812 | | |
813 | 0 | case JSON_SERIALIZED_OBJECT: |
814 | 0 | return !strcmp(json_serialized_object(a), json_serialized_object(b)); |
815 | | |
816 | 0 | case JSON_NULL: |
817 | 0 | case JSON_FALSE: |
818 | 0 | case JSON_TRUE: |
819 | 0 | return true; |
820 | | |
821 | 0 | case JSON_INTEGER: |
822 | 0 | return a->integer == b->integer; |
823 | | |
824 | 0 | case JSON_REAL: |
825 | 0 | return a->real == b->real; |
826 | | |
827 | 0 | case JSON_N_TYPES: |
828 | 0 | default: |
829 | 0 | OVS_NOT_REACHED(); |
830 | 0 | } |
831 | 0 | } |
832 | | |
833 | | /* Lexical analysis. */ |
834 | | |
835 | | static void |
836 | | json_lex_keyword(struct json_parser *p) |
837 | 0 | { |
838 | 0 | struct json_token token; |
839 | 0 | const char *s; |
840 | |
|
841 | 0 | s = ds_cstr(&p->buffer); |
842 | 0 | if (!strcmp(s, "false")) { |
843 | 0 | token.type = T_FALSE; |
844 | 0 | } else if (!strcmp(s, "true")) { |
845 | 0 | token.type = T_TRUE; |
846 | 0 | } else if (!strcmp(s, "null")) { |
847 | 0 | token.type = T_NULL; |
848 | 0 | } else { |
849 | 0 | json_error(p, "invalid keyword '%s'", s); |
850 | 0 | return; |
851 | 0 | } |
852 | 0 | json_parser_input(p, &token); |
853 | 0 | } |
854 | | |
855 | | static void |
856 | | json_lex_number(struct json_parser *p) |
857 | 0 | { |
858 | 0 | const char *cp = ds_cstr(&p->buffer); |
859 | 0 | unsigned long long int significand = 0; |
860 | 0 | struct json_token token; |
861 | 0 | bool imprecise = false; |
862 | 0 | bool negative = false; |
863 | 0 | int pow10 = 0; |
864 | | |
865 | | /* Leading minus sign. */ |
866 | 0 | if (*cp == '-') { |
867 | 0 | negative = true; |
868 | 0 | cp++; |
869 | 0 | } |
870 | | |
871 | | /* At least one integer digit, but 0 may not be used as a leading digit for |
872 | | * a longer number. */ |
873 | 0 | significand = 0; |
874 | 0 | if (*cp == '0') { |
875 | 0 | cp++; |
876 | 0 | if (isdigit((unsigned char) *cp)) { |
877 | 0 | json_error(p, "leading zeros not allowed"); |
878 | 0 | return; |
879 | 0 | } |
880 | 0 | } else if (isdigit((unsigned char) *cp)) { |
881 | 0 | do { |
882 | 0 | if (significand <= ULLONG_MAX / 10) { |
883 | 0 | significand = significand * 10 + (*cp - '0'); |
884 | 0 | } else { |
885 | 0 | pow10++; |
886 | 0 | if (*cp != '0') { |
887 | 0 | imprecise = true; |
888 | 0 | } |
889 | 0 | } |
890 | 0 | cp++; |
891 | 0 | } while (isdigit((unsigned char) *cp)); |
892 | 0 | } else { |
893 | 0 | json_error(p, "'-' must be followed by digit"); |
894 | 0 | return; |
895 | 0 | } |
896 | | |
897 | | /* Optional fraction. */ |
898 | 0 | if (*cp == '.') { |
899 | 0 | cp++; |
900 | 0 | if (!isdigit((unsigned char) *cp)) { |
901 | 0 | json_error(p, "decimal point must be followed by digit"); |
902 | 0 | return; |
903 | 0 | } |
904 | 0 | do { |
905 | 0 | if (significand <= ULLONG_MAX / 10) { |
906 | 0 | significand = significand * 10 + (*cp - '0'); |
907 | 0 | pow10--; |
908 | 0 | } else if (*cp != '0') { |
909 | 0 | imprecise = true; |
910 | 0 | } |
911 | 0 | cp++; |
912 | 0 | } while (isdigit((unsigned char) *cp)); |
913 | 0 | } |
914 | | |
915 | | /* Optional exponent. */ |
916 | 0 | if (*cp == 'e' || *cp == 'E') { |
917 | 0 | bool negative_exponent = false; |
918 | 0 | int exponent; |
919 | |
|
920 | 0 | cp++; |
921 | 0 | if (*cp == '+') { |
922 | 0 | cp++; |
923 | 0 | } else if (*cp == '-') { |
924 | 0 | negative_exponent = true; |
925 | 0 | cp++; |
926 | 0 | } |
927 | |
|
928 | 0 | if (!isdigit((unsigned char) *cp)) { |
929 | 0 | json_error(p, "exponent must contain at least one digit"); |
930 | 0 | return; |
931 | 0 | } |
932 | | |
933 | 0 | exponent = 0; |
934 | 0 | do { |
935 | 0 | if (exponent >= INT_MAX / 10) { |
936 | 0 | goto bad_exponent; |
937 | 0 | } |
938 | 0 | exponent = exponent * 10 + (*cp - '0'); |
939 | 0 | cp++; |
940 | 0 | } while (isdigit((unsigned char) *cp)); |
941 | | |
942 | 0 | if (negative_exponent) { |
943 | 0 | if (pow10 < INT_MIN + exponent) { |
944 | 0 | goto bad_exponent; |
945 | 0 | } |
946 | 0 | pow10 -= exponent; |
947 | 0 | } else { |
948 | 0 | if (pow10 > INT_MAX - exponent) { |
949 | 0 | goto bad_exponent; |
950 | 0 | } |
951 | 0 | pow10 += exponent; |
952 | 0 | } |
953 | 0 | } |
954 | | |
955 | 0 | if (*cp != '\0') { |
956 | 0 | json_error(p, "syntax error in number"); |
957 | 0 | return; |
958 | 0 | } |
959 | | |
960 | | /* Figure out number. |
961 | | * |
962 | | * We suppress negative zeros as a matter of policy. */ |
963 | 0 | if (!significand) { |
964 | 0 | token.type = T_INTEGER; |
965 | 0 | token.integer = 0; |
966 | 0 | json_parser_input(p, &token); |
967 | 0 | return; |
968 | 0 | } |
969 | | |
970 | 0 | if (!imprecise) { |
971 | 0 | while (pow10 > 0 && significand < ULLONG_MAX / 10) { |
972 | 0 | significand *= 10; |
973 | 0 | pow10--; |
974 | 0 | } |
975 | 0 | while (pow10 < 0 && significand % 10 == 0) { |
976 | 0 | significand /= 10; |
977 | 0 | pow10++; |
978 | 0 | } |
979 | 0 | if (pow10 == 0 |
980 | 0 | && significand <= (negative |
981 | 0 | ? (unsigned long long int) LLONG_MAX + 1 |
982 | 0 | : LLONG_MAX)) { |
983 | 0 | token.type = T_INTEGER; |
984 | 0 | token.integer = negative ? -significand : significand; |
985 | 0 | json_parser_input(p, &token); |
986 | 0 | return; |
987 | 0 | } |
988 | 0 | } |
989 | | |
990 | 0 | token.type = T_REAL; |
991 | 0 | if (!str_to_double(ds_cstr(&p->buffer), &token.real)) { |
992 | 0 | json_error(p, "number outside valid range"); |
993 | 0 | return; |
994 | 0 | } |
995 | | /* Suppress negative zero. */ |
996 | 0 | if (token.real == 0) { |
997 | 0 | token.real = 0; |
998 | 0 | } |
999 | 0 | json_parser_input(p, &token); |
1000 | 0 | return; |
1001 | | |
1002 | 0 | bad_exponent: |
1003 | 0 | json_error(p, "exponent outside valid range"); |
1004 | 0 | } |
1005 | | |
1006 | | static const char * |
1007 | | json_lex_4hex(const char *cp, const char *end, int *valuep) |
1008 | 0 | { |
1009 | 0 | unsigned int value; |
1010 | 0 | bool ok; |
1011 | |
|
1012 | 0 | if (cp + 4 > end) { |
1013 | 0 | return "quoted string ends within \\u escape"; |
1014 | 0 | } |
1015 | | |
1016 | 0 | value = hexits_value(cp, 4, &ok); |
1017 | 0 | if (!ok) { |
1018 | 0 | return "malformed \\u escape"; |
1019 | 0 | } |
1020 | 0 | if (!value) { |
1021 | 0 | return "null bytes not supported in quoted strings"; |
1022 | 0 | } |
1023 | 0 | *valuep = value; |
1024 | 0 | return NULL; |
1025 | 0 | } |
1026 | | |
1027 | | static const char * |
1028 | | json_lex_unicode(const char *cp, const char *end, struct ds *out) |
1029 | 0 | { |
1030 | 0 | const char *error; |
1031 | 0 | int c0, c1; |
1032 | |
|
1033 | 0 | error = json_lex_4hex(cp, end, &c0); |
1034 | 0 | if (error) { |
1035 | 0 | ds_clear(out); |
1036 | 0 | ds_put_cstr(out, error); |
1037 | 0 | return NULL; |
1038 | 0 | } |
1039 | 0 | cp += 4; |
1040 | 0 | if (!uc_is_leading_surrogate(c0)) { |
1041 | 0 | ds_put_utf8(out, c0); |
1042 | 0 | return cp; |
1043 | 0 | } |
1044 | | |
1045 | 0 | if (cp + 2 > end || *cp++ != '\\' || *cp++ != 'u') { |
1046 | 0 | ds_clear(out); |
1047 | 0 | ds_put_cstr(out, "malformed escaped surrogate pair"); |
1048 | 0 | return NULL; |
1049 | 0 | } |
1050 | | |
1051 | 0 | error = json_lex_4hex(cp, end, &c1); |
1052 | 0 | if (error) { |
1053 | 0 | ds_clear(out); |
1054 | 0 | ds_put_cstr(out, error); |
1055 | 0 | return NULL; |
1056 | 0 | } |
1057 | 0 | cp += 4; |
1058 | 0 | if (!uc_is_trailing_surrogate(c1)) { |
1059 | 0 | ds_clear(out); |
1060 | 0 | ds_put_cstr(out, "second half of escaped surrogate pair is not " |
1061 | 0 | "trailing surrogate"); |
1062 | 0 | return NULL; |
1063 | 0 | } |
1064 | | |
1065 | 0 | ds_put_utf8(out, utf16_decode_surrogate_pair(c0, c1)); |
1066 | 0 | return cp; |
1067 | 0 | } |
1068 | | |
1069 | | bool |
1070 | | json_string_unescape(const char *in, size_t in_len, char **outp) |
1071 | 0 | { |
1072 | 0 | const char *end = in + in_len; |
1073 | 0 | bool ok = false; |
1074 | 0 | struct ds out; |
1075 | |
|
1076 | 0 | ds_init(&out); |
1077 | 0 | ds_reserve(&out, in_len); |
1078 | 0 | while (in < end) { |
1079 | 0 | if (*in == '"') { |
1080 | 0 | ds_clear(&out); |
1081 | 0 | ds_put_cstr(&out, "quoted string may not include unescaped \""); |
1082 | 0 | goto exit; |
1083 | 0 | } |
1084 | 0 | if (*in != '\\') { |
1085 | 0 | ds_put_char(&out, *in++); |
1086 | 0 | continue; |
1087 | 0 | } |
1088 | | |
1089 | 0 | in++; |
1090 | 0 | if (in >= end) { |
1091 | | /* The JSON parser will never trigger this message, because its |
1092 | | * lexer will never pass in a string that ends in a single |
1093 | | * backslash, but json_string_unescape() has other callers that |
1094 | | * are not as careful.*/ |
1095 | 0 | ds_clear(&out); |
1096 | 0 | ds_put_cstr(&out, "quoted string may not end with backslash"); |
1097 | 0 | goto exit; |
1098 | 0 | } |
1099 | 0 | switch (*in++) { |
1100 | 0 | case '"': case '\\': case '/': |
1101 | 0 | ds_put_char(&out, in[-1]); |
1102 | 0 | break; |
1103 | | |
1104 | 0 | case 'b': |
1105 | 0 | ds_put_char(&out, '\b'); |
1106 | 0 | break; |
1107 | | |
1108 | 0 | case 'f': |
1109 | 0 | ds_put_char(&out, '\f'); |
1110 | 0 | break; |
1111 | | |
1112 | 0 | case 'n': |
1113 | 0 | ds_put_char(&out, '\n'); |
1114 | 0 | break; |
1115 | | |
1116 | 0 | case 'r': |
1117 | 0 | ds_put_char(&out, '\r'); |
1118 | 0 | break; |
1119 | | |
1120 | 0 | case 't': |
1121 | 0 | ds_put_char(&out, '\t'); |
1122 | 0 | break; |
1123 | | |
1124 | 0 | case 'u': |
1125 | 0 | in = json_lex_unicode(in, end, &out); |
1126 | 0 | if (!in) { |
1127 | 0 | goto exit; |
1128 | 0 | } |
1129 | 0 | break; |
1130 | | |
1131 | 0 | default: |
1132 | 0 | ds_clear(&out); |
1133 | 0 | ds_put_format(&out, "bad escape \\%c", in[-1]); |
1134 | 0 | goto exit; |
1135 | 0 | } |
1136 | 0 | } |
1137 | 0 | ok = true; |
1138 | |
|
1139 | 0 | exit: |
1140 | 0 | *outp = ds_cstr(&out); |
1141 | 0 | return ok; |
1142 | 0 | } |
1143 | | |
1144 | | void |
1145 | | json_string_escape(const char *in, struct ds *out) |
1146 | 0 | { |
1147 | 0 | struct json json = { |
1148 | 0 | .type = JSON_STRING, |
1149 | 0 | .storage_type = JSON_STRING_DYNAMIC, |
1150 | 0 | .str_ptr = CONST_CAST(char *, in), |
1151 | 0 | }; |
1152 | 0 | json_to_ds(&json, 0, out); |
1153 | 0 | } |
1154 | | |
1155 | | static void |
1156 | | json_parser_input_string(struct json_parser *p, const char *s) |
1157 | 0 | { |
1158 | 0 | struct json_token token; |
1159 | |
|
1160 | 0 | token.type = T_STRING; |
1161 | 0 | token.string = s; |
1162 | 0 | json_parser_input(p, &token); |
1163 | 0 | } |
1164 | | |
1165 | | static void |
1166 | | json_lex_string(struct json_parser *p) |
1167 | 0 | { |
1168 | 0 | const char *raw = ds_cstr(&p->buffer); |
1169 | 0 | if (!strchr(raw, '\\')) { |
1170 | 0 | json_parser_input_string(p, raw); |
1171 | 0 | } else { |
1172 | 0 | char *cooked; |
1173 | |
|
1174 | 0 | if (json_string_unescape(raw, strlen(raw), &cooked)) { |
1175 | 0 | json_parser_input_string(p, cooked); |
1176 | 0 | } else { |
1177 | 0 | json_error(p, "%s", cooked); |
1178 | 0 | } |
1179 | |
|
1180 | 0 | free(cooked); |
1181 | 0 | } |
1182 | 0 | } |
1183 | | |
1184 | | |
1185 | | /* Parsing. */ |
1186 | | |
1187 | | /* Parses 'string' as a JSON object or array and returns a newly allocated |
1188 | | * 'struct json'. The caller must free the returned structure with |
1189 | | * json_destroy() when it is no longer needed. |
1190 | | * |
1191 | | * 'string' must be encoded in UTF-8. |
1192 | | * |
1193 | | * If 'string' is valid JSON, then the returned 'struct json' will be either an |
1194 | | * object (JSON_OBJECT) or an array (JSON_ARRAY). |
1195 | | * |
1196 | | * If 'string' is not valid JSON, then the returned 'struct json' will be a |
1197 | | * string (JSON_STRING) that describes the particular error encountered during |
1198 | | * parsing. (This is an acceptable means of error reporting because at its top |
1199 | | * level JSON must be either an object or an array; a bare string is not |
1200 | | * valid.) */ |
1201 | | struct json * |
1202 | | json_from_string(const char *string) |
1203 | 0 | { |
1204 | 0 | struct json_parser *p = json_parser_create(JSPF_TRAILER); |
1205 | 0 | json_parser_feed(p, string, strlen(string)); |
1206 | 0 | return json_parser_finish(p); |
1207 | 0 | } |
1208 | | |
1209 | | /* Parses data of JSON_SERIALIZED_OBJECT to the real JSON. */ |
1210 | | struct json * |
1211 | | json_from_serialized_object(const struct json *json) |
1212 | 0 | { |
1213 | 0 | return json_from_string(json_serialized_object(json)); |
1214 | 0 | } |
1215 | | |
1216 | | /* Reads the file named 'file_name', parses its contents as a JSON object or |
1217 | | * array, and returns a newly allocated 'struct json'. The caller must free |
1218 | | * the returned structure with json_destroy() when it is no longer needed. |
1219 | | * |
1220 | | * The file must be encoded in UTF-8. |
1221 | | * |
1222 | | * See json_from_string() for return value semantics. |
1223 | | */ |
1224 | | struct json * |
1225 | | json_from_file(const char *file_name) |
1226 | 0 | { |
1227 | 0 | struct json *json; |
1228 | 0 | FILE *stream; |
1229 | |
|
1230 | 0 | stream = fopen(file_name, "r"); |
1231 | 0 | if (!stream) { |
1232 | 0 | return json_string_create_nocopy( |
1233 | 0 | xasprintf("error opening \"%s\": %s", file_name, |
1234 | 0 | ovs_strerror(errno))); |
1235 | 0 | } |
1236 | 0 | json = json_from_stream(stream); |
1237 | 0 | fclose(stream); |
1238 | |
|
1239 | 0 | return json; |
1240 | 0 | } |
1241 | | |
1242 | | /* Parses the contents of 'stream' as a JSON object or array, and returns a |
1243 | | * newly allocated 'struct json'. The caller must free the returned structure |
1244 | | * with json_destroy() when it is no longer needed. |
1245 | | * |
1246 | | * The file must be encoded in UTF-8. |
1247 | | * |
1248 | | * See json_from_string() for return value semantics. |
1249 | | */ |
1250 | | struct json * |
1251 | | json_from_stream(FILE *stream) |
1252 | 0 | { |
1253 | 0 | struct json_parser *p; |
1254 | 0 | struct json *json; |
1255 | |
|
1256 | 0 | p = json_parser_create(JSPF_TRAILER); |
1257 | 0 | for (;;) { |
1258 | 0 | char buffer[BUFSIZ]; |
1259 | 0 | size_t n; |
1260 | |
|
1261 | 0 | n = fread(buffer, 1, sizeof buffer, stream); |
1262 | 0 | if (!n || json_parser_feed(p, buffer, n) != n) { |
1263 | 0 | break; |
1264 | 0 | } |
1265 | 0 | } |
1266 | 0 | json = json_parser_finish(p); |
1267 | |
|
1268 | 0 | if (ferror(stream)) { |
1269 | 0 | json_destroy(json); |
1270 | 0 | json = json_string_create_nocopy( |
1271 | 0 | xasprintf("error reading JSON stream: %s", ovs_strerror(errno))); |
1272 | 0 | } |
1273 | |
|
1274 | 0 | return json; |
1275 | 0 | } |
1276 | | |
1277 | | struct json_parser * |
1278 | | json_parser_create(int flags) |
1279 | 0 | { |
1280 | 0 | struct json_parser *p = xzalloc(sizeof *p); |
1281 | 0 | p->flags = flags; |
1282 | 0 | return p; |
1283 | 0 | } |
1284 | | |
1285 | | static inline void ALWAYS_INLINE |
1286 | | json_parser_account_byte(struct json_parser *p, unsigned char c) |
1287 | 0 | { |
1288 | 0 | p->byte_number++; |
1289 | 0 | if (OVS_UNLIKELY(c == '\n')) { |
1290 | 0 | p->column_number = 0; |
1291 | 0 | p->line_number++; |
1292 | 0 | } else { |
1293 | 0 | p->column_number++; |
1294 | 0 | } |
1295 | 0 | } |
1296 | | |
1297 | | size_t |
1298 | | json_parser_feed(struct json_parser *p, const char *input, size_t n) |
1299 | 0 | { |
1300 | 0 | size_t token_start = 0; |
1301 | 0 | size_t i; |
1302 | |
|
1303 | 0 | for (i = 0; !p->done && i < n; ) { |
1304 | 0 | bool consumed = true; |
1305 | |
|
1306 | 0 | const char *start_p = &input[token_start]; |
1307 | 0 | unsigned char c = input[i]; |
1308 | 0 | struct json_token token; |
1309 | |
|
1310 | 0 | switch (p->lex_state) { |
1311 | 0 | case JSON_LEX_START: |
1312 | 0 | switch (c) { |
1313 | 0 | case ' ': case '\t': case '\n': case '\r': |
1314 | | /* Nothing to do. */ |
1315 | 0 | token_start = i + 1; |
1316 | 0 | break; |
1317 | | |
1318 | 0 | case 'a': case 'b': case 'c': case 'd': case 'e': |
1319 | 0 | case 'f': case 'g': case 'h': case 'i': case 'j': |
1320 | 0 | case 'k': case 'l': case 'm': case 'n': case 'o': |
1321 | 0 | case 'p': case 'q': case 'r': case 's': case 't': |
1322 | 0 | case 'u': case 'v': case 'w': case 'x': case 'y': |
1323 | 0 | case 'z': |
1324 | 0 | p->lex_state = JSON_LEX_KEYWORD; |
1325 | 0 | token_start = i; |
1326 | 0 | break; |
1327 | | |
1328 | 0 | case '[': case '{': case ']': case '}': case ':': case ',': |
1329 | 0 | token.type = c; |
1330 | 0 | json_parser_input(p, &token); |
1331 | 0 | token_start = i + 1; |
1332 | 0 | break; |
1333 | | |
1334 | 0 | case '-': |
1335 | 0 | case '0': case '1': case '2': case '3': case '4': |
1336 | 0 | case '5': case '6': case '7': case '8': case '9': |
1337 | 0 | p->lex_state = JSON_LEX_NUMBER; |
1338 | 0 | token_start = i; |
1339 | 0 | break; |
1340 | | |
1341 | 0 | case '"': |
1342 | 0 | p->lex_state = JSON_LEX_STRING; |
1343 | 0 | token_start = i + 1; |
1344 | 0 | break; |
1345 | | |
1346 | 0 | default: |
1347 | 0 | if (isprint(c)) { |
1348 | 0 | json_error(p, "invalid character '%c'", c); |
1349 | 0 | } else { |
1350 | 0 | json_error(p, "invalid character U+%04x", c); |
1351 | 0 | } |
1352 | 0 | break; |
1353 | 0 | } |
1354 | 0 | break; |
1355 | | |
1356 | 0 | case JSON_LEX_KEYWORD: |
1357 | 0 | if (!isalpha((unsigned char) c)) { |
1358 | 0 | ds_put_buffer(&p->buffer, start_p, i - token_start); |
1359 | 0 | json_lex_keyword(p); |
1360 | 0 | consumed = false; |
1361 | 0 | break; |
1362 | 0 | } |
1363 | 0 | break; |
1364 | | |
1365 | 0 | case JSON_LEX_NUMBER: |
1366 | 0 | if (!strchr(".0123456789eE-+", c)) { |
1367 | 0 | ds_put_buffer(&p->buffer, start_p, i - token_start); |
1368 | 0 | json_lex_number(p); |
1369 | 0 | consumed = false; |
1370 | 0 | break; |
1371 | 0 | } |
1372 | 0 | break; |
1373 | | |
1374 | 0 | case JSON_LEX_STRING: |
1375 | 0 | if (c == '\\') { |
1376 | 0 | p->lex_state = JSON_LEX_ESCAPE; |
1377 | 0 | } else if (c == '"') { |
1378 | 0 | ds_put_buffer(&p->buffer, start_p, i - token_start); |
1379 | 0 | json_lex_string(p); |
1380 | 0 | } else if (c < 0x20) { |
1381 | 0 | json_error(p, "U+%04X must be escaped in quoted string", c); |
1382 | 0 | } |
1383 | 0 | break; |
1384 | | |
1385 | 0 | case JSON_LEX_ESCAPE: |
1386 | 0 | p->lex_state = JSON_LEX_STRING; |
1387 | 0 | break; |
1388 | | |
1389 | 0 | default: |
1390 | 0 | ovs_abort(0, "unexpected lexer state"); |
1391 | 0 | } |
1392 | | |
1393 | 0 | if (consumed) { |
1394 | 0 | json_parser_account_byte(p, c); |
1395 | 0 | i++; |
1396 | 0 | } |
1397 | 0 | } |
1398 | | |
1399 | 0 | if (!p->done) { |
1400 | 0 | ds_put_buffer(&p->buffer, &input[token_start], i - token_start); |
1401 | 0 | } |
1402 | 0 | return i; |
1403 | 0 | } |
1404 | | |
1405 | | bool |
1406 | | json_parser_is_done(const struct json_parser *p) |
1407 | 0 | { |
1408 | 0 | return p->done; |
1409 | 0 | } |
1410 | | |
1411 | | struct json * |
1412 | | json_parser_finish(struct json_parser *p) |
1413 | 0 | { |
1414 | 0 | struct json *json; |
1415 | |
|
1416 | 0 | switch (p->lex_state) { |
1417 | 0 | case JSON_LEX_START: |
1418 | 0 | break; |
1419 | | |
1420 | 0 | case JSON_LEX_STRING: |
1421 | 0 | case JSON_LEX_ESCAPE: |
1422 | 0 | json_error(p, "unexpected end of input in quoted string"); |
1423 | 0 | break; |
1424 | | |
1425 | 0 | case JSON_LEX_NUMBER: |
1426 | 0 | case JSON_LEX_KEYWORD: |
1427 | 0 | json_parser_feed(p, " ", 1); |
1428 | 0 | break; |
1429 | 0 | } |
1430 | | |
1431 | 0 | if (p->parse_state == JSON_PARSE_START) { |
1432 | 0 | json_error(p, "empty input stream"); |
1433 | 0 | } else if (p->parse_state != JSON_PARSE_END) { |
1434 | 0 | json_error(p, "unexpected end of input"); |
1435 | 0 | } |
1436 | |
|
1437 | 0 | if (!p->error) { |
1438 | 0 | ovs_assert(p->height == 1); |
1439 | 0 | ovs_assert(p->stack[0].json != NULL); |
1440 | 0 | json = p->stack[--p->height].json; |
1441 | 0 | } else { |
1442 | 0 | json = json_string_create_nocopy(p->error); |
1443 | 0 | p->error = NULL; |
1444 | 0 | } |
1445 | |
|
1446 | 0 | json_parser_abort(p); |
1447 | |
|
1448 | 0 | return json; |
1449 | 0 | } |
1450 | | |
1451 | | void |
1452 | | json_parser_abort(struct json_parser *p) |
1453 | 0 | { |
1454 | 0 | if (p) { |
1455 | 0 | ds_destroy(&p->buffer); |
1456 | 0 | if (p->height) { |
1457 | 0 | json_destroy(p->stack[0].json); |
1458 | 0 | } |
1459 | 0 | free(p->stack); |
1460 | 0 | free(p->member_name); |
1461 | 0 | free(p->error); |
1462 | 0 | free(p); |
1463 | 0 | } |
1464 | 0 | } |
1465 | | |
1466 | | static struct json_parser_node * |
1467 | | json_parser_top(struct json_parser *p) |
1468 | 0 | { |
1469 | 0 | return &p->stack[p->height - 1]; |
1470 | 0 | } |
1471 | | |
1472 | | static void |
1473 | | json_parser_put_value(struct json_parser *p, struct json *value) |
1474 | 0 | { |
1475 | 0 | struct json_parser_node *node = json_parser_top(p); |
1476 | 0 | if (node->json->type == JSON_OBJECT) { |
1477 | 0 | json_object_put_nocopy(node->json, p->member_name, value); |
1478 | 0 | p->member_name = NULL; |
1479 | 0 | } else if (node->json->type == JSON_ARRAY) { |
1480 | 0 | json_array_add(node->json, value); |
1481 | 0 | } else { |
1482 | 0 | OVS_NOT_REACHED(); |
1483 | 0 | } |
1484 | 0 | } |
1485 | | |
1486 | | static void |
1487 | | json_parser_push(struct json_parser *p, |
1488 | | struct json *new_json, enum json_parse_state new_state) |
1489 | 0 | { |
1490 | 0 | if (p->height < JSON_MAX_HEIGHT) { |
1491 | 0 | struct json_parser_node *node; |
1492 | |
|
1493 | 0 | if (p->height >= p->allocated_height) { |
1494 | 0 | p->stack = x2nrealloc(p->stack, &p->allocated_height, |
1495 | 0 | sizeof *p->stack); |
1496 | 0 | } |
1497 | |
|
1498 | 0 | if (p->height > 0) { |
1499 | 0 | json_parser_put_value(p, new_json); |
1500 | 0 | } |
1501 | |
|
1502 | 0 | node = &p->stack[p->height++]; |
1503 | 0 | node->json = new_json; |
1504 | 0 | p->parse_state = new_state; |
1505 | 0 | } else { |
1506 | 0 | json_destroy(new_json); |
1507 | 0 | json_error(p, "input exceeds maximum nesting depth %d", |
1508 | 0 | JSON_MAX_HEIGHT); |
1509 | 0 | } |
1510 | 0 | } |
1511 | | |
1512 | | static void |
1513 | | json_parser_push_object(struct json_parser *p) |
1514 | 0 | { |
1515 | 0 | json_parser_push(p, json_object_create(), JSON_PARSE_OBJECT_INIT); |
1516 | 0 | } |
1517 | | |
1518 | | static void |
1519 | | json_parser_push_array(struct json_parser *p) |
1520 | 0 | { |
1521 | 0 | json_parser_push(p, json_array_create_empty(), JSON_PARSE_ARRAY_INIT); |
1522 | 0 | } |
1523 | | |
1524 | | static void |
1525 | | json_parse_value(struct json_parser *p, struct json_token *token, |
1526 | | enum json_parse_state next_state) |
1527 | 0 | { |
1528 | 0 | struct json *value; |
1529 | |
|
1530 | 0 | switch (token->type) { |
1531 | 0 | case T_FALSE: |
1532 | 0 | value = json_boolean_create(false); |
1533 | 0 | break; |
1534 | | |
1535 | 0 | case T_NULL: |
1536 | 0 | value = json_null_create(); |
1537 | 0 | break; |
1538 | | |
1539 | 0 | case T_TRUE: |
1540 | 0 | value = json_boolean_create(true); |
1541 | 0 | break; |
1542 | | |
1543 | 0 | case '{': |
1544 | 0 | json_parser_push_object(p); |
1545 | 0 | return; |
1546 | | |
1547 | 0 | case '[': |
1548 | 0 | json_parser_push_array(p); |
1549 | 0 | return; |
1550 | | |
1551 | 0 | case T_INTEGER: |
1552 | 0 | value = json_integer_create(token->integer); |
1553 | 0 | break; |
1554 | | |
1555 | 0 | case T_REAL: |
1556 | 0 | value = json_real_create(token->real); |
1557 | 0 | break; |
1558 | | |
1559 | 0 | case T_STRING: |
1560 | 0 | value = json_string_create(token->string); |
1561 | 0 | break; |
1562 | | |
1563 | 0 | case T_EOF: |
1564 | 0 | case '}': |
1565 | 0 | case ']': |
1566 | 0 | case ':': |
1567 | 0 | case ',': |
1568 | 0 | default: |
1569 | 0 | json_error(p, "syntax error expecting value"); |
1570 | 0 | return; |
1571 | 0 | } |
1572 | | |
1573 | 0 | json_parser_put_value(p, value); |
1574 | 0 | p->parse_state = next_state; |
1575 | 0 | } |
1576 | | |
1577 | | static void |
1578 | | json_parser_pop(struct json_parser *p) |
1579 | 0 | { |
1580 | 0 | struct json_parser_node *node; |
1581 | | |
1582 | | /* Conserve memory. */ |
1583 | 0 | node = json_parser_top(p); |
1584 | 0 | if (node->json->type == JSON_ARRAY) { |
1585 | 0 | json_array_trim(node->json); |
1586 | 0 | } |
1587 | | |
1588 | | /* Pop off the top-of-stack. */ |
1589 | 0 | if (p->height == 1) { |
1590 | 0 | p->parse_state = JSON_PARSE_END; |
1591 | 0 | if (!(p->flags & JSPF_TRAILER)) { |
1592 | 0 | p->done = true; |
1593 | 0 | } |
1594 | 0 | } else { |
1595 | 0 | p->height--; |
1596 | 0 | node = json_parser_top(p); |
1597 | 0 | if (node->json->type == JSON_ARRAY) { |
1598 | 0 | p->parse_state = JSON_PARSE_ARRAY_NEXT; |
1599 | 0 | } else if (node->json->type == JSON_OBJECT) { |
1600 | 0 | p->parse_state = JSON_PARSE_OBJECT_NEXT; |
1601 | 0 | } else { |
1602 | 0 | OVS_NOT_REACHED(); |
1603 | 0 | } |
1604 | 0 | } |
1605 | 0 | } |
1606 | | |
1607 | | static void |
1608 | | json_parser_input(struct json_parser *p, struct json_token *token) |
1609 | 0 | { |
1610 | 0 | switch (p->parse_state) { |
1611 | 0 | case JSON_PARSE_START: |
1612 | 0 | if (token->type == '{') { |
1613 | 0 | json_parser_push_object(p); |
1614 | 0 | } else if (token->type == '[') { |
1615 | 0 | json_parser_push_array(p); |
1616 | 0 | } else { |
1617 | 0 | json_error(p, "syntax error at beginning of input"); |
1618 | 0 | } |
1619 | 0 | break; |
1620 | | |
1621 | 0 | case JSON_PARSE_END: |
1622 | 0 | json_error(p, "trailing garbage at end of input"); |
1623 | 0 | break; |
1624 | | |
1625 | 0 | case JSON_PARSE_OBJECT_INIT: |
1626 | 0 | if (token->type == '}') { |
1627 | 0 | json_parser_pop(p); |
1628 | 0 | break; |
1629 | 0 | } |
1630 | | /* Fall through. */ |
1631 | 0 | case JSON_PARSE_OBJECT_NAME: |
1632 | 0 | if (token->type == T_STRING) { |
1633 | 0 | p->member_name = xstrdup(token->string); |
1634 | 0 | p->parse_state = JSON_PARSE_OBJECT_COLON; |
1635 | 0 | } else { |
1636 | 0 | json_error(p, "syntax error parsing object expecting string"); |
1637 | 0 | } |
1638 | 0 | break; |
1639 | | |
1640 | 0 | case JSON_PARSE_OBJECT_COLON: |
1641 | 0 | if (token->type == ':') { |
1642 | 0 | p->parse_state = JSON_PARSE_OBJECT_VALUE; |
1643 | 0 | } else { |
1644 | 0 | json_error(p, "syntax error parsing object expecting ':'"); |
1645 | 0 | } |
1646 | 0 | break; |
1647 | | |
1648 | 0 | case JSON_PARSE_OBJECT_VALUE: |
1649 | 0 | json_parse_value(p, token, JSON_PARSE_OBJECT_NEXT); |
1650 | 0 | break; |
1651 | | |
1652 | 0 | case JSON_PARSE_OBJECT_NEXT: |
1653 | 0 | if (token->type == ',') { |
1654 | 0 | p->parse_state = JSON_PARSE_OBJECT_NAME; |
1655 | 0 | } else if (token->type == '}') { |
1656 | 0 | json_parser_pop(p); |
1657 | 0 | } else { |
1658 | 0 | json_error(p, "syntax error expecting '}' or ','"); |
1659 | 0 | } |
1660 | 0 | break; |
1661 | | |
1662 | 0 | case JSON_PARSE_ARRAY_INIT: |
1663 | 0 | if (token->type == ']') { |
1664 | 0 | json_parser_pop(p); |
1665 | 0 | break; |
1666 | 0 | } |
1667 | | /* Fall through. */ |
1668 | 0 | case JSON_PARSE_ARRAY_VALUE: |
1669 | 0 | json_parse_value(p, token, JSON_PARSE_ARRAY_NEXT); |
1670 | 0 | break; |
1671 | | |
1672 | 0 | case JSON_PARSE_ARRAY_NEXT: |
1673 | 0 | if (token->type == ',') { |
1674 | 0 | p->parse_state = JSON_PARSE_ARRAY_VALUE; |
1675 | 0 | } else if (token->type == ']') { |
1676 | 0 | json_parser_pop(p); |
1677 | 0 | } else { |
1678 | 0 | json_error(p, "syntax error expecting ']' or ','"); |
1679 | 0 | } |
1680 | 0 | break; |
1681 | | |
1682 | 0 | default: |
1683 | 0 | abort(); |
1684 | 0 | } |
1685 | | |
1686 | 0 | p->lex_state = JSON_LEX_START; |
1687 | 0 | ds_clear(&p->buffer); |
1688 | 0 | } |
1689 | | |
1690 | | static struct json * |
1691 | | json_create(enum json_type type) |
1692 | 0 | { |
1693 | 0 | struct json *json = xmalloc(sizeof *json); |
1694 | 0 | json->type = type; |
1695 | 0 | json->count = 1; |
1696 | 0 | return json; |
1697 | 0 | } |
1698 | | |
1699 | | static void |
1700 | | json_error(struct json_parser *p, const char *format, ...) |
1701 | 0 | { |
1702 | 0 | if (!p->error) { |
1703 | 0 | struct ds msg; |
1704 | 0 | va_list args; |
1705 | |
|
1706 | 0 | ds_init(&msg); |
1707 | 0 | ds_put_format(&msg, "line %d, column %d, byte %d: ", |
1708 | 0 | p->line_number, p->column_number, p->byte_number); |
1709 | 0 | va_start(args, format); |
1710 | 0 | ds_put_format_valist(&msg, format, args); |
1711 | 0 | va_end(args); |
1712 | |
|
1713 | 0 | p->error = ds_steal_cstr(&msg); |
1714 | |
|
1715 | 0 | p->done = true; |
1716 | 0 | } |
1717 | 0 | } |
1718 | | |
1719 | 0 | #define SPACES_PER_LEVEL 2 |
1720 | | |
1721 | | struct json_serializer { |
1722 | | struct ds *ds; |
1723 | | int depth; |
1724 | | int flags; |
1725 | | }; |
1726 | | |
1727 | | static void json_serialize(const struct json *, struct json_serializer *); |
1728 | | static void json_serialize_object(const struct shash *object, |
1729 | | struct json_serializer *); |
1730 | | static void json_serialize_array(const struct json *, |
1731 | | struct json_serializer *); |
1732 | | static void json_serialize_string(const char *, struct ds *); |
1733 | | |
1734 | | /* Converts 'json' to a string in JSON format, encoded in UTF-8, and returns |
1735 | | * that string. The caller is responsible for freeing the returned string, |
1736 | | * with free(), when it is no longer needed. |
1737 | | * |
1738 | | * If 'flags' contains JSSF_PRETTY, the output is pretty-printed with each |
1739 | | * nesting level introducing an additional indentation. Otherwise, the |
1740 | | * returned string does not contain any new-line characters. |
1741 | | * |
1742 | | * If 'flags' contains JSSF_SORT, members of objects in the output are sorted |
1743 | | * in bytewise lexicographic order for reproducibility. Otherwise, members of |
1744 | | * objects are output in an indeterminate order. |
1745 | | * |
1746 | | * The returned string is valid JSON only if 'json' represents an array or an |
1747 | | * object, since a bare literal does not satisfy the JSON grammar. */ |
1748 | | char * |
1749 | | json_to_string(const struct json *json, int flags) |
1750 | 0 | { |
1751 | 0 | struct ds ds; |
1752 | |
|
1753 | 0 | ds_init(&ds); |
1754 | 0 | json_to_ds(json, flags, &ds); |
1755 | 0 | return ds_steal_cstr(&ds); |
1756 | 0 | } |
1757 | | |
1758 | | /* Same as json_to_string(), but the output is appended to 'ds'. */ |
1759 | | void |
1760 | | json_to_ds(const struct json *json, int flags, struct ds *ds) |
1761 | 0 | { |
1762 | 0 | struct json_serializer s; |
1763 | |
|
1764 | 0 | s.ds = ds; |
1765 | 0 | s.depth = 0; |
1766 | 0 | s.flags = flags; |
1767 | 0 | json_serialize(json, &s); |
1768 | 0 | } |
1769 | | |
1770 | | static void |
1771 | | json_serialize(const struct json *json, struct json_serializer *s) |
1772 | 0 | { |
1773 | 0 | struct ds *ds = s->ds; |
1774 | |
|
1775 | 0 | switch (json->type) { |
1776 | 0 | case JSON_NULL: |
1777 | 0 | ds_put_cstr(ds, "null"); |
1778 | 0 | break; |
1779 | | |
1780 | 0 | case JSON_FALSE: |
1781 | 0 | ds_put_cstr(ds, "false"); |
1782 | 0 | break; |
1783 | | |
1784 | 0 | case JSON_TRUE: |
1785 | 0 | ds_put_cstr(ds, "true"); |
1786 | 0 | break; |
1787 | | |
1788 | 0 | case JSON_OBJECT: |
1789 | 0 | json_serialize_object(json->object, s); |
1790 | 0 | break; |
1791 | | |
1792 | 0 | case JSON_ARRAY: |
1793 | 0 | json_serialize_array(json, s); |
1794 | 0 | break; |
1795 | | |
1796 | 0 | case JSON_INTEGER: |
1797 | 0 | ds_put_format(ds, "%lld", json->integer); |
1798 | 0 | break; |
1799 | | |
1800 | 0 | case JSON_REAL: |
1801 | 0 | ds_put_format(ds, "%.*g", DBL_DIG, json->real); |
1802 | 0 | break; |
1803 | | |
1804 | 0 | case JSON_STRING: |
1805 | 0 | json_serialize_string(json_string(json), ds); |
1806 | 0 | break; |
1807 | | |
1808 | 0 | case JSON_SERIALIZED_OBJECT: |
1809 | 0 | ds_put_cstr(ds, json_serialized_object(json)); |
1810 | 0 | break; |
1811 | | |
1812 | 0 | case JSON_N_TYPES: |
1813 | 0 | default: |
1814 | 0 | OVS_NOT_REACHED(); |
1815 | 0 | } |
1816 | 0 | } |
1817 | | |
1818 | | static void |
1819 | | indent_line(struct json_serializer *s) |
1820 | 0 | { |
1821 | 0 | if (s->flags & JSSF_PRETTY) { |
1822 | 0 | ds_put_char(s->ds, '\n'); |
1823 | 0 | ds_put_char_multiple(s->ds, ' ', SPACES_PER_LEVEL * s->depth); |
1824 | 0 | } |
1825 | 0 | } |
1826 | | |
1827 | | static void |
1828 | | json_serialize_object_member(size_t i, const struct shash_node *node, |
1829 | | struct json_serializer *s) |
1830 | 0 | { |
1831 | 0 | struct ds *ds = s->ds; |
1832 | |
|
1833 | 0 | if (i) { |
1834 | 0 | ds_put_char(ds, ','); |
1835 | 0 | indent_line(s); |
1836 | 0 | } |
1837 | |
|
1838 | 0 | json_serialize_string(node->name, ds); |
1839 | 0 | ds_put_char(ds, ':'); |
1840 | 0 | if (s->flags & JSSF_PRETTY) { |
1841 | 0 | ds_put_char(ds, ' '); |
1842 | 0 | } |
1843 | 0 | json_serialize(node->data, s); |
1844 | 0 | } |
1845 | | |
1846 | | static void |
1847 | | json_serialize_object(const struct shash *object, struct json_serializer *s) |
1848 | 0 | { |
1849 | 0 | struct ds *ds = s->ds; |
1850 | |
|
1851 | 0 | ds_put_char(ds, '{'); |
1852 | |
|
1853 | 0 | s->depth++; |
1854 | 0 | indent_line(s); |
1855 | |
|
1856 | 0 | if (s->flags & JSSF_YIELD) { |
1857 | 0 | cooperative_multitasking_yield(); |
1858 | 0 | } |
1859 | |
|
1860 | 0 | if (s->flags & JSSF_SORT) { |
1861 | 0 | const struct shash_node **nodes; |
1862 | 0 | size_t n, i; |
1863 | |
|
1864 | 0 | nodes = shash_sort(object); |
1865 | 0 | n = shash_count(object); |
1866 | 0 | for (i = 0; i < n; i++) { |
1867 | 0 | json_serialize_object_member(i, nodes[i], s); |
1868 | 0 | } |
1869 | 0 | free(nodes); |
1870 | 0 | } else { |
1871 | 0 | struct shash_node *node; |
1872 | 0 | size_t i; |
1873 | |
|
1874 | 0 | i = 0; |
1875 | 0 | SHASH_FOR_EACH (node, object) { |
1876 | 0 | json_serialize_object_member(i++, node, s); |
1877 | 0 | } |
1878 | 0 | } |
1879 | |
|
1880 | 0 | ds_put_char(ds, '}'); |
1881 | 0 | s->depth--; |
1882 | 0 | } |
1883 | | |
1884 | | static void |
1885 | | json_serialize_array(const struct json *json, struct json_serializer *s) |
1886 | 0 | { |
1887 | 0 | size_t i, n = json_array_size(json); |
1888 | 0 | struct ds *ds = s->ds; |
1889 | |
|
1890 | 0 | ds_put_char(ds, '['); |
1891 | 0 | s->depth++; |
1892 | |
|
1893 | 0 | if (s->flags & JSSF_YIELD) { |
1894 | 0 | cooperative_multitasking_yield(); |
1895 | 0 | } |
1896 | |
|
1897 | 0 | if (n > 0) { |
1898 | 0 | indent_line(s); |
1899 | |
|
1900 | 0 | for (i = 0; i < n; i++) { |
1901 | 0 | if (i) { |
1902 | 0 | ds_put_char(ds, ','); |
1903 | 0 | indent_line(s); |
1904 | 0 | } |
1905 | 0 | json_serialize(json_array_at(json, i), s); |
1906 | 0 | } |
1907 | 0 | } |
1908 | |
|
1909 | 0 | s->depth--; |
1910 | 0 | ds_put_char(ds, ']'); |
1911 | 0 | } |
1912 | | |
1913 | | static const char *chars_escaping[256] = { |
1914 | | "\\u0000", "\\u0001", "\\u0002", "\\u0003", "\\u0004", "\\u0005", "\\u0006", "\\u0007", |
1915 | | "\\b", "\\t", "\\n", "\\u000b", "\\f", "\\r", "\\u000e", "\\u000f", |
1916 | | "\\u0010", "\\u0011", "\\u0012", "\\u0013", "\\u0014", "\\u0015", "\\u0016", "\\u0017", |
1917 | | "\\u0018", "\\u0019", "\\u001a", "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f", |
1918 | | " ", "!", "\\\"", "#", "$", "%", "&", "'", |
1919 | | "(", ")", "*", "+", ",", "-", ".", "/", |
1920 | | "0", "1", "2", "3", "4", "5", "6", "7", |
1921 | | "8", "9", ":", ";", "<", "=", ">", "?", |
1922 | | "@", "A", "B", "C", "D", "E", "F", "G", |
1923 | | "H", "I", "J", "K", "L", "M", "N", "O", |
1924 | | "P", "Q", "R", "S", "T", "U", "V", "W", |
1925 | | "X", "Y", "Z", "[", "\\\\", "]", "^", "_", |
1926 | | "`", "a", "b", "c", "d", "e", "f", "g", |
1927 | | "h", "i", "j", "k", "l", "m", "n", "o", |
1928 | | "p", "q", "r", "s", "t", "u", "v", "w", |
1929 | | "x", "y", "z", "{", "|", "}", "~", "\x7f", |
1930 | | "\x80", "\x81", "\x82", "\x83", "\x84", "\x85", "\x86", "\x87", |
1931 | | "\x88", "\x89", "\x8a", "\x8b", "\x8c", "\x8d", "\x8e", "\x8f", |
1932 | | "\x90", "\x91", "\x92", "\x93", "\x94", "\x95", "\x96", "\x97", |
1933 | | "\x98", "\x99", "\x9a", "\x9b", "\x9c", "\x9d", "\x9e", "\x9f", |
1934 | | "\xa0", "\xa1", "\xa2", "\xa3", "\xa4", "\xa5", "\xa6", "\xa7", |
1935 | | "\xa8", "\xa9", "\xaa", "\xab", "\xac", "\xad", "\xae", "\xaf", |
1936 | | "\xb0", "\xb1", "\xb2", "\xb3", "\xb4", "\xb5", "\xb6", "\xb7", |
1937 | | "\xb8", "\xb9", "\xba", "\xbb", "\xbc", "\xbd", "\xbe", "\xbf", |
1938 | | "\xc0", "\xc1", "\xc2", "\xc3", "\xc4", "\xc5", "\xc6", "\xc7", |
1939 | | "\xc8", "\xc9", "\xca", "\xcb", "\xcc", "\xcd", "\xce", "\xcf", |
1940 | | "\xd0", "\xd1", "\xd2", "\xd3", "\xd4", "\xd5", "\xd6", "\xd7", |
1941 | | "\xd8", "\xd9", "\xda", "\xdb", "\xdc", "\xdd", "\xde", "\xdf", |
1942 | | "\xe0", "\xe1", "\xe2", "\xe3", "\xe4", "\xe5", "\xe6", "\xe7", |
1943 | | "\xe8", "\xe9", "\xea", "\xeb", "\xec", "\xed", "\xee", "\xef", |
1944 | | "\xf0", "\xf1", "\xf2", "\xf3", "\xf4", "\xf5", "\xf6", "\xf7", |
1945 | | "\xf8", "\xf9", "\xfa", "\xfb", "\xfc", "\xfd", "\xfe", "\xff" |
1946 | | }; |
1947 | | |
1948 | | static void |
1949 | | json_serialize_string(const char *string, struct ds *ds) |
1950 | 0 | { |
1951 | 0 | uint8_t c; |
1952 | 0 | uint8_t c2; |
1953 | 0 | size_t count; |
1954 | 0 | const char *escape; |
1955 | 0 | const char *start; |
1956 | |
|
1957 | 0 | ds_put_char(ds, '"'); |
1958 | 0 | count = 0; |
1959 | 0 | start = string; |
1960 | 0 | while ((c = *string++) != '\0') { |
1961 | 0 | if (c >= ' ' && c != '"' && c != '\\') { |
1962 | 0 | count++; |
1963 | 0 | } else { |
1964 | 0 | if (count) { |
1965 | 0 | ds_put_buffer(ds, start, count); |
1966 | 0 | count = 0; |
1967 | 0 | } |
1968 | 0 | start = string; |
1969 | 0 | escape = chars_escaping[c]; |
1970 | 0 | while ((c2 = *escape++) != '\0') { |
1971 | 0 | ds_put_char(ds, c2); |
1972 | 0 | } |
1973 | 0 | } |
1974 | 0 | } |
1975 | 0 | if (count) { |
1976 | 0 | ds_put_buffer(ds, start, count); |
1977 | 0 | } |
1978 | 0 | ds_put_char(ds, '"'); |
1979 | 0 | } |