json.c (20428B)
1 /*
2 * Copyright (c) 2019-2022 Joris Vink <joris@coders.se>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <sys/types.h>
18
19 #include <ctype.h>
20 #include <float.h>
21 #include <inttypes.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26
27 #include "kore.h"
28
29 static int json_guess_type(u_int8_t, u_int32_t *);
30 static int json_next(struct kore_json *, u_int8_t *);
31 static int json_peek(struct kore_json *, u_int8_t *);
32
33 static int json_consume_whitespace(struct kore_json *);
34 static int json_next_byte(struct kore_json *, u_int8_t *, int);
35
36 static char *json_get_string(struct kore_json *);
37 static void json_build_string(struct kore_json_item *, const char *);
38
39 static int json_parse_array(struct kore_json *, struct kore_json_item *);
40 static int json_parse_object(struct kore_json *, struct kore_json_item *);
41 static int json_parse_string(struct kore_json *, struct kore_json_item *);
42 static int json_parse_number(struct kore_json *, struct kore_json_item *);
43 static int json_parse_literal(struct kore_json *, struct kore_json_item *);
44
45 static struct kore_json_item *json_item_alloc(int, const char *,
46 struct kore_json_item *);
47 static struct kore_json_item *json_find_item(struct kore_json_item *,
48 char **, u_int32_t, int);
49
50 static u_int8_t json_null_literal[] = { 'n', 'u', 'l', 'l' };
51 static u_int8_t json_true_literal[] = { 't', 'r', 'u', 'e' };
52 static u_int8_t json_false_literal[] = { 'f', 'a', 'l', 's', 'e' };
53
54 static int json_errno = 0;
55
56 static const char *json_errtab[] = {
57 "no error",
58 "invalid JSON object",
59 "invalid JSON array",
60 "invalid JSON string",
61 "invalid JSON number",
62 "invalid JSON literal",
63 "too many nested items",
64 "end of stream while parsing JSON",
65 "invalid JSON",
66 "invalid search query specified",
67 "item not found",
68 "item found, but not expected value"
69 };
70
71 void
72 kore_json_init(struct kore_json *json, const void *data, size_t len)
73 {
74 memset(json, 0, sizeof(*json));
75
76 json->data = data;
77 json->length = len;
78
79 kore_buf_init(&json->tmpbuf, 1024);
80 }
81
82 int
83 kore_json_parse(struct kore_json *json)
84 {
85 u_int8_t ch;
86 u_int32_t type;
87
88 if (json->root)
89 return (KORE_RESULT_OK);
90
91 json_errno = 0;
92
93 if (json_consume_whitespace(json) == -1) {
94 json_errno = KORE_JSON_ERR_INVALID_JSON;
95 return (KORE_RESULT_ERROR);
96 }
97
98 if (!json_peek(json, &ch))
99 return (KORE_RESULT_ERROR);
100
101 if (!json_guess_type(ch, &type)) {
102 json_errno = KORE_JSON_ERR_INVALID_JSON;
103 return (KORE_RESULT_ERROR);
104 }
105
106 json->root = json_item_alloc(type, NULL, NULL);
107
108 if (!json->root->parse(json, json->root)) {
109 if (json_errno == 0)
110 json_errno = KORE_JSON_ERR_INVALID_JSON;
111 return (KORE_RESULT_ERROR);
112 }
113
114 /* Don't allow garbage at the end. */
115 (void)json_consume_whitespace(json);
116 if (json->offset != json->length) {
117 json_errno = KORE_JSON_ERR_INVALID_JSON;
118 return (KORE_RESULT_ERROR);
119 }
120
121 return (KORE_RESULT_OK);
122 }
123
124 struct kore_json_item *
125 kore_json_find(struct kore_json_item *root, const char *path, u_int32_t type)
126 {
127 struct kore_json_item *item;
128 char *copy;
129 char *tokens[KORE_JSON_DEPTH_MAX + 1];
130
131 json_errno = 0;
132 copy = kore_strdup(path);
133
134 if (!kore_split_string(copy, "/", tokens, KORE_JSON_DEPTH_MAX)) {
135 kore_free(copy);
136 json_errno = KORE_JSON_ERR_INVALID_SEARCH;
137 return (NULL);
138 }
139
140 item = json_find_item(root, tokens, type, 0);
141 kore_free(copy);
142
143 if (item == NULL && json_errno == 0)
144 json_errno = KORE_JSON_ERR_INVALID_SEARCH;
145
146 return (item);
147 }
148
149 void
150 kore_json_cleanup(struct kore_json *json)
151 {
152 if (json == NULL)
153 return;
154
155 kore_buf_cleanup(&json->tmpbuf);
156 kore_json_item_free(json->root);
157 }
158
159 int
160 kore_json_errno(void)
161 {
162 return (json_errno);
163 }
164
165 const char *
166 kore_json_strerror(void)
167 {
168 if (json_errno >= 0 && json_errno <= KORE_JSON_ERR_LAST)
169 return (json_errtab[json_errno]);
170
171 return ("unknown JSON error");
172 }
173
174 struct kore_json_item *
175 kore_json_create_item(struct kore_json_item *parent, const char *name,
176 u_int32_t type, ...)
177 {
178 const char *p;
179 va_list args;
180 struct kore_json_item *item;
181
182 item = kore_calloc(1, sizeof(*item));
183 item->type = type;
184
185 va_start(args, type);
186
187 switch (item->type) {
188 case KORE_JSON_TYPE_OBJECT:
189 TAILQ_INIT(&item->data.items);
190 break;
191 case KORE_JSON_TYPE_ARRAY:
192 TAILQ_INIT(&item->data.items);
193 break;
194 case KORE_JSON_TYPE_STRING:
195 p = va_arg(args, const char *);
196 json_build_string(item, p);
197 break;
198 case KORE_JSON_TYPE_NUMBER:
199 item->data.number = va_arg(args, double);
200 break;
201 case KORE_JSON_TYPE_INTEGER:
202 item->data.integer = va_arg(args, int64_t);
203 break;
204 case KORE_JSON_TYPE_INTEGER_U64:
205 item->data.u64 = va_arg(args, u_int64_t);
206 break;
207 case KORE_JSON_TYPE_LITERAL:
208 item->data.literal = va_arg(args, int);
209 break;
210 default:
211 fatal("%s: unknown type %d", __func__, item->type);
212 }
213
214 if (name)
215 item->name = kore_strdup(name);
216
217 if (parent) {
218 if (parent->type != KORE_JSON_TYPE_OBJECT &&
219 parent->type != KORE_JSON_TYPE_ARRAY) {
220 fatal("%s: invalid parent type (%d)",
221 __func__, parent->type);
222 }
223
224 TAILQ_INSERT_TAIL(&parent->data.items, item, list);
225 }
226
227 va_end(args);
228
229 return (item);
230 }
231
232 void
233 kore_json_item_tobuf(struct kore_json_item *item, struct kore_buf *buf)
234 {
235 struct kore_json_item *nitem;
236
237 if (item->name)
238 kore_buf_appendf(buf, "\"%s\":", item->name);
239
240 switch (item->type) {
241 case KORE_JSON_TYPE_OBJECT:
242 kore_buf_appendf(buf, "{");
243 TAILQ_FOREACH(nitem, &item->data.items, list) {
244 kore_json_item_tobuf(nitem, buf);
245
246 if (TAILQ_NEXT(nitem, list))
247 kore_buf_appendf(buf, ",");
248 }
249 kore_buf_appendf(buf, "}");
250 break;
251 case KORE_JSON_TYPE_ARRAY:
252 kore_buf_appendf(buf, "[");
253 TAILQ_FOREACH(nitem, &item->data.items, list) {
254 kore_json_item_tobuf(nitem, buf);
255
256 if (TAILQ_NEXT(nitem, list))
257 kore_buf_appendf(buf, ",");
258 }
259 kore_buf_appendf(buf, "]");
260 break;
261 case KORE_JSON_TYPE_STRING:
262 kore_buf_appendf(buf, "\"%s\"", item->data.string);
263 break;
264 case KORE_JSON_TYPE_NUMBER:
265 kore_buf_appendf(buf, "%f", item->data.number);
266 break;
267 case KORE_JSON_TYPE_INTEGER:
268 kore_buf_appendf(buf, "%" PRId64, item->data.integer);
269 break;
270 case KORE_JSON_TYPE_INTEGER_U64:
271 kore_buf_appendf(buf, "%" PRIu64, item->data.u64);
272 break;
273 case KORE_JSON_TYPE_LITERAL:
274 switch (item->data.literal) {
275 case KORE_JSON_TRUE:
276 kore_buf_append(buf,
277 json_true_literal, sizeof(json_true_literal));
278 break;
279 case KORE_JSON_FALSE:
280 kore_buf_append(buf,
281 json_false_literal, sizeof(json_false_literal));
282 break;
283 case KORE_JSON_NULL:
284 kore_buf_append(buf,
285 json_null_literal, sizeof(json_null_literal));
286 break;
287 default:
288 fatal("%s: unknown literal %d", __func__,
289 item->data.literal);
290 }
291 break;
292 default:
293 fatal("%s: unknown type %d", __func__, item->type);
294 }
295 }
296
297 void
298 kore_json_item_attach(struct kore_json_item *parent,
299 struct kore_json_item *item)
300 {
301 if (item->parent != NULL)
302 fatal("%s: item already has parent", __func__);
303
304 item->parent = parent;
305
306 if (parent->type != KORE_JSON_TYPE_OBJECT &&
307 parent->type != KORE_JSON_TYPE_ARRAY) {
308 fatal("%s: invalid parent type (%d)",
309 __func__, parent->type);
310 }
311
312 TAILQ_INSERT_TAIL(&parent->data.items, item, list);
313 }
314
315 static struct kore_json_item *
316 json_find_item(struct kore_json_item *object, char **tokens,
317 u_int32_t type, int pos)
318 {
319 char *p, *str;
320 struct kore_json_item *item, *nitem;
321 int err, idx, spot;
322
323 if (tokens[pos] == NULL)
324 return (NULL);
325
326 if (object->type != KORE_JSON_TYPE_OBJECT &&
327 object->type != KORE_JSON_TYPE_ARRAY)
328 return (NULL);
329
330 if ((str = strchr(tokens[pos], '[')) != NULL) {
331 *(str)++ = '\0';
332
333 if ((p = strchr(str, ']')) == NULL)
334 return (NULL);
335
336 *p = '\0';
337
338 spot = kore_strtonum(str, 10, 0, USHRT_MAX, &err);
339 if (err != KORE_RESULT_OK)
340 return (NULL);
341 } else {
342 spot = -1;
343 }
344
345 item = NULL;
346
347 TAILQ_FOREACH(item, &object->data.items, list) {
348 if (item->name && strcmp(item->name, tokens[pos]))
349 continue;
350
351 if (item->type == KORE_JSON_TYPE_ARRAY && spot != -1) {
352 idx = 0;
353 nitem = NULL;
354 TAILQ_FOREACH(nitem, &item->data.items, list) {
355 if (idx++ == spot)
356 break;
357 }
358
359 if (nitem == NULL) {
360 json_errno = KORE_JSON_ERR_NOT_FOUND;
361 return (NULL);
362 }
363
364 item = nitem;
365 }
366
367 if (tokens[pos + 1] == NULL) {
368 /*
369 * If an uint64 was required and we find an item
370 * with the same name but marked as an integer check
371 * if it can be represented as a uint64.
372 *
373 * If it can, reduce the type to integer so we match
374 * on it as well.
375 */
376 if (type == KORE_JSON_TYPE_INTEGER_U64 &&
377 item->type == KORE_JSON_TYPE_INTEGER) {
378 if (item->data.integer >= 0)
379 type = KORE_JSON_TYPE_INTEGER;
380 }
381
382 if (item->type == type)
383 return (item);
384
385 json_errno = KORE_JSON_ERR_TYPE_MISMATCH;
386 return (NULL);
387 }
388
389 if (item->type == KORE_JSON_TYPE_OBJECT ||
390 item->type == KORE_JSON_TYPE_ARRAY) {
391 item = json_find_item(item, tokens, type, pos + 1);
392 } else {
393 item = NULL;
394 }
395
396 break;
397 }
398
399 if (item == NULL && json_errno == 0)
400 json_errno = KORE_JSON_ERR_NOT_FOUND;
401
402 return (item);
403 }
404
405 void
406 kore_json_item_free(struct kore_json_item *item)
407 {
408 struct kore_json_item *node;
409
410 if (item == NULL)
411 return;
412
413 switch (item->type) {
414 case KORE_JSON_TYPE_OBJECT:
415 case KORE_JSON_TYPE_ARRAY:
416 while ((node = TAILQ_FIRST(&item->data.items)) != NULL) {
417 TAILQ_REMOVE(&item->data.items, node, list);
418 kore_json_item_free(node);
419 }
420 break;
421 case KORE_JSON_TYPE_STRING:
422 kore_free(item->data.string);
423 break;
424 case KORE_JSON_TYPE_NUMBER:
425 case KORE_JSON_TYPE_LITERAL:
426 case KORE_JSON_TYPE_INTEGER:
427 case KORE_JSON_TYPE_INTEGER_U64:
428 break;
429 default:
430 fatal("%s: unknown type %d", __func__, item->type);
431 }
432
433 kore_free(item->name);
434 kore_free(item);
435 }
436
437 static struct kore_json_item *
438 json_item_alloc(int type, const char *name, struct kore_json_item *parent)
439 {
440 struct kore_json_item *item;
441
442 item = kore_calloc(1, sizeof(*item));
443 item->type = type;
444 item->parent = parent;
445
446 switch (item->type) {
447 case KORE_JSON_TYPE_OBJECT:
448 TAILQ_INIT(&item->data.items);
449 item->parse = json_parse_object;
450 break;
451 case KORE_JSON_TYPE_ARRAY:
452 TAILQ_INIT(&item->data.items);
453 item->parse = json_parse_array;
454 break;
455 case KORE_JSON_TYPE_STRING:
456 item->parse = json_parse_string;
457 break;
458 case KORE_JSON_TYPE_NUMBER:
459 case KORE_JSON_TYPE_INTEGER:
460 case KORE_JSON_TYPE_INTEGER_U64:
461 item->parse = json_parse_number;
462 break;
463 case KORE_JSON_TYPE_LITERAL:
464 item->parse = json_parse_literal;
465 break;
466 default:
467 fatal("%s: unknown type %d", __func__, item->type);
468 }
469
470 if (name)
471 item->name = kore_strdup(name);
472
473 if (parent) {
474 if (parent->type != KORE_JSON_TYPE_OBJECT &&
475 parent->type != KORE_JSON_TYPE_ARRAY) {
476 fatal("%s: invalid parent type (%d)",
477 __func__, parent->type);
478 }
479
480 TAILQ_INSERT_TAIL(&parent->data.items, item, list);
481 }
482
483 return (item);
484 }
485
486 static int
487 json_peek(struct kore_json *json, u_int8_t *ch)
488 {
489 return (json_next_byte(json, ch, 1));
490 }
491
492 static int
493 json_next(struct kore_json *json, u_int8_t *ch)
494 {
495 return (json_next_byte(json, ch, 0));
496 }
497
498 static int
499 json_next_byte(struct kore_json *json, u_int8_t *ch, int peek)
500 {
501 if (json->offset >= json->length) {
502 json_errno = KORE_JSON_ERR_EOF;
503 return (KORE_RESULT_ERROR);
504 }
505
506 *ch = json->data[json->offset];
507
508 if (peek == 0)
509 json->offset++;
510
511 return (KORE_RESULT_OK);
512 }
513
514 static int
515 json_consume_whitespace(struct kore_json *json)
516 {
517 u_int8_t ch;
518
519 for (;;) {
520 if (!json_peek(json, &ch))
521 return (KORE_RESULT_ERROR);
522
523 if (ch != ' ' && ch != '\n' && ch != '\r' && ch != '\t')
524 break;
525
526 json->offset++;
527 }
528
529 return (KORE_RESULT_OK);
530 }
531
532 static int
533 json_guess_type(u_int8_t ch, u_int32_t *type)
534 {
535 if (ch == '-' || (ch >= '0' && ch <= '9')) {
536 *type = KORE_JSON_TYPE_NUMBER;
537 return (KORE_RESULT_OK);
538 }
539
540 switch (ch) {
541 case '{':
542 *type = KORE_JSON_TYPE_OBJECT;
543 break;
544 case '"':
545 *type = KORE_JSON_TYPE_STRING;
546 break;
547 case '[':
548 *type = KORE_JSON_TYPE_ARRAY;
549 break;
550 case 'f':
551 case 'n':
552 case 't':
553 *type = KORE_JSON_TYPE_LITERAL;
554 break;
555 default:
556 return (KORE_RESULT_ERROR);
557 }
558
559 return (KORE_RESULT_OK);
560 }
561
562 static int
563 json_parse_object(struct kore_json *json, struct kore_json_item *object)
564 {
565 u_int8_t ch;
566 u_int32_t type;
567 char *key;
568 struct kore_json_item *item;
569 int ret, hasnext;
570
571 if (json->depth++ >= KORE_JSON_DEPTH_MAX) {
572 json_errno = KORE_JSON_ERR_DEPTH;
573 return (KORE_RESULT_ERROR);
574 }
575
576 key = NULL;
577 hasnext = 0;
578 ret = KORE_RESULT_ERROR;
579
580 if (!json_next(json, &ch))
581 goto cleanup;
582
583 if (ch != '{')
584 goto cleanup;
585
586 for (;;) {
587 if (!json_consume_whitespace(json))
588 goto cleanup;
589
590 if (!json_peek(json, &ch))
591 goto cleanup;
592
593 switch (ch) {
594 case '}':
595 if (hasnext) {
596 json_errno = KORE_JSON_ERR_INVALID_JSON;
597 goto cleanup;
598 }
599 json->offset++;
600 ret = KORE_RESULT_OK;
601 goto cleanup;
602 case '"':
603 if ((key = json_get_string(json)) == NULL)
604 goto cleanup;
605 break;
606 default:
607 goto cleanup;
608 }
609
610 if (!json_consume_whitespace(json))
611 goto cleanup;
612
613 if (!json_next(json, &ch))
614 goto cleanup;
615
616 if (ch != ':')
617 goto cleanup;
618
619 if (!json_consume_whitespace(json))
620 goto cleanup;
621
622 if (!json_peek(json, &ch))
623 goto cleanup;
624
625 if (!json_guess_type(ch, &type))
626 goto cleanup;
627
628 item = json_item_alloc(type, key, object);
629
630 if (!item->parse(json, item))
631 goto cleanup;
632
633 key = NULL;
634
635 if (!json_consume_whitespace(json))
636 goto cleanup;
637
638 if (!json_next(json, &ch))
639 goto cleanup;
640
641 if (ch == ',') {
642 hasnext = 1;
643 continue;
644 }
645
646 if (ch == '}') {
647 ret = KORE_RESULT_OK;
648 break;
649 }
650
651 break;
652 }
653
654 cleanup:
655 if (ret == KORE_RESULT_ERROR && json_errno == 0)
656 json_errno = KORE_JSON_ERR_INVALID_OBJECT;
657
658 json->depth--;
659
660 return (ret);
661 }
662
663 static int
664 json_parse_array(struct kore_json *json, struct kore_json_item *array)
665 {
666 u_int8_t ch;
667 u_int32_t type;
668 char *key;
669 struct kore_json_item *item;
670 int ret, hasnext;
671
672 if (json->depth++ >= KORE_JSON_DEPTH_MAX) {
673 json_errno = KORE_JSON_ERR_DEPTH;
674 return (KORE_RESULT_ERROR);
675 }
676
677 key = NULL;
678 hasnext = 0;
679 ret = KORE_RESULT_ERROR;
680
681 if (!json_next(json, &ch))
682 goto cleanup;
683
684 if (ch != '[')
685 goto cleanup;
686
687 for (;;) {
688 if (!json_consume_whitespace(json))
689 goto cleanup;
690
691 if (!json_peek(json, &ch))
692 goto cleanup;
693
694 if (ch == ']') {
695 if (hasnext) {
696 json_errno = KORE_JSON_ERR_INVALID_JSON;
697 goto cleanup;
698 }
699 json->offset++;
700 ret = KORE_RESULT_OK;
701 goto cleanup;
702 }
703
704 if (!json_guess_type(ch, &type))
705 goto cleanup;
706
707 item = json_item_alloc(type, key, array);
708
709 if (!item->parse(json, item))
710 goto cleanup;
711
712 key = NULL;
713
714 if (!json_consume_whitespace(json))
715 goto cleanup;
716
717 if (!json_next(json, &ch))
718 goto cleanup;
719
720 if (ch == ',') {
721 hasnext = 1;
722 continue;
723 }
724
725 if (ch == ']') {
726 ret = KORE_RESULT_OK;
727 break;
728 }
729
730 break;
731 }
732
733 cleanup:
734 if (ret == KORE_RESULT_ERROR && json_errno == 0)
735 json_errno = KORE_JSON_ERR_INVALID_ARRAY;
736
737 json->depth--;
738
739 return (ret);
740 }
741
742 static int
743 json_parse_string(struct kore_json *json, struct kore_json_item *string)
744 {
745 char *value;
746
747 if ((value = json_get_string(json)) == NULL)
748 return (KORE_RESULT_ERROR);
749
750 string->type = KORE_JSON_TYPE_STRING;
751 string->data.string = kore_strdup(value);
752
753 return (KORE_RESULT_OK);
754 }
755
756 static int
757 json_parse_number(struct kore_json *json, struct kore_json_item *number)
758 {
759 u_int8_t ch;
760 int ret;
761 char *str;
762 u_int32_t type;
763
764 str = NULL;
765 ret = KORE_RESULT_ERROR;
766 kore_buf_reset(&json->tmpbuf);
767
768 type = KORE_JSON_TYPE_NUMBER | KORE_JSON_TYPE_INTEGER |
769 KORE_JSON_TYPE_INTEGER_U64;
770
771 for (;;) {
772 if (!json_peek(json, &ch))
773 break;
774
775 switch (ch) {
776 case 'e':
777 case 'E':
778 case '.':
779 type = KORE_JSON_TYPE_NUMBER;
780 kore_buf_append(&json->tmpbuf, &ch, sizeof(ch));
781 json->offset++;
782 continue;
783 case '-':
784 if (json->tmpbuf.offset != 0)
785 goto cleanup;
786 type &= ~KORE_JSON_TYPE_INTEGER_U64;
787 /* FALLTHROUGH */
788 case '0':
789 case '1':
790 case '2':
791 case '3':
792 case '4':
793 case '5':
794 case '6':
795 case '7':
796 case '8':
797 case '9':
798 case '+':
799 kore_buf_append(&json->tmpbuf, &ch, sizeof(ch));
800 json->offset++;
801 continue;
802 }
803
804 break;
805 }
806
807 if (type & KORE_JSON_TYPE_INTEGER_U64)
808 type = KORE_JSON_TYPE_INTEGER_U64;
809
810 if (type & KORE_JSON_TYPE_INTEGER)
811 type = KORE_JSON_TYPE_INTEGER;
812
813 str = kore_buf_stringify(&json->tmpbuf, NULL);
814
815 switch (type) {
816 case KORE_JSON_TYPE_NUMBER:
817 number->data.number =
818 kore_strtodouble(str, -DBL_MAX, DBL_MAX, &ret);
819 break;
820 case KORE_JSON_TYPE_INTEGER:
821 number->data.integer = (int64_t)kore_strtonum64(str, 1, &ret);
822 break;
823 case KORE_JSON_TYPE_INTEGER_U64:
824 number->data.u64 = kore_strtonum64(str, 0, &ret);
825 if (number->data.u64 <= INT64_MAX) {
826 type = KORE_JSON_TYPE_INTEGER;
827 number->data.integer = number->data.u64;
828 }
829 break;
830 default:
831 goto cleanup;
832 }
833
834 number->type = type;
835
836 cleanup:
837 if (ret == KORE_RESULT_ERROR && json_errno == 0)
838 json_errno = KORE_JSON_ERR_INVALID_NUMBER;
839
840 return (ret);
841 }
842
843 static int
844 json_parse_literal(struct kore_json *json, struct kore_json_item *literal)
845 {
846 size_t len, idx;
847 int ret, val;
848 u_int8_t ch, *tmpl;
849
850 ret = KORE_RESULT_ERROR;
851
852 if (!json_next(json, &ch))
853 goto cleanup;
854
855 switch (ch) {
856 case 'f':
857 val = KORE_JSON_FALSE;
858 tmpl = json_false_literal;
859 len = sizeof(json_false_literal) - 1;
860 break;
861 case 'n':
862 val = KORE_JSON_NULL;
863 tmpl = json_null_literal;
864 len = sizeof(json_null_literal) - 1;
865 break;
866 case 't':
867 val = KORE_JSON_TRUE;
868 tmpl = json_true_literal;
869 len = sizeof(json_true_literal) - 1;
870 break;
871 default:
872 goto cleanup;
873 }
874
875 for (idx = 0; idx < len; idx++) {
876 if (!json_next(json, &ch))
877 goto cleanup;
878
879 if (ch != tmpl[idx + 1])
880 goto cleanup;
881 }
882
883 literal->data.literal = val;
884 literal->type = KORE_JSON_TYPE_LITERAL;
885
886 ret = KORE_RESULT_OK;
887
888 cleanup:
889 if (ret == KORE_RESULT_ERROR && json_errno == 0)
890 json_errno = KORE_JSON_ERR_INVALID_LITERAL;
891
892 return (ret);
893 }
894
895 static char *
896 json_get_string(struct kore_json *json)
897 {
898 u_int8_t ch;
899 char *res;
900
901 res = NULL;
902
903 if (!json_next(json, &ch))
904 goto cleanup;
905
906 if (ch != '"')
907 goto cleanup;
908
909 kore_buf_reset(&json->tmpbuf);
910
911 for (;;) {
912 if (!json_next(json, &ch))
913 goto cleanup;
914
915 if (ch == '"')
916 break;
917
918 if (ch <= 0x1f)
919 goto cleanup;
920
921 if (ch == '\\') {
922 if (!json_next(json, &ch))
923 goto cleanup;
924
925 switch (ch) {
926 case '\"':
927 case '\\':
928 case '/':
929 break;
930 case 'b':
931 ch = '\b';
932 break;
933 case 'f':
934 ch = '\f';
935 break;
936 case 'n':
937 ch = '\n';
938 break;
939 case 'r':
940 ch = '\r';
941 break;
942 case 't':
943 ch = '\t';
944 break;
945 case 'u':
946 default:
947 /* XXX - not supported. */
948 goto cleanup;
949 }
950 }
951
952 kore_buf_append(&json->tmpbuf, &ch, sizeof(ch));
953 }
954
955 res = kore_buf_stringify(&json->tmpbuf, NULL);
956
957 cleanup:
958 if (res == NULL && json_errno == 0)
959 json_errno = KORE_JSON_ERR_INVALID_STRING;
960
961 return (res);
962 }
963
964 static void
965 json_build_string(struct kore_json_item *item, const char *string)
966 {
967 char ch;
968 struct kore_buf buf;
969 char *res;
970
971 res = NULL;
972 kore_buf_init(&buf, 512);
973
974 while (*string) {
975 ch = *string;
976 switch (ch) {
977 case '\"':
978 case '\\':
979 case '/':
980 kore_buf_append(&buf, "\\", 1);
981 break;
982 case '\b':
983 kore_buf_append(&buf, "\\", 1);
984 ch = 'b';
985 break;
986 case '\f':
987 kore_buf_append(&buf, "\\", 1);
988 ch = 'f';
989 break;
990 case '\n':
991 kore_buf_append(&buf, "\\", 1);
992 ch = 'n';
993 break;
994 case '\r':
995 kore_buf_append(&buf, "\\", 1);
996 ch = 'r';
997 break;
998 case '\t':
999 kore_buf_append(&buf, "\\", 1);
1000 ch = 't';
1001 break;
1002 default:
1003 if (!isprint((unsigned char)ch))
1004 ch = '?';
1005 break;
1006 }
1007
1008 kore_buf_append(&buf, &ch, sizeof(ch));
1009 ++string;
1010 }
1011
1012 res = kore_buf_stringify(&buf, NULL);
1013 item->data.string = kore_strdup(res);
1014
1015 kore_buf_cleanup(&buf);
1016 }