blob: 05451654398275397d514b9eaf3c85e15c6197a4 [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 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of the Company nor the names of its contributors
18 * may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 */
21
22#include <assert.h>
23#include <ctype.h>
24#include <limits.h>
25#include <stdlib.h>
26#include <string.h>
27
28#include "libyang.h"
29#include "common.h"
30#include "context.h"
31#include "parser.h"
32#include "printer.h"
33#include "tree_internal.h"
34#include "validation.h"
35
Radek Krejci967e4bf2015-11-28 10:06:40 +010036static unsigned int lineno = 0;
Radek Krejci5449d472015-10-26 14:35:56 +010037
38static int
39lyjson_isspace(int c)
40{
41 switch(c) {
42 case 0x20: /* space */
43 case 0x09: /* horizontal tab */
44 case 0x0a: /* line feed or new line */
45 case 0x0d: /* carriage return */
46 return 1;
47 default:
48 return 0;
49 }
50}
51
52static unsigned int
53skip_ws(const char *data)
54{
55 unsigned int len = 0;
56
57 /* skip leading whitespaces */
58 while (data[len] && lyjson_isspace(data[len])) {
59 COUNTLINE(data[len]);
60 len++;
61 }
62
63 return len;
64}
65
Radek Krejci5449d472015-10-26 14:35:56 +010066static char *
67lyjson_parse_text(const char *data, unsigned int *len)
68{
69#define BUFSIZE 1024
70
71 char buf[BUFSIZE];
72 char *result = NULL, *aux;
Radek Krejci967e4bf2015-11-28 10:06:40 +010073 int o, size = 0;
Radek Krejci5449d472015-10-26 14:35:56 +010074 unsigned int r, i;
75 int32_t value;
76
77 for (*len = o = 0; data[*len] && data[*len] != '"'; o++) {
78 if (o > BUFSIZE - 3) {
79 /* add buffer into the result */
80 if (result) {
81 size = size + o;
Michal Vasko253035f2015-12-17 16:58:13 +010082 aux = ly_realloc(result, size + 1);
83 if (!aux) {
84 LOGMEM;
85 return NULL;
86 }
Radek Krejci5449d472015-10-26 14:35:56 +010087 result = aux;
88 } else {
89 size = o;
90 result = malloc((size + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +010091 if (!result) {
92 LOGMEM;
93 return NULL;
94 }
Radek Krejci5449d472015-10-26 14:35:56 +010095 }
96 memcpy(&result[size - o], buf, o);
97
98 /* write again into the beginning of the buffer */
99 o = 0;
100 }
101
102 if (data[*len] == '\\') {
103 /* parse escape sequence */
104 (*len)++;
105 i = 1;
106 switch (data[(*len)]) {
107 case '"':
108 /* quotation mark */
109 value = 0x22;
110 break;
111 case '\\':
112 /* reverse solidus */
113 value = 0x5c;
114 break;
115 case '/':
116 /* solidus */
117 value = 0x2f;
118 break;
119 case 'b':
120 /* backspace */
121 value = 0x08;
122 break;
123 case 'f':
124 /* form feed */
125 value = 0x0c;
126 break;
127 case 'n':
128 /* line feed */
129 value = 0x0a;
130 break;
131 case 'r':
132 /* carriage return */
133 value = 0x0d;
134 break;
135 case 't':
136 /* tab */
137 value = 0x09;
138 break;
139 case 'u':
140 /* Basic Multilingual Plane character \uXXXX */
141 (*len)++;
142 for (value = i = 0; i < 4; i++) {
143 if (isdigit(data[(*len) + i])) {
144 r = (data[(*len) + i] - '0');
145 } else if (data[(*len) + i] > 'F') {
146 r = 10 + (data[(*len) + i] - 'a');
147 } else {
148 r = 10 + (data[(*len) + i] - 'A');
149 }
150 value = (16 * value) + r;
151 }
152 break;
153 default:
154 /* invalid escape sequence */
155 LOGVAL(LYE_XML_INVAL, lineno, "character escape sequence");
156 goto error;
157
158 }
159 r = pututf8(&buf[o], value, lineno);
160 if (!r) {
161 LOGVAL(LYE_XML_INVAL, lineno, "character UTF8 character");
162 goto error;
163 }
164 o += r - 1; /* o is ++ in for loop */
165 (*len) += i; /* number of read characters */
166 } else if (data[*len] < 0x20 || data[*len] == 0x5c) {
167 /* control characters must be escaped */
168 LOGVAL(LYE_XML_INVAL, lineno, "control character (unescaped)");
169 goto error;
170 } else {
171 /* unescaped character */
172 buf[o] = data[*len];
173 COUNTLINE(buf[o]);
174 (*len)++;
175 }
176 }
177
178#undef BUFSIZE
179
180 if (o) {
181 if (result) {
182 size = size + o;
Michal Vasko253035f2015-12-17 16:58:13 +0100183 aux = ly_realloc(result, size + 1);
184 if (!aux) {
185 LOGMEM;
186 return NULL;
187 }
Radek Krejci5449d472015-10-26 14:35:56 +0100188 result = aux;
189 } else {
190 size = o;
191 result = malloc((size + 1) * sizeof *result);
Michal Vasko253035f2015-12-17 16:58:13 +0100192 if (!result) {
193 LOGMEM;
194 return NULL;
195 }
Radek Krejci5449d472015-10-26 14:35:56 +0100196 }
197 memcpy(&result[size - o], buf, o);
198 }
199 if (result) {
200 result[size] = '\0';
201 } else {
202 size = 0;
203 result = strdup("");
204 }
205
206 return result;
207
208error:
209 free(result);
210 return NULL;
211}
212
213static unsigned int
214lyjson_parse_number(const char *data)
215{
216 unsigned int len;
217 unsigned int i = 0;
218
219 for (len = 0;
220 data[len] && data[len] != ',' && data[len] != ']' && data[len] != '}' && !lyjson_isspace(data[len]);
221 len++) {
222
223 switch(data[len]) {
224 case '0':
Radek Krejci88f29302015-10-30 15:42:33 +0100225 if (!i && isdigit(data[len + 1])) {
Radek Krejci5449d472015-10-26 14:35:56 +0100226 /* leading 0 is not allowed */
227 LOGVAL(LYE_XML_INVAL, lineno, "JSON number (leading zero)");
228 return 0;
229 }
230 /* no break */
231 case '1':
232 case '2':
233 case '3':
234 case '4':
235 case '5':
236 case '6':
237 case '7':
238 case '8':
239 case '9':
240 i = 1;
241 /* no break */
242 case 0x2d: /* minus */
243 /* ok */
244 break;
245 default:
246 LOGVAL(LYE_XML_INVAL, lineno, "character in JSON Number value");
247 return 0;
248 }
249 }
250
251 return len;
252}
253
254static unsigned int
255lyjson_parse_boolean(const char *data)
256{
Radek Krejci6b47b502015-10-30 15:52:41 +0100257 unsigned int len = 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100258
259 if (!strncmp(data, "false", 5)) {
260 len = 5;
261 } else if (!strncmp(data, "true", 4)) {
262 len = 4;
263 }
264
265 if (data[len] && data[len] != ',' && data[len] != ']' && data[len] != '}' && !lyjson_isspace(data[len])) {
266 LOGVAL(LYE_XML_INVAL, lineno, "JSON literal value (expected true or false)");
267 return 0;
268 }
269
270 return len;
271}
272
273static unsigned int
274json_get_anyxml(struct lyd_node_anyxml *axml, const char *data)
275{
276 unsigned int len = 0;
277 char stop, start;
278 int level = 0;
279
280 switch (data[len]) {
281 case '"':
282 start = 0;
283 stop = '"';
284 level = 1;
285 break;
286 case '[':
287 start = '[';
288 stop = ']';
289 break;
290 case '{':
291 start = '{';
292 stop = '}';
293 break;
294 default:
295 /* number or one of literals */
296 while (!isspace(data[len])) {
297 len++;
298 }
299 axml->value = NULL; /* TODO ??? */
300 return len;
301 }
302
303 while (data[len]) {
304 if (start && data[len] == start) {
305 if (!len || data[len - 1] != '\\') {
306 level++;
307 }
308 } else if (data[len] == stop) {
309 if (!len || data[len - 1] != '\\') {
310 level--;
311 }
312 }
313 stop = len;
314 len++;
315 if (!level) {
316 /* we are done */
317 axml->value = NULL; /* TODO ??? */
318 return len;
319 }
320 }
321
322 return 0;
323}
324
325static unsigned int
Radek Krejci23238922015-10-27 17:13:34 +0100326json_get_value(struct lyd_node_leaf_list *leaf, const char *data, int options, struct unres_data *unres)
Radek Krejci5449d472015-10-26 14:35:56 +0100327{
328 struct lyd_node_leaf_list *new, *diter;
Radek Krejci37b756f2016-01-18 10:15:03 +0100329 struct lys_type *stype;
Radek Krejci5449d472015-10-26 14:35:56 +0100330 struct ly_ctx *ctx;
331 unsigned int len = 0, r;
Radek Krejci37b756f2016-01-18 10:15:03 +0100332 int resolve;
Radek Krejci5449d472015-10-26 14:35:56 +0100333 char *str;
334
335 assert(leaf && data && unres);
336 ctx = leaf->schema->module->ctx;
337
Radek Krejci20cdf632015-11-09 14:44:58 +0100338 if (options & (LYD_OPT_FILTER | LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG)) {
Radek Krejci23238922015-10-27 17:13:34 +0100339 resolve = 0;
340 } else {
341 resolve = 1;
342 }
343
Radek Krejci5449d472015-10-26 14:35:56 +0100344 stype = &((struct lys_node_leaf *)leaf->schema)->type;
Radek Krejci23238922015-10-27 17:13:34 +0100345
346 if (options & LYD_OPT_FILTER) {
347 /* no value in filter (selection) node is accepted in this case */
348 if (!strncmp(&data[len], "null", 4)) {
349 leaf->value_type = stype->base;
350 len +=4;
351 goto end;
352 }
353 }
354
Radek Krejci5449d472015-10-26 14:35:56 +0100355 if (leaf->schema->nodetype == LYS_LEAFLIST) {
356 /* expecting begin-array */
357 if (data[len++] != '[') {
358 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (expected begin-array)");
359 return 0;
360 }
361
362repeat:
363 len += skip_ws(&data[len]);
364 }
365
366 /* will be changed in case of union */
367 leaf->value_type = stype->base;
368
369 if (data[len] == '"') {
370 /* string representations */
371 if (data[len++] != '"') {
372 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing quotation-mark at the beginning of string)");
373 return 0;
374 }
375 str = lyjson_parse_text(&data[len], &r);
Radek Krejci23238922015-10-27 17:13:34 +0100376 if (!str) {
Radek Krejci5449d472015-10-26 14:35:56 +0100377 return 0;
378 }
379 leaf->value_str = lydict_insert_zc(ctx, str);
380 if (data[len + r] != '"') {
381 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing quotation-mark at the end of string)");
382 return 0;
383 }
384 len += r + 1;
385 } else if (data[len] == '-' || isdigit(data[len])) {
386 /* numeric type */
387 r = lyjson_parse_number(&data[len]);
388 if (!r) {
389 return 0;
390 }
391 leaf->value_str = lydict_insert(ctx, &data[len], r);
392 len += r;
393 } else if (data[len] == 'f' || data[len] == 't') {
394 /* boolean */
395 r = lyjson_parse_boolean(&data[len]);
396 if (!r) {
397 return 0;
398 }
399 leaf->value_str = lydict_insert(ctx, &data[len], r);
400 len += r;
401 } else if (!strncmp(&data[len], "[null]", 6)) {
402 /* empty */
403 leaf->value_str = NULL;
404 len += 6;
405 } else {
406 /* error */
407 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (unexpected value)");
408 return 0;
409 }
410
Radek Krejci37b756f2016-01-18 10:15:03 +0100411 if (lyp_parse_value(leaf, NULL, resolve, unres, lineno)) {
Radek Krejci23238922015-10-27 17:13:34 +0100412 ly_errno = LY_EVALID;
413 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100414 }
415
416 if (leaf->schema->nodetype == LYS_LEAFLIST) {
417 /* repeat until end-array */
418 len += skip_ws(&data[len]);
419 if (data[len] == ',') {
420 /* another instance of the leaf-list */
421 new = calloc(1, sizeof(struct lyd_node_leaf_list));
Michal Vasko253035f2015-12-17 16:58:13 +0100422 if (!new) {
423 LOGMEM;
424 return 0;
425 }
Radek Krejci5449d472015-10-26 14:35:56 +0100426 new->parent = leaf->parent;
427 new->prev = (struct lyd_node *)leaf;
428 leaf->next = (struct lyd_node *)new;
429
430 /* fix the "last" pointer */
431 for (diter = leaf; diter->prev != (struct lyd_node *)leaf; diter = (struct lyd_node_leaf_list *)diter->prev);
432 diter->prev = (struct lyd_node *)new;
433
434 new->schema = leaf->schema;
435
436 /* repeat value parsing */
437 leaf = new;
438 len++;
439 goto repeat;
440 } else if (data[len] == ']') {
441 len++;
442 len += skip_ws(&data[len]);
443 } else {
444 /* something unexpected */
445 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (expecting value-separator or end-array)");
446 return 0;
447 }
448 }
449
Radek Krejci23238922015-10-27 17:13:34 +0100450end:
Radek Krejci5449d472015-10-26 14:35:56 +0100451 len += skip_ws(&data[len]);
452 return len;
453}
454
455static unsigned int
Radek Krejci88f29302015-10-30 15:42:33 +0100456json_parse_attr(struct lys_module *parent_module, struct lyd_attr **attr, const char *data)
457{
458 unsigned int len = 0, r;
459 char *str = NULL, *name, *prefix, *value;
460 struct lys_module *module = parent_module;
461 struct lyd_attr *attr_new, *attr_last = NULL;
462
Radek Krejcide9d92c2015-10-30 15:59:59 +0100463 *attr = NULL;
464
Radek Krejci88f29302015-10-30 15:42:33 +0100465 if (data[len] != '{') {
466 if (!strncmp(&data[len], "null", 4)) {
Radek Krejci88f29302015-10-30 15:42:33 +0100467 len += 4;
468 len += skip_ws(&data[len]);
469 return len;
470 }
471 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing begin-object)");
472 goto error;
473 }
474
475repeat:
476 len++;
477 len += skip_ws(&data[len]);
478
479 if (data[len] != '"') {
480 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing quotation-mark at the begining of string)");
481 return 0;
482 }
483 len++;
484 str = lyjson_parse_text(&data[len], &r);
485 if (!r) {
486 goto error;
487 } else if (data[len + r] != '"') {
488 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing quotation-mark at the end of string)");
489 goto error;
490 }
491 if ((name = strchr(str, ':'))) {
492 *name = '\0';
493 name++;
494 prefix = str;
Michal Vasko1e62a092015-12-01 12:27:20 +0100495 module = (struct lys_module *)ly_ctx_get_module(parent_module->ctx, prefix, NULL);
Radek Krejci88f29302015-10-30 15:42:33 +0100496 if (!module) {
497 LOGVAL(LYE_INELEM, lineno, name);
498 goto error;
499 }
500 } else {
501 name = str;
502 }
503
504 /* prepare data for parsing node content */
505 len += r + 1;
506 len += skip_ws(&data[len]);
507 if (data[len] != ':') {
508 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing name-separator)");
509 goto error;
510 }
511 len++;
512 len += skip_ws(&data[len]);
513
514 if (data[len] != '"') {
515 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing quotation-mark at the beginning of string)");
Radek Krejcide9d92c2015-10-30 15:59:59 +0100516 goto error;
Radek Krejci88f29302015-10-30 15:42:33 +0100517 }
518 len++;
519 value = lyjson_parse_text(&data[len], &r);
520 if (!r) {
521 goto error;
522 } else if (data[len + r] != '"') {
523 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing quotation-mark at the end of string)");
Radek Krejcide9d92c2015-10-30 15:59:59 +0100524 free(value);
Radek Krejci88f29302015-10-30 15:42:33 +0100525 goto error;
526 }
527 len += r + 1;
528 len += skip_ws(&data[len]);
529
530 attr_new = malloc(sizeof **attr);
Michal Vasko253035f2015-12-17 16:58:13 +0100531 if (!attr_new) {
532 LOGMEM;
533 goto error;
534 }
Radek Krejci88f29302015-10-30 15:42:33 +0100535 attr_new->module = module;
536 attr_new->next = NULL;
537 attr_new->name = lydict_insert(module->ctx, name, 0);
538 attr_new->value = lydict_insert_zc(module->ctx, value);
539 if (!attr_last) {
540 *attr = attr_last = attr_new;
541 } else {
542 attr_last->next = attr_new;
543 attr_last = attr_new;
544 }
545
546 free(str);
Radek Krejcide9d92c2015-10-30 15:59:59 +0100547 str = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100548
549 if (data[len] == ',') {
550 goto repeat;
551 } else if (data[len] != '}') {
552 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing end-object)");
Radek Krejcide9d92c2015-10-30 15:59:59 +0100553 goto error;
Radek Krejci88f29302015-10-30 15:42:33 +0100554 }
555 len++;
556 len += skip_ws(&data[len]);
557
558 return len;
559
560error:
561 free(str);
Radek Krejcide9d92c2015-10-30 15:59:59 +0100562 if (*attr) {
563 lyd_free_attr((*attr)->module->ctx, NULL, *attr, 1);
564 *attr = NULL;
565 }
Radek Krejci88f29302015-10-30 15:42:33 +0100566 return 0;
567}
568
569struct attr_cont {
570 struct attr_cont *next;
571 struct lyd_attr *attr;
572 struct lys_node *schema;
573 unsigned int index; /** non-zero only in case of leaf-list */
574};
575
Radek Krejcic4831272015-11-01 19:26:34 +0100576static int
577store_attrs(struct ly_ctx *ctx, struct attr_cont *attrs, struct lyd_node *first)
578{
579 struct lyd_node *diter;
580 struct attr_cont *iter;
581 unsigned int flag_leaflist = 0;
582
583 while (attrs) {
584 iter = attrs;
585 attrs = attrs->next;
586
587 if (iter->index) {
588 flag_leaflist = 1;
589 }
590
591 LY_TREE_FOR(first, diter) {
592 if (iter->schema != diter->schema) {
593 continue;
594 }
595
596 if (flag_leaflist && flag_leaflist != iter->index) {
597 flag_leaflist++;
598 continue;
599 }
600
601 /* we have match */
602 if (diter->attr) {
603 LOGVAL(LYE_XML_INVAL, lineno, "attribute (multiple attribute definitions belong to a single element)");
604 free(iter);
605 goto error;
606 }
607
608 diter->attr = iter->attr;
609 break;
610 }
611
612 if (!diter) {
613 LOGVAL(LYE_XML_INVAL, lineno, "attribute with no corresponding element to belongs to");
614 lyd_free_attr(iter->schema->module->ctx, NULL, iter->attr, 1);
615 free(iter);
616 goto error;
617 }
618 free(iter);
619 }
620
621 return 0;
622
623error:
624
625 while (attrs) {
626 iter = attrs;
627 attrs = attrs->next;
628
629 lyd_free_attr(ctx, NULL, iter->attr, 1);
630 free(iter);
631 }
632
633 return -1;
634}
635
Radek Krejci88f29302015-10-30 15:42:33 +0100636static unsigned int
Michal Vasko36ef6932015-12-01 14:30:17 +0100637json_parse_data(struct ly_ctx *ctx, const char *data, const struct lys_node *schema_parent, struct lyd_node **parent,
638 struct lyd_node *prev, struct attr_cont **attrs, int options, struct unres_data *unres)
Radek Krejci5449d472015-10-26 14:35:56 +0100639{
640 unsigned int len = 0;
641 unsigned int r;
Radek Krejcic4831272015-11-01 19:26:34 +0100642 unsigned int flag_leaflist = 0;
Radek Krejci88f29302015-10-30 15:42:33 +0100643 char *name, *prefix = NULL, *str = NULL;
Michal Vasko1e62a092015-12-01 12:27:20 +0100644 const struct lys_module *module = NULL;
Radek Krejci5449d472015-10-26 14:35:56 +0100645 struct lys_node *schema = NULL;
646 struct lyd_node *result = NULL, *new, *list, *diter = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100647 struct lyd_attr *attr;
Radek Krejcic4831272015-11-01 19:26:34 +0100648 struct attr_cont *attrs_aux;
Radek Krejci5449d472015-10-26 14:35:56 +0100649
650 /* each YANG data node representation starts with string (node identifier) */
651 if (data[len] != '"') {
Radek Krejci88f29302015-10-30 15:42:33 +0100652 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing quotation-mark at the beginning of string)");
653 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100654 }
655 len++;
656
Radek Krejci23238922015-10-27 17:13:34 +0100657 str = lyjson_parse_text(&data[len], &r);
Radek Krejci5449d472015-10-26 14:35:56 +0100658 if (!r) {
659 goto error;
660 } else if (data[len + r] != '"') {
661 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing quotation-mark at the end of string)");
662 goto error;
663 }
Radek Krejci23238922015-10-27 17:13:34 +0100664 if ((name = strchr(str, ':'))) {
665 *name = '\0';
666 name++;
667 prefix = str;
Radek Krejci88f29302015-10-30 15:42:33 +0100668 if (prefix[0] == '@') {
669 prefix++;
670 }
Radek Krejci23238922015-10-27 17:13:34 +0100671 } else {
672 name = str;
Radek Krejci88f29302015-10-30 15:42:33 +0100673 if (name[0] == '@') {
674 name++;
675 }
Radek Krejci5449d472015-10-26 14:35:56 +0100676 }
677
Radek Krejci5449d472015-10-26 14:35:56 +0100678 /* prepare data for parsing node content */
679 len += r + 1;
680 len += skip_ws(&data[len]);
681 if (data[len] != ':') {
682 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing name-separator)");
683 goto error;
684 }
685 len++;
686 len += skip_ws(&data[len]);
687
Radek Krejci88f29302015-10-30 15:42:33 +0100688 if (str[0] == '@' && !str[1]) {
689 /* process attribute of the parent object (container or list) */
690 if (!*parent) {
691 LOGVAL(LYE_XML_INVAL, lineno, "attribute with no corresponding element to belongs to");
692 goto error;
693 }
694
695 r = json_parse_attr((*parent)->schema->module, &attr, &data[len]);
696 if (!r) {
697 goto error;
698 }
699 len += r;
700
701 if ((*parent)->attr) {
702 lyd_free_attr(ctx, NULL, attr, 1);
703 } else {
704 (*parent)->attr = attr;
705 }
Radek Krejcic4831272015-11-01 19:26:34 +0100706 free(str);
707 return len;
Radek Krejci88f29302015-10-30 15:42:33 +0100708 }
709
Radek Krejci5449d472015-10-26 14:35:56 +0100710 /* find schema node */
711 if (!(*parent)) {
712 /* starting in root */
713 /* get the proper schema */
714 module = ly_ctx_get_module(ctx, prefix, NULL);
715 if (module) {
716 /* get the proper schema node */
717 LY_TREE_FOR(module->data, schema) {
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100718 /* skip nodes in module's data which are not expected here according to options' data type */
719 if (options & LYD_OPT_RPC) {
720 if (schema->nodetype != LYS_RPC) {
721 continue;
722 }
723 } else if (options & LYD_OPT_NOTIF) {
724 if (schema->nodetype != LYS_NOTIF) {
725 continue;
726 }
727 } else if (!(options & LYD_OPT_RPCREPLY)) {
728 /* rest of the data types except RPCREPLY which cannot be here */
729 if (schema->nodetype & (LYS_RPC | LYS_NOTIF)) {
730 continue;
731 }
732 }
Radek Krejci5449d472015-10-26 14:35:56 +0100733 if (!strcmp(schema->name, name)) {
734 break;
735 }
736 }
Radek Krejci88f29302015-10-30 15:42:33 +0100737 } else {
738 LOGVAL(LYE_INELEM, lineno, name);
739 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100740 }
741 } else {
742 /* parsing some internal node, we start with parent's schema pointer */
743 if (prefix) {
744 /* get the proper schema */
745 module = ly_ctx_get_module(ctx, prefix, NULL);
746 if (!module) {
747 LOGVAL(LYE_INELEM, lineno, name);
Radek Krejci88f29302015-10-30 15:42:33 +0100748 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100749 }
750 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100751
752 /* go through RPC's input/output following the options' data type */
753 if ((*parent)->schema->nodetype == LYS_RPC) {
754 while ((schema = (struct lys_node *)lys_getnext(schema, (*parent)->schema, module, LYS_GETNEXT_WITHINOUT))) {
755 if ((options & LYD_OPT_RPC) && schema->nodetype == LYS_INPUT) {
756 break;
757 } else if ((options & LYD_OPT_RPCREPLY) && schema->nodetype == LYS_OUTPUT) {
758 break;
759 }
760 }
761 if (!schema) {
762 LOGVAL(LYE_INELEM, lineno, name);
763 goto error;
764 }
765 schema_parent = schema;
766 schema = NULL;
767 }
768
Michal Vasko36ef6932015-12-01 14:30:17 +0100769 if (schema_parent) {
770 while ((schema = (struct lys_node *)lys_getnext(schema, schema_parent, module, 0))) {
771 if (!strcmp(schema->name, name)) {
772 break;
773 }
774 }
775 } else {
776 while ((schema = (struct lys_node *)lys_getnext(schema, (*parent)->schema, module, 0))) {
777 if (!strcmp(schema->name, name)) {
778 break;
779 }
Radek Krejci5449d472015-10-26 14:35:56 +0100780 }
781 }
782 }
783 if (!schema) {
784 LOGVAL(LYE_INELEM, lineno, name);
Radek Krejci88f29302015-10-30 15:42:33 +0100785 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100786 }
Radek Krejci88f29302015-10-30 15:42:33 +0100787
788 if (str[0] == '@') {
Radek Krejci88f29302015-10-30 15:42:33 +0100789 /* attribute for some sibling node */
790 if (data[len] == '[') {
791 flag_leaflist = 1;
792 len++;
793 len += skip_ws(&data[len]);
794 }
795
796attr_repeat:
797 r = json_parse_attr(schema->module, &attr, &data[len]);
798 if (!r) {
799 goto error;
800 }
801 len += r;
802
803 if (attr) {
Radek Krejcic4831272015-11-01 19:26:34 +0100804 attrs_aux = malloc(sizeof *attrs_aux);
Michal Vasko253035f2015-12-17 16:58:13 +0100805 if (!attrs_aux) {
806 LOGMEM;
807 goto error;
808 }
Radek Krejcic4831272015-11-01 19:26:34 +0100809 attrs_aux->attr = attr;
810 attrs_aux->index = flag_leaflist;
811 attrs_aux->schema = schema;
812 attrs_aux->next = *attrs;
813 *attrs = attrs_aux;
Radek Krejci88f29302015-10-30 15:42:33 +0100814 } else if (!flag_leaflist) {
815 /* error */
816 LOGVAL(LYE_XML_INVAL, lineno, "attribute data");
817 goto error;
818 }
819
820 if (flag_leaflist) {
821 if (data[len] == ',') {
822 len++;
823 len += skip_ws(&data[len]);
824 flag_leaflist++;
825 goto attr_repeat;
826 } else if (data[len] != ']') {
827 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing end-array)");
828 goto error;
829 }
830 len++;
831 len += skip_ws(&data[len]);
832 }
833
Radek Krejcic4831272015-11-01 19:26:34 +0100834 free(str);
835 return len;
Radek Krejci88f29302015-10-30 15:42:33 +0100836 }
837
Radek Krejci5449d472015-10-26 14:35:56 +0100838 switch (schema->nodetype) {
839 case LYS_CONTAINER:
840 case LYS_LIST:
841 case LYS_NOTIF:
842 case LYS_RPC:
843 result = calloc(1, sizeof *result);
844 break;
845 case LYS_LEAF:
846 case LYS_LEAFLIST:
847 result = calloc(1, sizeof(struct lyd_node_leaf_list));
848 break;
849 case LYS_ANYXML:
850 result = calloc(1, sizeof(struct lyd_node_anyxml));
851 break;
852 default:
853 LOGINT;
Radek Krejci595060f2015-10-30 16:29:58 +0100854 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100855 }
Michal Vasko253035f2015-12-17 16:58:13 +0100856 if (!result) {
857 LOGMEM;
858 goto error;
859 }
860
Radek Krejci5449d472015-10-26 14:35:56 +0100861 result->parent = *parent;
862 if (*parent && !(*parent)->child) {
863 (*parent)->child = result;
864 }
865 if (prev) {
866 result->prev = prev;
867 prev->next = result;
868
869 /* fix the "last" pointer */
Radek Krejci93fab982016-02-03 15:58:19 +0100870 if (*parent) {
871 diter = (*parent)->child;
872 } else {
873 for (diter = prev; diter->prev != prev; diter = diter->prev);
874 }
Radek Krejci5449d472015-10-26 14:35:56 +0100875 diter->prev = result;
876 } else {
877 result->prev = result;
878 }
879 result->schema = schema;
Radek Krejcica7efb72016-01-18 13:06:01 +0100880 result->validity = LYD_VAL_NOT;
Radek Krejci5449d472015-10-26 14:35:56 +0100881
Radek Krejci93fab982016-02-03 15:58:19 +0100882 if (!(options & LYD_OPT_TRUSTED) && lyv_data_context(result, options, lineno, unres)) {
Radek Krejci5449d472015-10-26 14:35:56 +0100883 goto error;
884 }
885
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100886 /* TODO handle notifications */
887
Radek Krejci5449d472015-10-26 14:35:56 +0100888 /* type specific processing */
889 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
890 /* type detection and assigning the value */
Radek Krejci23238922015-10-27 17:13:34 +0100891 r = json_get_value((struct lyd_node_leaf_list *)result, &data[len], options, unres);
Radek Krejci5449d472015-10-26 14:35:56 +0100892 if (!r) {
893 goto error;
894 }
Radek Krejci88f29302015-10-30 15:42:33 +0100895 while(result->next) {
896 result = result->next;
897 }
898
Radek Krejci5449d472015-10-26 14:35:56 +0100899 len += r;
900 len += skip_ws(&data[len]);
901 } else if (schema->nodetype == LYS_ANYXML) {
902 r = json_get_anyxml((struct lyd_node_anyxml *)result, &data[len]);
903 if (!r) {
904 goto error;
905 }
906 len += r;
907 len += skip_ws(&data[len]);
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100908 } else if (schema->nodetype & (LYS_CONTAINER | LYS_RPC)) {
Radek Krejci5449d472015-10-26 14:35:56 +0100909 if (data[len] != '{') {
910 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing begin-object)");
911 goto error;
912 }
913 len++;
914 len += skip_ws(&data[len]);
915
916 if (data[len] != '}') {
917 /* non-empty container */
Radek Krejcic4831272015-11-01 19:26:34 +0100918 len--;
919 diter = NULL;
920 attrs_aux = NULL;
921 do {
922 len++;
923 len += skip_ws(&data[len]);
924
Michal Vasko36ef6932015-12-01 14:30:17 +0100925 r = json_parse_data(ctx, &data[len], NULL, &result, diter, &attrs_aux, options, unres);
Radek Krejcic4831272015-11-01 19:26:34 +0100926 if (!r) {
927 goto error;
928 }
929 len += r;
930
931 if (result->child) {
932 diter = result->child->prev;
933 }
934 } while(data[len] == ',');
935
936 /* store attributes */
937 if (store_attrs(ctx, attrs_aux, result->child)) {
Radek Krejci5449d472015-10-26 14:35:56 +0100938 goto error;
939 }
Radek Krejci5449d472015-10-26 14:35:56 +0100940 }
941
942 if (data[len] != '}') {
943 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing end-object)");
944 goto error;
945 }
946 len++;
947 len += skip_ws(&data[len]);
948
949 } else if (schema->nodetype == LYS_LIST) {
950 if (data[len] != '[') {
951 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing begin-array)");
952 goto error;
953 }
954
955 list = result;
956 do {
957 len++;
958 len += skip_ws(&data[len]);
Radek Krejci23238922015-10-27 17:13:34 +0100959
960 if (options & LYD_OPT_FILTER) {
961 /* filter selection node ? */
962 if (data[len] == ']') {
963 break;
964 } else if (!strcmp(&data[len], "null")) {
965 len += 4;
966 len += skip_ws(&data[len]);
967 break;
968 }
969 }
970
Radek Krejcic4831272015-11-01 19:26:34 +0100971 if (data[len] != '{') {
972 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing list instance's begin-object)");
Radek Krejci5449d472015-10-26 14:35:56 +0100973 goto error;
974 }
Radek Krejcic4831272015-11-01 19:26:34 +0100975 diter = NULL;
976 attrs_aux = NULL;
977 do {
978 len++;
979 len += skip_ws(&data[len]);
980
Michal Vasko36ef6932015-12-01 14:30:17 +0100981 r = json_parse_data(ctx, &data[len], NULL, &list, diter, &attrs_aux, options, unres);
Radek Krejcic4831272015-11-01 19:26:34 +0100982 if (!r) {
983 goto error;
984 }
985 len += r;
986
Radek Krejci52934692015-11-01 20:08:15 +0100987 if (list->child) {
Radek Krejcic4831272015-11-01 19:26:34 +0100988 diter = list->child->prev;
989 }
990 } while(data[len] == ',');
991
992 /* store attributes */
Radek Krejci52934692015-11-01 20:08:15 +0100993 if (store_attrs(ctx, attrs_aux, list->child)) {
Radek Krejcic4831272015-11-01 19:26:34 +0100994 goto error;
995 }
996
997 if (data[len] != '}') {
998 /* expecting end-object */
999 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing list instance's end-object)");
1000 goto error;
1001 }
1002 len++;
Radek Krejci5449d472015-10-26 14:35:56 +01001003 len += skip_ws(&data[len]);
1004
1005 if (data[len] == ',') {
Radek Krejci93fab982016-02-03 15:58:19 +01001006 /* various validation checks */
1007 ly_errno = 0;
1008 if (!(options & LYD_OPT_TRUSTED) && lyv_data_content(list, options, lineno, unres)) {
1009 if (ly_errno) {
1010 goto error;
1011 }
1012 }
1013 /* validation successful */
1014 list->validity = LYD_VAL_OK;
1015
Radek Krejci5449d472015-10-26 14:35:56 +01001016 /* another instance of the list */
1017 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001018 if (!new) {
1019 goto error;
1020 }
Radek Krejci5449d472015-10-26 14:35:56 +01001021 new->parent = list->parent;
1022 new->prev = list;
1023 list->next = new;
1024
1025 /* fix the "last" pointer */
Radek Krejci93fab982016-02-03 15:58:19 +01001026 if (*parent) {
1027 diter = (*parent)->child;
1028 } else {
1029 for (diter = prev; diter->prev != prev; diter = diter->prev);
1030 }
Radek Krejci5449d472015-10-26 14:35:56 +01001031 diter->prev = new;
1032
1033 new->schema = list->schema;
Radek Krejci5449d472015-10-26 14:35:56 +01001034 list = new;
1035 }
1036 } while (data[len] == ',');
1037 result = list;
1038
1039 if (data[len] != ']') {
1040 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing end-array)");
1041 goto error;
1042 }
1043 len++;
1044 len += skip_ws(&data[len]);
1045 }
1046
1047 /* various validation checks */
1048 ly_errno = 0;
Radek Krejci93fab982016-02-03 15:58:19 +01001049 if (!(options & LYD_OPT_TRUSTED) && lyv_data_content(result, options, lineno, unres)) {
Radek Krejci5449d472015-10-26 14:35:56 +01001050 if (ly_errno) {
1051 goto error;
1052 }
1053 }
1054
Radek Krejcica7efb72016-01-18 13:06:01 +01001055 /* validation successful */
1056 result->validity = LYD_VAL_OK;
1057
Radek Krejci88f29302015-10-30 15:42:33 +01001058 if (!(*parent)) {
1059 *parent = result;
1060 }
1061
Radek Krejcide9d92c2015-10-30 15:59:59 +01001062 free(str);
Radek Krejci5449d472015-10-26 14:35:56 +01001063 return len;
1064
1065error:
Radek Krejci88f29302015-10-30 15:42:33 +01001066 if ((*parent) == result) {
1067 (*parent) = NULL;
1068 }
1069 while (*attrs) {
Radek Krejcic4831272015-11-01 19:26:34 +01001070 attrs_aux = *attrs;
Radek Krejci88f29302015-10-30 15:42:33 +01001071 *attrs = (*attrs)->next;
1072
Radek Krejcic4831272015-11-01 19:26:34 +01001073 lyd_free_attr(ctx, NULL, attrs_aux->attr, 1);
1074 free(attrs_aux);
Radek Krejci88f29302015-10-30 15:42:33 +01001075 }
1076
Radek Krejci5449d472015-10-26 14:35:56 +01001077 lyd_free(result);
Radek Krejci88f29302015-10-30 15:42:33 +01001078 free(str);
1079
Radek Krejci5449d472015-10-26 14:35:56 +01001080 return 0;
1081}
1082
1083struct lyd_node *
Michal Vasko36ef6932015-12-01 14:30:17 +01001084lyd_parse_json(struct ly_ctx *ctx, const struct lys_node *parent, const char *data, int options)
Radek Krejci5449d472015-10-26 14:35:56 +01001085{
Radek Krejcic4831272015-11-01 19:26:34 +01001086 struct lyd_node *result = NULL, *next = NULL, *iter = NULL;
Radek Krejci5449d472015-10-26 14:35:56 +01001087 struct unres_data *unres = NULL;
Radek Krejcic4831272015-11-01 19:26:34 +01001088 unsigned int len = 0, r;
1089 struct attr_cont *attrs = NULL;
Radek Krejci5449d472015-10-26 14:35:56 +01001090
Radek Krejci2342cf62016-01-29 16:48:23 +01001091 ly_errno = LY_SUCCESS;
1092
Radek Krejci5449d472015-10-26 14:35:56 +01001093 if (!ctx || !data) {
1094 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1095 return NULL;
1096 }
1097
1098 unres = calloc(1, sizeof *unres);
Michal Vasko253035f2015-12-17 16:58:13 +01001099 if (!unres) {
1100 LOGMEM;
1101 return NULL;
1102 }
Radek Krejci5449d472015-10-26 14:35:56 +01001103
1104#ifndef NDEBUG
1105 lineno = 0;
1106#endif
Radek Krejcic4831272015-11-01 19:26:34 +01001107
1108 /* skip leading whitespaces */
1109 len += skip_ws(&data[len]);
1110
1111 /* expect top-level { */
1112 if (data[len] != '{') {
1113 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing top level begin-object)");
1114 goto cleanup;
1115 }
1116
1117 do {
1118 len++;
1119 len += skip_ws(&data[len]);
1120
Michal Vasko36ef6932015-12-01 14:30:17 +01001121 r = json_parse_data(ctx, &data[len], parent, &next, iter, &attrs, options, unres);
Radek Krejcic4831272015-11-01 19:26:34 +01001122 if (!r) {
1123 result = NULL;
1124 goto cleanup;
1125 }
1126 len += r;
1127
1128 if (!result) {
1129 result = next;
1130 }
1131 if (next) {
1132 iter = next;
1133 }
1134 next = NULL;
1135 } while(data[len] == ',');
1136
1137 if (data[len] != '}') {
1138 /* expecting end-object */
1139 LOGVAL(LYE_XML_INVAL, lineno, "JSON data (missing top-level end-object)");
1140 LY_TREE_FOR_SAFE(result, next, iter) {
1141 lyd_free(iter);
1142 }
1143 result = NULL;
1144 goto cleanup;
1145 }
1146 len++;
1147 len += skip_ws(&data[len]);
1148
1149 /* store attributes */
1150 if (store_attrs(ctx, attrs, result)) {
1151 LY_TREE_FOR_SAFE(result, next, iter) {
1152 lyd_free(iter);
1153 }
1154 result = NULL;
1155 goto cleanup;
1156 }
Radek Krejci5449d472015-10-26 14:35:56 +01001157
Michal Vaskoc1cf86f2015-11-04 09:54:51 +01001158 if (!result) {
1159 LOGERR(LY_EVALID, "Model for the data to be linked with not found.");
1160 goto cleanup;
1161 }
1162
Radek Krejci5449d472015-10-26 14:35:56 +01001163 /* check leafrefs and/or instids if any */
1164 if (result && resolve_unres_data(unres)) {
1165 /* leafref & instid checking failed */
Radek Krejcic4831272015-11-01 19:26:34 +01001166 LY_TREE_FOR_SAFE(result, next, iter) {
Radek Krejci5449d472015-10-26 14:35:56 +01001167 lyd_free(iter);
1168 }
1169 result = NULL;
1170 }
1171
Radek Krejcic4831272015-11-01 19:26:34 +01001172cleanup:
Radek Krejci5449d472015-10-26 14:35:56 +01001173 free(unres->node);
1174 free(unres->type);
1175#ifndef NDEBUG
1176 free(unres->line);
1177#endif
1178 free(unres);
1179
1180 return result;
1181}