blob: 0b2f00d2e6790b161fc668f17556455775bfa79d [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 */
zyinter20087fa65732016-11-17 10:55:12 +0800159 } else if ((data[*len] >= 0 && data[*len] < 0x20) || data[*len] == 0x5c) {
Radek Krejci5449d472015-10-26 14:35:56 +0100160 /* 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 Krejcia7177672016-11-17 14:53:03 +0900385 unsigned int len = 0, start, stop, c = 0;
386 char *str;
Radek Krejci5449d472015-10-26 14:35:56 +0100387
Radek Krejcia7177672016-11-17 14:53:03 +0900388 /* anydata (as well as meaningful anyxml) is supposed to be encoded as object,
389 * anyxml can be a string value, other JSON types are not supported since it is
390 * not clear how they are supposed to be represented/converted into an internal representation */
391 if (data[len] == '"' && any->schema->nodetype == LYS_ANYXML) {
392 len = 1;
393 str = lyjson_parse_text(&data[len], &c);
394 if (!str) {
395 return 0;
396 }
397 if (data[len + c] != '"') {
Radek Krejci7d6d2842016-11-28 11:21:38 +0100398 free(str);
Radek Krejcia7177672016-11-17 14:53:03 +0900399 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, any,
400 "JSON data (missing quotation-mark at the end of string)");
401 return 0;
402 }
403
404 any->value.str = lydict_insert_zc(any->schema->module->ctx, str);
405 any->value_type = LYD_ANYDATA_CONSTSTRING;
406 return len + c + 1;
407 } else if (data[len] != '{') {
408 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, any, "Unsupported Anydata/anyxml content (not an object nor string)");
Michal Vaskoa19f7d72016-05-18 13:24:08 +0200409 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100410 }
411
Radek Krejcia7177672016-11-17 14:53:03 +0900412 /* count opening '{' and closing '}' brackets to get the end of the object without its parsing */
413 c = len = 1;
Radek Krejci4ae82942016-09-19 16:41:06 +0200414 len += skip_ws(&data[len]);
Radek Krejcia7177672016-11-17 14:53:03 +0900415 start = len;
416 stop = start - 1;
Radek Krejci4ae82942016-09-19 16:41:06 +0200417 while (data[len] && c) {
418 switch (data[len]) {
419 case '{':
420 c++;
421 break;
422 case '}':
423 c--;
424 break;
425 default:
426 if (!isspace(data[len])) {
427 stop = len;
428 }
429 }
430 len++;
431 }
432 if (c) {
433 LOGVAL(LYE_EOF, LY_VLOG_LYD, any);
434 return 0;
435 }
436 any->value_type = LYD_ANYDATA_JSON;
Radek Krejcia7177672016-11-17 14:53:03 +0900437 if (stop >= start) {
438 any->value.str = lydict_insert(any->schema->module->ctx, &data[start], stop - start + 1);
439 } /* else no data */
Radek Krejci4ae82942016-09-19 16:41:06 +0200440
Michal Vaskoa19f7d72016-05-18 13:24:08 +0200441 return len;
Radek Krejci5449d472015-10-26 14:35:56 +0100442}
443
444static unsigned int
Radek Krejci45f41dd2017-02-09 14:11:09 +0100445json_get_value(struct lyd_node_leaf_list *leaf, struct lyd_node **first_sibling, const char *data, int options,
446 struct unres_data *unres)
Radek Krejci5449d472015-10-26 14:35:56 +0100447{
Radek Krejcibd930122016-08-10 13:28:26 +0200448 struct lyd_node_leaf_list *new;
Radek Krejci37b756f2016-01-18 10:15:03 +0100449 struct lys_type *stype;
Radek Krejci5449d472015-10-26 14:35:56 +0100450 struct ly_ctx *ctx;
451 unsigned int len = 0, r;
Radek Krejci5449d472015-10-26 14:35:56 +0100452 char *str;
453
Radek Krejci0b7704f2016-03-18 12:16:14 +0100454 assert(leaf && data);
Radek Krejci5449d472015-10-26 14:35:56 +0100455 ctx = leaf->schema->module->ctx;
456
457 stype = &((struct lys_node_leaf *)leaf->schema)->type;
Radek Krejci23238922015-10-27 17:13:34 +0100458
Radek Krejci5449d472015-10-26 14:35:56 +0100459 if (leaf->schema->nodetype == LYS_LEAFLIST) {
460 /* expecting begin-array */
461 if (data[len++] != '[') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100462 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expected begin-array)");
Radek Krejci5449d472015-10-26 14:35:56 +0100463 return 0;
464 }
465
466repeat:
467 len += skip_ws(&data[len]);
468 }
469
470 /* will be changed in case of union */
471 leaf->value_type = stype->base;
472
473 if (data[len] == '"') {
474 /* string representations */
Michal Vasko6baed1c2016-05-18 13:24:44 +0200475 ++len;
Radek Krejci5449d472015-10-26 14:35:56 +0100476 str = lyjson_parse_text(&data[len], &r);
Radek Krejci23238922015-10-27 17:13:34 +0100477 if (!str) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100478 LOGPATH(LY_VLOG_LYD, leaf);
Radek Krejci5449d472015-10-26 14:35:56 +0100479 return 0;
480 }
481 leaf->value_str = lydict_insert_zc(ctx, str);
482 if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100483 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf,
Radek Krejciadb57612016-02-16 13:34:34 +0100484 "JSON data (missing quotation-mark at the end of string)");
Radek Krejci5449d472015-10-26 14:35:56 +0100485 return 0;
486 }
487 len += r + 1;
488 } else if (data[len] == '-' || isdigit(data[len])) {
489 /* numeric type */
490 r = lyjson_parse_number(&data[len]);
491 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100492 LOGPATH(LY_VLOG_LYD, leaf);
Radek Krejci5449d472015-10-26 14:35:56 +0100493 return 0;
494 }
Michal Vasko1e676ca2016-06-24 15:23:54 +0200495 /* if it's a number with 'e' or 'E', get rid of it first */
496 if ((str = strnchr(&data[len], 'e', r)) || (str = strnchr(&data[len], 'E', r))) {
497 str = lyjson_convert_enumber(&data[len], r, str);
498 if (!str) {
499 return 0;
500 }
501 leaf->value_str = lydict_insert_zc(ctx, str);
502 } else {
503 leaf->value_str = lydict_insert(ctx, &data[len], r);
504 }
Radek Krejci5449d472015-10-26 14:35:56 +0100505 len += r;
506 } else if (data[len] == 'f' || data[len] == 't') {
507 /* boolean */
508 r = lyjson_parse_boolean(&data[len]);
509 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100510 LOGPATH(LY_VLOG_LYD, leaf);
Radek Krejci5449d472015-10-26 14:35:56 +0100511 return 0;
512 }
513 leaf->value_str = lydict_insert(ctx, &data[len], r);
514 len += r;
515 } else if (!strncmp(&data[len], "[null]", 6)) {
516 /* empty */
Michal Vasko44913842016-04-13 14:20:41 +0200517 leaf->value_str = lydict_insert(ctx, "", 0);
Radek Krejci5449d472015-10-26 14:35:56 +0100518 len += 6;
519 } else {
520 /* error */
Radek Krejci48464ed2016-03-17 15:44:09 +0100521 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (unexpected value)");
Radek Krejci5449d472015-10-26 14:35:56 +0100522 return 0;
523 }
524
Radek Krejci1899d6a2016-11-03 13:48:07 +0100525 /* the value is here converted to a JSON format if needed in case of LY_TYPE_IDENT and LY_TYPE_INST or to a
526 * canonical form of the value */
Radek Krejcia571d942017-02-24 09:26:49 +0100527 if (!lyp_parse_value(&((struct lys_node_leaf *)leaf->schema)->type, &leaf->value_str, NULL, leaf, NULL, 1, 0)) {
Radek Krejci23238922015-10-27 17:13:34 +0100528 ly_errno = LY_EVALID;
529 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100530 }
531
532 if (leaf->schema->nodetype == LYS_LEAFLIST) {
533 /* repeat until end-array */
534 len += skip_ws(&data[len]);
535 if (data[len] == ',') {
Radek Krejci45f41dd2017-02-09 14:11:09 +0100536 /* various validation checks */
537 if (lyv_data_context((struct lyd_node*)leaf, options, unres)) {
538 return 0;
539 }
540
541 ly_err_clean(1);
542 if (lyv_data_content((struct lyd_node*)leaf, options, unres) ||
543 lyv_multicases((struct lyd_node*)leaf, NULL, first_sibling, 0, NULL)) {
544 if (ly_errno) {
545 return 0;
546 }
547 }
548
Radek Krejci5449d472015-10-26 14:35:56 +0100549 /* another instance of the leaf-list */
550 new = calloc(1, sizeof(struct lyd_node_leaf_list));
Michal Vasko253035f2015-12-17 16:58:13 +0100551 if (!new) {
552 LOGMEM;
553 return 0;
554 }
Radek Krejci5449d472015-10-26 14:35:56 +0100555 new->parent = leaf->parent;
556 new->prev = (struct lyd_node *)leaf;
557 leaf->next = (struct lyd_node *)new;
558
Radek Krejcie1794882017-02-08 13:23:38 +0100559 /* copy the validity and when flags */
560 new->validity = leaf->validity;
561 new->when_status = leaf->when_status;
562
Radek Krejci5449d472015-10-26 14:35:56 +0100563 /* fix the "last" pointer */
Radek Krejci45f41dd2017-02-09 14:11:09 +0100564 (*first_sibling)->prev = (struct lyd_node *)new;
Radek Krejci5449d472015-10-26 14:35:56 +0100565
566 new->schema = leaf->schema;
567
568 /* repeat value parsing */
569 leaf = new;
570 len++;
571 goto repeat;
572 } else if (data[len] == ']') {
573 len++;
574 len += skip_ws(&data[len]);
575 } else {
576 /* something unexpected */
Radek Krejci48464ed2016-03-17 15:44:09 +0100577 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expecting value-separator or end-array)");
Radek Krejci5449d472015-10-26 14:35:56 +0100578 return 0;
579 }
580 }
581
582 len += skip_ws(&data[len]);
583 return len;
584}
585
586static unsigned int
Radek Krejci532e5e92017-02-22 12:59:24 +0100587json_parse_attr(struct lys_module *parent_module, struct lyd_attr **attr, const char *data, int options)
Radek Krejci88f29302015-10-30 15:42:33 +0100588{
589 unsigned int len = 0, r;
Radek Krejci532e5e92017-02-22 12:59:24 +0100590 char *str = NULL, *name, *prefix = NULL, *value;
Radek Krejci88f29302015-10-30 15:42:33 +0100591 struct lys_module *module = parent_module;
592 struct lyd_attr *attr_new, *attr_last = NULL;
Radek Krejci532e5e92017-02-22 12:59:24 +0100593 int pos, i;
Radek Krejci88f29302015-10-30 15:42:33 +0100594
Radek Krejcide9d92c2015-10-30 15:59:59 +0100595 *attr = NULL;
596
Radek Krejci88f29302015-10-30 15:42:33 +0100597 if (data[len] != '{') {
598 if (!strncmp(&data[len], "null", 4)) {
Radek Krejci88f29302015-10-30 15:42:33 +0100599 len += 4;
600 len += skip_ws(&data[len]);
601 return len;
602 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100603 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing begin-object)");
Radek Krejci88f29302015-10-30 15:42:33 +0100604 goto error;
605 }
606
607repeat:
Radek Krejci6a6326d2017-02-27 13:00:52 +0100608 prefix = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100609 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 begining of string)");
Radek Krejci88f29302015-10-30 15:42:33 +0100614 return 0;
615 }
616 len++;
617 str = 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 Krejci88f29302015-10-30 15:42:33 +0100622 goto error;
623 }
624 if ((name = strchr(str, ':'))) {
625 *name = '\0';
626 name++;
627 prefix = str;
Michal Vasko1e62a092015-12-01 12:27:20 +0100628 module = (struct lys_module *)ly_ctx_get_module(parent_module->ctx, prefix, NULL);
Radek Krejci88f29302015-10-30 15:42:33 +0100629 if (!module) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100630 LOGVAL(LYE_INELEM, LY_VLOG_NONE, NULL, name);
Radek Krejci88f29302015-10-30 15:42:33 +0100631 goto error;
632 }
633 } else {
634 name = str;
635 }
636
637 /* prepare data for parsing node content */
638 len += r + 1;
639 len += skip_ws(&data[len]);
640 if (data[len] != ':') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100641 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing name-separator)");
Radek Krejci88f29302015-10-30 15:42:33 +0100642 goto error;
643 }
644 len++;
645 len += skip_ws(&data[len]);
646
647 if (data[len] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100648 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 +0100649 goto error;
Radek Krejci88f29302015-10-30 15:42:33 +0100650 }
651 len++;
652 value = lyjson_parse_text(&data[len], &r);
653 if (!r) {
654 goto error;
655 } else if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100656 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 +0100657 free(value);
Radek Krejci88f29302015-10-30 15:42:33 +0100658 goto error;
659 }
660 len += r + 1;
661 len += skip_ws(&data[len]);
662
Radek Krejci532e5e92017-02-22 12:59:24 +0100663 /* find the appropriate annotation definition */
664 pos = lys_ext_instance_presence(&module->ctx->models.list[0]->extensions[0], module->ext, module->ext_size);
665 if (pos == -1) {
666 free(value);
667attr_error:
668 if (options & LYD_OPT_STRICT) {
669 LOGVAL(LYE_INELEM, LY_VLOG_NONE, NULL, name);
670 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Unknown metadata (%s%s%s).",
671 prefix ? prefix : "", prefix ? ":" : "", name);
672 goto error;
673 } else {
674 LOGWRN("Unknown metadata (%s%s%s) - skipping.",
675 prefix ? prefix : "", prefix ? ":" : "", name);
676 goto next;
677 }
678 }
679
Radek Krejcia571d942017-02-24 09:26:49 +0100680 attr_new = calloc(1, sizeof **attr);
Michal Vasko253035f2015-12-17 16:58:13 +0100681 if (!attr_new) {
682 LOGMEM;
683 goto error;
684 }
Radek Krejci532e5e92017-02-22 12:59:24 +0100685 /* will be filled later, at this moment it can be unknow due to a way
686 * how the attributes are encoded in JSON */
687 attr_new->parent = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100688 attr_new->next = NULL;
Radek Krejci532e5e92017-02-22 12:59:24 +0100689
690 while(pos != -1 && ((unsigned int)(pos + 1) < module->ext_size) &&
691 !ly_strequal(module->ext[pos]->arg_value, name, 0)) {
692 i = lys_ext_instance_presence(&module->ctx->models.list[0]->extensions[0],
693 &module->ext[pos + 1], module->ext_size - (pos + 1));
694 pos = (i == -1) ? -1 : pos + 1 + i;
695 }
696 if (pos == -1) {
697 goto attr_error;
698 }
699 attr_new->annotation = (struct lys_ext_instance_complex *)module->ext[pos];
700
Radek Krejci88f29302015-10-30 15:42:33 +0100701 attr_new->name = lydict_insert(module->ctx, name, 0);
Radek Krejcia571d942017-02-24 09:26:49 +0100702 attr_new->value_str = lydict_insert_zc(module->ctx, value);
703 if (!lyp_parse_value(*((struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, attr_new->annotation, NULL)),
704 &attr_new->value_str, NULL, NULL, attr_new, 1, 0)) {
705 goto attr_error;
706 }
707
Radek Krejci88f29302015-10-30 15:42:33 +0100708 if (!attr_last) {
709 *attr = attr_last = attr_new;
710 } else {
711 attr_last->next = attr_new;
712 attr_last = attr_new;
713 }
714
Radek Krejci532e5e92017-02-22 12:59:24 +0100715next:
Radek Krejci88f29302015-10-30 15:42:33 +0100716 free(str);
Radek Krejcide9d92c2015-10-30 15:59:59 +0100717 str = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100718
719 if (data[len] == ',') {
720 goto repeat;
721 } else if (data[len] != '}') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100722 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing end-object)");
Radek Krejcide9d92c2015-10-30 15:59:59 +0100723 goto error;
Radek Krejci88f29302015-10-30 15:42:33 +0100724 }
725 len++;
726 len += skip_ws(&data[len]);
727
728 return len;
729
730error:
731 free(str);
Radek Krejcide9d92c2015-10-30 15:59:59 +0100732 if (*attr) {
Radek Krejci532e5e92017-02-22 12:59:24 +0100733 lyd_free_attr(module->ctx, NULL, *attr, 1);
Radek Krejcide9d92c2015-10-30 15:59:59 +0100734 *attr = NULL;
735 }
Radek Krejci88f29302015-10-30 15:42:33 +0100736 return 0;
737}
738
739struct attr_cont {
740 struct attr_cont *next;
741 struct lyd_attr *attr;
742 struct lys_node *schema;
743 unsigned int index; /** non-zero only in case of leaf-list */
744};
745
Radek Krejcic4831272015-11-01 19:26:34 +0100746static int
747store_attrs(struct ly_ctx *ctx, struct attr_cont *attrs, struct lyd_node *first)
748{
749 struct lyd_node *diter;
750 struct attr_cont *iter;
Radek Krejci532e5e92017-02-22 12:59:24 +0100751 struct lyd_attr *aiter;
Radek Krejcic4831272015-11-01 19:26:34 +0100752 unsigned int flag_leaflist = 0;
753
754 while (attrs) {
755 iter = attrs;
756 attrs = attrs->next;
757
758 if (iter->index) {
759 flag_leaflist = 1;
760 }
761
762 LY_TREE_FOR(first, diter) {
763 if (iter->schema != diter->schema) {
764 continue;
765 }
766
767 if (flag_leaflist && flag_leaflist != iter->index) {
768 flag_leaflist++;
769 continue;
770 }
771
772 /* we have match */
773 if (diter->attr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100774 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, diter,
Radek Krejciadb57612016-02-16 13:34:34 +0100775 "attribute (multiple attribute definitions belong to a single element)");
Radek Krejcic4831272015-11-01 19:26:34 +0100776 free(iter);
777 goto error;
778 }
779
780 diter->attr = iter->attr;
Radek Krejci532e5e92017-02-22 12:59:24 +0100781 for (aiter = iter->attr; aiter; aiter = aiter->next) {
782 aiter->parent = diter;
783 }
Radek Krejcic4831272015-11-01 19:26:34 +0100784 break;
785 }
786
787 if (!diter) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100788 LOGVAL(LYE_XML_MISS, LY_VLOG_NONE, NULL, "element for the specified attribute", iter->attr->name);
Radek Krejcic4831272015-11-01 19:26:34 +0100789 lyd_free_attr(iter->schema->module->ctx, NULL, iter->attr, 1);
790 free(iter);
791 goto error;
792 }
793 free(iter);
794 }
795
796 return 0;
797
798error:
799
800 while (attrs) {
801 iter = attrs;
802 attrs = attrs->next;
803
804 lyd_free_attr(ctx, NULL, iter->attr, 1);
805 free(iter);
806 }
807
808 return -1;
809}
810
Radek Krejci88f29302015-10-30 15:42:33 +0100811static unsigned int
Michal Vasko36ef6932015-12-01 14:30:17 +0100812json_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 +0200813 struct lyd_node *first_sibling, struct lyd_node *prev, struct attr_cont **attrs, int options,
Michal Vaskoafa7a642016-10-18 15:11:38 +0200814 struct unres_data *unres, struct lyd_node **act_notif)
Radek Krejci5449d472015-10-26 14:35:56 +0100815{
816 unsigned int len = 0;
817 unsigned int r;
Radek Krejcic4831272015-11-01 19:26:34 +0100818 unsigned int flag_leaflist = 0;
Radek Krejci61767ca2016-09-19 14:21:55 +0200819 int i, pos;
Radek Krejci88f29302015-10-30 15:42:33 +0100820 char *name, *prefix = NULL, *str = NULL;
Michal Vasko1e62a092015-12-01 12:27:20 +0100821 const struct lys_module *module = NULL;
Radek Krejci5449d472015-10-26 14:35:56 +0100822 struct lys_node *schema = NULL;
Radek Krejcibd930122016-08-10 13:28:26 +0200823 struct lyd_node *result = NULL, *new, *list, *diter = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100824 struct lyd_attr *attr;
Radek Krejcic4831272015-11-01 19:26:34 +0100825 struct attr_cont *attrs_aux;
Radek Krejci5449d472015-10-26 14:35:56 +0100826
827 /* each YANG data node representation starts with string (node identifier) */
828 if (data[len] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100829 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent),
Radek Krejciadb57612016-02-16 13:34:34 +0100830 "JSON data (missing quotation-mark at the beginning of string)");
Radek Krejci88f29302015-10-30 15:42:33 +0100831 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100832 }
833 len++;
834
Radek Krejci23238922015-10-27 17:13:34 +0100835 str = lyjson_parse_text(&data[len], &r);
Radek Krejci5449d472015-10-26 14:35:56 +0100836 if (!r) {
837 goto error;
838 } else if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100839 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent),
Radek Krejciadb57612016-02-16 13:34:34 +0100840 "JSON data (missing quotation-mark at the end of string)");
Radek Krejci5449d472015-10-26 14:35:56 +0100841 goto error;
842 }
Radek Krejci23238922015-10-27 17:13:34 +0100843 if ((name = strchr(str, ':'))) {
844 *name = '\0';
845 name++;
846 prefix = str;
Radek Krejci88f29302015-10-30 15:42:33 +0100847 if (prefix[0] == '@') {
848 prefix++;
849 }
Radek Krejci23238922015-10-27 17:13:34 +0100850 } else {
851 name = str;
Radek Krejci88f29302015-10-30 15:42:33 +0100852 if (name[0] == '@') {
853 name++;
854 }
Radek Krejci5449d472015-10-26 14:35:56 +0100855 }
856
Radek Krejci5449d472015-10-26 14:35:56 +0100857 /* prepare data for parsing node content */
858 len += r + 1;
859 len += skip_ws(&data[len]);
860 if (data[len] != ':') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100861 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "JSON data (missing name-separator)");
Radek Krejci5449d472015-10-26 14:35:56 +0100862 goto error;
863 }
864 len++;
865 len += skip_ws(&data[len]);
866
Radek Krejci88f29302015-10-30 15:42:33 +0100867 if (str[0] == '@' && !str[1]) {
868 /* process attribute of the parent object (container or list) */
Radek Krejci2a0efef2016-03-24 15:10:40 +0100869 if (!(*parent)) {
870 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "attribute with no corresponding element to belongs to");
Radek Krejci88f29302015-10-30 15:42:33 +0100871 goto error;
872 }
873
Radek Krejci532e5e92017-02-22 12:59:24 +0100874 r = json_parse_attr((*parent)->schema->module, &attr, &data[len], options);
Radek Krejci88f29302015-10-30 15:42:33 +0100875 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100876 LOGPATH(LY_VLOG_LYD, (*parent));
Radek Krejci88f29302015-10-30 15:42:33 +0100877 goto error;
878 }
879 len += r;
880
881 if ((*parent)->attr) {
882 lyd_free_attr(ctx, NULL, attr, 1);
883 } else {
884 (*parent)->attr = attr;
Radek Krejci532e5e92017-02-22 12:59:24 +0100885 for (; attr; attr = attr->next) {
886 attr->parent = *parent;
887 }
Radek Krejci88f29302015-10-30 15:42:33 +0100888 }
Radek Krejcic4831272015-11-01 19:26:34 +0100889 free(str);
890 return len;
Radek Krejci88f29302015-10-30 15:42:33 +0100891 }
892
Radek Krejci5449d472015-10-26 14:35:56 +0100893 /* find schema node */
894 if (!(*parent)) {
895 /* starting in root */
896 /* get the proper schema */
897 module = ly_ctx_get_module(ctx, prefix, NULL);
Michal Vaskof53187d2017-01-13 13:23:14 +0100898 if (ctx->data_clb) {
899 if (!module) {
900 module = ctx->data_clb(ctx, prefix, NULL, 0, ctx->data_clb_data);
901 } else if (!module->implemented) {
902 module = ctx->data_clb(ctx, module->name, module->ns, LY_MODCLB_NOT_IMPLEMENTED, ctx->data_clb_data);
903 }
904 }
905 if (module && module->implemented) {
Radek Krejci5449d472015-10-26 14:35:56 +0100906 /* get the proper schema node */
Radek Krejci919a9242016-07-27 08:17:13 +0200907 while ((schema = (struct lys_node *)lys_getnext(schema, NULL, module, 0))) {
Radek Krejci5449d472015-10-26 14:35:56 +0100908 if (!strcmp(schema->name, name)) {
909 break;
910 }
911 }
912 }
913 } else {
Radek Krejci5449d472015-10-26 14:35:56 +0100914 if (prefix) {
Michal Vaskof53187d2017-01-13 13:23:14 +0100915 /* get the proper module to give the chance to load/implement it */
Radek Krejci5449d472015-10-26 14:35:56 +0100916 module = ly_ctx_get_module(ctx, prefix, NULL);
Michal Vaskof53187d2017-01-13 13:23:14 +0100917 if (ctx->data_clb) {
918 if (!module) {
Michal Vaskoad43c182017-01-23 09:55:28 +0100919 ctx->data_clb(ctx, prefix, NULL, 0, ctx->data_clb_data);
Michal Vaskof53187d2017-01-13 13:23:14 +0100920 } else if (!module->implemented) {
Michal Vaskoad43c182017-01-23 09:55:28 +0100921 ctx->data_clb(ctx, module->name, module->ns, LY_MODCLB_NOT_IMPLEMENTED, ctx->data_clb_data);
Michal Vaskof53187d2017-01-13 13:23:14 +0100922 }
Radek Krejci5449d472015-10-26 14:35:56 +0100923 }
924 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100925
926 /* go through RPC's input/output following the options' data type */
927 if ((*parent)->schema->nodetype == LYS_RPC) {
Michal Vaskof53187d2017-01-13 13:23:14 +0100928 while ((schema = (struct lys_node *)lys_getnext(schema, (*parent)->schema, NULL, LYS_GETNEXT_WITHINOUT))) {
Michal Vaskoafa7a642016-10-18 15:11:38 +0200929 if ((options & LYD_OPT_RPC) && (schema->nodetype == LYS_INPUT)) {
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100930 break;
Michal Vaskoafa7a642016-10-18 15:11:38 +0200931 } else if ((options & LYD_OPT_RPCREPLY) && (schema->nodetype == LYS_OUTPUT)) {
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100932 break;
933 }
934 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100935 schema_parent = schema;
936 schema = NULL;
937 }
938
Michal Vasko36ef6932015-12-01 14:30:17 +0100939 if (schema_parent) {
Michal Vaskof53187d2017-01-13 13:23:14 +0100940 while ((schema = (struct lys_node *)lys_getnext(schema, schema_parent, NULL, 0))) {
941 if (!strcmp(schema->name, name)
942 && ((prefix && !strcmp(lys_node_module(schema)->name, prefix))
943 || (!prefix && (lys_node_module(schema) == lys_node_module(schema_parent))))) {
Michal Vasko36ef6932015-12-01 14:30:17 +0100944 break;
945 }
946 }
947 } else {
Michal Vaskof53187d2017-01-13 13:23:14 +0100948 while ((schema = (struct lys_node *)lys_getnext(schema, (*parent)->schema, NULL, 0))) {
949 if (!strcmp(schema->name, name)
950 && ((prefix && !strcmp(lys_node_module(schema)->name, prefix))
951 || (!prefix && (lys_node_module(schema) == lyd_node_module(*parent))))) {
Michal Vasko36ef6932015-12-01 14:30:17 +0100952 break;
953 }
Radek Krejci5449d472015-10-26 14:35:56 +0100954 }
955 }
956 }
Michal Vaskof53187d2017-01-13 13:23:14 +0100957
958 module = lys_node_module(schema);
959 if (!module || !module->implemented || module->disabled) {
960 LOGVAL(LYE_INELEM, (*parent ? LY_VLOG_LYD : LY_VLOG_NONE), (*parent), name);
Radek Krejci88f29302015-10-30 15:42:33 +0100961 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100962 }
Radek Krejci88f29302015-10-30 15:42:33 +0100963
964 if (str[0] == '@') {
Radek Krejci88f29302015-10-30 15:42:33 +0100965 /* attribute for some sibling node */
966 if (data[len] == '[') {
967 flag_leaflist = 1;
968 len++;
969 len += skip_ws(&data[len]);
970 }
971
972attr_repeat:
Radek Krejci532e5e92017-02-22 12:59:24 +0100973 r = json_parse_attr((struct lys_module *)module, &attr, &data[len], options);
Radek Krejci88f29302015-10-30 15:42:33 +0100974 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100975 LOGPATH(LY_VLOG_LYD, (*parent));
Radek Krejci88f29302015-10-30 15:42:33 +0100976 goto error;
977 }
978 len += r;
979
980 if (attr) {
Radek Krejcic4831272015-11-01 19:26:34 +0100981 attrs_aux = malloc(sizeof *attrs_aux);
Michal Vasko253035f2015-12-17 16:58:13 +0100982 if (!attrs_aux) {
983 LOGMEM;
984 goto error;
985 }
Radek Krejcic4831272015-11-01 19:26:34 +0100986 attrs_aux->attr = attr;
987 attrs_aux->index = flag_leaflist;
988 attrs_aux->schema = schema;
989 attrs_aux->next = *attrs;
990 *attrs = attrs_aux;
Radek Krejci88f29302015-10-30 15:42:33 +0100991 } else if (!flag_leaflist) {
992 /* error */
Radek Krejci48464ed2016-03-17 15:44:09 +0100993 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "attribute data");
Radek Krejci88f29302015-10-30 15:42:33 +0100994 goto error;
995 }
996
997 if (flag_leaflist) {
998 if (data[len] == ',') {
999 len++;
1000 len += skip_ws(&data[len]);
1001 flag_leaflist++;
1002 goto attr_repeat;
1003 } else if (data[len] != ']') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001004 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "JSON data (missing end-array)");
Radek Krejci88f29302015-10-30 15:42:33 +01001005 goto error;
1006 }
1007 len++;
1008 len += skip_ws(&data[len]);
1009 }
1010
Radek Krejcic4831272015-11-01 19:26:34 +01001011 free(str);
1012 return len;
Radek Krejci88f29302015-10-30 15:42:33 +01001013 }
1014
Radek Krejci5449d472015-10-26 14:35:56 +01001015 switch (schema->nodetype) {
1016 case LYS_CONTAINER:
1017 case LYS_LIST:
1018 case LYS_NOTIF:
1019 case LYS_RPC:
Michal Vaskoafa7a642016-10-18 15:11:38 +02001020 case LYS_ACTION:
Radek Krejci5449d472015-10-26 14:35:56 +01001021 result = calloc(1, sizeof *result);
1022 break;
1023 case LYS_LEAF:
1024 case LYS_LEAFLIST:
1025 result = calloc(1, sizeof(struct lyd_node_leaf_list));
1026 break;
1027 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +02001028 case LYS_ANYDATA:
1029 result = calloc(1, sizeof(struct lyd_node_anydata));
Radek Krejci5449d472015-10-26 14:35:56 +01001030 break;
1031 default:
1032 LOGINT;
Radek Krejci595060f2015-10-30 16:29:58 +01001033 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +01001034 }
Michal Vasko253035f2015-12-17 16:58:13 +01001035 if (!result) {
1036 LOGMEM;
1037 goto error;
1038 }
1039
Radek Krejci61767ca2016-09-19 14:21:55 +02001040 result->prev = result;
Radek Krejci5449d472015-10-26 14:35:56 +01001041 result->schema = schema;
Radek Krejci61767ca2016-09-19 14:21:55 +02001042 result->parent = *parent;
1043 diter = NULL;
1044 if (*parent && (*parent)->child && schema->nodetype == LYS_LEAF && (*parent)->schema->nodetype == LYS_LIST &&
1045 (pos = lys_is_key((struct lys_node_list *)(*parent)->schema, (struct lys_node_leaf *)schema))) {
1046 /* it is key and we need to insert it into a correct place */
1047 for (i = 0, diter = (*parent)->child;
1048 diter && i < (pos - 1) && diter->schema->nodetype == LYS_LEAF &&
1049 lys_is_key((struct lys_node_list *)(*parent)->schema, (struct lys_node_leaf *)diter->schema);
1050 i++, diter = diter->next);
1051 if (diter) {
1052 /* out of order insertion - insert list's key to the correct position, before the diter */
1053 if ((*parent)->child == diter) {
1054 (*parent)->child = result;
1055 /* update first_sibling */
1056 first_sibling = result;
1057 }
1058 if (diter->prev->next) {
1059 diter->prev->next = result;
1060 }
1061 result->prev = diter->prev;
1062 diter->prev = result;
1063 result->next = diter;
1064 }
1065 }
1066 if (!diter) {
1067 /* simplified (faster) insert as the last node */
1068 if (*parent && !(*parent)->child) {
1069 (*parent)->child = result;
1070 }
1071 if (prev) {
1072 result->prev = prev;
1073 prev->next = result;
1074
1075 /* fix the "last" pointer */
1076 first_sibling->prev = result;
1077 } else {
1078 result->prev = result;
1079 first_sibling = result;
1080 }
1081 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001082 result->validity = ly_new_node_validity(result->schema);
Radek Krejci46165822016-08-26 14:06:27 +02001083 if (resolve_applies_when(schema, 0, NULL)) {
Radek Krejci0b7704f2016-03-18 12:16:14 +01001084 result->when_status = LYD_WHEN;
1085 }
Radek Krejci5449d472015-10-26 14:35:56 +01001086
Radek Krejci5449d472015-10-26 14:35:56 +01001087 /* type specific processing */
1088 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
1089 /* type detection and assigning the value */
Radek Krejci45f41dd2017-02-09 14:11:09 +01001090 r = json_get_value((struct lyd_node_leaf_list *)result, &first_sibling, &data[len], options, unres);
Radek Krejci5449d472015-10-26 14:35:56 +01001091 if (!r) {
1092 goto error;
1093 }
Radek Krejci88f29302015-10-30 15:42:33 +01001094 while(result->next) {
1095 result = result->next;
1096 }
1097
Radek Krejci5449d472015-10-26 14:35:56 +01001098 len += r;
1099 len += skip_ws(&data[len]);
Radek Krejcibf2abff2016-08-23 15:51:52 +02001100 } else if (schema->nodetype & LYS_ANYDATA) {
Radek Krejci4ae82942016-09-19 16:41:06 +02001101 r = json_get_anydata((struct lyd_node_anydata *)result, &data[len]);
Radek Krejci5449d472015-10-26 14:35:56 +01001102 if (!r) {
1103 goto error;
1104 }
1105 len += r;
1106 len += skip_ws(&data[len]);
Michal Vaskoafa7a642016-10-18 15:11:38 +02001107 } else if (schema->nodetype & (LYS_CONTAINER | LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1108 if (schema->nodetype & (LYS_RPC | LYS_ACTION)) {
1109 if (!(options & LYD_OPT_RPC) || *act_notif) {
1110 LOGVAL(LYE_INELEM, LY_VLOG_LYD, result, schema->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01001111 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Unexpected %s node \"%s\".",
Michal Vaskoafa7a642016-10-18 15:11:38 +02001112 (schema->nodetype == LYS_RPC ? "rpc" : "action"), schema->name);
1113 goto error;
1114 }
1115 *act_notif = result;
1116 } else if (schema->nodetype == LYS_NOTIF) {
1117 if (!(options & LYD_OPT_NOTIF) || *act_notif) {
1118 LOGVAL(LYE_INELEM, LY_VLOG_LYD, result, schema->name);
Michal Vasko51e5c582017-01-19 14:16:39 +01001119 LOGVAL(LYE_SPEC, LY_VLOG_PREV, NULL, "Unexpected notification node \"%s\".", schema->name);
Michal Vaskoafa7a642016-10-18 15:11:38 +02001120 goto error;
1121 }
1122 *act_notif = result;
1123 }
1124
Radek Krejci5449d472015-10-26 14:35:56 +01001125 if (data[len] != '{') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001126 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing begin-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001127 goto error;
1128 }
1129 len++;
1130 len += skip_ws(&data[len]);
1131
1132 if (data[len] != '}') {
1133 /* non-empty container */
Radek Krejcic4831272015-11-01 19:26:34 +01001134 len--;
1135 diter = NULL;
1136 attrs_aux = NULL;
1137 do {
1138 len++;
1139 len += skip_ws(&data[len]);
1140
Michal Vaskoafa7a642016-10-18 15:11:38 +02001141 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 +01001142 if (!r) {
1143 goto error;
1144 }
1145 len += r;
1146
1147 if (result->child) {
1148 diter = result->child->prev;
1149 }
1150 } while(data[len] == ',');
1151
1152 /* store attributes */
1153 if (store_attrs(ctx, attrs_aux, result->child)) {
Radek Krejci5449d472015-10-26 14:35:56 +01001154 goto error;
1155 }
Radek Krejci5449d472015-10-26 14:35:56 +01001156 }
1157
1158 if (data[len] != '}') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001159 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing end-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001160 goto error;
1161 }
1162 len++;
1163 len += skip_ws(&data[len]);
1164
Radek Krejcifb7156e2016-10-27 13:39:56 +02001165 /* if we have empty non-presence container, mark it as default */
Radek Krejci2537fd32016-09-07 16:22:41 +02001166 if (schema->nodetype == LYS_CONTAINER && !result->child &&
Radek Krejcid3e73722016-05-23 12:24:55 +02001167 !result->attr && !((struct lys_node_container *)schema)->presence) {
Radek Krejcifb7156e2016-10-27 13:39:56 +02001168 result->dflt = 1;
Radek Krejci0c0086a2016-03-24 15:20:28 +01001169 }
1170
Radek Krejci5449d472015-10-26 14:35:56 +01001171 } else if (schema->nodetype == LYS_LIST) {
1172 if (data[len] != '[') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001173 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing begin-array)");
Radek Krejci5449d472015-10-26 14:35:56 +01001174 goto error;
1175 }
1176
1177 list = result;
1178 do {
1179 len++;
1180 len += skip_ws(&data[len]);
Radek Krejci23238922015-10-27 17:13:34 +01001181
Radek Krejcic4831272015-11-01 19:26:34 +01001182 if (data[len] != '{') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001183 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result,
Radek Krejciadb57612016-02-16 13:34:34 +01001184 "JSON data (missing list instance's begin-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001185 goto error;
1186 }
Radek Krejcic4831272015-11-01 19:26:34 +01001187 diter = NULL;
1188 attrs_aux = NULL;
1189 do {
1190 len++;
1191 len += skip_ws(&data[len]);
1192
Michal Vaskoafa7a642016-10-18 15:11:38 +02001193 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 +01001194 if (!r) {
1195 goto error;
1196 }
1197 len += r;
1198
Radek Krejci52934692015-11-01 20:08:15 +01001199 if (list->child) {
Radek Krejcic4831272015-11-01 19:26:34 +01001200 diter = list->child->prev;
1201 }
1202 } while(data[len] == ',');
1203
1204 /* store attributes */
Radek Krejci52934692015-11-01 20:08:15 +01001205 if (store_attrs(ctx, attrs_aux, list->child)) {
Radek Krejcic4831272015-11-01 19:26:34 +01001206 goto error;
1207 }
1208
1209 if (data[len] != '}') {
1210 /* expecting end-object */
Radek Krejci48464ed2016-03-17 15:44:09 +01001211 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result,
Radek Krejciadb57612016-02-16 13:34:34 +01001212 "JSON data (missing list instance's end-object)");
Radek Krejcic4831272015-11-01 19:26:34 +01001213 goto error;
1214 }
1215 len++;
Radek Krejci5449d472015-10-26 14:35:56 +01001216 len += skip_ws(&data[len]);
1217
1218 if (data[len] == ',') {
Radek Krejci93fab982016-02-03 15:58:19 +01001219 /* various validation checks */
Radek Krejci45f41dd2017-02-09 14:11:09 +01001220 if (lyv_data_context(list, options, unres)) {
1221 goto error;
1222 }
1223
Radek Krejci00a0e712016-10-26 10:24:46 +02001224 ly_err_clean(1);
Michal Vaskoad2e44a2017-01-03 10:31:35 +01001225 if (lyv_data_content(list, options, unres) ||
1226 lyv_multicases(list, NULL, prev ? &first_sibling : NULL, 0, NULL)) {
Radek Krejci93fab982016-02-03 15:58:19 +01001227 if (ly_errno) {
1228 goto error;
1229 }
1230 }
Radek Krejci93fab982016-02-03 15:58:19 +01001231
Radek Krejci5449d472015-10-26 14:35:56 +01001232 /* another instance of the list */
1233 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001234 if (!new) {
1235 goto error;
1236 }
Radek Krejci5449d472015-10-26 14:35:56 +01001237 new->parent = list->parent;
1238 new->prev = list;
1239 list->next = new;
1240
Radek Krejcie1794882017-02-08 13:23:38 +01001241 /* copy the validity and when flags */
1242 new->validity = list->validity;
1243 new->when_status = list->when_status;
1244
Radek Krejci5449d472015-10-26 14:35:56 +01001245 /* fix the "last" pointer */
Radek Krejci2d5525d2016-04-04 15:43:30 +02001246 first_sibling->prev = new;
Radek Krejci5449d472015-10-26 14:35:56 +01001247
1248 new->schema = list->schema;
Radek Krejci5449d472015-10-26 14:35:56 +01001249 list = new;
1250 }
1251 } while (data[len] == ',');
Radek Krejcib915fb92017-02-08 14:12:40 +01001252 result = list;
Radek Krejci5449d472015-10-26 14:35:56 +01001253
1254 if (data[len] != ']') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001255 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing end-array)");
Radek Krejci5449d472015-10-26 14:35:56 +01001256 goto error;
1257 }
1258 len++;
1259 len += skip_ws(&data[len]);
1260 }
1261
1262 /* various validation checks */
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001263 if (lyv_data_context(result, options, unres)) {
Michal Vasko10e586f2016-05-18 13:25:30 +02001264 goto error;
1265 }
1266
Radek Krejci00a0e712016-10-26 10:24:46 +02001267 ly_err_clean(1);
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001268 if (lyv_data_content(result, options, unres) ||
1269 lyv_multicases(result, NULL, prev ? &first_sibling : NULL, 0, NULL)) {
Radek Krejci5449d472015-10-26 14:35:56 +01001270 if (ly_errno) {
1271 goto error;
1272 }
1273 }
1274
Radek Krejcica7efb72016-01-18 13:06:01 +01001275 /* validation successful */
Radek Krejci63b79c82016-08-10 10:09:33 +02001276 if (result->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001277 /* postpone checking of unique when there will be all list/leaflist instances */
1278 result->validity |= LYD_VAL_UNIQUE;
Radek Krejci63b79c82016-08-10 10:09:33 +02001279 }
Radek Krejcica7efb72016-01-18 13:06:01 +01001280
Radek Krejci88f29302015-10-30 15:42:33 +01001281 if (!(*parent)) {
1282 *parent = result;
1283 }
1284
Radek Krejcide9d92c2015-10-30 15:59:59 +01001285 free(str);
Radek Krejci5449d472015-10-26 14:35:56 +01001286 return len;
1287
1288error:
Radek Krejci0c0086a2016-03-24 15:20:28 +01001289 len = 0;
Radek Krejci0c0086a2016-03-24 15:20:28 +01001290 /* cleanup */
1291 for (i = unres->count - 1; i >= 0; i--) {
1292 /* remove unres items connected with the node being removed */
1293 if (unres->node[i] == result) {
1294 unres_data_del(unres, i);
1295 }
Radek Krejci88f29302015-10-30 15:42:33 +01001296 }
1297 while (*attrs) {
Radek Krejcic4831272015-11-01 19:26:34 +01001298 attrs_aux = *attrs;
Radek Krejci88f29302015-10-30 15:42:33 +01001299 *attrs = (*attrs)->next;
1300
Radek Krejcic4831272015-11-01 19:26:34 +01001301 lyd_free_attr(ctx, NULL, attrs_aux->attr, 1);
1302 free(attrs_aux);
Radek Krejci88f29302015-10-30 15:42:33 +01001303 }
1304
Radek Krejci5449d472015-10-26 14:35:56 +01001305 lyd_free(result);
Radek Krejci88f29302015-10-30 15:42:33 +01001306 free(str);
1307
Radek Krejci0c0086a2016-03-24 15:20:28 +01001308 return len;
Radek Krejci5449d472015-10-26 14:35:56 +01001309}
1310
1311struct lyd_node *
Michal Vasko945b96b2016-10-18 11:49:12 +02001312lyd_parse_json(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *rpc_act,
1313 const struct lyd_node *data_tree)
Radek Krejci5449d472015-10-26 14:35:56 +01001314{
Michal Vaskoafa7a642016-10-18 15:11:38 +02001315 struct lyd_node *result = NULL, *next, *iter, *reply_parent = NULL, *reply_top = NULL, *act_notif = NULL;
Radek Krejci5449d472015-10-26 14:35:56 +01001316 struct unres_data *unres = NULL;
Radek Krejcic4831272015-11-01 19:26:34 +01001317 unsigned int len = 0, r;
Michal Vaskoafa7a642016-10-18 15:11:38 +02001318 int i, act_cont = 0;
Radek Krejcic4831272015-11-01 19:26:34 +01001319 struct attr_cont *attrs = NULL;
Radek Krejci63b79c82016-08-10 10:09:33 +02001320 struct ly_set *set;
Radek Krejci5449d472015-10-26 14:35:56 +01001321
Radek Krejci00a0e712016-10-26 10:24:46 +02001322 ly_err_clean(1);
Radek Krejci2342cf62016-01-29 16:48:23 +01001323
Michal Vaskoafa7a642016-10-18 15:11:38 +02001324 if (!ctx || !data) {
Radek Krejci5449d472015-10-26 14:35:56 +01001325 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1326 return NULL;
1327 }
1328
Radek Krejcic4831272015-11-01 19:26:34 +01001329 /* skip leading whitespaces */
1330 len += skip_ws(&data[len]);
1331
Michal Vasko24d982f2016-04-18 15:13:58 +02001332 /* no data (or whitespaces only) are fine */
1333 if (!data[len]) {
1334 lyd_validate(&result, options, ctx);
1335 return result;
1336 }
1337
Radek Krejcic4831272015-11-01 19:26:34 +01001338 /* expect top-level { */
1339 if (data[len] != '{') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001340 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top level begin-object)");
Michal Vasko24d982f2016-04-18 15:13:58 +02001341 return NULL;
1342 }
1343
1344 unres = calloc(1, sizeof *unres);
1345 if (!unres) {
1346 LOGMEM;
1347 return NULL;
Radek Krejcic4831272015-11-01 19:26:34 +01001348 }
1349
Michal Vaskoafa7a642016-10-18 15:11:38 +02001350 /* create RPC/action reply part that is not in the parsed data */
1351 if (rpc_act) {
1352 assert(options & LYD_OPT_RPCREPLY);
1353 if (rpc_act->schema->nodetype == LYS_RPC) {
1354 /* RPC request */
1355 reply_top = reply_parent = _lyd_new(NULL, rpc_act->schema, 0);
1356 } else {
1357 /* action request */
1358 reply_top = lyd_dup(rpc_act, 1);
1359 LY_TREE_DFS_BEGIN(reply_top, iter, reply_parent) {
1360 if (reply_parent->schema->nodetype == LYS_ACTION) {
1361 break;
1362 }
1363 LY_TREE_DFS_END(reply_top, iter, reply_parent);
1364 }
1365 if (!reply_parent) {
1366 LOGERR(LY_EINVAL, "%s: invalid variable parameter (const struct lyd_node *rpc_act).", __func__);
1367 lyd_free_withsiblings(reply_top);
1368 goto error;
1369 }
1370 lyd_free_withsiblings(reply_parent->child);
1371 }
1372 }
1373
1374 iter = NULL;
1375 next = reply_parent;
Radek Krejcic4831272015-11-01 19:26:34 +01001376 do {
1377 len++;
1378 len += skip_ws(&data[len]);
1379
Michal Vaskoafa7a642016-10-18 15:11:38 +02001380 if (!act_cont) {
1381 if (!strncmp(&data[len], "\"yang:action\"", 13)) {
1382 len += 13;
1383 len += skip_ws(&data[len]);
1384 if (data[len] != ':') {
1385 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top-level begin-object)");
1386 lyd_free_withsiblings(reply_top);
1387 goto error;
1388 }
1389 ++len;
1390 len += skip_ws(&data[len]);
1391 if (data[len] != '{') {
1392 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top level yang:action object)");
1393 lyd_free_withsiblings(reply_top);
1394 goto error;
1395 }
1396 ++len;
1397 len += skip_ws(&data[len]);
1398
1399 act_cont = 1;
1400 } else {
1401 act_cont = -1;
1402 }
1403 }
1404
1405 r = json_parse_data(ctx, &data[len], NULL, &next, result, iter, &attrs, options, unres, &act_notif);
Radek Krejcic4831272015-11-01 19:26:34 +01001406 if (!r) {
Michal Vaskoafa7a642016-10-18 15:11:38 +02001407 lyd_free_withsiblings(reply_top);
Michal Vasko24d982f2016-04-18 15:13:58 +02001408 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001409 }
1410 len += r;
1411
1412 if (!result) {
Radek Krejciba024522017-02-20 10:59:58 +01001413 for (iter = next; iter && iter->prev->next; iter = iter->prev);
1414 result = iter;
Radek Krejcic4831272015-11-01 19:26:34 +01001415 }
1416 if (next) {
1417 iter = next;
1418 }
1419 next = NULL;
Michal Vaskoafa7a642016-10-18 15:11:38 +02001420 } while (data[len] == ',');
Radek Krejcic4831272015-11-01 19:26:34 +01001421
1422 if (data[len] != '}') {
1423 /* expecting end-object */
Radek Krejci48464ed2016-03-17 15:44:09 +01001424 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top-level end-object)");
Michal Vasko24d982f2016-04-18 15:13:58 +02001425 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001426 }
1427 len++;
1428 len += skip_ws(&data[len]);
1429
Michal Vaskoafa7a642016-10-18 15:11:38 +02001430 if (act_cont == 1) {
1431 if (data[len] != '}') {
1432 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top-level end-object)");
1433 goto error;
1434 }
1435 len++;
1436 len += skip_ws(&data[len]);
1437 }
1438
Radek Krejcic4831272015-11-01 19:26:34 +01001439 /* store attributes */
1440 if (store_attrs(ctx, attrs, result)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001441 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001442 }
Radek Krejci5449d472015-10-26 14:35:56 +01001443
Michal Vaskoafa7a642016-10-18 15:11:38 +02001444 if (reply_top) {
1445 result = reply_top;
1446 }
1447
Michal Vaskoc1cf86f2015-11-04 09:54:51 +01001448 if (!result) {
1449 LOGERR(LY_EVALID, "Model for the data to be linked with not found.");
Michal Vasko24d982f2016-04-18 15:13:58 +02001450 goto error;
Michal Vaskoc1cf86f2015-11-04 09:54:51 +01001451 }
1452
Michal Vaskoafa7a642016-10-18 15:11:38 +02001453 if ((options & LYD_OPT_RPCREPLY) && (rpc_act->schema->nodetype != LYS_RPC)) {
1454 /* action reply */
1455 act_notif = reply_parent;
1456 } else if ((options & (LYD_OPT_RPC | LYD_OPT_NOTIF)) && !act_notif) {
1457 ly_vecode = LYVE_INELEM;
1458 LOGVAL(LYE_SPEC, LY_VLOG_LYD, result, "Missing %s node.", (options & LYD_OPT_RPC ? "action" : "notification"));
1459 goto error;
1460 }
1461
Radek Krejci63b79c82016-08-10 10:09:33 +02001462 /* check for uniquness of top-level lists/leaflists because
1463 * only the inner instances were tested in lyv_data_content() */
1464 set = ly_set_new();
1465 LY_TREE_FOR(result, iter) {
1466 if (!(iter->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(iter->validity & LYD_VAL_UNIQUE)) {
1467 continue;
1468 }
1469
1470 /* check each list/leaflist only once */
1471 i = set->number;
1472 if (ly_set_add(set, iter->schema, 0) != i) {
1473 /* already checked */
1474 continue;
1475 }
1476
1477 if (lyv_data_unique(iter, result)) {
1478 ly_set_free(set);
1479 goto error;
1480 }
1481 }
1482 ly_set_free(set);
1483
Radek Krejci46165822016-08-26 14:06:27 +02001484 /* add/validate default values, unres */
Michal Vaskoafa7a642016-10-18 15:11:38 +02001485 if (lyd_defaults_add_unres(&result, options, ctx, data_tree, act_notif, unres)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001486 goto error;
Radek Krejci5c162452016-03-23 13:36:01 +01001487 }
1488
Radek Krejci46165822016-08-26 14:06:27 +02001489 /* check for missing top level mandatory nodes */
Michal Vaskoad2e44a2017-01-03 10:31:35 +01001490 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER))
1491 && lyd_check_mandatory_tree((act_notif ? act_notif : result), ctx, options)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001492 goto error;
Radek Krejci5c162452016-03-23 13:36:01 +01001493 }
1494
Radek Krejci5449d472015-10-26 14:35:56 +01001495 free(unres->node);
1496 free(unres->type);
Radek Krejci5449d472015-10-26 14:35:56 +01001497 free(unres);
1498
1499 return result;
Michal Vasko24d982f2016-04-18 15:13:58 +02001500
1501error:
1502 lyd_free_withsiblings(result);
1503 free(unres->node);
1504 free(unres->type);
1505 free(unres);
1506
1507 return NULL;
Radek Krejci5449d472015-10-26 14:35:56 +01001508}