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