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