1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2010 Index Data
3 * See the file LICENSE for details.
8 * \brief JSON encoding/decoding
19 #include <yaz/xmalloc.h>
21 struct json_subst_info {
23 struct json_subst_info *next;
24 struct json_node *node;
27 struct json_parser_s {
31 struct json_subst_info *subst;
34 json_parser_t json_parser_create(void)
36 json_parser_t p = (json_parser_t) xmalloc(sizeof(*p));
45 void json_parser_subst(json_parser_t p, int idx, struct json_node *n)
47 struct json_subst_info **sb = &p->subst;
48 for (; *sb; sb = &(*sb)->next)
49 if ((*sb)->idx == idx)
54 *sb = xmalloc(sizeof(**sb));
60 void json_parser_destroy(json_parser_t p)
62 struct json_subst_info *sb = p->subst;
65 struct json_subst_info *sb_next = sb->next;
72 static int look_ch(json_parser_t p)
74 while (*p->cp && strchr(" \t\r\n\f", *p->cp))
79 static void move_ch(json_parser_t p)
85 static struct json_node *json_new_node(json_parser_t p, enum json_node_type type)
87 struct json_node *n = (struct json_node *) xmalloc(sizeof(*n));
89 n->u.link[0] = n->u.link[1] = 0;
93 void json_remove_node(struct json_node *n)
99 case json_node_object:
100 case json_node_array:
103 json_remove_node(n->u.link[0]);
104 json_remove_node(n->u.link[1]);
106 case json_node_string:
109 case json_node_number:
111 case json_node_false:
118 static struct json_node *json_parse_object(json_parser_t p);
119 static struct json_node *json_parse_array(json_parser_t p);
121 static int json_one_char(const char **p, char *out)
123 if (**p == '\\' && p[0][1])
150 size_t outbytesleft = 6;
151 sscanf(*p + 1, "%4x", &code);
152 if (!yaz_write_UTF8_char(code, &outp, &outbytesleft, &error))
173 static struct json_node *json_parse_string(json_parser_t p)
179 if (look_ch(p) != '\"')
181 p->err_msg = "string expected";
187 while (*cp && *cp != '"')
190 l += json_one_char(&cp, out);
194 p->err_msg = "missing \"";
197 n = json_new_node(p, json_node_string);
198 dst = n->u.string = (char *) xmalloc(l + 1);
201 while (*cp && *cp != '"')
205 l = json_one_char(&cp, out);
214 static struct json_node *json_parse_number(json_parser_t p)
220 look_ch(p); // skip spaces
221 v = strtod(p->cp, &endptr);
225 p->err_msg = "bad number";
229 n = json_new_node(p, json_node_number);
234 static struct json_node *json_parse_value(json_parser_t p)
238 return json_parse_string(p);
239 else if (strchr("0123456789-+", c))
240 return json_parse_number(p);
242 return json_parse_object(p);
244 return json_parse_array(p);
247 struct json_subst_info *sb;
251 while (c >= '0' && c <= '9')
253 idx = idx*10 + (c - '0');
257 for (sb = p->subst; sb; sb = sb->next)
265 while (c >= 'a' && c <= 'z' && i < 7)
272 if (!strcmp(tok, "true"))
273 return json_new_node(p, json_node_true);
274 else if (!strcmp(tok, "false"))
275 return json_new_node(p, json_node_false);
276 else if (!strcmp(tok, "null"))
277 return json_new_node(p, json_node_null);
279 p->err_msg = "bad token";
283 static struct json_node *json_parse_elements(json_parser_t p)
285 struct json_node *n1 = json_parse_value(p);
286 struct json_node *m0, *m1;
289 m0 = m1 = json_new_node(p, json_node_list);
291 while (look_ch(p) == ',')
293 struct json_node *n2, *m2;
295 n2 = json_parse_value(p);
298 json_remove_node(m0);
301 m2 = json_new_node(p, json_node_list);
310 static struct json_node *json_parse_array(json_parser_t p)
313 if (look_ch(p) != '[')
315 p->err_msg = "expecting [";
319 n = json_new_node(p, json_node_array);
320 if (look_ch(p) != ']')
321 n->u.link[0] = json_parse_elements(p);
323 if (look_ch(p) != ']')
325 p->err_msg = "expecting ]";
333 static struct json_node *json_parse_pair(json_parser_t p)
335 struct json_node *s = json_parse_string(p);
336 struct json_node *v, *n;
339 if (look_ch(p) != ':')
341 p->err_msg = "missing :";
346 v = json_parse_value(p);
352 n = json_new_node(p, json_node_pair);
358 static struct json_node *json_parse_members(json_parser_t p)
360 struct json_node *n1 = json_parse_pair(p);
361 struct json_node *m0, *m1;
364 m0 = m1 = json_new_node(p, json_node_list);
366 while (look_ch(p) == ',')
368 struct json_node *n2, *m2;
370 n2 = json_parse_pair(p);
373 json_remove_node(m0);
376 m2 = json_new_node(p, json_node_list);
385 static struct json_node *json_parse_object(json_parser_t p)
388 if (look_ch(p) != '{')
390 p->err_msg = "{ expected";
395 n = json_new_node(p, json_node_object);
396 if (look_ch(p) != '}')
398 struct json_node *m = json_parse_members(p);
406 if (look_ch(p) != '}')
408 p->err_msg = "Missing }";
416 struct json_node *json_parser_parse(json_parser_t p, const char *json_str)
423 n = json_parse_object(p);
429 p->err_msg = "extra characters";
436 struct json_node *json_parse(const char *json_str, const char **errmsg)
438 json_parser_t p = json_parser_create();
439 struct json_node *n = 0;
443 *errmsg = "could not create parser";
447 n = json_parser_parse(p, json_str);
449 *errmsg = json_parser_get_errmsg(p);
450 json_parser_destroy(p);
455 void json_write_wrbuf(struct json_node *node, WRBUF result)
459 case json_node_object:
460 wrbuf_puts(result, "{");
462 json_write_wrbuf(node->u.link[0], result);
463 wrbuf_puts(result, "}");
465 case json_node_array:
466 wrbuf_puts(result, "[");
468 json_write_wrbuf(node->u.link[0], result);
469 wrbuf_puts(result, "]");
472 json_write_wrbuf(node->u.link[0], result);
475 wrbuf_puts(result, ",");
476 json_write_wrbuf(node->u.link[1], result);
480 json_write_wrbuf(node->u.link[0], result);
481 wrbuf_puts(result, ":");
482 json_write_wrbuf(node->u.link[1], result);
484 case json_node_string:
485 wrbuf_puts(result, "\"");
486 wrbuf_puts(result, node->u.string);
487 wrbuf_puts(result, "\"");
489 case json_node_number:
490 wrbuf_printf(result, "%lg", node->u.number);
493 wrbuf_puts(result, "true");
495 case json_node_false:
496 wrbuf_puts(result, "false");
499 wrbuf_puts(result, "null");
504 static struct json_node **json_get_objectp(struct json_node *n,
507 if (n && n->type == json_node_object)
509 for (n = n->u.link[0]; n; n = n->u.link[1])
511 struct json_node *c = n->u.link[0];
512 if (c && c->type == json_node_pair &&
513 c->u.link[0] && c->u.link[0]->type == json_node_string)
514 if (!strcmp(name, c->u.link[0]->u.string))
515 return &c->u.link[1];
521 struct json_node *json_get_object(struct json_node *n, const char *name)
523 struct json_node **np = json_get_objectp(n, name);
530 struct json_node *json_detach_object(struct json_node *n, const char *name)
532 struct json_node **np = json_get_objectp(n, name);
536 struct json_node *n = *np;
543 struct json_node *json_get_elem(struct json_node *n, int idx)
545 if (n && n->type == json_node_array)
547 for (n = n->u.link[0]; n; n = n->u.link[1])
556 int json_count_children(struct json_node *n)
560 if (n && (n->type == json_node_array || n->type == json_node_object))
562 for (n = n->u.link[0]; n; n = n->u.link[1])
568 int json_append_array(struct json_node *dst, struct json_node *src)
571 dst->type == json_node_array && src->type == json_node_array)
573 struct json_node **np = &dst->u.link[0];
575 np = &(*np)->u.link[1];
576 *np = src->u.link[0];
578 json_remove_node(src);
584 const char *json_parser_get_errmsg(json_parser_t p)
592 * c-file-style: "Stroustrup"
593 * indent-tabs-mode: nil
595 * vim: shiftwidth=4 tabstop=8 expandtab