1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2013 Index Data
3 * See the file LICENSE for details.
7 * \brief JSON encoding/decoding
21 #include <yaz/xmalloc.h>
23 struct json_subst_info {
25 struct json_subst_info *next;
26 struct json_node *node;
29 struct json_parser_s {
33 struct json_subst_info *subst;
36 json_parser_t json_parser_create(void)
38 json_parser_t p = (json_parser_t) xmalloc(sizeof(*p));
47 void json_parser_subst(json_parser_t p, int idx, struct json_node *n)
49 struct json_subst_info **sb = &p->subst;
50 for (; *sb; sb = &(*sb)->next)
51 if ((*sb)->idx == idx)
56 *sb = xmalloc(sizeof(**sb));
62 void json_parser_destroy(json_parser_t p)
64 struct json_subst_info *sb = p->subst;
67 struct json_subst_info *sb_next = sb->next;
74 static int look_ch(json_parser_t p)
76 while (*p->cp && strchr(" \t\r\n\f", *p->cp))
81 static void move_ch(json_parser_t p)
87 static struct json_node *json_new_node(json_parser_t p, enum json_node_type type)
89 struct json_node *n = (struct json_node *) xmalloc(sizeof(*n));
91 n->u.link[0] = n->u.link[1] = 0;
95 void json_remove_node(struct json_node *n)
101 case json_node_object:
102 case json_node_array:
105 json_remove_node(n->u.link[0]);
106 json_remove_node(n->u.link[1]);
108 case json_node_string:
111 case json_node_number:
113 case json_node_false:
120 static struct json_node *json_parse_object(json_parser_t p);
121 static struct json_node *json_parse_array(json_parser_t p);
123 static int json_one_char(const char **p, char *out)
125 if (**p == '\\' && p[0][1])
152 size_t outbytesleft = 6;
153 sscanf(*p + 1, "%4x", &code);
154 if (!yaz_write_UTF8_char(code, &outp, &outbytesleft, &error))
175 static struct json_node *json_parse_string(json_parser_t p)
181 if (look_ch(p) != '\"')
183 p->err_msg = "string expected";
189 while (*cp && *cp != '"')
192 l += json_one_char(&cp, out);
196 p->err_msg = "missing \"";
199 n = json_new_node(p, json_node_string);
200 dst = n->u.string = (char *) xmalloc(l + 1);
203 while (*cp && *cp != '"')
207 l = json_one_char(&cp, out);
216 static struct json_node *json_parse_number(json_parser_t p)
222 look_ch(p); // skip spaces
223 v = strtod(p->cp, &endptr);
227 p->err_msg = "bad number";
231 n = json_new_node(p, json_node_number);
236 static struct json_node *json_parse_value(json_parser_t p)
240 return json_parse_string(p);
241 else if (strchr("0123456789-+", c))
242 return json_parse_number(p);
244 return json_parse_object(p);
246 return json_parse_array(p);
249 struct json_subst_info *sb;
253 while (c >= '0' && c <= '9')
255 idx = idx*10 + (c - '0');
259 for (sb = p->subst; sb; sb = sb->next)
267 while (c >= 'a' && c <= 'z' && i < 7)
274 if (!strcmp(tok, "true"))
275 return json_new_node(p, json_node_true);
276 else if (!strcmp(tok, "false"))
277 return json_new_node(p, json_node_false);
278 else if (!strcmp(tok, "null"))
279 return json_new_node(p, json_node_null);
281 p->err_msg = "bad token";
285 static struct json_node *json_parse_elements(json_parser_t p)
287 struct json_node *n1 = json_parse_value(p);
288 struct json_node *m0, *m1;
291 m0 = m1 = json_new_node(p, json_node_list);
293 while (look_ch(p) == ',')
295 struct json_node *n2, *m2;
297 n2 = json_parse_value(p);
300 json_remove_node(m0);
303 m2 = json_new_node(p, json_node_list);
312 static struct json_node *json_parse_array(json_parser_t p)
315 if (look_ch(p) != '[')
317 p->err_msg = "expecting [";
321 n = json_new_node(p, json_node_array);
322 if (look_ch(p) != ']')
323 n->u.link[0] = json_parse_elements(p);
325 if (look_ch(p) != ']')
327 p->err_msg = "expecting ]";
335 static struct json_node *json_parse_pair(json_parser_t p)
337 struct json_node *s = json_parse_string(p);
338 struct json_node *v, *n;
341 if (look_ch(p) != ':')
343 p->err_msg = "missing :";
348 v = json_parse_value(p);
354 n = json_new_node(p, json_node_pair);
360 static struct json_node *json_parse_members(json_parser_t p)
362 struct json_node *n1 = json_parse_pair(p);
363 struct json_node *m0, *m1;
366 m0 = m1 = json_new_node(p, json_node_list);
368 while (look_ch(p) == ',')
370 struct json_node *n2, *m2;
372 n2 = json_parse_pair(p);
375 json_remove_node(m0);
378 m2 = json_new_node(p, json_node_list);
387 static struct json_node *json_parse_object(json_parser_t p)
390 if (look_ch(p) != '{')
392 p->err_msg = "{ expected";
397 n = json_new_node(p, json_node_object);
398 if (look_ch(p) != '}')
400 struct json_node *m = json_parse_members(p);
408 if (look_ch(p) != '}')
410 p->err_msg = "Missing }";
418 struct json_node *json_parser_parse(json_parser_t p, const char *json_str)
425 n = json_parse_value(p);
431 p->err_msg = "extra characters";
438 struct json_node *json_parse2(const char *json_str, const char **errmsg,
441 json_parser_t p = json_parser_create();
442 struct json_node *n = 0;
446 *errmsg = "could not create parser";
450 n = json_parser_parse(p, json_str);
452 *errmsg = json_parser_get_errmsg(p);
454 *pos = json_parser_get_position(p);
455 json_parser_destroy(p);
460 struct json_node *json_parse(const char *json_str, const char **errmsg)
462 return json_parse2(json_str, errmsg, 0);
465 static void wrbuf_json_write(WRBUF b, const char *cp, size_t sz)
468 for (i = 0; i < sz; i++)
470 if (cp[i] > 0 && cp[i] < 32)
475 case '\b': wrbuf_putc(b, 'b'); break;
476 case '\f': wrbuf_putc(b, 'f'); break;
477 case '\n': wrbuf_putc(b, 'n'); break;
478 case '\r': wrbuf_putc(b, 'r'); break;
479 case '\t': wrbuf_putc(b, 't'); break;
481 wrbuf_printf(b, "u%04x", cp[i]);
484 else if (cp[i] == '"')
486 wrbuf_putc(b, '\\'); wrbuf_putc(b, '"');
488 else if (cp[i] == '\\')
490 wrbuf_putc(b, '\\'); wrbuf_putc(b, '\\');
493 { /* leave encoding as raw UTF-8 */
494 wrbuf_putc(b, cp[i]);
500 void wrbuf_json_puts(WRBUF b, const char *str)
502 wrbuf_json_write(b, str, strlen(str));
505 static void json_indent(WRBUF result, int indent)
507 size_t l = wrbuf_len(result);
508 if (l == 0 || wrbuf_buf(result)[l-1] == '\n')
511 for (i = 0; i < indent; i++)
512 wrbuf_putc(result, ' ');
516 static void json_write_wrbuf_r(struct json_node *node, WRBUF result, int indent)
520 sub_indent = indent + 1;
523 case json_node_object:
524 json_indent(result, indent);
525 wrbuf_puts(result, "{");
528 wrbuf_puts(result, "\n");
529 json_indent(result, sub_indent);
532 json_write_wrbuf_r(node->u.link[0], result, sub_indent);
535 wrbuf_puts(result, "\n");
536 json_indent(result, indent);
538 wrbuf_puts(result, "}");
540 case json_node_array:
541 json_indent(result, indent);
542 wrbuf_puts(result, "[");
545 wrbuf_puts(result, "\n");
546 json_indent(result, sub_indent);
550 json_write_wrbuf_r(node->u.link[0], result, sub_indent);
554 wrbuf_puts(result, "\n");
555 json_indent(result, indent);
557 wrbuf_puts(result, "]");
560 json_write_wrbuf_r(node->u.link[0], result, indent);
563 wrbuf_puts(result, ",");
565 wrbuf_puts(result, " ");
566 json_write_wrbuf_r(node->u.link[1], result, indent);
570 json_write_wrbuf_r(node->u.link[0], result, indent);
571 wrbuf_puts(result, ":");
573 wrbuf_puts(result, " ");
574 json_write_wrbuf_r(node->u.link[1], result, indent);
576 case json_node_string:
577 wrbuf_puts(result, "\"");
578 wrbuf_json_puts(result, node->u.string);
579 wrbuf_puts(result, "\"");
581 case json_node_number:
582 wrbuf_printf(result, "%lg", node->u.number);
585 wrbuf_puts(result, "true");
587 case json_node_false:
588 wrbuf_puts(result, "false");
591 wrbuf_puts(result, "null");
596 void json_write_wrbuf_pretty(struct json_node *node, WRBUF result)
598 json_write_wrbuf_r(node, result, 1);
601 void json_write_wrbuf(struct json_node *node, WRBUF result)
603 json_write_wrbuf_r(node, result, -1);
606 static struct json_node **json_get_objectp(struct json_node *n,
609 if (n && n->type == json_node_object)
611 for (n = n->u.link[0]; n; n = n->u.link[1])
613 struct json_node *c = n->u.link[0];
614 if (c && c->type == json_node_pair &&
615 c->u.link[0] && c->u.link[0]->type == json_node_string)
616 if (!strcmp(name, c->u.link[0]->u.string))
617 return &c->u.link[1];
623 struct json_node *json_get_object(struct json_node *n, const char *name)
625 struct json_node **np = json_get_objectp(n, name);
632 struct json_node *json_detach_object(struct json_node *n, const char *name)
634 struct json_node **np = json_get_objectp(n, name);
638 struct json_node *n = *np;
645 struct json_node *json_get_elem(struct json_node *n, int idx)
647 if (n && n->type == json_node_array)
649 for (n = n->u.link[0]; n; n = n->u.link[1])
658 int json_count_children(struct json_node *n)
662 if (n && (n->type == json_node_array || n->type == json_node_object))
664 for (n = n->u.link[0]; n; n = n->u.link[1])
670 int json_append_array(struct json_node *dst, struct json_node *src)
673 dst->type == json_node_array && src->type == json_node_array)
675 struct json_node **np = &dst->u.link[0];
677 np = &(*np)->u.link[1];
678 *np = src->u.link[0];
680 json_remove_node(src);
686 const char *json_parser_get_errmsg(json_parser_t p)
691 size_t json_parser_get_position(json_parser_t p)
693 return p->cp - p->buf;
699 * c-file-style: "Stroustrup"
700 * indent-tabs-mode: nil
702 * vim: shiftwidth=4 tabstop=8 expandtab