ISC DHCP  4.4.2-P1
A reference DHCPv4 and DHCPv6 implementation
json.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 by Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
14  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  *
16  * Internet Systems Consortium, Inc.
17  * 950 Charter Street
18  * Redwood City, CA 94063
19  * <info@isc.org>
20  * https://www.isc.org/
21  *
22  */
23 
24 /* From Kea src/lib/cc/data.cc fromJSON() */
25 
26 #include "keama.h"
27 
28 #include <stdlib.h>
29 #include <string.h>
30 
31 struct element *
32 json_parse(struct parse *cfile)
33 {
34  struct element *elem;
35  const char *val;
36  enum dhcp_token token;
37 
38  elem = create();
39  stackPush(cfile, elem);
40  cfile->stack[0] = elem;
41  cfile->stack_top = 0;
42 
43  token = next_token(&val, NULL, cfile);
44  switch (token) {
45  case NUMBER:
46  elem = createInt(atoll(val));
47  TAILQ_CONCAT(&elem->comments, &cfile->comments);
48  break;
49  case STRING:
50  elem = createString(makeString(-1, val));
51  TAILQ_CONCAT(&elem->comments, &cfile->comments);
52  break;
53  case NAME:
54  if (strcmp(val, "null") == 0)
55  elem = createNull();
56  else if (strcmp(val, "true") == 0)
57  elem = createBool(ISC_TRUE);
58  else if (strcmp(val, "false") == 0) {
59  elem = createBool(ISC_FALSE);
60  elem->skip = ISC_TRUE;
61  } else
62  parse_error(cfile, "unknown name %s", val);
63  TAILQ_CONCAT(&elem->comments, &cfile->comments);
64  break;
65  case LBRACKET:
66  elem = json_list_parse(cfile);
67  break;
68  case LBRACE:
69  elem = json_map_parse(cfile);
70  break;
71  case END_OF_FILE:
72  parse_error(cfile, "unexpected end of file");
73  default:
74  parse_error(cfile, "unexpected %s", val);
75  }
76  return elem;
77 }
78 
79 struct element *
80 json_list_parse(struct parse *cfile)
81 {
82  struct element *list;
83  struct element *item;
84  const char *val;
85  enum dhcp_token token;
86  isc_boolean_t done = ISC_FALSE;
87 
88  list = createList();
89  TAILQ_CONCAT(&list->comments, &cfile->comments);
90  stackPush(cfile, list);
91  do {
92  token = peek_token(&val, NULL, cfile);
93  switch (token) {
94  case RBRACKET:
95  done = ISC_TRUE;
96  break;
97  case END_OF_FILE:
98  parse_error(cfile, "unexpected end of file");
99  case COMMA:
100  skip_token(&val, NULL, cfile);
101  if (listSize(list) == 0)
102  parse_error(cfile, "unexpected ','");
103  item = json_parse(cfile);
104  listPush(list, item);
105  break;
106  default:
107  if (listSize(list) > 0)
108  parse_error(cfile, "expected ','");
109  item = json_parse(cfile);
110  listPush(list, item);
111  break;
112  }
113  } while (!done);
114  skip_token(&val, NULL, cfile);
115  cfile->stack_top--;
116  return list;
117 }
118 
119 struct element *
120 json_map_parse(struct parse *cfile)
121 {
122  struct element *map;
123  struct element *item;
124  const char *val;
125  const char *key;
126  enum dhcp_token token;
127  isc_boolean_t done = ISC_FALSE;
128 
129  map = createMap();
130  TAILQ_CONCAT(&map->comments, &cfile->comments);
131  stackPush(cfile, map);
132  do {
133  token = peek_token(&val, NULL, cfile);
134  switch (token) {
135  case RBRACE:
136  done = ISC_TRUE;
137  break;
138  case END_OF_FILE:
139  parse_error(cfile, "unexpected end of file");
140  case COMMA:
141  skip_token(&val, NULL, cfile);
142  if (mapSize(map) == 0)
143  parse_error(cfile, "unexpected ','");
144  token = next_token(&val, NULL, cfile);
145  if (token != STRING)
146  parse_error(cfile, "unexpected %s, "
147  "expected \"key\":value", val);
148  key = strdup(val);
149  token = next_token(&val, NULL, cfile);
150  if (token != COLON)
151  parse_error(cfile, "unexpected %s, "
152  "expected ':'", val);
153  item = json_parse(cfile);
154  mapSet(map, item, key);
155  break;
156  case STRING:
157  skip_token(&val, NULL, cfile);
158  if (mapSize(map) > 0)
159  parse_error(cfile, "unexpected \"%s\", "
160  "expected ','", val);
161  key = strdup(val);
162  token = next_token(&val, NULL, cfile);
163  if (token != COLON)
164  parse_error(cfile, "unexpected %s, "
165  "expected ':'", val);
166  item = json_parse(cfile);
167  mapSet(map, item, key);
168  break;
169  default:
170  if (mapSize(map) == 0)
171  parse_error(cfile, "unexpected %s, "
172  "expected \"key\":value or '}'",
173  val);
174  else
175  parse_error(cfile, "unexpected %s, "
176  "expected ',' or '}'", val);
177  }
178  } while (!done);
179  skip_token(&val, NULL, cfile);
180  cfile->stack_top--;
181  return map;
182 }
enum dhcp_token peek_token(const char **rval, unsigned *rlen, struct parse *cfile)
Definition: conflex.c:443
enum dhcp_token next_token(const char **rval, unsigned *rlen, struct parse *cfile)
Definition: conflex.c:369
void listPush(struct element *l, struct element *e)
Definition: data.c:697
struct string * makeString(int l, const char *s)
Definition: data.c:44
struct element * create(void)
Definition: data.c:432
struct element * createBool(isc_boolean_t b)
Definition: data.c:469
size_t mapSize(const struct element *m)
Definition: data.c:829
struct element * createList(void)
Definition: data.c:504
struct element * createInt(int64_t i)
Definition: data.c:445
struct element * createNull(void)
Definition: data.c:481
struct element * createString(const struct string *s)
Definition: data.c:492
void mapSet(struct element *m, struct element *e, const char *k)
Definition: data.c:777
size_t listSize(const struct element *l)
Definition: data.c:730
struct element * createMap(void)
Definition: data.c:516
#define TAILQ_CONCAT(head1, head2)
Definition: data.h:49
isc_boolean_t
Definition: data.h:150
#define ISC_TRUE
Definition: data.h:153
#define ISC_FALSE
Definition: data.h:152
#define skip_token(a, b, c)
Definition: dhcpd.h:2187
dhcp_token
Definition: dhctoken.h:34
@ LBRACE
Definition: dhctoken.h:40
@ LBRACKET
Definition: dhctoken.h:42
@ NUMBER
Definition: dhctoken.h:67
@ COLON
Definition: dhctoken.h:37
@ NAME
Definition: dhctoken.h:69
@ END_OF_FILE
Definition: dhctoken.h:307
@ RBRACE
Definition: dhctoken.h:41
@ RBRACKET
Definition: dhctoken.h:43
@ STRING
Definition: dhctoken.h:66
@ COMMA
Definition: dhctoken.h:38
struct element * json_parse(struct parse *cfile)
Definition: json.c:32
struct element * json_map_parse(struct parse *cfile)
Definition: json.c:120
struct element * json_list_parse(struct parse *cfile)
Definition: json.c:80
void parse_error(struct parse *cfile, const char *fmt,...)
Definition: keama.c:194
void stackPush(struct parse *pc, struct element *elem)
Definition: keama.c:178
Definition: data.h:216
isc_boolean_t skip
Definition: data.h:219
char * key
Definition: data.h:220
struct comments comments
Definition: data.h:222
Definition: dhcpd.h:288
struct comments comments
Definition: keama.h:116
size_t stack_top
Definition: keama.h:112
struct element ** stack
Definition: keama.h:110