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