blob: a5204d007ee1b16d2c440d2977c8637dd5b963ad [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 */
165 buf[o] = data[*len];
Radek Krejci5449d472015-10-26 14:35:56 +0100166 (*len)++;
167 }
168 }
169
170#undef BUFSIZE
171
172 if (o) {
173 if (result) {
174 size = size + o;
Michal Vasko253035f2015-12-17 16:58:13 +0100175 aux = ly_realloc(result, size + 1);
176 if (!aux) {
177 LOGMEM;
178 return NULL;
179 }
Radek Krejci5449d472015-10-26 14:35:56 +0100180 result = aux;
181 } else {
182 size = o;
183 result = malloc((size + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +0100184 if (!result) {
185 LOGMEM;
186 return NULL;
187 }
Radek Krejci5449d472015-10-26 14:35:56 +0100188 }
189 memcpy(&result[size - o], buf, o);
190 }
191 if (result) {
192 result[size] = '\0';
193 } else {
194 size = 0;
195 result = strdup("");
196 }
197
198 return result;
199
200error:
201 free(result);
202 return NULL;
203}
204
205static unsigned int
206lyjson_parse_number(const char *data)
207{
Michal Vasko8f32c112016-05-18 13:22:59 +0200208 unsigned int len = 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100209
Michal Vasko8f32c112016-05-18 13:22:59 +0200210 if (data[len] == '-') {
211 ++len;
212 }
Radek Krejci5449d472015-10-26 14:35:56 +0100213
Michal Vasko8f32c112016-05-18 13:22:59 +0200214 if (data[len] == '0') {
215 ++len;
216 } else if (isdigit(data[len])) {
217 ++len;
218 while (isdigit(data[len])) {
219 ++len;
220 }
221 } else {
222 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value ('%c').", data[len]);
223 return 0;
224 }
225
226 if (data[len] == '.') {
227 ++len;
228 if (!isdigit(data[len])) {
229 if (data[len]) {
230 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value ('%c').", data[len]);
231 } else {
232 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value (EOF).");
Radek Krejci5449d472015-10-26 14:35:56 +0100233 }
Radek Krejci5449d472015-10-26 14:35:56 +0100234 return 0;
235 }
Michal Vasko8f32c112016-05-18 13:22:59 +0200236 while (isdigit(data[len])) {
237 ++len;
238 }
239 }
240
Michal Vasko1e676ca2016-06-24 15:23:54 +0200241 if ((data[len] == 'e') || (data[len] == 'E')) {
242 ++len;
243 if ((data[len] == '+') || (data[len] == '-')) {
244 ++len;
245 }
246 while (isdigit(data[len])) {
247 ++len;
248 }
249 }
250
Michal Vasko8f32c112016-05-18 13:22:59 +0200251 if (data[len] && (data[len] != ',') && (data[len] != ']') && (data[len] != '}') && !lyjson_isspace(data[len])) {
252 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value ('%c').", data[len]);
253 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100254 }
255
256 return len;
257}
258
Michal Vasko1e676ca2016-06-24 15:23:54 +0200259static char *
260lyjson_convert_enumber(const char *number, unsigned int num_len, char *e_ptr)
261{
262 char *ptr, *num;
263 const char *number_ptr;
264 long int e_val;
265 int dot_pos, chars_to_dot, minus;
266 unsigned int num_len_no_e;
267
268 if (*number == '-') {
269 minus = 1;
270 ++number;
271 --num_len;
272 } else {
273 minus = 0;
274 }
275
276 num_len_no_e = e_ptr - number;
277
278 errno = 0;
279 ++e_ptr;
280 e_val = strtol(e_ptr, &ptr, 10);
281 if (errno) {
282 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Exponent out-of-bounds in a JSON Number value (%.*s).",
283 num_len - (e_ptr - number), e_ptr);
284 return NULL;
285 } else if (ptr != number + num_len) {
286 /* we checked this already */
287 LOGINT;
288 return NULL;
289 }
290
291 if ((ptr = strnchr(number, '.', num_len_no_e))) {
292 dot_pos = ptr - number;
293 } else {
294 dot_pos = num_len_no_e;
295 }
296
297 dot_pos += e_val;
298
299 /* allocate enough memory */
300 if (dot_pos < 1) {
301 /* (.XXX)XXX[.]XXXX */
302 num = malloc((minus ? 1 : 0) + -dot_pos + 2 + (num_len_no_e - (ptr ? 1 : 0)) + 1);
303 } else if (dot_pos < (signed)num_len_no_e) {
304 /* XXXX(.)XX.XXX */
305 num = malloc((minus ? 1 : 0) + num_len_no_e + (ptr ? 0 : 1) + 1);
306 } else {
307 /* XXX[.]XXXX(XXX.) */
308 num = malloc((minus ? 1 : 0) + (dot_pos - (ptr ? 2 : 1)) + 1);
309 }
310
311 if (!num) {
312 LOGMEM;
313 return NULL;
314 }
315 if (minus) {
316 strcpy(num, "-");
317 } else {
318 num[0] = '\0';
319 }
320
321 if (dot_pos < 1) {
322 strcat(num, "0.");
323 }
324 if (dot_pos < 0) {
325 sprintf(num + strlen(num), "%0*d", -dot_pos, 0);
326 }
327
328 chars_to_dot = dot_pos;
329 for (ptr = num + strlen(num), number_ptr = number; number_ptr - number < num_len_no_e; ) {
330 if (!chars_to_dot) {
331 *ptr = '.';
332 ++ptr;
333 chars_to_dot = -1;
334 } else if (isdigit(*number_ptr)) {
335 *ptr = *number_ptr;
336 ++ptr;
337 ++number_ptr;
338 if (chars_to_dot > 0) {
339 --chars_to_dot;
340 }
341 } else if (*number_ptr == '.') {
342 ++number_ptr;
343 } else {
344 LOGINT;
345 free(num);
346 return NULL;
347 }
348 }
349 *ptr = '\0';
350
351 if (dot_pos > (signed)num_len_no_e) {
352 sprintf(num + strlen(num), "%0*d", dot_pos - num_len_no_e, 0);
353 }
354
355 return num;
356}
357
Radek Krejci5449d472015-10-26 14:35:56 +0100358static unsigned int
359lyjson_parse_boolean(const char *data)
360{
Radek Krejci6b47b502015-10-30 15:52:41 +0100361 unsigned int len = 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100362
363 if (!strncmp(data, "false", 5)) {
364 len = 5;
365 } else if (!strncmp(data, "true", 4)) {
366 len = 4;
367 }
368
369 if (data[len] && data[len] != ',' && data[len] != ']' && data[len] != '}' && !lyjson_isspace(data[len])) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100370 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON literal value (expected true or false)");
Radek Krejci5449d472015-10-26 14:35:56 +0100371 return 0;
372 }
373
374 return len;
375}
376
377static unsigned int
Radek Krejci4ae82942016-09-19 16:41:06 +0200378json_get_anydata(struct lyd_node_anydata *any, const char *data)
Radek Krejci5449d472015-10-26 14:35:56 +0100379{
Radek Krejci4ae82942016-09-19 16:41:06 +0200380 unsigned int len = 0, start, stop, c;
Radek Krejci5449d472015-10-26 14:35:56 +0100381
Radek Krejci4ae82942016-09-19 16:41:06 +0200382 /* anydata (as well as meaningful anyxml) is supposed to be encoded as object */
383 if (data[len] != '{') {
384 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, any, "Anydata/anyxml content (not an object)");
Michal Vaskoa19f7d72016-05-18 13:24:08 +0200385 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100386 }
387
Radek Krejci4ae82942016-09-19 16:41:06 +0200388 /* count opening '{' and closing '}' to get the end of the object without its parsing */
389 c = 1;
390 len++;
391 len += skip_ws(&data[len]);
392 start = stop = len;
393 while (data[len] && c) {
394 switch (data[len]) {
395 case '{':
396 c++;
397 break;
398 case '}':
399 c--;
400 break;
401 default:
402 if (!isspace(data[len])) {
403 stop = len;
404 }
405 }
406 len++;
407 }
408 if (c) {
409 LOGVAL(LYE_EOF, LY_VLOG_LYD, any);
410 return 0;
411 }
412 any->value_type = LYD_ANYDATA_JSON;
413 any->value.str = lydict_insert(any->schema->module->ctx, &data[start], stop - start + 1);
414
Michal Vaskoa19f7d72016-05-18 13:24:08 +0200415 len += skip_ws(&data[len]);
416 return len;
Radek Krejci5449d472015-10-26 14:35:56 +0100417}
418
419static unsigned int
Radek Krejcibd930122016-08-10 13:28:26 +0200420json_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 +0100421{
Radek Krejcibd930122016-08-10 13:28:26 +0200422 struct lyd_node_leaf_list *new;
Radek Krejci37b756f2016-01-18 10:15:03 +0100423 struct lys_type *stype;
Radek Krejci5449d472015-10-26 14:35:56 +0100424 struct ly_ctx *ctx;
425 unsigned int len = 0, r;
Radek Krejci37b756f2016-01-18 10:15:03 +0100426 int resolve;
Radek Krejci5449d472015-10-26 14:35:56 +0100427 char *str;
428
Radek Krejci0b7704f2016-03-18 12:16:14 +0100429 assert(leaf && data);
Radek Krejci5449d472015-10-26 14:35:56 +0100430 ctx = leaf->schema->module->ctx;
431
Radek Krejci92ece002016-04-04 15:45:05 +0200432 if (options & (LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG)) {
Radek Krejci23238922015-10-27 17:13:34 +0100433 resolve = 0;
434 } else {
435 resolve = 1;
436 }
437
Radek Krejci5449d472015-10-26 14:35:56 +0100438 stype = &((struct lys_node_leaf *)leaf->schema)->type;
Radek Krejci23238922015-10-27 17:13:34 +0100439
Radek Krejci5449d472015-10-26 14:35:56 +0100440 if (leaf->schema->nodetype == LYS_LEAFLIST) {
441 /* expecting begin-array */
442 if (data[len++] != '[') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100443 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expected begin-array)");
Radek Krejci5449d472015-10-26 14:35:56 +0100444 return 0;
445 }
446
447repeat:
448 len += skip_ws(&data[len]);
449 }
450
451 /* will be changed in case of union */
452 leaf->value_type = stype->base;
453
454 if (data[len] == '"') {
455 /* string representations */
Michal Vasko6baed1c2016-05-18 13:24:44 +0200456 ++len;
Radek Krejci5449d472015-10-26 14:35:56 +0100457 str = lyjson_parse_text(&data[len], &r);
Radek Krejci23238922015-10-27 17:13:34 +0100458 if (!str) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100459 LOGPATH(LY_VLOG_LYD, leaf);
Radek Krejci5449d472015-10-26 14:35:56 +0100460 return 0;
461 }
462 leaf->value_str = lydict_insert_zc(ctx, str);
463 if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100464 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf,
Radek Krejciadb57612016-02-16 13:34:34 +0100465 "JSON data (missing quotation-mark at the end of string)");
Radek Krejci5449d472015-10-26 14:35:56 +0100466 return 0;
467 }
468 len += r + 1;
469 } else if (data[len] == '-' || isdigit(data[len])) {
470 /* numeric type */
471 r = lyjson_parse_number(&data[len]);
472 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100473 LOGPATH(LY_VLOG_LYD, leaf);
Radek Krejci5449d472015-10-26 14:35:56 +0100474 return 0;
475 }
Michal Vasko1e676ca2016-06-24 15:23:54 +0200476 /* if it's a number with 'e' or 'E', get rid of it first */
477 if ((str = strnchr(&data[len], 'e', r)) || (str = strnchr(&data[len], 'E', r))) {
478 str = lyjson_convert_enumber(&data[len], r, str);
479 if (!str) {
480 return 0;
481 }
482 leaf->value_str = lydict_insert_zc(ctx, str);
483 } else {
484 leaf->value_str = lydict_insert(ctx, &data[len], r);
485 }
Radek Krejci5449d472015-10-26 14:35:56 +0100486 len += r;
487 } else if (data[len] == 'f' || data[len] == 't') {
488 /* boolean */
489 r = lyjson_parse_boolean(&data[len]);
490 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100491 LOGPATH(LY_VLOG_LYD, leaf);
Radek Krejci5449d472015-10-26 14:35:56 +0100492 return 0;
493 }
494 leaf->value_str = lydict_insert(ctx, &data[len], r);
495 len += r;
496 } else if (!strncmp(&data[len], "[null]", 6)) {
497 /* empty */
Michal Vasko44913842016-04-13 14:20:41 +0200498 leaf->value_str = lydict_insert(ctx, "", 0);
Radek Krejci5449d472015-10-26 14:35:56 +0100499 len += 6;
500 } else {
501 /* error */
Radek Krejci48464ed2016-03-17 15:44:09 +0100502 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (unexpected value)");
Radek Krejci5449d472015-10-26 14:35:56 +0100503 return 0;
504 }
505
Radek Krejci0b7704f2016-03-18 12:16:14 +0100506 if (lyp_parse_value(leaf, NULL, resolve)) {
Radek Krejci23238922015-10-27 17:13:34 +0100507 ly_errno = LY_EVALID;
508 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100509 }
510
511 if (leaf->schema->nodetype == LYS_LEAFLIST) {
512 /* repeat until end-array */
513 len += skip_ws(&data[len]);
514 if (data[len] == ',') {
515 /* another instance of the leaf-list */
516 new = calloc(1, sizeof(struct lyd_node_leaf_list));
Michal Vasko253035f2015-12-17 16:58:13 +0100517 if (!new) {
518 LOGMEM;
519 return 0;
520 }
Radek Krejci5449d472015-10-26 14:35:56 +0100521 new->parent = leaf->parent;
522 new->prev = (struct lyd_node *)leaf;
523 leaf->next = (struct lyd_node *)new;
524
525 /* fix the "last" pointer */
Radek Krejcibd930122016-08-10 13:28:26 +0200526 first_sibling->prev = (struct lyd_node *)new;
Radek Krejci5449d472015-10-26 14:35:56 +0100527
528 new->schema = leaf->schema;
529
530 /* repeat value parsing */
531 leaf = new;
532 len++;
533 goto repeat;
534 } else if (data[len] == ']') {
535 len++;
536 len += skip_ws(&data[len]);
537 } else {
538 /* something unexpected */
Radek Krejci48464ed2016-03-17 15:44:09 +0100539 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expecting value-separator or end-array)");
Radek Krejci5449d472015-10-26 14:35:56 +0100540 return 0;
541 }
542 }
543
544 len += skip_ws(&data[len]);
545 return len;
546}
547
548static unsigned int
Radek Krejci88f29302015-10-30 15:42:33 +0100549json_parse_attr(struct lys_module *parent_module, struct lyd_attr **attr, const char *data)
550{
551 unsigned int len = 0, r;
552 char *str = NULL, *name, *prefix, *value;
553 struct lys_module *module = parent_module;
554 struct lyd_attr *attr_new, *attr_last = NULL;
555
Radek Krejcide9d92c2015-10-30 15:59:59 +0100556 *attr = NULL;
557
Radek Krejci88f29302015-10-30 15:42:33 +0100558 if (data[len] != '{') {
559 if (!strncmp(&data[len], "null", 4)) {
Radek Krejci88f29302015-10-30 15:42:33 +0100560 len += 4;
561 len += skip_ws(&data[len]);
562 return len;
563 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100564 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing begin-object)");
Radek Krejci88f29302015-10-30 15:42:33 +0100565 goto error;
566 }
567
568repeat:
569 len++;
570 len += skip_ws(&data[len]);
571
572 if (data[len] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100573 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 +0100574 return 0;
575 }
576 len++;
577 str = lyjson_parse_text(&data[len], &r);
578 if (!r) {
579 goto error;
580 } else if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100581 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 +0100582 goto error;
583 }
584 if ((name = strchr(str, ':'))) {
585 *name = '\0';
586 name++;
587 prefix = str;
Michal Vasko1e62a092015-12-01 12:27:20 +0100588 module = (struct lys_module *)ly_ctx_get_module(parent_module->ctx, prefix, NULL);
Radek Krejci88f29302015-10-30 15:42:33 +0100589 if (!module) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100590 LOGVAL(LYE_INELEM, LY_VLOG_NONE, NULL, name);
Radek Krejci88f29302015-10-30 15:42:33 +0100591 goto error;
592 }
593 } else {
594 name = str;
595 }
596
597 /* prepare data for parsing node content */
598 len += r + 1;
599 len += skip_ws(&data[len]);
600 if (data[len] != ':') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100601 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing name-separator)");
Radek Krejci88f29302015-10-30 15:42:33 +0100602 goto error;
603 }
604 len++;
605 len += skip_ws(&data[len]);
606
607 if (data[len] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100608 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 +0100609 goto error;
Radek Krejci88f29302015-10-30 15:42:33 +0100610 }
611 len++;
612 value = lyjson_parse_text(&data[len], &r);
613 if (!r) {
614 goto error;
615 } else if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100616 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 +0100617 free(value);
Radek Krejci88f29302015-10-30 15:42:33 +0100618 goto error;
619 }
620 len += r + 1;
621 len += skip_ws(&data[len]);
622
623 attr_new = malloc(sizeof **attr);
Michal Vasko253035f2015-12-17 16:58:13 +0100624 if (!attr_new) {
625 LOGMEM;
626 goto error;
627 }
Radek Krejci88f29302015-10-30 15:42:33 +0100628 attr_new->module = module;
629 attr_new->next = NULL;
630 attr_new->name = lydict_insert(module->ctx, name, 0);
631 attr_new->value = lydict_insert_zc(module->ctx, value);
632 if (!attr_last) {
633 *attr = attr_last = attr_new;
634 } else {
635 attr_last->next = attr_new;
636 attr_last = attr_new;
637 }
638
639 free(str);
Radek Krejcide9d92c2015-10-30 15:59:59 +0100640 str = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100641
642 if (data[len] == ',') {
643 goto repeat;
644 } else if (data[len] != '}') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100645 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing end-object)");
Radek Krejcide9d92c2015-10-30 15:59:59 +0100646 goto error;
Radek Krejci88f29302015-10-30 15:42:33 +0100647 }
648 len++;
649 len += skip_ws(&data[len]);
650
651 return len;
652
653error:
654 free(str);
Radek Krejcide9d92c2015-10-30 15:59:59 +0100655 if (*attr) {
656 lyd_free_attr((*attr)->module->ctx, NULL, *attr, 1);
657 *attr = NULL;
658 }
Radek Krejci88f29302015-10-30 15:42:33 +0100659 return 0;
660}
661
662struct attr_cont {
663 struct attr_cont *next;
664 struct lyd_attr *attr;
665 struct lys_node *schema;
666 unsigned int index; /** non-zero only in case of leaf-list */
667};
668
Radek Krejcic4831272015-11-01 19:26:34 +0100669static int
670store_attrs(struct ly_ctx *ctx, struct attr_cont *attrs, struct lyd_node *first)
671{
672 struct lyd_node *diter;
673 struct attr_cont *iter;
674 unsigned int flag_leaflist = 0;
675
676 while (attrs) {
677 iter = attrs;
678 attrs = attrs->next;
679
680 if (iter->index) {
681 flag_leaflist = 1;
682 }
683
684 LY_TREE_FOR(first, diter) {
685 if (iter->schema != diter->schema) {
686 continue;
687 }
688
689 if (flag_leaflist && flag_leaflist != iter->index) {
690 flag_leaflist++;
691 continue;
692 }
693
694 /* we have match */
695 if (diter->attr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100696 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, diter,
Radek Krejciadb57612016-02-16 13:34:34 +0100697 "attribute (multiple attribute definitions belong to a single element)");
Radek Krejcic4831272015-11-01 19:26:34 +0100698 free(iter);
699 goto error;
700 }
701
702 diter->attr = iter->attr;
703 break;
704 }
705
706 if (!diter) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100707 LOGVAL(LYE_XML_MISS, LY_VLOG_NONE, NULL, "element for the specified attribute", iter->attr->name);
Radek Krejcic4831272015-11-01 19:26:34 +0100708 lyd_free_attr(iter->schema->module->ctx, NULL, iter->attr, 1);
709 free(iter);
710 goto error;
711 }
712 free(iter);
713 }
714
715 return 0;
716
717error:
718
719 while (attrs) {
720 iter = attrs;
721 attrs = attrs->next;
722
723 lyd_free_attr(ctx, NULL, iter->attr, 1);
724 free(iter);
725 }
726
727 return -1;
728}
729
Radek Krejci88f29302015-10-30 15:42:33 +0100730static unsigned int
Michal Vasko36ef6932015-12-01 14:30:17 +0100731json_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 +0200732 struct lyd_node *first_sibling, struct lyd_node *prev, struct attr_cont **attrs, int options,
733 struct unres_data *unres)
Radek Krejci5449d472015-10-26 14:35:56 +0100734{
735 unsigned int len = 0;
736 unsigned int r;
Radek Krejcic4831272015-11-01 19:26:34 +0100737 unsigned int flag_leaflist = 0;
Radek Krejci61767ca2016-09-19 14:21:55 +0200738 int i, pos;
Radek Krejci88f29302015-10-30 15:42:33 +0100739 char *name, *prefix = NULL, *str = NULL;
Michal Vasko1e62a092015-12-01 12:27:20 +0100740 const struct lys_module *module = NULL;
Radek Krejci5449d472015-10-26 14:35:56 +0100741 struct lys_node *schema = NULL;
Radek Krejcibd930122016-08-10 13:28:26 +0200742 struct lyd_node *result = NULL, *new, *list, *diter = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100743 struct lyd_attr *attr;
Radek Krejcic4831272015-11-01 19:26:34 +0100744 struct attr_cont *attrs_aux;
Radek Krejci5449d472015-10-26 14:35:56 +0100745
746 /* each YANG data node representation starts with string (node identifier) */
747 if (data[len] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100748 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent),
Radek Krejciadb57612016-02-16 13:34:34 +0100749 "JSON data (missing quotation-mark at the beginning of string)");
Radek Krejci88f29302015-10-30 15:42:33 +0100750 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100751 }
752 len++;
753
Radek Krejci23238922015-10-27 17:13:34 +0100754 str = lyjson_parse_text(&data[len], &r);
Radek Krejci5449d472015-10-26 14:35:56 +0100755 if (!r) {
756 goto error;
757 } else if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100758 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent),
Radek Krejciadb57612016-02-16 13:34:34 +0100759 "JSON data (missing quotation-mark at the end of string)");
Radek Krejci5449d472015-10-26 14:35:56 +0100760 goto error;
761 }
Radek Krejci23238922015-10-27 17:13:34 +0100762 if ((name = strchr(str, ':'))) {
763 *name = '\0';
764 name++;
765 prefix = str;
Radek Krejci88f29302015-10-30 15:42:33 +0100766 if (prefix[0] == '@') {
767 prefix++;
768 }
Radek Krejci23238922015-10-27 17:13:34 +0100769 } else {
770 name = str;
Radek Krejci88f29302015-10-30 15:42:33 +0100771 if (name[0] == '@') {
772 name++;
773 }
Radek Krejci5449d472015-10-26 14:35:56 +0100774 }
775
Radek Krejci5449d472015-10-26 14:35:56 +0100776 /* prepare data for parsing node content */
777 len += r + 1;
778 len += skip_ws(&data[len]);
779 if (data[len] != ':') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100780 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "JSON data (missing name-separator)");
Radek Krejci5449d472015-10-26 14:35:56 +0100781 goto error;
782 }
783 len++;
784 len += skip_ws(&data[len]);
785
Radek Krejci88f29302015-10-30 15:42:33 +0100786 if (str[0] == '@' && !str[1]) {
787 /* process attribute of the parent object (container or list) */
Radek Krejci2a0efef2016-03-24 15:10:40 +0100788 if (!(*parent)) {
789 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "attribute with no corresponding element to belongs to");
Radek Krejci88f29302015-10-30 15:42:33 +0100790 goto error;
791 }
792
793 r = json_parse_attr((*parent)->schema->module, &attr, &data[len]);
794 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100795 LOGPATH(LY_VLOG_LYD, (*parent));
Radek Krejci88f29302015-10-30 15:42:33 +0100796 goto error;
797 }
798 len += r;
799
800 if ((*parent)->attr) {
801 lyd_free_attr(ctx, NULL, attr, 1);
802 } else {
803 (*parent)->attr = attr;
804 }
Radek Krejcic4831272015-11-01 19:26:34 +0100805 free(str);
806 return len;
Radek Krejci88f29302015-10-30 15:42:33 +0100807 }
808
Radek Krejci5449d472015-10-26 14:35:56 +0100809 /* find schema node */
810 if (!(*parent)) {
811 /* starting in root */
812 /* get the proper schema */
813 module = ly_ctx_get_module(ctx, prefix, NULL);
814 if (module) {
815 /* get the proper schema node */
Radek Krejci919a9242016-07-27 08:17:13 +0200816 while ((schema = (struct lys_node *)lys_getnext(schema, NULL, module, 0))) {
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100817 /* skip nodes in module's data which are not expected here according to options' data type */
818 if (options & LYD_OPT_RPC) {
819 if (schema->nodetype != LYS_RPC) {
820 continue;
821 }
822 } else if (options & LYD_OPT_NOTIF) {
823 if (schema->nodetype != LYS_NOTIF) {
824 continue;
825 }
826 } else if (!(options & LYD_OPT_RPCREPLY)) {
827 /* rest of the data types except RPCREPLY which cannot be here */
Radek Krejci919a9242016-07-27 08:17:13 +0200828 if (schema->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_NOTIF)) {
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100829 continue;
830 }
831 }
Radek Krejci919a9242016-07-27 08:17:13 +0200832
Radek Krejci5449d472015-10-26 14:35:56 +0100833 if (!strcmp(schema->name, name)) {
834 break;
835 }
836 }
Radek Krejci88f29302015-10-30 15:42:33 +0100837 } else {
Radek Krejci2a0efef2016-03-24 15:10:40 +0100838 LOGVAL(LYE_INELEM, LY_VLOG_NONE, NULL, name);
Radek Krejci88f29302015-10-30 15:42:33 +0100839 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100840 }
841 } else {
842 /* parsing some internal node, we start with parent's schema pointer */
843 if (prefix) {
844 /* get the proper schema */
845 module = ly_ctx_get_module(ctx, prefix, NULL);
846 if (!module) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100847 LOGVAL(LYE_INELEM, LY_VLOG_LYD, (*parent), name);
Radek Krejci88f29302015-10-30 15:42:33 +0100848 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100849 }
850 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100851
852 /* go through RPC's input/output following the options' data type */
853 if ((*parent)->schema->nodetype == LYS_RPC) {
854 while ((schema = (struct lys_node *)lys_getnext(schema, (*parent)->schema, module, LYS_GETNEXT_WITHINOUT))) {
855 if ((options & LYD_OPT_RPC) && schema->nodetype == LYS_INPUT) {
856 break;
857 } else if ((options & LYD_OPT_RPCREPLY) && schema->nodetype == LYS_OUTPUT) {
858 break;
859 }
860 }
861 if (!schema) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100862 LOGVAL(LYE_INELEM, LY_VLOG_LYD, (*parent), name);
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100863 goto error;
864 }
865 schema_parent = schema;
866 schema = NULL;
867 }
868
Michal Vasko36ef6932015-12-01 14:30:17 +0100869 if (schema_parent) {
870 while ((schema = (struct lys_node *)lys_getnext(schema, schema_parent, module, 0))) {
871 if (!strcmp(schema->name, name)) {
872 break;
873 }
874 }
875 } else {
876 while ((schema = (struct lys_node *)lys_getnext(schema, (*parent)->schema, module, 0))) {
877 if (!strcmp(schema->name, name)) {
878 break;
879 }
Radek Krejci5449d472015-10-26 14:35:56 +0100880 }
881 }
882 }
Radek Krejci27fe55e2016-09-13 17:13:35 +0200883 if (!schema || !lys_node_module(schema)->implemented) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100884 LOGVAL(LYE_INELEM, LY_VLOG_LYD, (*parent), name);
Radek Krejci88f29302015-10-30 15:42:33 +0100885 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100886 }
Radek Krejci88f29302015-10-30 15:42:33 +0100887
888 if (str[0] == '@') {
Radek Krejci88f29302015-10-30 15:42:33 +0100889 /* attribute for some sibling node */
890 if (data[len] == '[') {
891 flag_leaflist = 1;
892 len++;
893 len += skip_ws(&data[len]);
894 }
895
896attr_repeat:
897 r = json_parse_attr(schema->module, &attr, &data[len]);
898 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100899 LOGPATH(LY_VLOG_LYD, (*parent));
Radek Krejci88f29302015-10-30 15:42:33 +0100900 goto error;
901 }
902 len += r;
903
904 if (attr) {
Radek Krejcic4831272015-11-01 19:26:34 +0100905 attrs_aux = malloc(sizeof *attrs_aux);
Michal Vasko253035f2015-12-17 16:58:13 +0100906 if (!attrs_aux) {
907 LOGMEM;
908 goto error;
909 }
Radek Krejcic4831272015-11-01 19:26:34 +0100910 attrs_aux->attr = attr;
911 attrs_aux->index = flag_leaflist;
912 attrs_aux->schema = schema;
913 attrs_aux->next = *attrs;
914 *attrs = attrs_aux;
Radek Krejci88f29302015-10-30 15:42:33 +0100915 } else if (!flag_leaflist) {
916 /* error */
Radek Krejci48464ed2016-03-17 15:44:09 +0100917 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "attribute data");
Radek Krejci88f29302015-10-30 15:42:33 +0100918 goto error;
919 }
920
921 if (flag_leaflist) {
922 if (data[len] == ',') {
923 len++;
924 len += skip_ws(&data[len]);
925 flag_leaflist++;
926 goto attr_repeat;
927 } else if (data[len] != ']') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100928 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "JSON data (missing end-array)");
Radek Krejci88f29302015-10-30 15:42:33 +0100929 goto error;
930 }
931 len++;
932 len += skip_ws(&data[len]);
933 }
934
Radek Krejcic4831272015-11-01 19:26:34 +0100935 free(str);
936 return len;
Radek Krejci88f29302015-10-30 15:42:33 +0100937 }
938
Radek Krejci5449d472015-10-26 14:35:56 +0100939 switch (schema->nodetype) {
940 case LYS_CONTAINER:
941 case LYS_LIST:
942 case LYS_NOTIF:
943 case LYS_RPC:
944 result = calloc(1, sizeof *result);
945 break;
946 case LYS_LEAF:
947 case LYS_LEAFLIST:
948 result = calloc(1, sizeof(struct lyd_node_leaf_list));
949 break;
950 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200951 case LYS_ANYDATA:
952 result = calloc(1, sizeof(struct lyd_node_anydata));
Radek Krejci5449d472015-10-26 14:35:56 +0100953 break;
954 default:
955 LOGINT;
Radek Krejci595060f2015-10-30 16:29:58 +0100956 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100957 }
Michal Vasko253035f2015-12-17 16:58:13 +0100958 if (!result) {
959 LOGMEM;
960 goto error;
961 }
962
Radek Krejci61767ca2016-09-19 14:21:55 +0200963 result->prev = result;
Radek Krejci5449d472015-10-26 14:35:56 +0100964 result->schema = schema;
Radek Krejci61767ca2016-09-19 14:21:55 +0200965 result->parent = *parent;
966 diter = NULL;
967 if (*parent && (*parent)->child && schema->nodetype == LYS_LEAF && (*parent)->schema->nodetype == LYS_LIST &&
968 (pos = lys_is_key((struct lys_node_list *)(*parent)->schema, (struct lys_node_leaf *)schema))) {
969 /* it is key and we need to insert it into a correct place */
970 for (i = 0, diter = (*parent)->child;
971 diter && i < (pos - 1) && diter->schema->nodetype == LYS_LEAF &&
972 lys_is_key((struct lys_node_list *)(*parent)->schema, (struct lys_node_leaf *)diter->schema);
973 i++, diter = diter->next);
974 if (diter) {
975 /* out of order insertion - insert list's key to the correct position, before the diter */
976 if ((*parent)->child == diter) {
977 (*parent)->child = result;
978 /* update first_sibling */
979 first_sibling = result;
980 }
981 if (diter->prev->next) {
982 diter->prev->next = result;
983 }
984 result->prev = diter->prev;
985 diter->prev = result;
986 result->next = diter;
987 }
988 }
989 if (!diter) {
990 /* simplified (faster) insert as the last node */
991 if (*parent && !(*parent)->child) {
992 (*parent)->child = result;
993 }
994 if (prev) {
995 result->prev = prev;
996 prev->next = result;
997
998 /* fix the "last" pointer */
999 first_sibling->prev = result;
1000 } else {
1001 result->prev = result;
1002 first_sibling = result;
1003 }
1004 }
Radek Krejcica7efb72016-01-18 13:06:01 +01001005 result->validity = LYD_VAL_NOT;
Radek Krejci46165822016-08-26 14:06:27 +02001006 if (resolve_applies_when(schema, 0, NULL)) {
Radek Krejci0b7704f2016-03-18 12:16:14 +01001007 result->when_status = LYD_WHEN;
1008 }
Radek Krejci5449d472015-10-26 14:35:56 +01001009
Radek Krejci5449d472015-10-26 14:35:56 +01001010 /* type specific processing */
1011 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
1012 /* type detection and assigning the value */
Radek Krejcibd930122016-08-10 13:28:26 +02001013 r = json_get_value((struct lyd_node_leaf_list *)result, first_sibling, &data[len], options);
Radek Krejci5449d472015-10-26 14:35:56 +01001014 if (!r) {
1015 goto error;
1016 }
Radek Krejci88f29302015-10-30 15:42:33 +01001017 while(result->next) {
1018 result = result->next;
1019 }
1020
Radek Krejci5449d472015-10-26 14:35:56 +01001021 len += r;
1022 len += skip_ws(&data[len]);
Radek Krejcibf2abff2016-08-23 15:51:52 +02001023 } else if (schema->nodetype & LYS_ANYDATA) {
Radek Krejci4ae82942016-09-19 16:41:06 +02001024 r = json_get_anydata((struct lyd_node_anydata *)result, &data[len]);
Radek Krejci5449d472015-10-26 14:35:56 +01001025 if (!r) {
1026 goto error;
1027 }
1028 len += r;
1029 len += skip_ws(&data[len]);
Michal Vasko0d634d02016-05-18 13:26:11 +02001030 } else if (schema->nodetype & (LYS_CONTAINER | LYS_RPC | LYS_NOTIF)) {
Radek Krejci5449d472015-10-26 14:35:56 +01001031 if (data[len] != '{') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001032 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing begin-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001033 goto error;
1034 }
1035 len++;
1036 len += skip_ws(&data[len]);
1037
1038 if (data[len] != '}') {
1039 /* non-empty container */
Radek Krejcic4831272015-11-01 19:26:34 +01001040 len--;
1041 diter = NULL;
1042 attrs_aux = NULL;
1043 do {
1044 len++;
1045 len += skip_ws(&data[len]);
1046
Radek Krejcibd930122016-08-10 13:28:26 +02001047 r = json_parse_data(ctx, &data[len], NULL, &result, result->child, diter, &attrs_aux, options, unres);
Radek Krejcic4831272015-11-01 19:26:34 +01001048 if (!r) {
1049 goto error;
1050 }
1051 len += r;
1052
1053 if (result->child) {
1054 diter = result->child->prev;
1055 }
1056 } while(data[len] == ',');
1057
1058 /* store attributes */
1059 if (store_attrs(ctx, attrs_aux, result->child)) {
Radek Krejci5449d472015-10-26 14:35:56 +01001060 goto error;
1061 }
Radek Krejci5449d472015-10-26 14:35:56 +01001062 }
1063
1064 if (data[len] != '}') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001065 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing end-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001066 goto error;
1067 }
1068 len++;
1069 len += skip_ws(&data[len]);
1070
Michal Vaskoc4280842016-04-19 16:10:42 +02001071 /* 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 +02001072 if (schema->nodetype == LYS_CONTAINER && !result->child &&
Radek Krejcid3e73722016-05-23 12:24:55 +02001073 !result->attr && !((struct lys_node_container *)schema)->presence) {
Michal Vaskoc4280842016-04-19 16:10:42 +02001074 if (unres_data_add(unres, result, UNRES_EMPTYCONT)) {
1075 goto error;
1076 }
Radek Krejci0c0086a2016-03-24 15:20:28 +01001077 }
1078
Radek Krejci5449d472015-10-26 14:35:56 +01001079 } else if (schema->nodetype == LYS_LIST) {
1080 if (data[len] != '[') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001081 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing begin-array)");
Radek Krejci5449d472015-10-26 14:35:56 +01001082 goto error;
1083 }
1084
1085 list = result;
1086 do {
1087 len++;
1088 len += skip_ws(&data[len]);
Radek Krejci23238922015-10-27 17:13:34 +01001089
Radek Krejcic4831272015-11-01 19:26:34 +01001090 if (data[len] != '{') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001091 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result,
Radek Krejciadb57612016-02-16 13:34:34 +01001092 "JSON data (missing list instance's begin-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001093 goto error;
1094 }
Radek Krejcic4831272015-11-01 19:26:34 +01001095 diter = NULL;
1096 attrs_aux = NULL;
1097 do {
1098 len++;
1099 len += skip_ws(&data[len]);
1100
Radek Krejcibd930122016-08-10 13:28:26 +02001101 r = json_parse_data(ctx, &data[len], NULL, &list, list->child, diter, &attrs_aux, options, unres);
Radek Krejcic4831272015-11-01 19:26:34 +01001102 if (!r) {
1103 goto error;
1104 }
1105 len += r;
1106
Radek Krejci52934692015-11-01 20:08:15 +01001107 if (list->child) {
Radek Krejcic4831272015-11-01 19:26:34 +01001108 diter = list->child->prev;
1109 }
1110 } while(data[len] == ',');
1111
1112 /* store attributes */
Radek Krejci52934692015-11-01 20:08:15 +01001113 if (store_attrs(ctx, attrs_aux, list->child)) {
Radek Krejcic4831272015-11-01 19:26:34 +01001114 goto error;
1115 }
1116
1117 if (data[len] != '}') {
1118 /* expecting end-object */
Radek Krejci48464ed2016-03-17 15:44:09 +01001119 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result,
Radek Krejciadb57612016-02-16 13:34:34 +01001120 "JSON data (missing list instance's end-object)");
Radek Krejcic4831272015-11-01 19:26:34 +01001121 goto error;
1122 }
1123 len++;
Radek Krejci5449d472015-10-26 14:35:56 +01001124 len += skip_ws(&data[len]);
1125
1126 if (data[len] == ',') {
Radek Krejci93fab982016-02-03 15:58:19 +01001127 /* various validation checks */
1128 ly_errno = 0;
Radek Krejci2d5525d2016-04-04 15:43:30 +02001129 if (!(options & LYD_OPT_TRUSTED) &&
1130 (lyv_data_content(list, options, unres) ||
Radek Krejci61767ca2016-09-19 14:21:55 +02001131 lyv_multicases(list, NULL, prev ? &first_sibling : NULL, 0, NULL))) {
Radek Krejci93fab982016-02-03 15:58:19 +01001132 if (ly_errno) {
1133 goto error;
1134 }
1135 }
1136 /* validation successful */
1137 list->validity = LYD_VAL_OK;
1138
Radek Krejci5449d472015-10-26 14:35:56 +01001139 /* another instance of the list */
1140 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001141 if (!new) {
1142 goto error;
1143 }
Radek Krejci5449d472015-10-26 14:35:56 +01001144 new->parent = list->parent;
1145 new->prev = list;
1146 list->next = new;
1147
1148 /* fix the "last" pointer */
Radek Krejci2d5525d2016-04-04 15:43:30 +02001149 first_sibling->prev = new;
Radek Krejci5449d472015-10-26 14:35:56 +01001150
1151 new->schema = list->schema;
Radek Krejci5449d472015-10-26 14:35:56 +01001152 list = new;
1153 }
1154 } while (data[len] == ',');
Michal Vaskod171d4e2016-06-06 13:33:19 +02001155 result = first_sibling;
Radek Krejci5449d472015-10-26 14:35:56 +01001156
1157 if (data[len] != ']') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001158 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing end-array)");
Radek Krejci5449d472015-10-26 14:35:56 +01001159 goto error;
1160 }
1161 len++;
1162 len += skip_ws(&data[len]);
1163 }
1164
1165 /* various validation checks */
Michal Vasko10e586f2016-05-18 13:25:30 +02001166 if (!(options & LYD_OPT_TRUSTED) && lyv_data_context(result, options, unres)) {
1167 goto error;
1168 }
1169
Radek Krejci5449d472015-10-26 14:35:56 +01001170 ly_errno = 0;
Radek Krejci2d5525d2016-04-04 15:43:30 +02001171 if (!(options & LYD_OPT_TRUSTED) &&
1172 (lyv_data_content(result, options, unres) ||
Radek Krejci61767ca2016-09-19 14:21:55 +02001173 lyv_multicases(result, NULL, prev ? &first_sibling : NULL, 0, NULL))) {
Radek Krejci5449d472015-10-26 14:35:56 +01001174 if (ly_errno) {
1175 goto error;
1176 }
1177 }
1178
Radek Krejcica7efb72016-01-18 13:06:01 +01001179 /* validation successful */
Radek Krejci63b79c82016-08-10 10:09:33 +02001180 if (result->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
1181 /* postpone checking when there will be all list/leaflist instances */
1182 result->validity = LYD_VAL_UNIQUE;
1183 } else {
1184 result->validity = LYD_VAL_OK;
1185 }
Radek Krejcica7efb72016-01-18 13:06:01 +01001186
Radek Krejci88f29302015-10-30 15:42:33 +01001187 if (!(*parent)) {
1188 *parent = result;
1189 }
1190
Radek Krejcide9d92c2015-10-30 15:59:59 +01001191 free(str);
Radek Krejci5449d472015-10-26 14:35:56 +01001192 return len;
1193
1194error:
Radek Krejci0c0086a2016-03-24 15:20:28 +01001195 len = 0;
Radek Krejci0c0086a2016-03-24 15:20:28 +01001196 /* cleanup */
1197 for (i = unres->count - 1; i >= 0; i--) {
1198 /* remove unres items connected with the node being removed */
1199 if (unres->node[i] == result) {
1200 unres_data_del(unres, i);
1201 }
Radek Krejci88f29302015-10-30 15:42:33 +01001202 }
1203 while (*attrs) {
Radek Krejcic4831272015-11-01 19:26:34 +01001204 attrs_aux = *attrs;
Radek Krejci88f29302015-10-30 15:42:33 +01001205 *attrs = (*attrs)->next;
1206
Radek Krejcic4831272015-11-01 19:26:34 +01001207 lyd_free_attr(ctx, NULL, attrs_aux->attr, 1);
1208 free(attrs_aux);
Radek Krejci88f29302015-10-30 15:42:33 +01001209 }
1210
Radek Krejci5449d472015-10-26 14:35:56 +01001211 lyd_free(result);
Radek Krejci88f29302015-10-30 15:42:33 +01001212 free(str);
1213
Radek Krejci0c0086a2016-03-24 15:20:28 +01001214 return len;
Radek Krejci5449d472015-10-26 14:35:56 +01001215}
1216
1217struct lyd_node *
Michal Vasko6b44d712016-09-12 16:25:46 +02001218lyd_parse_json(struct ly_ctx *ctx, const char *data, int options, const struct lys_node *parent, struct lyd_node *data_tree)
Radek Krejci5449d472015-10-26 14:35:56 +01001219{
Radek Krejcic4831272015-11-01 19:26:34 +01001220 struct lyd_node *result = NULL, *next = NULL, *iter = NULL;
Radek Krejci5449d472015-10-26 14:35:56 +01001221 struct unres_data *unres = NULL;
Radek Krejcic4831272015-11-01 19:26:34 +01001222 unsigned int len = 0, r;
Radek Krejci63b79c82016-08-10 10:09:33 +02001223 int i;
Radek Krejcic4831272015-11-01 19:26:34 +01001224 struct attr_cont *attrs = NULL;
Radek Krejci63b79c82016-08-10 10:09:33 +02001225 struct ly_set *set;
Radek Krejci5449d472015-10-26 14:35:56 +01001226
Radek Krejci2342cf62016-01-29 16:48:23 +01001227 ly_errno = LY_SUCCESS;
1228
Michal Vasko0a073da2016-05-10 15:48:40 +02001229 if (!ctx || !data || (options & LYD_OPT_RPCREPLY)) {
Radek Krejci5449d472015-10-26 14:35:56 +01001230 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1231 return NULL;
1232 }
1233
Radek Krejcic4831272015-11-01 19:26:34 +01001234 /* skip leading whitespaces */
1235 len += skip_ws(&data[len]);
1236
Michal Vasko24d982f2016-04-18 15:13:58 +02001237 /* no data (or whitespaces only) are fine */
1238 if (!data[len]) {
1239 lyd_validate(&result, options, ctx);
1240 return result;
1241 }
1242
Radek Krejcic4831272015-11-01 19:26:34 +01001243 /* expect top-level { */
1244 if (data[len] != '{') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001245 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top level begin-object)");
Michal Vasko24d982f2016-04-18 15:13:58 +02001246 return NULL;
1247 }
1248
1249 unres = calloc(1, sizeof *unres);
1250 if (!unres) {
1251 LOGMEM;
1252 return NULL;
Radek Krejcic4831272015-11-01 19:26:34 +01001253 }
1254
1255 do {
1256 len++;
1257 len += skip_ws(&data[len]);
1258
Radek Krejcibd930122016-08-10 13:28:26 +02001259 r = json_parse_data(ctx, &data[len], parent, &next, result, iter, &attrs, options, unres);
Radek Krejcic4831272015-11-01 19:26:34 +01001260 if (!r) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001261 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001262 }
1263 len += r;
1264
1265 if (!result) {
1266 result = next;
1267 }
1268 if (next) {
1269 iter = next;
1270 }
1271 next = NULL;
1272 } while(data[len] == ',');
1273
1274 if (data[len] != '}') {
1275 /* expecting end-object */
Radek Krejci48464ed2016-03-17 15:44:09 +01001276 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top-level end-object)");
Michal Vasko24d982f2016-04-18 15:13:58 +02001277 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001278 }
1279 len++;
1280 len += skip_ws(&data[len]);
1281
1282 /* store attributes */
1283 if (store_attrs(ctx, attrs, result)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001284 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001285 }
Radek Krejci5449d472015-10-26 14:35:56 +01001286
Michal Vaskoc1cf86f2015-11-04 09:54:51 +01001287 if (!result) {
1288 LOGERR(LY_EVALID, "Model for the data to be linked with not found.");
Michal Vasko24d982f2016-04-18 15:13:58 +02001289 goto error;
Michal Vaskoc1cf86f2015-11-04 09:54:51 +01001290 }
1291
Radek Krejci63b79c82016-08-10 10:09:33 +02001292 /* check for uniquness of top-level lists/leaflists because
1293 * only the inner instances were tested in lyv_data_content() */
1294 set = ly_set_new();
1295 LY_TREE_FOR(result, iter) {
1296 if (!(iter->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(iter->validity & LYD_VAL_UNIQUE)) {
1297 continue;
1298 }
1299
1300 /* check each list/leaflist only once */
1301 i = set->number;
1302 if (ly_set_add(set, iter->schema, 0) != i) {
1303 /* already checked */
1304 continue;
1305 }
1306
1307 if (lyv_data_unique(iter, result)) {
1308 ly_set_free(set);
1309 goto error;
1310 }
1311 }
1312 ly_set_free(set);
1313
Radek Krejci46165822016-08-26 14:06:27 +02001314 /* add/validate default values, unres */
Michal Vasko6b44d712016-09-12 16:25:46 +02001315 if (lyd_defaults_add_unres(&result, options, ctx, data_tree, NULL, unres)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001316 goto error;
Radek Krejci5c162452016-03-23 13:36:01 +01001317 }
1318
Radek Krejci46165822016-08-26 14:06:27 +02001319 /* check for missing top level mandatory nodes */
1320 if (!(options & LYD_OPT_TRUSTED) && lyd_check_mandatory_tree(result, ctx, options)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001321 goto error;
Radek Krejci5c162452016-03-23 13:36:01 +01001322 }
1323
Radek Krejci5449d472015-10-26 14:35:56 +01001324 free(unres->node);
1325 free(unres->type);
Radek Krejci5449d472015-10-26 14:35:56 +01001326 free(unres);
1327
1328 return result;
Michal Vasko24d982f2016-04-18 15:13:58 +02001329
1330error:
1331 lyd_free_withsiblings(result);
1332 free(unres->node);
1333 free(unres->type);
1334 free(unres);
1335
1336 return NULL;
Radek Krejci5449d472015-10-26 14:35:56 +01001337}