YAZ 5.38.1
json.c
Go to the documentation of this file.
1/* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
4 */
9#if HAVE_CONFIG_H
10#include <config.h>
11#endif
12
13#include <yaz/json.h>
14
15#include <stdlib.h>
16#include <errno.h>
17#include <string.h>
18#include <assert.h>
19#include <stdio.h>
20
21#include <yaz/xmalloc.h>
22
24 int idx;
26 struct json_node *node;
27};
28
30 const char *buf;
31 const char *cp;
32 const char *err_msg;
36};
37
39{
40 json_parser_t p = (json_parser_t) xmalloc(sizeof(*p));
41
42 p->buf = 0;
43 p->cp = 0;
44 p->subst = 0;
45 return p;
46}
47
49{
50 struct json_subst_info **sb = &p->subst;
51 for (; *sb; sb = &(*sb)->next)
52 if ((*sb)->idx == idx)
53 {
54 if ((*sb)->node != n)
55 json_remove_node((*sb)->node);
56 (*sb)->node = n;
57 return;
58 }
59 *sb = xmalloc(sizeof(**sb));
60 (*sb)->next = 0;
61 (*sb)->node = n;
62 (*sb)->idx = idx;
63}
64
66{
67 struct json_subst_info *sb = p->subst;
68 while (sb)
69 {
70 struct json_subst_info *sb_next = sb->next;
72 xfree(sb);
73 sb = sb_next;
74 }
75 xfree(p);
76}
77
79{
80 while (*p->cp && strchr(" \t\r\n", *p->cp))
81 (p->cp)++;
82 return *p->cp;
83}
84
85static void move_ch(json_parser_t p)
86{
87 if (*p->cp)
88 (p->cp)++;
89}
90
92{
93 struct json_node *n = (struct json_node *) xmalloc(sizeof(*n));
94 n->type = type;
95 n->u.link[0] = n->u.link[1] = 0;
96 return n;
97}
98
100{
101 if (!n)
102 return;
103 switch (n->type)
104 {
105 case json_node_object:
106 case json_node_array:
107 case json_node_pair:
108 json_remove_node(n->u.link[0]);
109 json_remove_node(n->u.link[1]);
110 break;
111 case json_node_list:
112 while (n)
113 {
114 struct json_node *next = n->u.link[1];
115 json_remove_node(n->u.link[0]);
116 xfree(n);
117 n = next;
118 }
119 return;
120 case json_node_string:
121 xfree(n->u.string);
122 break;
123 case json_node_number:
124 case json_node_true:
125 case json_node_false:
126 case json_node_null:
127 break;
128 }
129 xfree(n);
130}
131
132struct json_node *json_clone_node(const struct json_node *n)
133{
134 struct json_node *n2;
135
136 if (!n)
137 return 0;
138 n2 = json_new_node(0, n->type);
139 switch (n->type)
140 {
141 case json_node_object:
142 case json_node_array:
143 case json_node_pair:
144 n2->u.link[0] = json_clone_node(n->u.link[0]);
145 n2->u.link[1] = json_clone_node(n->u.link[1]);
146 break;
147 case json_node_list:
148 {
149 struct json_node *tail = n2;
150 while (n)
151 {
152 tail->u.link[0] = json_clone_node(n->u.link[0]);
153 n = n->u.link[1];
154 if (n)
155 {
156 tail->u.link[1] = json_new_node(0, json_node_list);
157 tail = tail->u.link[1];
158 }
159 }
160 }
161 break;
162 case json_node_string:
163 n2->u.string = xstrdup(n->u.string);
164 break;
165 case json_node_number:
166 n2->u.number = n->u.number;
167 break;
168 case json_node_true:
169 case json_node_false:
170 case json_node_null:
171 break;
172 }
173 return n2;
174}
175
178
179static int json_one_char(const char **p, char *out)
180{
181 if (**p == '\\' && p[0][1])
182 {
183 (*p)++;
184 switch(**p)
185 {
186 case '"':
187 *out = '"'; break;
188 case '\\':
189 *out = '\\'; break;
190 case '/':
191 *out = '/'; break;
192 case 'b':
193 *out = '\b'; break;
194 case 'f':
195 *out = '\f'; break;
196 case 'n':
197 *out = '\n'; break;
198 case 'r':
199 *out = '\r'; break;
200 case 't':
201 *out = '\t'; break;
202 case 'u':
203 if (p[0][1] > 0 && p[0][2] > 0 && p[0][3] > 0 && p[0][4] > 0)
204 {
205 unsigned code;
206 char *outp = out;
207 int error;
208 size_t outbytesleft = 6;
209 int no_read = 0;
210 sscanf(*p + 1, "%4x%n", &code, &no_read);
211 if (no_read != 4)
212 return 0;
213 if (!yaz_write_UTF8_char(code, &outp, &outbytesleft, &error))
214 {
215 *p += 5;
216 return outp - out;
217 }
218 }
219 default:
220 return 0;
221 }
222 (*p)++;
223 return 1;
224 }
225 else if (**p > 0 && **p <= 31)
226 {
227 return 0;
228 }
229 else
230 {
231 *out = **p;
232 (*p)++;
233 return 1;
234 }
235}
236
238{
239 struct json_node *n;
240 const char *cp;
241 char *dst;
242 int l = 0;
243 if (look_ch(p) != '\"')
244 {
245 p->err_msg = "string expected";
246 return 0;
247 }
248 move_ch(p);
249
250 cp = p->cp;
251 while (*cp && *cp != '"')
252 {
253 char out[6];
254 int r = json_one_char(&cp, out);
255 if (r == 0)
256 {
257 p->err_msg = "invalid character";
258 return 0;
259 }
260 l += r;
261 }
262 if (!*cp)
263 {
264 p->err_msg = "missing \"";
265 return 0;
266 }
268 dst = n->u.string = (char *) xmalloc(l + 1);
269
270 cp = p->cp;
271 while (*cp && *cp != '"')
272 {
273 char out[6];
274
275 l = json_one_char(&cp, out);
276 memcpy(dst, out, l);
277 dst += l;
278 }
279 *dst = '\0';
280 p->cp = cp+1;
281 return n;
282}
283
285{
286 struct json_node *n;
287 char *endptr;
288 const char *cp;
289 double v;
290
291 cp = p->cp;
292 if (*cp == '-')
293 cp++;
294 if (*cp == '0')
295 cp++;
296 else if (*cp >= '1' && *cp <= '9')
297 {
298 cp++;
299 while (*cp >= '0' && *cp <= '9')
300 cp++;
301 }
302 else
303 {
304 p->err_msg = "bad number";
305 return 0;
306 }
307 if (*cp == '.')
308 {
309 cp++;
310 if (*cp >= '0' && *cp <= '9')
311 {
312 while (*cp >= '0' && *cp <= '9')
313 cp++;
314 }
315 else
316 {
317 p->err_msg = "bad number";
318 return 0;
319 }
320 }
321 if (*cp == 'e' || *cp == 'E')
322 {
323 cp++;
324 if (*cp == '+' || *cp == '-')
325 cp++;
326 if (*cp >= '0' && *cp <= '9')
327 {
328 while (*cp >= '0' && *cp <= '9')
329 cp++;
330 }
331 else
332 {
333 p->err_msg = "bad number";
334 return 0;
335 }
336 }
337 v = strtod(p->cp, &endptr);
338
339 if (endptr == p->cp)
340 {
341 p->err_msg = "bad number";
342 return 0;
343 }
344 if (endptr != cp)
345 {
346 p->err_msg = "bad number";
347 return 0;
348 }
349 p->cp = endptr;
351 n->u.number = v;
352 return n;
353}
354
356{
357 int c = look_ch(p);
358 if (c == '\"')
359 return json_parse_string(p);
360 else if (c == 0)
361 {
362 p->err_msg = "expecting value";
363 return 0;
364 }
365 else if (strchr("0123456789-", c))
366 return json_parse_number(p);
367 else if (c == '{')
368 return json_parse_object(p);
369 else if (c == '[')
370 return json_parse_array(p);
371 else if (c == '%')
372 {
373 struct json_subst_info *sb;
374 int idx = 0;
375 p->cp++;
376 c = *p->cp;
377 while (c >= '0' && c <= '9')
378 {
379 idx = idx*10 + (c - '0');
380 p->cp++;
381 c = *p->cp;
382 }
383 for (sb = p->subst; sb; sb = sb->next)
384 if (sb->idx == idx)
385 {
386 struct json_node *ret = json_clone_node(sb->node);
387 if (!ret)
388 {
389 p->err_msg = "missing subst value";
390 return 0;
391 }
392 return ret;
393 }
394 }
395 else
396 {
397 char tok[8];
398 int i = 0;
399 while (yaz_islower(c) && i < 7)
400 {
401 tok[i++] = c;
402 p->cp++;
403 c = *p->cp;
404 }
405 tok[i] = 0;
406 if (!strcmp(tok, "true"))
407 return json_new_node(p, json_node_true);
408 else if (!strcmp(tok, "false"))
410 else if (!strcmp(tok, "null"))
411 return json_new_node(p, json_node_null);
412 }
413 p->err_msg = "bad token";
414 return 0;
415}
416
418{
419 struct json_node *n1 = json_parse_value(p);
420 struct json_node *m0, *m1;
421 if (!n1)
422 return 0;
423 m0 = m1 = json_new_node(p, json_node_list);
424 m1->u.link[0] = n1;
425 while (look_ch(p) == ',')
426 {
427 struct json_node *n2, *m2;
428 move_ch(p);
429 n2 = json_parse_value(p);
430 if (!n2)
431 {
433 return 0;
434 }
436 m2->u.link[0] = n2;
437
438 m1->u.link[1] = m2;
439 m1 = m2;
440 }
441 return m0;
442}
443
445{
446 struct json_node *n;
447 if (look_ch(p) != '[')
448 {
449 p->err_msg = "expecting [";
450 return 0;
451 }
452 move_ch(p);
453 if (p->parse_level >= p->max_level)
454 {
455 p->err_msg = "Too much nesting";
456 return 0;
457 }
458 p->parse_level++;
460 if (look_ch(p) != ']')
461 n->u.link[0] = json_parse_elements(p);
462
463 p->parse_level--;
464 if (look_ch(p) != ']')
465 {
466 if (!p->err_msg)
467 p->err_msg = "expecting ]";
469 return 0;
470 }
471 move_ch(p);
472 return n;
473}
474
476{
477 struct json_node *s = json_parse_string(p);
478 struct json_node *v, *n;
479 if (!s)
480 return 0;
481 if (look_ch(p) != ':')
482 {
483 p->err_msg = "missing :";
485 return 0;
486 }
487 move_ch(p);
488 v = json_parse_value(p);
489 if (!v)
490 {
492 return 0;
493 }
495 n->u.link[0] = s;
496 n->u.link[1] = v;
497 return n;
498}
499
501{
502 struct json_node *n1 = json_parse_pair(p);
503 struct json_node *m0, *m1;
504 if (!n1)
505 return 0;
506 m0 = m1 = json_new_node(p, json_node_list);
507 m1->u.link[0] = n1;
508 while (look_ch(p) == ',')
509 {
510 struct json_node *n2, *m2;
511 move_ch(p);
512 n2 = json_parse_pair(p);
513 if (!n2)
514 {
516 return 0;
517 }
519 m2->u.link[0] = n2;
520
521 m1->u.link[1] = m2;
522 m1 = m2;
523 }
524 return m0;
525}
526
528{
529 struct json_node *n;
530 if (look_ch(p) != '{')
531 {
532 p->err_msg = "{ expected";
533 return 0;
534 }
535 move_ch(p);
536
538 if (look_ch(p) != '}')
539 {
540 struct json_node *m;
541 if (p->parse_level >= p->max_level)
542 {
543 p->err_msg = "Too much nesting";
545 return 0;
546 }
547 p->parse_level++;
548 m = json_parse_members(p);
549 p->parse_level--;
550 if (!m)
551 {
553 return 0;
554 }
555 n->u.link[0] = m;
556 }
557 if (look_ch(p) != '}')
558 {
559 p->err_msg = "missing }";
561 return 0;
562 }
563 move_ch(p);
564 return n;
565}
566
567struct json_node *json_parser_parse(json_parser_t p, const char *json_str)
568{
569 int c;
570 struct json_node *n;
571 p->buf = json_str;
572 p->cp = p->buf;
573 p->err_msg = 0;
574 p->parse_level = 0;
575 p->max_level = 1000;
576
577 n = json_parse_value(p);
578 if (!n)
579 return 0;
580 if (p->err_msg)
581 {
583 return 0;
584 }
585 c = look_ch(p);
586 if (c != 0)
587 {
588 p->err_msg = "extra characters";
590 return 0;
591 }
592 return n;
593}
594
595struct json_node *json_parse2(const char *json_str, const char **errmsg,
596 size_t *pos)
597{
599 struct json_node *n = 0;
600 if (!p)
601 {
602 if (errmsg)
603 *errmsg = "could not create parser";
604 }
605 else
606 {
607 n = json_parser_parse(p, json_str);
608 if (!n && errmsg)
609 *errmsg = json_parser_get_errmsg(p);
610 if (pos)
611 *pos = json_parser_get_position(p);
613 }
614 return n;
615}
616
617struct json_node *json_parse(const char *json_str, const char **errmsg)
618{
619 return json_parse2(json_str, errmsg, 0);
620}
621
622static void json_indent(WRBUF result, int indent)
623{
624 size_t l = wrbuf_len(result);
625 if (l == 0 || wrbuf_buf(result)[l-1] == '\n')
626 {
627 int i;
628 for (i = 0; i < indent; i++)
629 wrbuf_putc(result, ' ');
630 }
631}
632
633static void json_write_wrbuf_r(struct json_node *node, WRBUF result, int indent)
634{
635 int sub_indent = -1;
636 if (indent >= 0)
637 sub_indent = indent + 2;
638 switch (node->type)
639 {
640 case json_node_object:
641 json_indent(result, indent);
642 wrbuf_puts(result, "{");
643 if (node->u.link[0])
644 {
645 if (indent >= 0)
646 {
647 wrbuf_puts(result, "\n");
648 json_indent(result, sub_indent);
649 }
650 json_write_wrbuf_r(node->u.link[0], result, sub_indent);
651 if (indent >= 0)
652 {
653 wrbuf_puts(result, "\n");
654 json_indent(result, indent);
655 }
656 }
657 wrbuf_puts(result, "}");
658 break;
659 case json_node_array:
660 json_indent(result, indent);
661 wrbuf_puts(result, "[");
662 if (node->u.link[0])
663 {
664 if (indent >= 0)
665 wrbuf_puts(result, "\n");
666 json_write_wrbuf_r(node->u.link[0], result, sub_indent);
667 if (indent >= 0)
668 {
669 wrbuf_puts(result, "\n");
670 json_indent(result, indent);
671 }
672 }
673 wrbuf_puts(result, "]");
674 break;
675 case json_node_list:
676 while (node)
677 {
678 if (indent >= 0)
679 json_indent(result, indent);
680 json_write_wrbuf_r(node->u.link[0], result, indent);
681 node = node->u.link[1];
682 if (node)
683 {
684 wrbuf_puts(result, ",");
685 if (indent >= 0)
686 wrbuf_puts(result, "\n");
687 }
688 }
689 break;
690 case json_node_pair:
691 if (indent >= 0)
692 json_indent(result, indent);
693 json_write_wrbuf_r(node->u.link[0], result, indent);
694 wrbuf_puts(result, ":");
695 if (indent >= 0)
696 wrbuf_puts(result, " ");
697 json_write_wrbuf_r(node->u.link[1], result, indent);
698 break;
699 case json_node_string:
700 wrbuf_puts(result, "\"");
701 wrbuf_json_puts(result, node->u.string);
702 wrbuf_puts(result, "\"");
703 break;
704 case json_node_number:
705 wrbuf_printf(result, "%lg", node->u.number);
706 break;
707 case json_node_true:
708 wrbuf_puts(result, "true");
709 break;
710 case json_node_false:
711 wrbuf_puts(result, "false");
712 break;
713 case json_node_null:
714 wrbuf_puts(result, "null");
715 break;
716 }
717}
718
719void json_write_wrbuf_pretty(struct json_node *node, WRBUF result)
720{
721 json_write_wrbuf_r(node, result, 0);
722}
723
724void json_write_wrbuf(struct json_node *node, WRBUF result)
725{
726 json_write_wrbuf_r(node, result, -1);
727}
728
729static struct json_node **json_get_objectp(struct json_node *n,
730 const char *name)
731{
732 if (n && n->type == json_node_object)
733 {
734 for (n = n->u.link[0]; n; n = n->u.link[1])
735 {
736 struct json_node *c = n->u.link[0];
737 if (c && c->type == json_node_pair &&
738 c->u.link[0] && c->u.link[0]->type == json_node_string)
739 if (!strcmp(name, c->u.link[0]->u.string))
740 return &c->u.link[1];
741 }
742 }
743 return 0;
744}
745
746struct json_node *json_get_object(struct json_node *n, const char *name)
747{
748 struct json_node **np = json_get_objectp(n, name);
749
750 if (np)
751 return *np;
752 return 0;
753}
754
755struct json_node *json_detach_object(struct json_node *n, const char *name)
756{
757 struct json_node **np = json_get_objectp(n, name);
758
759 if (np)
760 {
761 struct json_node *n = *np;
762 *np = 0;
763 return n;
764 }
765 return 0;
766}
767
768struct json_node *json_get_elem(struct json_node *n, int idx)
769{
770 if (n && n->type == json_node_array)
771 {
772 for (n = n->u.link[0]; n; n = n->u.link[1])
773 {
774 if (--idx < 0)
775 return n->u.link[0];
776 }
777 }
778 return 0;
779}
780
782{
783 int i = 0;
784
785 if (n && (n->type == json_node_array || n->type == json_node_object))
786 {
787 for (n = n->u.link[0]; n; n = n->u.link[1])
788 i++;
789 }
790 return i;
791}
792
793int json_append_array(struct json_node *dst, struct json_node *src)
794{
795 if (dst && src &&
796 dst->type == json_node_array && src->type == json_node_array)
797 {
798 struct json_node **np = &dst->u.link[0];
799 while (*np)
800 np = &(*np)->u.link[1];
801 *np = src->u.link[0];
802 src->u.link[0] = 0;
803 json_remove_node(src);
804 return 0;
805 }
806 return -1;
807}
808
810{
811 return p->err_msg;
812}
813
815{
816 return p->cp - p->buf;
817}
818
819/*
820 * Local variables:
821 * c-basic-offset: 4
822 * c-file-style: "Stroustrup"
823 * indent-tabs-mode: nil
824 * End:
825 * vim: shiftwidth=4 tabstop=8 expandtab
826 */
Header for errno utilities.
void json_parser_destroy(json_parser_t p)
destroys JSON parser
Definition json.c:65
struct json_node * json_parse(const char *json_str, const char **errmsg)
parses JSON string
Definition json.c:617
static int json_one_char(const char **p, char *out)
Definition json.c:179
struct json_node * json_get_object(struct json_node *n, const char *name)
gets object pair value for some name
Definition json.c:746
static struct json_node * json_parse_pair(json_parser_t p)
Definition json.c:475
void json_parser_subst(json_parser_t p, int idx, struct json_node *n)
configure subst rule
Definition json.c:48
static void json_indent(WRBUF result, int indent)
Definition json.c:622
struct json_node * json_parse2(const char *json_str, const char **errmsg, size_t *pos)
parses JSON string
Definition json.c:595
static int look_ch(json_parser_t p)
Definition json.c:78
static void move_ch(json_parser_t p)
Definition json.c:85
struct json_node * json_get_elem(struct json_node *n, int idx)
gets array element
Definition json.c:768
void json_write_wrbuf(struct json_node *node, WRBUF result)
converts JSON tree to JSON string
Definition json.c:724
static struct json_node * json_parse_elements(json_parser_t p)
Definition json.c:417
void json_write_wrbuf_pretty(struct json_node *node, WRBUF result)
writes JSON tree with indentation (pretty print)
Definition json.c:719
size_t json_parser_get_position(json_parser_t p)
returns parser position
Definition json.c:814
static void json_write_wrbuf_r(struct json_node *node, WRBUF result, int indent)
Definition json.c:633
static struct json_node * json_parse_members(json_parser_t p)
Definition json.c:500
static struct json_node ** json_get_objectp(struct json_node *n, const char *name)
Definition json.c:729
static struct json_node * json_parse_string(json_parser_t p)
Definition json.c:237
int json_count_children(struct json_node *n)
returns number of children (array or object)
Definition json.c:781
static struct json_node * json_new_node(json_parser_t p, enum json_node_type type)
Definition json.c:91
static struct json_node * json_parse_object(json_parser_t p)
Definition json.c:527
void json_remove_node(struct json_node *n)
destroys JSON tree node and its children
Definition json.c:99
const char * json_parser_get_errmsg(json_parser_t p)
returns parser error
Definition json.c:809
static struct json_node * json_parse_number(json_parser_t p)
Definition json.c:284
struct json_node * json_clone_node(const struct json_node *n)
clones JSON tree node and its children
Definition json.c:132
struct json_node * json_parser_parse(json_parser_t p, const char *json_str)
parses JSON string
Definition json.c:567
static struct json_node * json_parse_array(json_parser_t p)
Definition json.c:444
struct json_node * json_detach_object(struct json_node *n, const char *name)
gets object value and detaches from existing tree
Definition json.c:755
static struct json_node * json_parse_value(json_parser_t p)
Definition json.c:355
json_parser_t json_parser_create(void)
create JSON parser
Definition json.c:38
int json_append_array(struct json_node *dst, struct json_node *src)
appends array to another
Definition json.c:793
Header for JSON functions.
struct json_parser_s * json_parser_t
JSON parser (opaque).
Definition json.h:63
json_node_type
JSON node type for json_node.
Definition json.h:39
@ json_node_null
Definition json.h:49
@ json_node_pair
Definition json.h:44
@ json_node_array
Definition json.h:41
@ json_node_list
Definition json.h:42
@ json_node_string
Definition json.h:45
@ json_node_true
Definition json.h:47
@ json_node_number
Definition json.h:46
@ json_node_false
Definition json.h:48
@ json_node_object
Definition json.h:40
JSON node.
Definition json.h:53
union json_node::@230023163253300164160223011376007025006274114226 u
enum json_node_type type
Definition json.h:54
const char * cp
Definition json.c:31
struct json_subst_info * subst
Definition json.c:35
const char * err_msg
Definition json.c:32
int max_level
Definition json.c:34
const char * buf
Definition json.c:30
int parse_level
Definition json.c:33
struct json_node * node
Definition json.c:26
struct json_subst_info * next
Definition json.c:25
size_t yaz_write_UTF8_char(unsigned long x, char **outbuf, size_t *outbytesleft, int *error)
encodes UTF-8 sequence
Definition utf8.c:127
void wrbuf_json_puts(WRBUF b, const char *str)
writes JSON text to WRBUF with escaping
Definition wrbuf.c:372
void wrbuf_printf(WRBUF b, const char *fmt,...)
writes printf result to WRBUF
Definition wrbuf.c:189
void wrbuf_puts(WRBUF b, const char *buf)
appends C-string to WRBUF
Definition wrbuf.c:89
#define wrbuf_putc(b, c)
Definition wrbuf.h:287
#define wrbuf_buf(b)
Definition wrbuf.h:270
#define wrbuf_len(b)
Definition wrbuf.h:269
struct wrbuf * WRBUF
Header for memory handling functions.
#define xstrdup(s)
utility macro which calls xstrdup_f
Definition xmalloc.h:55
#define xfree(x)
utility macro which calls xfree_f
Definition xmalloc.h:53
#define xmalloc(x)
utility macro which calls malloc_f
Definition xmalloc.h:49
#define yaz_islower(x)
Definition yaz-iconv.h:91