Fixed the asn1 for facets
[yaz-moved-to-github.git] / src / json.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2010 Index Data
3  * See the file LICENSE for details.
4  */
5
6 /**
7  * \file json.c
8  * \brief JSON encoding/decoding
9  */
10
11 #include <yaz/json.h>
12
13 #include <stdlib.h>
14 #include <errno.h>
15 #include <string.h>
16 #include <assert.h>
17 #include <stdio.h>
18
19 #include <yaz/xmalloc.h>
20
21 struct json_subst_info {
22     int idx;
23     struct json_subst_info *next;
24     struct json_node *node;
25 };
26
27 struct json_parser_s {
28     const char *buf;
29     const char *cp;
30     const char *err_msg;
31     struct json_subst_info *subst;
32 };
33
34 json_parser_t json_parser_create(void)
35 {
36     json_parser_t p = (json_parser_t) xmalloc(sizeof(*p));
37     
38     p->buf = 0;
39     p->cp = 0;
40     p->err_msg = 0;
41     p->subst = 0;
42     return p;
43 }
44
45 void json_parser_subst(json_parser_t p, int idx, struct json_node *n)
46 {
47     struct json_subst_info **sb = &p->subst;
48     for (; *sb; sb = &(*sb)->next)
49         if ((*sb)->idx == idx)
50         {
51             (*sb)->node = n;
52             return;
53         }
54     *sb = xmalloc(sizeof(**sb));
55     (*sb)->next = 0;
56     (*sb)->node = n;
57     (*sb)->idx = idx;
58 }
59
60 void json_parser_destroy(json_parser_t p)
61 {
62     struct json_subst_info *sb = p->subst;
63     while (sb)
64     {
65         struct json_subst_info *sb_next = sb->next;
66         xfree(sb);
67         sb = sb_next;
68     }
69     xfree(p);
70 }
71
72 static int look_ch(json_parser_t p)
73 {
74     while (*p->cp && strchr(" \t\r\n\f", *p->cp))
75         (p->cp)++;
76     return *p->cp;
77 }
78
79 static void move_ch(json_parser_t p)
80 {
81     if (*p->cp)
82         (p->cp)++;
83 }
84
85 static struct json_node *json_new_node(json_parser_t p, enum json_node_type type)
86 {
87     struct json_node *n = (struct json_node *) xmalloc(sizeof(*n));
88     n->type = type;
89     n->u.link[0] = n->u.link[1] = 0;
90     return n;
91 }
92
93 void json_remove_node(struct json_node *n)
94 {
95     if (!n)
96         return;
97     switch (n->type)
98     {
99     case json_node_object:
100     case json_node_array:
101     case json_node_list:
102     case json_node_pair:
103         json_remove_node(n->u.link[0]);
104         json_remove_node(n->u.link[1]);
105         break;
106     case json_node_string:
107         xfree(n->u.string);
108         break;
109     case json_node_number:
110     case json_node_true:
111     case json_node_false:
112     case json_node_null:
113         break;
114     }
115     xfree(n);
116 }
117
118 static struct json_node *json_parse_object(json_parser_t p);
119 static struct json_node *json_parse_array(json_parser_t p);
120
121 static int json_one_char(const char **p, char *out)
122 {
123     if (**p == '\\' && p[0][1])
124     {
125         (*p)++;
126         switch(**p)
127         {
128         case '"':
129             *out = '"'; break;
130         case '\\':
131             *out = '\\'; break;
132         case '/':
133             *out = '/'; break;
134         case 'b':
135             *out = '\b'; break;
136         case 'f':
137             *out = '\f'; break;
138         case 'n':
139             *out = '\n'; break;
140         case 'r':
141             *out = '\r'; break;
142         case 't':
143             *out = '\t'; break;
144         case 'u':
145             if (p[0][1])
146             {
147                 unsigned code;
148                 char *outp = out;
149                 int error;
150                 size_t outbytesleft = 6;
151                 sscanf(*p + 1, "%4x", &code);
152                 if (!yaz_write_UTF8_char(code, &outp, &outbytesleft, &error))
153                 {
154                     *p += 5;
155                     return outp - out;
156                 }
157             }
158         default:
159             *out = '_'; break;
160             break;
161         }
162         (*p)++;
163         return 1;
164     }
165     else
166     {
167         *out = **p;
168         (*p)++;
169         return 1;
170     }
171 }
172
173 static struct json_node *json_parse_string(json_parser_t p)
174 {
175     struct json_node *n;
176     const char *cp;
177     char *dst;
178     int l = 0;
179     if (look_ch(p) != '\"')
180     {
181         p->err_msg = "string expected";
182         return 0;
183     }
184     move_ch(p);
185
186     cp = p->cp;
187     while (*cp && *cp != '"')
188     {
189         char out[6];
190         l += json_one_char(&cp, out);
191     }
192     if (!*cp)
193     {
194         p->err_msg = "missing \"";
195         return 0;
196     }
197     n = json_new_node(p, json_node_string);
198     dst = n->u.string = (char *) xmalloc(l + 1);
199     
200     cp = p->cp;
201     while (*cp && *cp != '"')
202     {
203         char out[6];
204
205         l = json_one_char(&cp, out);
206         memcpy(dst, out, l);
207         dst += l;
208     }
209     *dst = '\0';
210     p->cp = cp+1;
211     return n;
212 }
213
214 static struct json_node *json_parse_number(json_parser_t p)
215 {
216     struct json_node *n;
217     char *endptr;
218     double v;
219
220     look_ch(p); // skip spaces
221     v = strtod(p->cp, &endptr);
222
223     if (endptr == p->cp)
224     {
225         p->err_msg = "bad number";
226         return 0;
227     }
228     p->cp = endptr;
229     n = json_new_node(p, json_node_number);
230     n->u.number = v;
231     return n;
232 }
233
234 static struct json_node *json_parse_value(json_parser_t p)
235 {
236     int c = look_ch(p);
237     if (c == '\"')
238         return json_parse_string(p);
239     else if (strchr("0123456789-+", c))
240         return json_parse_number(p);
241     else if (c == '{')
242         return json_parse_object(p);
243     else if (c == '[')
244         return json_parse_array(p);
245     else if (c == '%')
246     {
247         struct json_subst_info *sb;
248         int idx = 0;
249         p->cp++;
250         c = *p->cp;
251         while (c >= '0' && c <= '9')
252         {
253             idx = idx*10 + (c - '0');
254             p->cp++;
255             c = *p->cp;
256         }
257         for (sb = p->subst; sb; sb = sb->next)
258             if (sb->idx == idx)
259                 return sb->node;
260     }
261     else
262     {
263         char tok[8];
264         int i = 0;
265         while (c >= 'a' && c <= 'z' && i < 7)
266         {
267             tok[i++] = c;
268             p->cp++;
269             c = *p->cp;
270         }
271         tok[i] = 0;
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);
278     }
279     p->err_msg = "bad token";
280     return 0;
281 }
282
283 static struct json_node *json_parse_elements(json_parser_t p)
284 {
285     struct json_node *n1 = json_parse_value(p);
286     struct json_node *m0, *m1;
287     if (!n1)
288         return 0;
289     m0 = m1 = json_new_node(p, json_node_list);
290     m1->u.link[0] = n1;
291     while (look_ch(p) == ',')
292     {
293         struct json_node *n2, *m2;
294         move_ch(p);
295         n2 = json_parse_value(p);
296         if (!n2)
297         {
298             json_remove_node(m0);
299             return 0;
300         }
301         m2 = json_new_node(p, json_node_list);
302         m2->u.link[0] = n2;
303         
304         m1->u.link[1] = m2;
305         m1 = m2;
306     }
307     return m0;
308 }
309
310 static struct json_node *json_parse_array(json_parser_t p)
311 {
312     struct json_node *n;
313     if (look_ch(p) != '[')
314     {
315         p->err_msg = "expecting [";
316         return 0;
317     }
318     move_ch(p);
319     n = json_new_node(p, json_node_array);
320     if (look_ch(p) != ']')
321         n->u.link[0] = json_parse_elements(p);
322
323     if (look_ch(p) != ']')
324     {
325         p->err_msg = "expecting ]";
326         json_remove_node(n);
327         return 0;
328     }
329     move_ch(p);
330     return n;
331 }
332
333 static struct json_node *json_parse_pair(json_parser_t p)
334 {
335     struct json_node *s = json_parse_string(p);
336     struct json_node *v, *n;
337     if (!s)
338         return 0;
339     if (look_ch(p) != ':')
340     {
341         p->err_msg = "missing :";
342         json_remove_node(s);
343         return 0;
344     }
345     move_ch(p);
346     v = json_parse_value(p);
347     if (!v)
348     {
349         json_remove_node(s);
350         return 0;
351     }
352     n = json_new_node(p, json_node_pair);
353     n->u.link[0] = s;
354     n->u.link[1] = v;
355     return n;
356 }
357
358 static struct json_node *json_parse_members(json_parser_t p)
359 {
360     struct json_node *n1 = json_parse_pair(p);
361     struct json_node *m0, *m1;
362     if (!n1)
363         return 0;
364     m0 = m1 = json_new_node(p, json_node_list);
365     m1->u.link[0] = n1;
366     while (look_ch(p) == ',')
367     {
368         struct json_node *n2, *m2;
369         move_ch(p);
370         n2 = json_parse_pair(p);
371         if (!n2)
372         {
373             json_remove_node(m0);
374             return 0;
375         }
376         m2 = json_new_node(p, json_node_list);
377         m2->u.link[0] = n2;
378         
379         m1->u.link[1] = m2;
380         m1 = m2;
381     }
382     return m0;
383 }
384
385 static struct json_node *json_parse_object(json_parser_t p)
386 {
387     struct json_node *n;
388     if (look_ch(p) != '{')
389     {
390         p->err_msg = "{ expected";
391         return 0;
392     }
393     move_ch(p);
394
395     n = json_new_node(p, json_node_object);
396     if (look_ch(p) != '}')
397     {
398         struct json_node *m = json_parse_members(p);
399         if (!m)
400         {
401             json_remove_node(n);
402             return 0;
403         }
404         n->u.link[0] = m;
405     }
406     if (look_ch(p) != '}')
407     {
408         p->err_msg = "Missing }";
409         json_remove_node(n);
410         return 0;
411     }
412     move_ch(p);
413     return n;
414 }
415
416 struct json_node *json_parser_parse(json_parser_t p, const char *json_str)
417 {
418     int c;
419     struct json_node *n;
420     p->buf = json_str;
421     p->cp = p->buf;
422
423     n = json_parse_value(p);
424     if (!n)
425         return 0;
426     c = look_ch(p);
427     if (c != 0)
428     {
429         p->err_msg = "extra characters";
430         json_remove_node(n);
431         return 0;
432     }
433     return n;
434 }
435
436 struct json_node *json_parse2(const char *json_str, const char **errmsg,
437                               size_t *pos)
438 {
439     json_parser_t p = json_parser_create();
440     struct json_node *n = 0;
441     if (!p)
442     {
443         if (errmsg)
444             *errmsg = "could not create parser";
445     }
446     else
447     {
448         n = json_parser_parse(p, json_str);
449         if (!n && errmsg)
450             *errmsg = json_parser_get_errmsg(p);
451         if (pos)
452             *pos = json_parser_get_position(p);
453         json_parser_destroy(p);
454     }
455     return n;
456 }
457
458 struct json_node *json_parse(const char *json_str, const char **errmsg)
459 {
460     return json_parse2(json_str, errmsg, 0);
461 }
462
463 static void wrbuf_json_write(WRBUF b, const char *cp, size_t sz)
464 {
465     size_t i;
466     for (i = 0; i < sz; i++)
467     {
468         if (cp[i] > 0 && cp[i] < 32)
469         {
470             wrbuf_putc(b, '\\');
471             switch (cp[i])
472             {
473             case '\b': wrbuf_putc(b, 'b'); break;
474             case '\f': wrbuf_putc(b, 'f'); break;
475             case '\n': wrbuf_putc(b, 'n'); break;
476             case '\r': wrbuf_putc(b, 'r'); break;
477             case '\t': wrbuf_putc(b, 't'); break;
478             default:
479                 wrbuf_printf(b, "u%04x", cp[i]);
480             }
481         }
482         else if (cp[i] == '"')
483         {
484             wrbuf_putc(b, '\\'); wrbuf_putc(b, '"');
485         }
486         else if (cp[i] == '\\')
487         {
488             wrbuf_putc(b, '\\'); wrbuf_putc(b, '\\');
489         }
490         else
491         {   /* leave encoding as raw UTF-8 */
492             wrbuf_putc(b, cp[i]);
493         }
494     }       
495         
496 }
497
498 void wrbuf_json_puts(WRBUF b, const char *str)
499 {
500     wrbuf_json_write(b, str, strlen(str));
501 }
502
503 void json_write_wrbuf(struct json_node *node, WRBUF result)
504 {
505     switch (node->type)
506     {
507     case json_node_object:
508         wrbuf_puts(result, "{");
509         if (node->u.link[0])
510             json_write_wrbuf(node->u.link[0], result);
511         wrbuf_puts(result, "}");
512         break;
513     case json_node_array:
514         wrbuf_puts(result, "[");
515         if (node->u.link[0])
516             json_write_wrbuf(node->u.link[0], result);
517         wrbuf_puts(result, "]");
518         break;
519     case json_node_list:
520         json_write_wrbuf(node->u.link[0], result);
521         if (node->u.link[1])
522         {
523             wrbuf_puts(result, ",");
524             json_write_wrbuf(node->u.link[1], result);
525         }
526         break;
527     case json_node_pair:
528         json_write_wrbuf(node->u.link[0], result);
529         wrbuf_puts(result, ":");
530         json_write_wrbuf(node->u.link[1], result);
531         break;
532     case json_node_string:
533         wrbuf_puts(result, "\"");
534         wrbuf_json_puts(result, node->u.string);
535         wrbuf_puts(result, "\"");
536         break;
537     case json_node_number:
538         wrbuf_printf(result, "%lg", node->u.number);
539         break;
540     case json_node_true:
541         wrbuf_puts(result, "true");
542         break;
543     case json_node_false:
544         wrbuf_puts(result, "false");
545         break;
546     case json_node_null:
547         wrbuf_puts(result, "null");
548         break;
549     }
550 }
551
552 static struct json_node **json_get_objectp(struct json_node *n,
553                                            const char *name)
554 {
555     if (n && n->type == json_node_object)
556     {
557         for (n = n->u.link[0]; n; n = n->u.link[1])
558         {
559             struct json_node *c = n->u.link[0];
560             if (c && c->type == json_node_pair &&
561                 c->u.link[0] && c->u.link[0]->type == json_node_string)
562                 if (!strcmp(name, c->u.link[0]->u.string))
563                     return &c->u.link[1];
564         }
565     }
566     return 0;
567 }
568
569 struct json_node *json_get_object(struct json_node *n, const char *name)
570 {
571     struct json_node **np = json_get_objectp(n, name);
572     
573     if (np)
574         return *np;
575     return 0;
576 }
577
578 struct json_node *json_detach_object(struct json_node *n, const char *name)
579 {
580     struct json_node **np = json_get_objectp(n, name);
581     
582     if (np)
583     {
584         struct json_node *n = *np;
585         *np = 0;
586         return n;
587     }
588     return 0;
589 }
590
591 struct json_node *json_get_elem(struct json_node *n, int idx)
592 {
593     if (n && n->type == json_node_array)
594     {
595         for (n = n->u.link[0]; n; n = n->u.link[1])
596         {
597             if (--idx < 0)
598                 return n->u.link[0];
599         }
600     }
601     return 0;
602 }
603
604 int json_count_children(struct json_node *n)
605 {
606     int i = 0;
607
608     if (n && (n->type == json_node_array || n->type == json_node_object))
609     {
610         for (n = n->u.link[0]; n; n = n->u.link[1])
611             i++;
612     }
613     return i;
614 }
615
616 int json_append_array(struct json_node *dst, struct json_node *src)
617 {
618     if (dst && src &&
619         dst->type == json_node_array && src->type == json_node_array)
620     {
621         struct json_node **np = &dst->u.link[0];
622         while (*np)
623             np = &(*np)->u.link[1];
624         *np = src->u.link[0];
625         src->u.link[0] = 0;
626         json_remove_node(src);
627         return 0;
628     }
629     return -1;
630 }
631
632 const char *json_parser_get_errmsg(json_parser_t p)
633 {
634     return p->err_msg;
635 }
636
637 size_t json_parser_get_position(json_parser_t p)
638 {
639     return p->cp - p->buf;
640 }
641
642 /*
643  * Local variables:
644  * c-basic-offset: 4
645  * c-file-style: "Stroustrup"
646  * indent-tabs-mode: nil
647  * End:
648  * vim: shiftwidth=4 tabstop=8 expandtab
649  */