blob: 0a464a511ea7af5bbba93ccc1387e47f4030d569 [file] [log] [blame]
Radek Krejci5449d472015-10-26 14:35:56 +01001/**
2 * @file parser_json.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief JSON data parser for libyang
5 *
6 * Copyright (c) 2015 CESNET, z.s.p.o.
7 *
Radek Krejci54f6fb32016-02-24 12:56:39 +01008 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
Michal Vasko8de098c2016-02-26 10:00:25 +010011 *
Radek Krejci54f6fb32016-02-24 12:56:39 +010012 * https://opensource.org/licenses/BSD-3-Clause
Radek Krejci5449d472015-10-26 14:35:56 +010013 */
14
Radek Krejci9a5daea2016-03-02 16:49:40 +010015#define _GNU_SOURCE
Radek Krejci5449d472015-10-26 14:35:56 +010016#include <assert.h>
17#include <ctype.h>
18#include <limits.h>
Michal Vasko1e676ca2016-06-24 15:23:54 +020019#include <errno.h>
Radek Krejci5449d472015-10-26 14:35:56 +010020#include <stdlib.h>
21#include <string.h>
22
23#include "libyang.h"
24#include "common.h"
25#include "context.h"
26#include "parser.h"
27#include "printer.h"
28#include "tree_internal.h"
29#include "validation.h"
Radek Krejci9a5daea2016-03-02 16:49:40 +010030#include "xml_internal.h"
Radek Krejci5449d472015-10-26 14:35:56 +010031
Radek Krejci5449d472015-10-26 14:35:56 +010032static int
33lyjson_isspace(int c)
34{
35 switch(c) {
36 case 0x20: /* space */
37 case 0x09: /* horizontal tab */
38 case 0x0a: /* line feed or new line */
39 case 0x0d: /* carriage return */
40 return 1;
41 default:
42 return 0;
43 }
44}
45
46static unsigned int
47skip_ws(const char *data)
48{
49 unsigned int len = 0;
50
51 /* skip leading whitespaces */
52 while (data[len] && lyjson_isspace(data[len])) {
Radek Krejci5449d472015-10-26 14:35:56 +010053 len++;
54 }
55
56 return len;
57}
58
Radek Krejci5449d472015-10-26 14:35:56 +010059static char *
60lyjson_parse_text(const char *data, unsigned int *len)
61{
62#define BUFSIZE 1024
63
64 char buf[BUFSIZE];
65 char *result = NULL, *aux;
Radek Krejci967e4bf2015-11-28 10:06:40 +010066 int o, size = 0;
Radek Krejci5449d472015-10-26 14:35:56 +010067 unsigned int r, i;
68 int32_t value;
69
70 for (*len = o = 0; data[*len] && data[*len] != '"'; o++) {
71 if (o > BUFSIZE - 3) {
72 /* add buffer into the result */
73 if (result) {
74 size = size + o;
Michal Vasko253035f2015-12-17 16:58:13 +010075 aux = ly_realloc(result, size + 1);
76 if (!aux) {
77 LOGMEM;
78 return NULL;
79 }
Radek Krejci5449d472015-10-26 14:35:56 +010080 result = aux;
81 } else {
82 size = o;
83 result = malloc((size + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +010084 if (!result) {
85 LOGMEM;
86 return NULL;
87 }
Radek Krejci5449d472015-10-26 14:35:56 +010088 }
89 memcpy(&result[size - o], buf, o);
90
91 /* write again into the beginning of the buffer */
92 o = 0;
93 }
94
95 if (data[*len] == '\\') {
96 /* parse escape sequence */
97 (*len)++;
98 i = 1;
99 switch (data[(*len)]) {
100 case '"':
101 /* quotation mark */
102 value = 0x22;
103 break;
104 case '\\':
105 /* reverse solidus */
106 value = 0x5c;
107 break;
108 case '/':
109 /* solidus */
110 value = 0x2f;
111 break;
112 case 'b':
113 /* backspace */
114 value = 0x08;
115 break;
116 case 'f':
117 /* form feed */
118 value = 0x0c;
119 break;
120 case 'n':
121 /* line feed */
122 value = 0x0a;
123 break;
124 case 'r':
125 /* carriage return */
126 value = 0x0d;
127 break;
128 case 't':
129 /* tab */
130 value = 0x09;
131 break;
132 case 'u':
133 /* Basic Multilingual Plane character \uXXXX */
134 (*len)++;
135 for (value = i = 0; i < 4; i++) {
136 if (isdigit(data[(*len) + i])) {
137 r = (data[(*len) + i] - '0');
138 } else if (data[(*len) + i] > 'F') {
139 r = 10 + (data[(*len) + i] - 'a');
140 } else {
141 r = 10 + (data[(*len) + i] - 'A');
142 }
143 value = (16 * value) + r;
144 }
145 break;
146 default:
147 /* invalid escape sequence */
Radek Krejci48464ed2016-03-17 15:44:09 +0100148 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "character escape sequence");
Radek Krejci5449d472015-10-26 14:35:56 +0100149 goto error;
150
151 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100152 r = pututf8(&buf[o], value);
Radek Krejci5449d472015-10-26 14:35:56 +0100153 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100154 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "character UTF8 character");
Radek Krejci5449d472015-10-26 14:35:56 +0100155 goto error;
156 }
157 o += r - 1; /* o is ++ in for loop */
158 (*len) += i; /* number of read characters */
159 } else if (data[*len] < 0x20 || data[*len] == 0x5c) {
160 /* control characters must be escaped */
Radek Krejci48464ed2016-03-17 15:44:09 +0100161 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "control character (unescaped)");
Radek Krejci5449d472015-10-26 14:35:56 +0100162 goto error;
163 } else {
164 /* unescaped character */
Radek Krejcideee60e2016-09-23 15:21:14 +0200165 r = copyutf8(&buf[o], &data[*len]);
166 if (!r) {
167 goto error;
168 }
169
170 o += r - 1; /* o is ++ in for loop */
171 (*len) += r;
Radek Krejci5449d472015-10-26 14:35:56 +0100172 }
173 }
174
175#undef BUFSIZE
176
177 if (o) {
178 if (result) {
179 size = size + o;
Michal Vasko253035f2015-12-17 16:58:13 +0100180 aux = ly_realloc(result, size + 1);
181 if (!aux) {
182 LOGMEM;
183 return NULL;
184 }
Radek Krejci5449d472015-10-26 14:35:56 +0100185 result = aux;
186 } else {
187 size = o;
188 result = malloc((size + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +0100189 if (!result) {
190 LOGMEM;
191 return NULL;
192 }
Radek Krejci5449d472015-10-26 14:35:56 +0100193 }
194 memcpy(&result[size - o], buf, o);
195 }
196 if (result) {
197 result[size] = '\0';
198 } else {
199 size = 0;
200 result = strdup("");
201 }
202
203 return result;
204
205error:
206 free(result);
207 return NULL;
208}
209
210static unsigned int
211lyjson_parse_number(const char *data)
212{
Michal Vasko8f32c112016-05-18 13:22:59 +0200213 unsigned int len = 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100214
Michal Vasko8f32c112016-05-18 13:22:59 +0200215 if (data[len] == '-') {
216 ++len;
217 }
Radek Krejci5449d472015-10-26 14:35:56 +0100218
Michal Vasko8f32c112016-05-18 13:22:59 +0200219 if (data[len] == '0') {
220 ++len;
221 } else if (isdigit(data[len])) {
222 ++len;
223 while (isdigit(data[len])) {
224 ++len;
225 }
226 } else {
227 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value ('%c').", data[len]);
228 return 0;
229 }
230
231 if (data[len] == '.') {
232 ++len;
233 if (!isdigit(data[len])) {
234 if (data[len]) {
235 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value ('%c').", data[len]);
236 } else {
237 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value (EOF).");
Radek Krejci5449d472015-10-26 14:35:56 +0100238 }
Radek Krejci5449d472015-10-26 14:35:56 +0100239 return 0;
240 }
Michal Vasko8f32c112016-05-18 13:22:59 +0200241 while (isdigit(data[len])) {
242 ++len;
243 }
244 }
245
Michal Vasko1e676ca2016-06-24 15:23:54 +0200246 if ((data[len] == 'e') || (data[len] == 'E')) {
247 ++len;
248 if ((data[len] == '+') || (data[len] == '-')) {
249 ++len;
250 }
251 while (isdigit(data[len])) {
252 ++len;
253 }
254 }
255
Michal Vasko8f32c112016-05-18 13:22:59 +0200256 if (data[len] && (data[len] != ',') && (data[len] != ']') && (data[len] != '}') && !lyjson_isspace(data[len])) {
257 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value ('%c').", data[len]);
258 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100259 }
260
261 return len;
262}
263
Michal Vasko1e676ca2016-06-24 15:23:54 +0200264static char *
265lyjson_convert_enumber(const char *number, unsigned int num_len, char *e_ptr)
266{
267 char *ptr, *num;
268 const char *number_ptr;
269 long int e_val;
270 int dot_pos, chars_to_dot, minus;
271 unsigned int num_len_no_e;
272
273 if (*number == '-') {
274 minus = 1;
275 ++number;
276 --num_len;
277 } else {
278 minus = 0;
279 }
280
281 num_len_no_e = e_ptr - number;
282
283 errno = 0;
284 ++e_ptr;
285 e_val = strtol(e_ptr, &ptr, 10);
286 if (errno) {
287 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Exponent out-of-bounds in a JSON Number value (%.*s).",
288 num_len - (e_ptr - number), e_ptr);
289 return NULL;
290 } else if (ptr != number + num_len) {
291 /* we checked this already */
292 LOGINT;
293 return NULL;
294 }
295
296 if ((ptr = strnchr(number, '.', num_len_no_e))) {
297 dot_pos = ptr - number;
298 } else {
299 dot_pos = num_len_no_e;
300 }
301
302 dot_pos += e_val;
303
304 /* allocate enough memory */
305 if (dot_pos < 1) {
306 /* (.XXX)XXX[.]XXXX */
307 num = malloc((minus ? 1 : 0) + -dot_pos + 2 + (num_len_no_e - (ptr ? 1 : 0)) + 1);
308 } else if (dot_pos < (signed)num_len_no_e) {
309 /* XXXX(.)XX.XXX */
310 num = malloc((minus ? 1 : 0) + num_len_no_e + (ptr ? 0 : 1) + 1);
311 } else {
312 /* XXX[.]XXXX(XXX.) */
313 num = malloc((minus ? 1 : 0) + (dot_pos - (ptr ? 2 : 1)) + 1);
314 }
315
316 if (!num) {
317 LOGMEM;
318 return NULL;
319 }
320 if (minus) {
321 strcpy(num, "-");
322 } else {
323 num[0] = '\0';
324 }
325
326 if (dot_pos < 1) {
327 strcat(num, "0.");
328 }
329 if (dot_pos < 0) {
330 sprintf(num + strlen(num), "%0*d", -dot_pos, 0);
331 }
332
333 chars_to_dot = dot_pos;
Michal Vasko9d1593d2016-09-30 12:33:34 +0200334 for (ptr = num + strlen(num), number_ptr = number; (unsigned)(number_ptr - number) < num_len_no_e; ) {
Michal Vasko1e676ca2016-06-24 15:23:54 +0200335 if (!chars_to_dot) {
336 *ptr = '.';
337 ++ptr;
338 chars_to_dot = -1;
339 } else if (isdigit(*number_ptr)) {
340 *ptr = *number_ptr;
341 ++ptr;
342 ++number_ptr;
343 if (chars_to_dot > 0) {
344 --chars_to_dot;
345 }
346 } else if (*number_ptr == '.') {
347 ++number_ptr;
348 } else {
349 LOGINT;
350 free(num);
351 return NULL;
352 }
353 }
354 *ptr = '\0';
355
356 if (dot_pos > (signed)num_len_no_e) {
357 sprintf(num + strlen(num), "%0*d", dot_pos - num_len_no_e, 0);
358 }
359
360 return num;
361}
362
Radek Krejci5449d472015-10-26 14:35:56 +0100363static unsigned int
364lyjson_parse_boolean(const char *data)
365{
Radek Krejci6b47b502015-10-30 15:52:41 +0100366 unsigned int len = 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100367
368 if (!strncmp(data, "false", 5)) {
369 len = 5;
370 } else if (!strncmp(data, "true", 4)) {
371 len = 4;
372 }
373
374 if (data[len] && data[len] != ',' && data[len] != ']' && data[len] != '}' && !lyjson_isspace(data[len])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100375 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON literal value (expected true or false)");
Radek Krejci5449d472015-10-26 14:35:56 +0100376 return 0;
377 }
378
379 return len;
380}
381
382static unsigned int
Radek Krejci4ae82942016-09-19 16:41:06 +0200383json_get_anydata(struct lyd_node_anydata *any, const char *data)
Radek Krejci5449d472015-10-26 14:35:56 +0100384{
Radek Krejci4ae82942016-09-19 16:41:06 +0200385 unsigned int len = 0, start, stop, c;
Radek Krejci5449d472015-10-26 14:35:56 +0100386
Radek Krejci4ae82942016-09-19 16:41:06 +0200387 /* anydata (as well as meaningful anyxml) is supposed to be encoded as object */
388 if (data[len] != '{') {
389 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, any, "Anydata/anyxml content (not an object)");
Michal Vaskoa19f7d72016-05-18 13:24:08 +0200390 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100391 }
392
Radek Krejci4ae82942016-09-19 16:41:06 +0200393 /* count opening '{' and closing '}' to get the end of the object without its parsing */
394 c = 1;
395 len++;
396 len += skip_ws(&data[len]);
397 start = stop = len;
398 while (data[len] && c) {
399 switch (data[len]) {
400 case '{':
401 c++;
402 break;
403 case '}':
404 c--;
405 break;
406 default:
407 if (!isspace(data[len])) {
408 stop = len;
409 }
410 }
411 len++;
412 }
413 if (c) {
414 LOGVAL(LYE_EOF, LY_VLOG_LYD, any);
415 return 0;
416 }
417 any->value_type = LYD_ANYDATA_JSON;
418 any->value.str = lydict_insert(any->schema->module->ctx, &data[start], stop - start + 1);
419
Michal Vaskoa19f7d72016-05-18 13:24:08 +0200420 len += skip_ws(&data[len]);
421 return len;
Radek Krejci5449d472015-10-26 14:35:56 +0100422}
423
424static unsigned int
Radek Krejcibd930122016-08-10 13:28:26 +0200425json_get_value(struct lyd_node_leaf_list *leaf, struct lyd_node *first_sibling, const char *data, int options)
Radek Krejci5449d472015-10-26 14:35:56 +0100426{
Radek Krejcibd930122016-08-10 13:28:26 +0200427 struct lyd_node_leaf_list *new;
Radek Krejci37b756f2016-01-18 10:15:03 +0100428 struct lys_type *stype;
Radek Krejci5449d472015-10-26 14:35:56 +0100429 struct ly_ctx *ctx;
430 unsigned int len = 0, r;
Radek Krejci37b756f2016-01-18 10:15:03 +0100431 int resolve;
Radek Krejci5449d472015-10-26 14:35:56 +0100432 char *str;
433
Radek Krejci0b7704f2016-03-18 12:16:14 +0100434 assert(leaf && data);
Radek Krejci5449d472015-10-26 14:35:56 +0100435 ctx = leaf->schema->module->ctx;
436
Radek Krejci92ece002016-04-04 15:45:05 +0200437 if (options & (LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG)) {
Radek Krejci23238922015-10-27 17:13:34 +0100438 resolve = 0;
439 } else {
440 resolve = 1;
441 }
442
Radek Krejci5449d472015-10-26 14:35:56 +0100443 stype = &((struct lys_node_leaf *)leaf->schema)->type;
Radek Krejci23238922015-10-27 17:13:34 +0100444
Radek Krejci5449d472015-10-26 14:35:56 +0100445 if (leaf->schema->nodetype == LYS_LEAFLIST) {
446 /* expecting begin-array */
447 if (data[len++] != '[') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100448 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expected begin-array)");
Radek Krejci5449d472015-10-26 14:35:56 +0100449 return 0;
450 }
451
452repeat:
453 len += skip_ws(&data[len]);
454 }
455
456 /* will be changed in case of union */
457 leaf->value_type = stype->base;
458
459 if (data[len] == '"') {
460 /* string representations */
Michal Vasko6baed1c2016-05-18 13:24:44 +0200461 ++len;
Radek Krejci5449d472015-10-26 14:35:56 +0100462 str = lyjson_parse_text(&data[len], &r);
Radek Krejci23238922015-10-27 17:13:34 +0100463 if (!str) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100464 LOGPATH(LY_VLOG_LYD, leaf);
Radek Krejci5449d472015-10-26 14:35:56 +0100465 return 0;
466 }
467 leaf->value_str = lydict_insert_zc(ctx, str);
468 if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100469 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf,
Radek Krejciadb57612016-02-16 13:34:34 +0100470 "JSON data (missing quotation-mark at the end of string)");
Radek Krejci5449d472015-10-26 14:35:56 +0100471 return 0;
472 }
473 len += r + 1;
474 } else if (data[len] == '-' || isdigit(data[len])) {
475 /* numeric type */
476 r = lyjson_parse_number(&data[len]);
477 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100478 LOGPATH(LY_VLOG_LYD, leaf);
Radek Krejci5449d472015-10-26 14:35:56 +0100479 return 0;
480 }
Michal Vasko1e676ca2016-06-24 15:23:54 +0200481 /* if it's a number with 'e' or 'E', get rid of it first */
482 if ((str = strnchr(&data[len], 'e', r)) || (str = strnchr(&data[len], 'E', r))) {
483 str = lyjson_convert_enumber(&data[len], r, str);
484 if (!str) {
485 return 0;
486 }
487 leaf->value_str = lydict_insert_zc(ctx, str);
488 } else {
489 leaf->value_str = lydict_insert(ctx, &data[len], r);
490 }
Radek Krejci5449d472015-10-26 14:35:56 +0100491 len += r;
492 } else if (data[len] == 'f' || data[len] == 't') {
493 /* boolean */
494 r = lyjson_parse_boolean(&data[len]);
495 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100496 LOGPATH(LY_VLOG_LYD, leaf);
Radek Krejci5449d472015-10-26 14:35:56 +0100497 return 0;
498 }
499 leaf->value_str = lydict_insert(ctx, &data[len], r);
500 len += r;
501 } else if (!strncmp(&data[len], "[null]", 6)) {
502 /* empty */
Michal Vasko44913842016-04-13 14:20:41 +0200503 leaf->value_str = lydict_insert(ctx, "", 0);
Radek Krejci5449d472015-10-26 14:35:56 +0100504 len += 6;
505 } else {
506 /* error */
Radek Krejci48464ed2016-03-17 15:44:09 +0100507 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (unexpected value)");
Radek Krejci5449d472015-10-26 14:35:56 +0100508 return 0;
509 }
510
Radek Krejci0b7704f2016-03-18 12:16:14 +0100511 if (lyp_parse_value(leaf, NULL, resolve)) {
Radek Krejci23238922015-10-27 17:13:34 +0100512 ly_errno = LY_EVALID;
513 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100514 }
515
516 if (leaf->schema->nodetype == LYS_LEAFLIST) {
517 /* repeat until end-array */
518 len += skip_ws(&data[len]);
519 if (data[len] == ',') {
520 /* another instance of the leaf-list */
521 new = calloc(1, sizeof(struct lyd_node_leaf_list));
Michal Vasko253035f2015-12-17 16:58:13 +0100522 if (!new) {
523 LOGMEM;
524 return 0;
525 }
Radek Krejci5449d472015-10-26 14:35:56 +0100526 new->parent = leaf->parent;
527 new->prev = (struct lyd_node *)leaf;
528 leaf->next = (struct lyd_node *)new;
529
530 /* fix the "last" pointer */
Radek Krejcibd930122016-08-10 13:28:26 +0200531 first_sibling->prev = (struct lyd_node *)new;
Radek Krejci5449d472015-10-26 14:35:56 +0100532
533 new->schema = leaf->schema;
534
535 /* repeat value parsing */
536 leaf = new;
537 len++;
538 goto repeat;
539 } else if (data[len] == ']') {
540 len++;
541 len += skip_ws(&data[len]);
542 } else {
543 /* something unexpected */
Radek Krejci48464ed2016-03-17 15:44:09 +0100544 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expecting value-separator or end-array)");
Radek Krejci5449d472015-10-26 14:35:56 +0100545 return 0;
546 }
547 }
548
549 len += skip_ws(&data[len]);
550 return len;
551}
552
553static unsigned int
Radek Krejci88f29302015-10-30 15:42:33 +0100554json_parse_attr(struct lys_module *parent_module, struct lyd_attr **attr, const char *data)
555{
556 unsigned int len = 0, r;
557 char *str = NULL, *name, *prefix, *value;
558 struct lys_module *module = parent_module;
559 struct lyd_attr *attr_new, *attr_last = NULL;
560
Radek Krejcide9d92c2015-10-30 15:59:59 +0100561 *attr = NULL;
562
Radek Krejci88f29302015-10-30 15:42:33 +0100563 if (data[len] != '{') {
564 if (!strncmp(&data[len], "null", 4)) {
Radek Krejci88f29302015-10-30 15:42:33 +0100565 len += 4;
566 len += skip_ws(&data[len]);
567 return len;
568 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100569 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing begin-object)");
Radek Krejci88f29302015-10-30 15:42:33 +0100570 goto error;
571 }
572
573repeat:
574 len++;
575 len += skip_ws(&data[len]);
576
577 if (data[len] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100578 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing quotation-mark at the begining of string)");
Radek Krejci88f29302015-10-30 15:42:33 +0100579 return 0;
580 }
581 len++;
582 str = lyjson_parse_text(&data[len], &r);
583 if (!r) {
584 goto error;
585 } else if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100586 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing quotation-mark at the end of string)");
Radek Krejci88f29302015-10-30 15:42:33 +0100587 goto error;
588 }
589 if ((name = strchr(str, ':'))) {
590 *name = '\0';
591 name++;
592 prefix = str;
Michal Vasko1e62a092015-12-01 12:27:20 +0100593 module = (struct lys_module *)ly_ctx_get_module(parent_module->ctx, prefix, NULL);
Radek Krejci88f29302015-10-30 15:42:33 +0100594 if (!module) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100595 LOGVAL(LYE_INELEM, LY_VLOG_NONE, NULL, name);
Radek Krejci88f29302015-10-30 15:42:33 +0100596 goto error;
597 }
598 } else {
599 name = str;
600 }
601
602 /* prepare data for parsing node content */
603 len += r + 1;
604 len += skip_ws(&data[len]);
605 if (data[len] != ':') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100606 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing name-separator)");
Radek Krejci88f29302015-10-30 15:42:33 +0100607 goto error;
608 }
609 len++;
610 len += skip_ws(&data[len]);
611
612 if (data[len] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100613 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing quotation-mark at the beginning of string)");
Radek Krejcide9d92c2015-10-30 15:59:59 +0100614 goto error;
Radek Krejci88f29302015-10-30 15:42:33 +0100615 }
616 len++;
617 value = lyjson_parse_text(&data[len], &r);
618 if (!r) {
619 goto error;
620 } else if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100621 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing quotation-mark at the end of string)");
Radek Krejcide9d92c2015-10-30 15:59:59 +0100622 free(value);
Radek Krejci88f29302015-10-30 15:42:33 +0100623 goto error;
624 }
625 len += r + 1;
626 len += skip_ws(&data[len]);
627
628 attr_new = malloc(sizeof **attr);
Michal Vasko253035f2015-12-17 16:58:13 +0100629 if (!attr_new) {
630 LOGMEM;
631 goto error;
632 }
Radek Krejci88f29302015-10-30 15:42:33 +0100633 attr_new->module = module;
634 attr_new->next = NULL;
635 attr_new->name = lydict_insert(module->ctx, name, 0);
636 attr_new->value = lydict_insert_zc(module->ctx, value);
637 if (!attr_last) {
638 *attr = attr_last = attr_new;
639 } else {
640 attr_last->next = attr_new;
641 attr_last = attr_new;
642 }
643
644 free(str);
Radek Krejcide9d92c2015-10-30 15:59:59 +0100645 str = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100646
647 if (data[len] == ',') {
648 goto repeat;
649 } else if (data[len] != '}') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100650 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing end-object)");
Radek Krejcide9d92c2015-10-30 15:59:59 +0100651 goto error;
Radek Krejci88f29302015-10-30 15:42:33 +0100652 }
653 len++;
654 len += skip_ws(&data[len]);
655
656 return len;
657
658error:
659 free(str);
Radek Krejcide9d92c2015-10-30 15:59:59 +0100660 if (*attr) {
661 lyd_free_attr((*attr)->module->ctx, NULL, *attr, 1);
662 *attr = NULL;
663 }
Radek Krejci88f29302015-10-30 15:42:33 +0100664 return 0;
665}
666
667struct attr_cont {
668 struct attr_cont *next;
669 struct lyd_attr *attr;
670 struct lys_node *schema;
671 unsigned int index; /** non-zero only in case of leaf-list */
672};
673
Radek Krejcic4831272015-11-01 19:26:34 +0100674static int
675store_attrs(struct ly_ctx *ctx, struct attr_cont *attrs, struct lyd_node *first)
676{
677 struct lyd_node *diter;
678 struct attr_cont *iter;
679 unsigned int flag_leaflist = 0;
680
681 while (attrs) {
682 iter = attrs;
683 attrs = attrs->next;
684
685 if (iter->index) {
686 flag_leaflist = 1;
687 }
688
689 LY_TREE_FOR(first, diter) {
690 if (iter->schema != diter->schema) {
691 continue;
692 }
693
694 if (flag_leaflist && flag_leaflist != iter->index) {
695 flag_leaflist++;
696 continue;
697 }
698
699 /* we have match */
700 if (diter->attr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100701 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, diter,
Radek Krejciadb57612016-02-16 13:34:34 +0100702 "attribute (multiple attribute definitions belong to a single element)");
Radek Krejcic4831272015-11-01 19:26:34 +0100703 free(iter);
704 goto error;
705 }
706
707 diter->attr = iter->attr;
708 break;
709 }
710
711 if (!diter) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100712 LOGVAL(LYE_XML_MISS, LY_VLOG_NONE, NULL, "element for the specified attribute", iter->attr->name);
Radek Krejcic4831272015-11-01 19:26:34 +0100713 lyd_free_attr(iter->schema->module->ctx, NULL, iter->attr, 1);
714 free(iter);
715 goto error;
716 }
717 free(iter);
718 }
719
720 return 0;
721
722error:
723
724 while (attrs) {
725 iter = attrs;
726 attrs = attrs->next;
727
728 lyd_free_attr(ctx, NULL, iter->attr, 1);
729 free(iter);
730 }
731
732 return -1;
733}
734
Radek Krejci88f29302015-10-30 15:42:33 +0100735static unsigned int
Michal Vasko36ef6932015-12-01 14:30:17 +0100736json_parse_data(struct ly_ctx *ctx, const char *data, const struct lys_node *schema_parent, struct lyd_node **parent,
Radek Krejcibd930122016-08-10 13:28:26 +0200737 struct lyd_node *first_sibling, struct lyd_node *prev, struct attr_cont **attrs, int options,
Michal Vaskoafa7a642016-10-18 15:11:38 +0200738 struct unres_data *unres, struct lyd_node **act_notif)
Radek Krejci5449d472015-10-26 14:35:56 +0100739{
740 unsigned int len = 0;
741 unsigned int r;
Radek Krejcic4831272015-11-01 19:26:34 +0100742 unsigned int flag_leaflist = 0;
Radek Krejci61767ca2016-09-19 14:21:55 +0200743 int i, pos;
Radek Krejci88f29302015-10-30 15:42:33 +0100744 char *name, *prefix = NULL, *str = NULL;
Michal Vasko1e62a092015-12-01 12:27:20 +0100745 const struct lys_module *module = NULL;
Radek Krejci5449d472015-10-26 14:35:56 +0100746 struct lys_node *schema = NULL;
Radek Krejcibd930122016-08-10 13:28:26 +0200747 struct lyd_node *result = NULL, *new, *list, *diter = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100748 struct lyd_attr *attr;
Radek Krejcic4831272015-11-01 19:26:34 +0100749 struct attr_cont *attrs_aux;
Radek Krejci5449d472015-10-26 14:35:56 +0100750
751 /* each YANG data node representation starts with string (node identifier) */
752 if (data[len] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100753 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent),
Radek Krejciadb57612016-02-16 13:34:34 +0100754 "JSON data (missing quotation-mark at the beginning of string)");
Radek Krejci88f29302015-10-30 15:42:33 +0100755 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100756 }
757 len++;
758
Radek Krejci23238922015-10-27 17:13:34 +0100759 str = lyjson_parse_text(&data[len], &r);
Radek Krejci5449d472015-10-26 14:35:56 +0100760 if (!r) {
761 goto error;
762 } else if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100763 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent),
Radek Krejciadb57612016-02-16 13:34:34 +0100764 "JSON data (missing quotation-mark at the end of string)");
Radek Krejci5449d472015-10-26 14:35:56 +0100765 goto error;
766 }
Radek Krejci23238922015-10-27 17:13:34 +0100767 if ((name = strchr(str, ':'))) {
768 *name = '\0';
769 name++;
770 prefix = str;
Radek Krejci88f29302015-10-30 15:42:33 +0100771 if (prefix[0] == '@') {
772 prefix++;
773 }
Radek Krejci23238922015-10-27 17:13:34 +0100774 } else {
775 name = str;
Radek Krejci88f29302015-10-30 15:42:33 +0100776 if (name[0] == '@') {
777 name++;
778 }
Radek Krejci5449d472015-10-26 14:35:56 +0100779 }
780
Radek Krejci5449d472015-10-26 14:35:56 +0100781 /* prepare data for parsing node content */
782 len += r + 1;
783 len += skip_ws(&data[len]);
784 if (data[len] != ':') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100785 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "JSON data (missing name-separator)");
Radek Krejci5449d472015-10-26 14:35:56 +0100786 goto error;
787 }
788 len++;
789 len += skip_ws(&data[len]);
790
Radek Krejci88f29302015-10-30 15:42:33 +0100791 if (str[0] == '@' && !str[1]) {
792 /* process attribute of the parent object (container or list) */
Radek Krejci2a0efef2016-03-24 15:10:40 +0100793 if (!(*parent)) {
794 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "attribute with no corresponding element to belongs to");
Radek Krejci88f29302015-10-30 15:42:33 +0100795 goto error;
796 }
797
798 r = json_parse_attr((*parent)->schema->module, &attr, &data[len]);
799 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100800 LOGPATH(LY_VLOG_LYD, (*parent));
Radek Krejci88f29302015-10-30 15:42:33 +0100801 goto error;
802 }
803 len += r;
804
805 if ((*parent)->attr) {
806 lyd_free_attr(ctx, NULL, attr, 1);
807 } else {
808 (*parent)->attr = attr;
809 }
Radek Krejcic4831272015-11-01 19:26:34 +0100810 free(str);
811 return len;
Radek Krejci88f29302015-10-30 15:42:33 +0100812 }
813
Radek Krejci5449d472015-10-26 14:35:56 +0100814 /* find schema node */
815 if (!(*parent)) {
816 /* starting in root */
817 /* get the proper schema */
818 module = ly_ctx_get_module(ctx, prefix, NULL);
819 if (module) {
820 /* get the proper schema node */
Radek Krejci919a9242016-07-27 08:17:13 +0200821 while ((schema = (struct lys_node *)lys_getnext(schema, NULL, module, 0))) {
Radek Krejci5449d472015-10-26 14:35:56 +0100822 if (!strcmp(schema->name, name)) {
823 break;
824 }
825 }
Radek Krejci88f29302015-10-30 15:42:33 +0100826 } else {
Radek Krejci2a0efef2016-03-24 15:10:40 +0100827 LOGVAL(LYE_INELEM, LY_VLOG_NONE, NULL, name);
Radek Krejci88f29302015-10-30 15:42:33 +0100828 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100829 }
830 } else {
831 /* parsing some internal node, we start with parent's schema pointer */
832 if (prefix) {
833 /* get the proper schema */
834 module = ly_ctx_get_module(ctx, prefix, NULL);
835 if (!module) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100836 LOGVAL(LYE_INELEM, LY_VLOG_LYD, (*parent), name);
Radek Krejci88f29302015-10-30 15:42:33 +0100837 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100838 }
839 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100840
841 /* go through RPC's input/output following the options' data type */
842 if ((*parent)->schema->nodetype == LYS_RPC) {
843 while ((schema = (struct lys_node *)lys_getnext(schema, (*parent)->schema, module, LYS_GETNEXT_WITHINOUT))) {
Michal Vaskoafa7a642016-10-18 15:11:38 +0200844 if ((options & LYD_OPT_RPC) && (schema->nodetype == LYS_INPUT)) {
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100845 break;
Michal Vaskoafa7a642016-10-18 15:11:38 +0200846 } else if ((options & LYD_OPT_RPCREPLY) && (schema->nodetype == LYS_OUTPUT)) {
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100847 break;
848 }
849 }
850 if (!schema) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100851 LOGVAL(LYE_INELEM, LY_VLOG_LYD, (*parent), name);
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100852 goto error;
853 }
854 schema_parent = schema;
855 schema = NULL;
856 }
857
Michal Vasko36ef6932015-12-01 14:30:17 +0100858 if (schema_parent) {
859 while ((schema = (struct lys_node *)lys_getnext(schema, schema_parent, module, 0))) {
860 if (!strcmp(schema->name, name)) {
861 break;
862 }
863 }
864 } else {
865 while ((schema = (struct lys_node *)lys_getnext(schema, (*parent)->schema, module, 0))) {
866 if (!strcmp(schema->name, name)) {
867 break;
868 }
Radek Krejci5449d472015-10-26 14:35:56 +0100869 }
870 }
871 }
Radek Krejci27fe55e2016-09-13 17:13:35 +0200872 if (!schema || !lys_node_module(schema)->implemented) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100873 LOGVAL(LYE_INELEM, LY_VLOG_LYD, (*parent), name);
Radek Krejci88f29302015-10-30 15:42:33 +0100874 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100875 }
Radek Krejci88f29302015-10-30 15:42:33 +0100876
877 if (str[0] == '@') {
Radek Krejci88f29302015-10-30 15:42:33 +0100878 /* attribute for some sibling node */
879 if (data[len] == '[') {
880 flag_leaflist = 1;
881 len++;
882 len += skip_ws(&data[len]);
883 }
884
885attr_repeat:
886 r = json_parse_attr(schema->module, &attr, &data[len]);
887 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100888 LOGPATH(LY_VLOG_LYD, (*parent));
Radek Krejci88f29302015-10-30 15:42:33 +0100889 goto error;
890 }
891 len += r;
892
893 if (attr) {
Radek Krejcic4831272015-11-01 19:26:34 +0100894 attrs_aux = malloc(sizeof *attrs_aux);
Michal Vasko253035f2015-12-17 16:58:13 +0100895 if (!attrs_aux) {
896 LOGMEM;
897 goto error;
898 }
Radek Krejcic4831272015-11-01 19:26:34 +0100899 attrs_aux->attr = attr;
900 attrs_aux->index = flag_leaflist;
901 attrs_aux->schema = schema;
902 attrs_aux->next = *attrs;
903 *attrs = attrs_aux;
Radek Krejci88f29302015-10-30 15:42:33 +0100904 } else if (!flag_leaflist) {
905 /* error */
Radek Krejci48464ed2016-03-17 15:44:09 +0100906 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "attribute data");
Radek Krejci88f29302015-10-30 15:42:33 +0100907 goto error;
908 }
909
910 if (flag_leaflist) {
911 if (data[len] == ',') {
912 len++;
913 len += skip_ws(&data[len]);
914 flag_leaflist++;
915 goto attr_repeat;
916 } else if (data[len] != ']') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100917 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "JSON data (missing end-array)");
Radek Krejci88f29302015-10-30 15:42:33 +0100918 goto error;
919 }
920 len++;
921 len += skip_ws(&data[len]);
922 }
923
Radek Krejcic4831272015-11-01 19:26:34 +0100924 free(str);
925 return len;
Radek Krejci88f29302015-10-30 15:42:33 +0100926 }
927
Radek Krejci5449d472015-10-26 14:35:56 +0100928 switch (schema->nodetype) {
929 case LYS_CONTAINER:
930 case LYS_LIST:
931 case LYS_NOTIF:
932 case LYS_RPC:
Michal Vaskoafa7a642016-10-18 15:11:38 +0200933 case LYS_ACTION:
Radek Krejci5449d472015-10-26 14:35:56 +0100934 result = calloc(1, sizeof *result);
935 break;
936 case LYS_LEAF:
937 case LYS_LEAFLIST:
938 result = calloc(1, sizeof(struct lyd_node_leaf_list));
939 break;
940 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200941 case LYS_ANYDATA:
942 result = calloc(1, sizeof(struct lyd_node_anydata));
Radek Krejci5449d472015-10-26 14:35:56 +0100943 break;
944 default:
945 LOGINT;
Radek Krejci595060f2015-10-30 16:29:58 +0100946 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100947 }
Michal Vasko253035f2015-12-17 16:58:13 +0100948 if (!result) {
949 LOGMEM;
950 goto error;
951 }
952
Radek Krejci61767ca2016-09-19 14:21:55 +0200953 result->prev = result;
Radek Krejci5449d472015-10-26 14:35:56 +0100954 result->schema = schema;
Radek Krejci61767ca2016-09-19 14:21:55 +0200955 result->parent = *parent;
956 diter = NULL;
957 if (*parent && (*parent)->child && schema->nodetype == LYS_LEAF && (*parent)->schema->nodetype == LYS_LIST &&
958 (pos = lys_is_key((struct lys_node_list *)(*parent)->schema, (struct lys_node_leaf *)schema))) {
959 /* it is key and we need to insert it into a correct place */
960 for (i = 0, diter = (*parent)->child;
961 diter && i < (pos - 1) && diter->schema->nodetype == LYS_LEAF &&
962 lys_is_key((struct lys_node_list *)(*parent)->schema, (struct lys_node_leaf *)diter->schema);
963 i++, diter = diter->next);
964 if (diter) {
965 /* out of order insertion - insert list's key to the correct position, before the diter */
966 if ((*parent)->child == diter) {
967 (*parent)->child = result;
968 /* update first_sibling */
969 first_sibling = result;
970 }
971 if (diter->prev->next) {
972 diter->prev->next = result;
973 }
974 result->prev = diter->prev;
975 diter->prev = result;
976 result->next = diter;
977 }
978 }
979 if (!diter) {
980 /* simplified (faster) insert as the last node */
981 if (*parent && !(*parent)->child) {
982 (*parent)->child = result;
983 }
984 if (prev) {
985 result->prev = prev;
986 prev->next = result;
987
988 /* fix the "last" pointer */
989 first_sibling->prev = result;
990 } else {
991 result->prev = result;
992 first_sibling = result;
993 }
994 }
Radek Krejcica7efb72016-01-18 13:06:01 +0100995 result->validity = LYD_VAL_NOT;
Radek Krejci46165822016-08-26 14:06:27 +0200996 if (resolve_applies_when(schema, 0, NULL)) {
Radek Krejci0b7704f2016-03-18 12:16:14 +0100997 result->when_status = LYD_WHEN;
998 }
Radek Krejci5449d472015-10-26 14:35:56 +0100999
Radek Krejci5449d472015-10-26 14:35:56 +01001000 /* type specific processing */
1001 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
1002 /* type detection and assigning the value */
Radek Krejcibd930122016-08-10 13:28:26 +02001003 r = json_get_value((struct lyd_node_leaf_list *)result, first_sibling, &data[len], options);
Radek Krejci5449d472015-10-26 14:35:56 +01001004 if (!r) {
1005 goto error;
1006 }
Radek Krejci88f29302015-10-30 15:42:33 +01001007 while(result->next) {
1008 result = result->next;
1009 }
1010
Radek Krejci5449d472015-10-26 14:35:56 +01001011 len += r;
1012 len += skip_ws(&data[len]);
Radek Krejcibf2abff2016-08-23 15:51:52 +02001013 } else if (schema->nodetype & LYS_ANYDATA) {
Radek Krejci4ae82942016-09-19 16:41:06 +02001014 r = json_get_anydata((struct lyd_node_anydata *)result, &data[len]);
Radek Krejci5449d472015-10-26 14:35:56 +01001015 if (!r) {
1016 goto error;
1017 }
1018 len += r;
1019 len += skip_ws(&data[len]);
Michal Vaskoafa7a642016-10-18 15:11:38 +02001020 } else if (schema->nodetype & (LYS_CONTAINER | LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1021 if (schema->nodetype & (LYS_RPC | LYS_ACTION)) {
1022 if (!(options & LYD_OPT_RPC) || *act_notif) {
1023 LOGVAL(LYE_INELEM, LY_VLOG_LYD, result, schema->name);
1024 LOGVAL(LYE_SPEC, LY_VLOG_LYD, result, "Unexpected %s node \"%s\".",
1025 (schema->nodetype == LYS_RPC ? "rpc" : "action"), schema->name);
1026 goto error;
1027 }
1028 *act_notif = result;
1029 } else if (schema->nodetype == LYS_NOTIF) {
1030 if (!(options & LYD_OPT_NOTIF) || *act_notif) {
1031 LOGVAL(LYE_INELEM, LY_VLOG_LYD, result, schema->name);
1032 LOGVAL(LYE_SPEC, LY_VLOG_LYD, result, "Unexpected notification node \"%s\".", schema->name);
1033 goto error;
1034 }
1035 *act_notif = result;
1036 }
1037
Radek Krejci5449d472015-10-26 14:35:56 +01001038 if (data[len] != '{') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001039 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing begin-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001040 goto error;
1041 }
1042 len++;
1043 len += skip_ws(&data[len]);
1044
1045 if (data[len] != '}') {
1046 /* non-empty container */
Radek Krejcic4831272015-11-01 19:26:34 +01001047 len--;
1048 diter = NULL;
1049 attrs_aux = NULL;
1050 do {
1051 len++;
1052 len += skip_ws(&data[len]);
1053
Michal Vaskoafa7a642016-10-18 15:11:38 +02001054 r = json_parse_data(ctx, &data[len], NULL, &result, result->child, diter, &attrs_aux, options, unres, act_notif);
Radek Krejcic4831272015-11-01 19:26:34 +01001055 if (!r) {
1056 goto error;
1057 }
1058 len += r;
1059
1060 if (result->child) {
1061 diter = result->child->prev;
1062 }
1063 } while(data[len] == ',');
1064
1065 /* store attributes */
1066 if (store_attrs(ctx, attrs_aux, result->child)) {
Radek Krejci5449d472015-10-26 14:35:56 +01001067 goto error;
1068 }
Radek Krejci5449d472015-10-26 14:35:56 +01001069 }
1070
1071 if (data[len] != '}') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001072 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing end-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001073 goto error;
1074 }
1075 len++;
1076 len += skip_ws(&data[len]);
1077
Michal Vaskoc4280842016-04-19 16:10:42 +02001078 /* if we have empty non-presence container, we could remove it immediately if there were no attributes of it, who knows */
Radek Krejci2537fd32016-09-07 16:22:41 +02001079 if (schema->nodetype == LYS_CONTAINER && !result->child &&
Radek Krejcid3e73722016-05-23 12:24:55 +02001080 !result->attr && !((struct lys_node_container *)schema)->presence) {
Michal Vaskoc4280842016-04-19 16:10:42 +02001081 if (unres_data_add(unres, result, UNRES_EMPTYCONT)) {
1082 goto error;
1083 }
Radek Krejci0c0086a2016-03-24 15:20:28 +01001084 }
1085
Radek Krejci5449d472015-10-26 14:35:56 +01001086 } else if (schema->nodetype == LYS_LIST) {
1087 if (data[len] != '[') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001088 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing begin-array)");
Radek Krejci5449d472015-10-26 14:35:56 +01001089 goto error;
1090 }
1091
1092 list = result;
1093 do {
1094 len++;
1095 len += skip_ws(&data[len]);
Radek Krejci23238922015-10-27 17:13:34 +01001096
Radek Krejcic4831272015-11-01 19:26:34 +01001097 if (data[len] != '{') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001098 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result,
Radek Krejciadb57612016-02-16 13:34:34 +01001099 "JSON data (missing list instance's begin-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001100 goto error;
1101 }
Radek Krejcic4831272015-11-01 19:26:34 +01001102 diter = NULL;
1103 attrs_aux = NULL;
1104 do {
1105 len++;
1106 len += skip_ws(&data[len]);
1107
Michal Vaskoafa7a642016-10-18 15:11:38 +02001108 r = json_parse_data(ctx, &data[len], NULL, &list, list->child, diter, &attrs_aux, options, unres, act_notif);
Radek Krejcic4831272015-11-01 19:26:34 +01001109 if (!r) {
1110 goto error;
1111 }
1112 len += r;
1113
Radek Krejci52934692015-11-01 20:08:15 +01001114 if (list->child) {
Radek Krejcic4831272015-11-01 19:26:34 +01001115 diter = list->child->prev;
1116 }
1117 } while(data[len] == ',');
1118
1119 /* store attributes */
Radek Krejci52934692015-11-01 20:08:15 +01001120 if (store_attrs(ctx, attrs_aux, list->child)) {
Radek Krejcic4831272015-11-01 19:26:34 +01001121 goto error;
1122 }
1123
1124 if (data[len] != '}') {
1125 /* expecting end-object */
Radek Krejci48464ed2016-03-17 15:44:09 +01001126 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result,
Radek Krejciadb57612016-02-16 13:34:34 +01001127 "JSON data (missing list instance's end-object)");
Radek Krejcic4831272015-11-01 19:26:34 +01001128 goto error;
1129 }
1130 len++;
Radek Krejci5449d472015-10-26 14:35:56 +01001131 len += skip_ws(&data[len]);
1132
1133 if (data[len] == ',') {
Radek Krejci93fab982016-02-03 15:58:19 +01001134 /* various validation checks */
1135 ly_errno = 0;
Radek Krejci2d5525d2016-04-04 15:43:30 +02001136 if (!(options & LYD_OPT_TRUSTED) &&
1137 (lyv_data_content(list, options, unres) ||
Radek Krejci61767ca2016-09-19 14:21:55 +02001138 lyv_multicases(list, NULL, prev ? &first_sibling : NULL, 0, NULL))) {
Radek Krejci93fab982016-02-03 15:58:19 +01001139 if (ly_errno) {
1140 goto error;
1141 }
1142 }
1143 /* validation successful */
1144 list->validity = LYD_VAL_OK;
1145
Radek Krejci5449d472015-10-26 14:35:56 +01001146 /* another instance of the list */
1147 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001148 if (!new) {
1149 goto error;
1150 }
Radek Krejci5449d472015-10-26 14:35:56 +01001151 new->parent = list->parent;
1152 new->prev = list;
1153 list->next = new;
1154
1155 /* fix the "last" pointer */
Radek Krejci2d5525d2016-04-04 15:43:30 +02001156 first_sibling->prev = new;
Radek Krejci5449d472015-10-26 14:35:56 +01001157
1158 new->schema = list->schema;
Radek Krejci5449d472015-10-26 14:35:56 +01001159 list = new;
1160 }
1161 } while (data[len] == ',');
Michal Vaskod171d4e2016-06-06 13:33:19 +02001162 result = first_sibling;
Radek Krejci5449d472015-10-26 14:35:56 +01001163
1164 if (data[len] != ']') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001165 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing end-array)");
Radek Krejci5449d472015-10-26 14:35:56 +01001166 goto error;
1167 }
1168 len++;
1169 len += skip_ws(&data[len]);
1170 }
1171
1172 /* various validation checks */
Michal Vasko10e586f2016-05-18 13:25:30 +02001173 if (!(options & LYD_OPT_TRUSTED) && lyv_data_context(result, options, unres)) {
1174 goto error;
1175 }
1176
Radek Krejci5449d472015-10-26 14:35:56 +01001177 ly_errno = 0;
Radek Krejci2d5525d2016-04-04 15:43:30 +02001178 if (!(options & LYD_OPT_TRUSTED) &&
1179 (lyv_data_content(result, options, unres) ||
Radek Krejci61767ca2016-09-19 14:21:55 +02001180 lyv_multicases(result, NULL, prev ? &first_sibling : NULL, 0, NULL))) {
Radek Krejci5449d472015-10-26 14:35:56 +01001181 if (ly_errno) {
1182 goto error;
1183 }
1184 }
1185
Radek Krejcica7efb72016-01-18 13:06:01 +01001186 /* validation successful */
Radek Krejci63b79c82016-08-10 10:09:33 +02001187 if (result->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
1188 /* postpone checking when there will be all list/leaflist instances */
1189 result->validity = LYD_VAL_UNIQUE;
1190 } else {
1191 result->validity = LYD_VAL_OK;
1192 }
Radek Krejcica7efb72016-01-18 13:06:01 +01001193
Radek Krejci88f29302015-10-30 15:42:33 +01001194 if (!(*parent)) {
1195 *parent = result;
1196 }
1197
Radek Krejcide9d92c2015-10-30 15:59:59 +01001198 free(str);
Radek Krejci5449d472015-10-26 14:35:56 +01001199 return len;
1200
1201error:
Radek Krejci0c0086a2016-03-24 15:20:28 +01001202 len = 0;
Radek Krejci0c0086a2016-03-24 15:20:28 +01001203 /* cleanup */
1204 for (i = unres->count - 1; i >= 0; i--) {
1205 /* remove unres items connected with the node being removed */
1206 if (unres->node[i] == result) {
1207 unres_data_del(unres, i);
1208 }
Radek Krejci88f29302015-10-30 15:42:33 +01001209 }
1210 while (*attrs) {
Radek Krejcic4831272015-11-01 19:26:34 +01001211 attrs_aux = *attrs;
Radek Krejci88f29302015-10-30 15:42:33 +01001212 *attrs = (*attrs)->next;
1213
Radek Krejcic4831272015-11-01 19:26:34 +01001214 lyd_free_attr(ctx, NULL, attrs_aux->attr, 1);
1215 free(attrs_aux);
Radek Krejci88f29302015-10-30 15:42:33 +01001216 }
1217
Radek Krejci5449d472015-10-26 14:35:56 +01001218 lyd_free(result);
Radek Krejci88f29302015-10-30 15:42:33 +01001219 free(str);
1220
Radek Krejci0c0086a2016-03-24 15:20:28 +01001221 return len;
Radek Krejci5449d472015-10-26 14:35:56 +01001222}
1223
1224struct lyd_node *
Michal Vasko945b96b2016-10-18 11:49:12 +02001225lyd_parse_json(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *rpc_act,
1226 const struct lyd_node *data_tree)
Radek Krejci5449d472015-10-26 14:35:56 +01001227{
Michal Vaskoafa7a642016-10-18 15:11:38 +02001228 struct lyd_node *result = NULL, *next, *iter, *reply_parent = NULL, *reply_top = NULL, *act_notif = NULL;
Radek Krejci5449d472015-10-26 14:35:56 +01001229 struct unres_data *unres = NULL;
Radek Krejcic4831272015-11-01 19:26:34 +01001230 unsigned int len = 0, r;
Michal Vaskoafa7a642016-10-18 15:11:38 +02001231 int i, act_cont = 0;
Radek Krejcic4831272015-11-01 19:26:34 +01001232 struct attr_cont *attrs = NULL;
Radek Krejci63b79c82016-08-10 10:09:33 +02001233 struct ly_set *set;
Radek Krejci5449d472015-10-26 14:35:56 +01001234
Radek Krejci2342cf62016-01-29 16:48:23 +01001235 ly_errno = LY_SUCCESS;
1236
Michal Vaskoafa7a642016-10-18 15:11:38 +02001237 if (!ctx || !data) {
Radek Krejci5449d472015-10-26 14:35:56 +01001238 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1239 return NULL;
1240 }
1241
Radek Krejcic4831272015-11-01 19:26:34 +01001242 /* skip leading whitespaces */
1243 len += skip_ws(&data[len]);
1244
Michal Vasko24d982f2016-04-18 15:13:58 +02001245 /* no data (or whitespaces only) are fine */
1246 if (!data[len]) {
1247 lyd_validate(&result, options, ctx);
1248 return result;
1249 }
1250
Radek Krejcic4831272015-11-01 19:26:34 +01001251 /* expect top-level { */
1252 if (data[len] != '{') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001253 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top level begin-object)");
Michal Vasko24d982f2016-04-18 15:13:58 +02001254 return NULL;
1255 }
1256
1257 unres = calloc(1, sizeof *unres);
1258 if (!unres) {
1259 LOGMEM;
1260 return NULL;
Radek Krejcic4831272015-11-01 19:26:34 +01001261 }
1262
Michal Vaskoafa7a642016-10-18 15:11:38 +02001263 /* create RPC/action reply part that is not in the parsed data */
1264 if (rpc_act) {
1265 assert(options & LYD_OPT_RPCREPLY);
1266 if (rpc_act->schema->nodetype == LYS_RPC) {
1267 /* RPC request */
1268 reply_top = reply_parent = _lyd_new(NULL, rpc_act->schema, 0);
1269 } else {
1270 /* action request */
1271 reply_top = lyd_dup(rpc_act, 1);
1272 LY_TREE_DFS_BEGIN(reply_top, iter, reply_parent) {
1273 if (reply_parent->schema->nodetype == LYS_ACTION) {
1274 break;
1275 }
1276 LY_TREE_DFS_END(reply_top, iter, reply_parent);
1277 }
1278 if (!reply_parent) {
1279 LOGERR(LY_EINVAL, "%s: invalid variable parameter (const struct lyd_node *rpc_act).", __func__);
1280 lyd_free_withsiblings(reply_top);
1281 goto error;
1282 }
1283 lyd_free_withsiblings(reply_parent->child);
1284 }
1285 }
1286
1287 iter = NULL;
1288 next = reply_parent;
Radek Krejcic4831272015-11-01 19:26:34 +01001289 do {
1290 len++;
1291 len += skip_ws(&data[len]);
1292
Michal Vaskoafa7a642016-10-18 15:11:38 +02001293 if (!act_cont) {
1294 if (!strncmp(&data[len], "\"yang:action\"", 13)) {
1295 len += 13;
1296 len += skip_ws(&data[len]);
1297 if (data[len] != ':') {
1298 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top-level begin-object)");
1299 lyd_free_withsiblings(reply_top);
1300 goto error;
1301 }
1302 ++len;
1303 len += skip_ws(&data[len]);
1304 if (data[len] != '{') {
1305 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top level yang:action object)");
1306 lyd_free_withsiblings(reply_top);
1307 goto error;
1308 }
1309 ++len;
1310 len += skip_ws(&data[len]);
1311
1312 act_cont = 1;
1313 } else {
1314 act_cont = -1;
1315 }
1316 }
1317
1318 r = json_parse_data(ctx, &data[len], NULL, &next, result, iter, &attrs, options, unres, &act_notif);
Radek Krejcic4831272015-11-01 19:26:34 +01001319 if (!r) {
Michal Vaskoafa7a642016-10-18 15:11:38 +02001320 lyd_free_withsiblings(reply_top);
Michal Vasko24d982f2016-04-18 15:13:58 +02001321 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001322 }
1323 len += r;
1324
1325 if (!result) {
1326 result = next;
1327 }
1328 if (next) {
1329 iter = next;
1330 }
1331 next = NULL;
Michal Vaskoafa7a642016-10-18 15:11:38 +02001332 } while (data[len] == ',');
Radek Krejcic4831272015-11-01 19:26:34 +01001333
1334 if (data[len] != '}') {
1335 /* expecting end-object */
Radek Krejci48464ed2016-03-17 15:44:09 +01001336 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top-level end-object)");
Michal Vasko24d982f2016-04-18 15:13:58 +02001337 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001338 }
1339 len++;
1340 len += skip_ws(&data[len]);
1341
Michal Vaskoafa7a642016-10-18 15:11:38 +02001342 if (act_cont == 1) {
1343 if (data[len] != '}') {
1344 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top-level end-object)");
1345 goto error;
1346 }
1347 len++;
1348 len += skip_ws(&data[len]);
1349 }
1350
Radek Krejcic4831272015-11-01 19:26:34 +01001351 /* store attributes */
1352 if (store_attrs(ctx, attrs, result)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001353 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001354 }
Radek Krejci5449d472015-10-26 14:35:56 +01001355
Michal Vaskoafa7a642016-10-18 15:11:38 +02001356 if (reply_top) {
1357 result = reply_top;
1358 }
1359
Michal Vaskoc1cf86f2015-11-04 09:54:51 +01001360 if (!result) {
1361 LOGERR(LY_EVALID, "Model for the data to be linked with not found.");
Michal Vasko24d982f2016-04-18 15:13:58 +02001362 goto error;
Michal Vaskoc1cf86f2015-11-04 09:54:51 +01001363 }
1364
Michal Vaskoafa7a642016-10-18 15:11:38 +02001365 if ((options & LYD_OPT_RPCREPLY) && (rpc_act->schema->nodetype != LYS_RPC)) {
1366 /* action reply */
1367 act_notif = reply_parent;
1368 } else if ((options & (LYD_OPT_RPC | LYD_OPT_NOTIF)) && !act_notif) {
1369 ly_vecode = LYVE_INELEM;
1370 LOGVAL(LYE_SPEC, LY_VLOG_LYD, result, "Missing %s node.", (options & LYD_OPT_RPC ? "action" : "notification"));
1371 goto error;
1372 }
1373
Radek Krejci63b79c82016-08-10 10:09:33 +02001374 /* check for uniquness of top-level lists/leaflists because
1375 * only the inner instances were tested in lyv_data_content() */
1376 set = ly_set_new();
1377 LY_TREE_FOR(result, iter) {
1378 if (!(iter->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(iter->validity & LYD_VAL_UNIQUE)) {
1379 continue;
1380 }
1381
1382 /* check each list/leaflist only once */
1383 i = set->number;
1384 if (ly_set_add(set, iter->schema, 0) != i) {
1385 /* already checked */
1386 continue;
1387 }
1388
1389 if (lyv_data_unique(iter, result)) {
1390 ly_set_free(set);
1391 goto error;
1392 }
1393 }
1394 ly_set_free(set);
1395
Radek Krejci46165822016-08-26 14:06:27 +02001396 /* add/validate default values, unres */
Michal Vaskoafa7a642016-10-18 15:11:38 +02001397 if (lyd_defaults_add_unres(&result, options, ctx, data_tree, act_notif, unres)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001398 goto error;
Radek Krejci5c162452016-03-23 13:36:01 +01001399 }
1400
Radek Krejci46165822016-08-26 14:06:27 +02001401 /* check for missing top level mandatory nodes */
Michal Vaskoafa7a642016-10-18 15:11:38 +02001402 if (!(options & LYD_OPT_TRUSTED) && lyd_check_mandatory_tree((act_notif ? act_notif : result), ctx, options)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001403 goto error;
Radek Krejci5c162452016-03-23 13:36:01 +01001404 }
1405
Radek Krejci5449d472015-10-26 14:35:56 +01001406 free(unres->node);
1407 free(unres->type);
Radek Krejci5449d472015-10-26 14:35:56 +01001408 free(unres);
1409
1410 return result;
Michal Vasko24d982f2016-04-18 15:13:58 +02001411
1412error:
1413 lyd_free_withsiblings(result);
1414 free(unres->node);
1415 free(unres->type);
1416 free(unres);
1417
1418 return NULL;
Radek Krejci5449d472015-10-26 14:35:56 +01001419}