blob: d08159e08f737a3aa8c75277185f8ae5b3018a2a [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 Krejcibf2abff2016-08-23 15:51:52 +0200378json_get_anyxml(struct lyd_node_anydata *axml, const char *data)
Radek Krejci5449d472015-10-26 14:35:56 +0100379{
Michal Vaskoa19f7d72016-05-18 13:24:08 +0200380 struct ly_ctx *ctx;
381 unsigned int len = 0, r;
382 char *str;
Radek Krejci5449d472015-10-26 14:35:56 +0100383
Michal Vaskoa19f7d72016-05-18 13:24:08 +0200384 ctx = axml->schema->module->ctx;
385
386 if (data[len] == '"') {
387 /* string representations */
388 ++len;
389 str = lyjson_parse_text(&data[len], &r);
390 if (!str) {
391 LOGPATH(LY_VLOG_LYD, axml);
392 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100393 }
Michal Vaskof748dbc2016-04-05 11:27:47 +0200394 axml->xml_struct = 0;
Michal Vaskoa19f7d72016-05-18 13:24:08 +0200395 axml->value.str = lydict_insert_zc(ctx, str);
396 if (data[len + r] != '"') {
397 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, axml,
398 "JSON data (missing quotation-mark at the end of string)");
399 return 0;
400 }
401 len += r + 1;
402 } else if (data[len] == '-' || isdigit(data[len])) {
403 /* numeric type */
404 r = lyjson_parse_number(&data[len]);
405 if (!r) {
406 LOGPATH(LY_VLOG_LYD, axml);
407 return 0;
408 }
409 axml->xml_struct = 0;
410 axml->value.str = lydict_insert(ctx, &data[len], r);
411 len += r;
412 } else if (data[len] == 'f' || data[len] == 't') {
413 /* boolean */
414 r = lyjson_parse_boolean(&data[len]);
415 if (!r) {
416 LOGPATH(LY_VLOG_LYD, axml);
417 return 0;
418 }
419 axml->xml_struct = 0;
420 axml->value.str = lydict_insert(ctx, &data[len], r);
421 len += r;
422 } else if (!strncmp(&data[len], "[null]", 6)) {
423 /* empty */
424 axml->xml_struct = 0;
425 axml->value.str = lydict_insert(ctx, "", 0);
426 len += 6;
427 } else {
428 /* error */
429 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, axml, "JSON data (unexpected value)");
430 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100431 }
432
Michal Vaskoa19f7d72016-05-18 13:24:08 +0200433 len += skip_ws(&data[len]);
434 return len;
Radek Krejci5449d472015-10-26 14:35:56 +0100435}
436
437static unsigned int
Radek Krejcibd930122016-08-10 13:28:26 +0200438json_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 +0100439{
Radek Krejcibd930122016-08-10 13:28:26 +0200440 struct lyd_node_leaf_list *new;
Radek Krejci37b756f2016-01-18 10:15:03 +0100441 struct lys_type *stype;
Radek Krejci5449d472015-10-26 14:35:56 +0100442 struct ly_ctx *ctx;
443 unsigned int len = 0, r;
Radek Krejci37b756f2016-01-18 10:15:03 +0100444 int resolve;
Radek Krejci5449d472015-10-26 14:35:56 +0100445 char *str;
446
Radek Krejci0b7704f2016-03-18 12:16:14 +0100447 assert(leaf && data);
Radek Krejci5449d472015-10-26 14:35:56 +0100448 ctx = leaf->schema->module->ctx;
449
Radek Krejci92ece002016-04-04 15:45:05 +0200450 if (options & (LYD_OPT_EDIT | LYD_OPT_GET | LYD_OPT_GETCONFIG)) {
Radek Krejci23238922015-10-27 17:13:34 +0100451 resolve = 0;
452 } else {
453 resolve = 1;
454 }
455
Radek Krejci5449d472015-10-26 14:35:56 +0100456 stype = &((struct lys_node_leaf *)leaf->schema)->type;
Radek Krejci23238922015-10-27 17:13:34 +0100457
Radek Krejci5449d472015-10-26 14:35:56 +0100458 if (leaf->schema->nodetype == LYS_LEAFLIST) {
459 /* expecting begin-array */
460 if (data[len++] != '[') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100461 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expected begin-array)");
Radek Krejci5449d472015-10-26 14:35:56 +0100462 return 0;
463 }
464
465repeat:
466 len += skip_ws(&data[len]);
467 }
468
469 /* will be changed in case of union */
470 leaf->value_type = stype->base;
471
472 if (data[len] == '"') {
473 /* string representations */
Michal Vasko6baed1c2016-05-18 13:24:44 +0200474 ++len;
Radek Krejci5449d472015-10-26 14:35:56 +0100475 str = lyjson_parse_text(&data[len], &r);
Radek Krejci23238922015-10-27 17:13:34 +0100476 if (!str) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100477 LOGPATH(LY_VLOG_LYD, leaf);
Radek Krejci5449d472015-10-26 14:35:56 +0100478 return 0;
479 }
480 leaf->value_str = lydict_insert_zc(ctx, str);
481 if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100482 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf,
Radek Krejciadb57612016-02-16 13:34:34 +0100483 "JSON data (missing quotation-mark at the end of string)");
Radek Krejci5449d472015-10-26 14:35:56 +0100484 return 0;
485 }
486 len += r + 1;
487 } else if (data[len] == '-' || isdigit(data[len])) {
488 /* numeric type */
489 r = lyjson_parse_number(&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 }
Michal Vasko1e676ca2016-06-24 15:23:54 +0200494 /* if it's a number with 'e' or 'E', get rid of it first */
495 if ((str = strnchr(&data[len], 'e', r)) || (str = strnchr(&data[len], 'E', r))) {
496 str = lyjson_convert_enumber(&data[len], r, str);
497 if (!str) {
498 return 0;
499 }
500 leaf->value_str = lydict_insert_zc(ctx, str);
501 } else {
502 leaf->value_str = lydict_insert(ctx, &data[len], r);
503 }
Radek Krejci5449d472015-10-26 14:35:56 +0100504 len += r;
505 } else if (data[len] == 'f' || data[len] == 't') {
506 /* boolean */
507 r = lyjson_parse_boolean(&data[len]);
508 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100509 LOGPATH(LY_VLOG_LYD, leaf);
Radek Krejci5449d472015-10-26 14:35:56 +0100510 return 0;
511 }
512 leaf->value_str = lydict_insert(ctx, &data[len], r);
513 len += r;
514 } else if (!strncmp(&data[len], "[null]", 6)) {
515 /* empty */
Michal Vasko44913842016-04-13 14:20:41 +0200516 leaf->value_str = lydict_insert(ctx, "", 0);
Radek Krejci5449d472015-10-26 14:35:56 +0100517 len += 6;
518 } else {
519 /* error */
Radek Krejci48464ed2016-03-17 15:44:09 +0100520 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (unexpected value)");
Radek Krejci5449d472015-10-26 14:35:56 +0100521 return 0;
522 }
523
Radek Krejci0b7704f2016-03-18 12:16:14 +0100524 if (lyp_parse_value(leaf, NULL, resolve)) {
Radek Krejci23238922015-10-27 17:13:34 +0100525 ly_errno = LY_EVALID;
526 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100527 }
528
529 if (leaf->schema->nodetype == LYS_LEAFLIST) {
530 /* repeat until end-array */
531 len += skip_ws(&data[len]);
532 if (data[len] == ',') {
533 /* another instance of the leaf-list */
534 new = calloc(1, sizeof(struct lyd_node_leaf_list));
Michal Vasko253035f2015-12-17 16:58:13 +0100535 if (!new) {
536 LOGMEM;
537 return 0;
538 }
Radek Krejci5449d472015-10-26 14:35:56 +0100539 new->parent = leaf->parent;
540 new->prev = (struct lyd_node *)leaf;
541 leaf->next = (struct lyd_node *)new;
542
543 /* fix the "last" pointer */
Radek Krejcibd930122016-08-10 13:28:26 +0200544 first_sibling->prev = (struct lyd_node *)new;
Radek Krejci5449d472015-10-26 14:35:56 +0100545
546 new->schema = leaf->schema;
547
548 /* repeat value parsing */
549 leaf = new;
550 len++;
551 goto repeat;
552 } else if (data[len] == ']') {
553 len++;
554 len += skip_ws(&data[len]);
555 } else {
556 /* something unexpected */
Radek Krejci48464ed2016-03-17 15:44:09 +0100557 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expecting value-separator or end-array)");
Radek Krejci5449d472015-10-26 14:35:56 +0100558 return 0;
559 }
560 }
561
562 len += skip_ws(&data[len]);
563 return len;
564}
565
566static unsigned int
Radek Krejci88f29302015-10-30 15:42:33 +0100567json_parse_attr(struct lys_module *parent_module, struct lyd_attr **attr, const char *data)
568{
569 unsigned int len = 0, r;
570 char *str = NULL, *name, *prefix, *value;
571 struct lys_module *module = parent_module;
572 struct lyd_attr *attr_new, *attr_last = NULL;
573
Radek Krejcide9d92c2015-10-30 15:59:59 +0100574 *attr = NULL;
575
Radek Krejci88f29302015-10-30 15:42:33 +0100576 if (data[len] != '{') {
577 if (!strncmp(&data[len], "null", 4)) {
Radek Krejci88f29302015-10-30 15:42:33 +0100578 len += 4;
579 len += skip_ws(&data[len]);
580 return len;
581 }
Radek Krejci48464ed2016-03-17 15:44:09 +0100582 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing begin-object)");
Radek Krejci88f29302015-10-30 15:42:33 +0100583 goto error;
584 }
585
586repeat:
587 len++;
588 len += skip_ws(&data[len]);
589
590 if (data[len] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100591 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 +0100592 return 0;
593 }
594 len++;
595 str = lyjson_parse_text(&data[len], &r);
596 if (!r) {
597 goto error;
598 } else if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100599 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 +0100600 goto error;
601 }
602 if ((name = strchr(str, ':'))) {
603 *name = '\0';
604 name++;
605 prefix = str;
Michal Vasko1e62a092015-12-01 12:27:20 +0100606 module = (struct lys_module *)ly_ctx_get_module(parent_module->ctx, prefix, NULL);
Radek Krejci88f29302015-10-30 15:42:33 +0100607 if (!module) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100608 LOGVAL(LYE_INELEM, LY_VLOG_NONE, NULL, name);
Radek Krejci88f29302015-10-30 15:42:33 +0100609 goto error;
610 }
611 } else {
612 name = str;
613 }
614
615 /* prepare data for parsing node content */
616 len += r + 1;
617 len += skip_ws(&data[len]);
618 if (data[len] != ':') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100619 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing name-separator)");
Radek Krejci88f29302015-10-30 15:42:33 +0100620 goto error;
621 }
622 len++;
623 len += skip_ws(&data[len]);
624
625 if (data[len] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100626 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 +0100627 goto error;
Radek Krejci88f29302015-10-30 15:42:33 +0100628 }
629 len++;
630 value = lyjson_parse_text(&data[len], &r);
631 if (!r) {
632 goto error;
633 } else if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100634 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 +0100635 free(value);
Radek Krejci88f29302015-10-30 15:42:33 +0100636 goto error;
637 }
638 len += r + 1;
639 len += skip_ws(&data[len]);
640
641 attr_new = malloc(sizeof **attr);
Michal Vasko253035f2015-12-17 16:58:13 +0100642 if (!attr_new) {
643 LOGMEM;
644 goto error;
645 }
Radek Krejci88f29302015-10-30 15:42:33 +0100646 attr_new->module = module;
647 attr_new->next = NULL;
648 attr_new->name = lydict_insert(module->ctx, name, 0);
649 attr_new->value = lydict_insert_zc(module->ctx, value);
650 if (!attr_last) {
651 *attr = attr_last = attr_new;
652 } else {
653 attr_last->next = attr_new;
654 attr_last = attr_new;
655 }
656
657 free(str);
Radek Krejcide9d92c2015-10-30 15:59:59 +0100658 str = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100659
660 if (data[len] == ',') {
661 goto repeat;
662 } else if (data[len] != '}') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100663 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing end-object)");
Radek Krejcide9d92c2015-10-30 15:59:59 +0100664 goto error;
Radek Krejci88f29302015-10-30 15:42:33 +0100665 }
666 len++;
667 len += skip_ws(&data[len]);
668
669 return len;
670
671error:
672 free(str);
Radek Krejcide9d92c2015-10-30 15:59:59 +0100673 if (*attr) {
674 lyd_free_attr((*attr)->module->ctx, NULL, *attr, 1);
675 *attr = NULL;
676 }
Radek Krejci88f29302015-10-30 15:42:33 +0100677 return 0;
678}
679
680struct attr_cont {
681 struct attr_cont *next;
682 struct lyd_attr *attr;
683 struct lys_node *schema;
684 unsigned int index; /** non-zero only in case of leaf-list */
685};
686
Radek Krejcic4831272015-11-01 19:26:34 +0100687static int
688store_attrs(struct ly_ctx *ctx, struct attr_cont *attrs, struct lyd_node *first)
689{
690 struct lyd_node *diter;
691 struct attr_cont *iter;
692 unsigned int flag_leaflist = 0;
693
694 while (attrs) {
695 iter = attrs;
696 attrs = attrs->next;
697
698 if (iter->index) {
699 flag_leaflist = 1;
700 }
701
702 LY_TREE_FOR(first, diter) {
703 if (iter->schema != diter->schema) {
704 continue;
705 }
706
707 if (flag_leaflist && flag_leaflist != iter->index) {
708 flag_leaflist++;
709 continue;
710 }
711
712 /* we have match */
713 if (diter->attr) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100714 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, diter,
Radek Krejciadb57612016-02-16 13:34:34 +0100715 "attribute (multiple attribute definitions belong to a single element)");
Radek Krejcic4831272015-11-01 19:26:34 +0100716 free(iter);
717 goto error;
718 }
719
720 diter->attr = iter->attr;
721 break;
722 }
723
724 if (!diter) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100725 LOGVAL(LYE_XML_MISS, LY_VLOG_NONE, NULL, "element for the specified attribute", iter->attr->name);
Radek Krejcic4831272015-11-01 19:26:34 +0100726 lyd_free_attr(iter->schema->module->ctx, NULL, iter->attr, 1);
727 free(iter);
728 goto error;
729 }
730 free(iter);
731 }
732
733 return 0;
734
735error:
736
737 while (attrs) {
738 iter = attrs;
739 attrs = attrs->next;
740
741 lyd_free_attr(ctx, NULL, iter->attr, 1);
742 free(iter);
743 }
744
745 return -1;
746}
747
Radek Krejci88f29302015-10-30 15:42:33 +0100748static unsigned int
Michal Vasko36ef6932015-12-01 14:30:17 +0100749json_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 +0200750 struct lyd_node *first_sibling, struct lyd_node *prev, struct attr_cont **attrs, int options,
751 struct unres_data *unres)
Radek Krejci5449d472015-10-26 14:35:56 +0100752{
753 unsigned int len = 0;
754 unsigned int r;
Radek Krejcic4831272015-11-01 19:26:34 +0100755 unsigned int flag_leaflist = 0;
Radek Krejci0c0086a2016-03-24 15:20:28 +0100756 int i;
Radek Krejci88f29302015-10-30 15:42:33 +0100757 char *name, *prefix = NULL, *str = NULL;
Michal Vasko1e62a092015-12-01 12:27:20 +0100758 const struct lys_module *module = NULL;
Radek Krejci5449d472015-10-26 14:35:56 +0100759 struct lys_node *schema = NULL;
Radek Krejcibd930122016-08-10 13:28:26 +0200760 struct lyd_node *result = NULL, *new, *list, *diter = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100761 struct lyd_attr *attr;
Radek Krejcic4831272015-11-01 19:26:34 +0100762 struct attr_cont *attrs_aux;
Radek Krejci5449d472015-10-26 14:35:56 +0100763
764 /* each YANG data node representation starts with string (node identifier) */
765 if (data[len] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100766 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent),
Radek Krejciadb57612016-02-16 13:34:34 +0100767 "JSON data (missing quotation-mark at the beginning of string)");
Radek Krejci88f29302015-10-30 15:42:33 +0100768 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100769 }
770 len++;
771
Radek Krejci23238922015-10-27 17:13:34 +0100772 str = lyjson_parse_text(&data[len], &r);
Radek Krejci5449d472015-10-26 14:35:56 +0100773 if (!r) {
774 goto error;
775 } else if (data[len + r] != '"') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100776 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent),
Radek Krejciadb57612016-02-16 13:34:34 +0100777 "JSON data (missing quotation-mark at the end of string)");
Radek Krejci5449d472015-10-26 14:35:56 +0100778 goto error;
779 }
Radek Krejci23238922015-10-27 17:13:34 +0100780 if ((name = strchr(str, ':'))) {
781 *name = '\0';
782 name++;
783 prefix = str;
Radek Krejci88f29302015-10-30 15:42:33 +0100784 if (prefix[0] == '@') {
785 prefix++;
786 }
Radek Krejci23238922015-10-27 17:13:34 +0100787 } else {
788 name = str;
Radek Krejci88f29302015-10-30 15:42:33 +0100789 if (name[0] == '@') {
790 name++;
791 }
Radek Krejci5449d472015-10-26 14:35:56 +0100792 }
793
Radek Krejci5449d472015-10-26 14:35:56 +0100794 /* prepare data for parsing node content */
795 len += r + 1;
796 len += skip_ws(&data[len]);
797 if (data[len] != ':') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100798 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "JSON data (missing name-separator)");
Radek Krejci5449d472015-10-26 14:35:56 +0100799 goto error;
800 }
801 len++;
802 len += skip_ws(&data[len]);
803
Radek Krejci88f29302015-10-30 15:42:33 +0100804 if (str[0] == '@' && !str[1]) {
805 /* process attribute of the parent object (container or list) */
Radek Krejci2a0efef2016-03-24 15:10:40 +0100806 if (!(*parent)) {
807 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "attribute with no corresponding element to belongs to");
Radek Krejci88f29302015-10-30 15:42:33 +0100808 goto error;
809 }
810
811 r = json_parse_attr((*parent)->schema->module, &attr, &data[len]);
812 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100813 LOGPATH(LY_VLOG_LYD, (*parent));
Radek Krejci88f29302015-10-30 15:42:33 +0100814 goto error;
815 }
816 len += r;
817
818 if ((*parent)->attr) {
819 lyd_free_attr(ctx, NULL, attr, 1);
820 } else {
821 (*parent)->attr = attr;
822 }
Radek Krejcic4831272015-11-01 19:26:34 +0100823 free(str);
824 return len;
Radek Krejci88f29302015-10-30 15:42:33 +0100825 }
826
Radek Krejci5449d472015-10-26 14:35:56 +0100827 /* find schema node */
828 if (!(*parent)) {
829 /* starting in root */
830 /* get the proper schema */
831 module = ly_ctx_get_module(ctx, prefix, NULL);
832 if (module) {
833 /* get the proper schema node */
Radek Krejci919a9242016-07-27 08:17:13 +0200834 while ((schema = (struct lys_node *)lys_getnext(schema, NULL, module, 0))) {
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100835 /* skip nodes in module's data which are not expected here according to options' data type */
836 if (options & LYD_OPT_RPC) {
837 if (schema->nodetype != LYS_RPC) {
838 continue;
839 }
840 } else if (options & LYD_OPT_NOTIF) {
841 if (schema->nodetype != LYS_NOTIF) {
842 continue;
843 }
844 } else if (!(options & LYD_OPT_RPCREPLY)) {
845 /* rest of the data types except RPCREPLY which cannot be here */
Radek Krejci919a9242016-07-27 08:17:13 +0200846 if (schema->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_NOTIF)) {
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100847 continue;
848 }
849 }
Radek Krejci919a9242016-07-27 08:17:13 +0200850
Radek Krejci5449d472015-10-26 14:35:56 +0100851 if (!strcmp(schema->name, name)) {
852 break;
853 }
854 }
Radek Krejci88f29302015-10-30 15:42:33 +0100855 } else {
Radek Krejci2a0efef2016-03-24 15:10:40 +0100856 LOGVAL(LYE_INELEM, LY_VLOG_NONE, NULL, name);
Radek Krejci88f29302015-10-30 15:42:33 +0100857 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100858 }
859 } else {
860 /* parsing some internal node, we start with parent's schema pointer */
861 if (prefix) {
862 /* get the proper schema */
863 module = ly_ctx_get_module(ctx, prefix, NULL);
864 if (!module) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100865 LOGVAL(LYE_INELEM, LY_VLOG_LYD, (*parent), name);
Radek Krejci88f29302015-10-30 15:42:33 +0100866 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100867 }
868 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100869
870 /* go through RPC's input/output following the options' data type */
871 if ((*parent)->schema->nodetype == LYS_RPC) {
872 while ((schema = (struct lys_node *)lys_getnext(schema, (*parent)->schema, module, LYS_GETNEXT_WITHINOUT))) {
873 if ((options & LYD_OPT_RPC) && schema->nodetype == LYS_INPUT) {
874 break;
875 } else if ((options & LYD_OPT_RPCREPLY) && schema->nodetype == LYS_OUTPUT) {
876 break;
877 }
878 }
879 if (!schema) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100880 LOGVAL(LYE_INELEM, LY_VLOG_LYD, (*parent), name);
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100881 goto error;
882 }
883 schema_parent = schema;
884 schema = NULL;
885 }
886
Michal Vasko36ef6932015-12-01 14:30:17 +0100887 if (schema_parent) {
888 while ((schema = (struct lys_node *)lys_getnext(schema, schema_parent, module, 0))) {
889 if (!strcmp(schema->name, name)) {
890 break;
891 }
892 }
893 } else {
894 while ((schema = (struct lys_node *)lys_getnext(schema, (*parent)->schema, module, 0))) {
895 if (!strcmp(schema->name, name)) {
896 break;
897 }
Radek Krejci5449d472015-10-26 14:35:56 +0100898 }
899 }
900 }
901 if (!schema) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100902 LOGVAL(LYE_INELEM, LY_VLOG_LYD, (*parent), name);
Radek Krejci88f29302015-10-30 15:42:33 +0100903 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100904 }
Radek Krejci88f29302015-10-30 15:42:33 +0100905
906 if (str[0] == '@') {
Radek Krejci88f29302015-10-30 15:42:33 +0100907 /* attribute for some sibling node */
908 if (data[len] == '[') {
909 flag_leaflist = 1;
910 len++;
911 len += skip_ws(&data[len]);
912 }
913
914attr_repeat:
915 r = json_parse_attr(schema->module, &attr, &data[len]);
916 if (!r) {
Radek Krejci48464ed2016-03-17 15:44:09 +0100917 LOGPATH(LY_VLOG_LYD, (*parent));
Radek Krejci88f29302015-10-30 15:42:33 +0100918 goto error;
919 }
920 len += r;
921
922 if (attr) {
Radek Krejcic4831272015-11-01 19:26:34 +0100923 attrs_aux = malloc(sizeof *attrs_aux);
Michal Vasko253035f2015-12-17 16:58:13 +0100924 if (!attrs_aux) {
925 LOGMEM;
926 goto error;
927 }
Radek Krejcic4831272015-11-01 19:26:34 +0100928 attrs_aux->attr = attr;
929 attrs_aux->index = flag_leaflist;
930 attrs_aux->schema = schema;
931 attrs_aux->next = *attrs;
932 *attrs = attrs_aux;
Radek Krejci88f29302015-10-30 15:42:33 +0100933 } else if (!flag_leaflist) {
934 /* error */
Radek Krejci48464ed2016-03-17 15:44:09 +0100935 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "attribute data");
Radek Krejci88f29302015-10-30 15:42:33 +0100936 goto error;
937 }
938
939 if (flag_leaflist) {
940 if (data[len] == ',') {
941 len++;
942 len += skip_ws(&data[len]);
943 flag_leaflist++;
944 goto attr_repeat;
945 } else if (data[len] != ']') {
Radek Krejci48464ed2016-03-17 15:44:09 +0100946 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "JSON data (missing end-array)");
Radek Krejci88f29302015-10-30 15:42:33 +0100947 goto error;
948 }
949 len++;
950 len += skip_ws(&data[len]);
951 }
952
Radek Krejcic4831272015-11-01 19:26:34 +0100953 free(str);
954 return len;
Radek Krejci88f29302015-10-30 15:42:33 +0100955 }
956
Radek Krejci5449d472015-10-26 14:35:56 +0100957 switch (schema->nodetype) {
958 case LYS_CONTAINER:
959 case LYS_LIST:
960 case LYS_NOTIF:
961 case LYS_RPC:
962 result = calloc(1, sizeof *result);
963 break;
964 case LYS_LEAF:
965 case LYS_LEAFLIST:
966 result = calloc(1, sizeof(struct lyd_node_leaf_list));
967 break;
968 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200969 case LYS_ANYDATA:
970 result = calloc(1, sizeof(struct lyd_node_anydata));
Radek Krejci5449d472015-10-26 14:35:56 +0100971 break;
972 default:
973 LOGINT;
Radek Krejci595060f2015-10-30 16:29:58 +0100974 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100975 }
Michal Vasko253035f2015-12-17 16:58:13 +0100976 if (!result) {
977 LOGMEM;
978 goto error;
979 }
980
Radek Krejci5449d472015-10-26 14:35:56 +0100981 result->parent = *parent;
982 if (*parent && !(*parent)->child) {
983 (*parent)->child = result;
984 }
985 if (prev) {
986 result->prev = prev;
987 prev->next = result;
988
989 /* fix the "last" pointer */
Radek Krejcibd930122016-08-10 13:28:26 +0200990 first_sibling->prev = result;
Radek Krejci5449d472015-10-26 14:35:56 +0100991 } else {
992 result->prev = result;
Radek Krejci2d5525d2016-04-04 15:43:30 +0200993 first_sibling = result;
Radek Krejci5449d472015-10-26 14:35:56 +0100994 }
995 result->schema = schema;
Radek Krejcica7efb72016-01-18 13:06:01 +0100996 result->validity = LYD_VAL_NOT;
Radek Krejci0b7704f2016-03-18 12:16:14 +0100997 if (resolve_applies_when(result)) {
998 result->when_status = LYD_WHEN;
999 }
Radek Krejci5449d472015-10-26 14:35:56 +01001000
Radek Krejci5449d472015-10-26 14:35:56 +01001001 /* type specific processing */
1002 if (schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) {
1003 /* type detection and assigning the value */
Radek Krejcibd930122016-08-10 13:28:26 +02001004 r = json_get_value((struct lyd_node_leaf_list *)result, first_sibling, &data[len], options);
Radek Krejci5449d472015-10-26 14:35:56 +01001005 if (!r) {
1006 goto error;
1007 }
Radek Krejci88f29302015-10-30 15:42:33 +01001008 while(result->next) {
1009 result = result->next;
1010 }
1011
Radek Krejci5449d472015-10-26 14:35:56 +01001012 len += r;
1013 len += skip_ws(&data[len]);
Radek Krejcibf2abff2016-08-23 15:51:52 +02001014 } else if (schema->nodetype & LYS_ANYDATA) {
1015 r = json_get_anyxml((struct lyd_node_anydata *)result, &data[len]);
Radek Krejci5449d472015-10-26 14:35:56 +01001016 if (!r) {
1017 goto error;
1018 }
1019 len += r;
1020 len += skip_ws(&data[len]);
Michal Vasko0d634d02016-05-18 13:26:11 +02001021 } else if (schema->nodetype & (LYS_CONTAINER | LYS_RPC | LYS_NOTIF)) {
Radek Krejci5449d472015-10-26 14:35:56 +01001022 if (data[len] != '{') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001023 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing begin-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001024 goto error;
1025 }
1026 len++;
1027 len += skip_ws(&data[len]);
1028
1029 if (data[len] != '}') {
1030 /* non-empty container */
Radek Krejcic4831272015-11-01 19:26:34 +01001031 len--;
1032 diter = NULL;
1033 attrs_aux = NULL;
1034 do {
1035 len++;
1036 len += skip_ws(&data[len]);
1037
Radek Krejcibd930122016-08-10 13:28:26 +02001038 r = json_parse_data(ctx, &data[len], NULL, &result, result->child, diter, &attrs_aux, options, unres);
Radek Krejcic4831272015-11-01 19:26:34 +01001039 if (!r) {
1040 goto error;
1041 }
1042 len += r;
1043
1044 if (result->child) {
1045 diter = result->child->prev;
1046 }
1047 } while(data[len] == ',');
1048
1049 /* store attributes */
1050 if (store_attrs(ctx, attrs_aux, result->child)) {
Radek Krejci5449d472015-10-26 14:35:56 +01001051 goto error;
1052 }
Radek Krejci5449d472015-10-26 14:35:56 +01001053 }
1054
1055 if (data[len] != '}') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001056 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing end-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001057 goto error;
1058 }
1059 len++;
1060 len += skip_ws(&data[len]);
1061
Michal Vaskoc4280842016-04-19 16:10:42 +02001062 /* if we have empty non-presence container, we could remove it immediately if there were no attributes of it, who knows */
Radek Krejci0c0086a2016-03-24 15:20:28 +01001063 if (!(options & LYD_OPT_KEEPEMPTYCONT) && schema->nodetype == LYS_CONTAINER && !result->child &&
Radek Krejcid3e73722016-05-23 12:24:55 +02001064 !result->attr && !((struct lys_node_container *)schema)->presence) {
Michal Vaskoc4280842016-04-19 16:10:42 +02001065 if (unres_data_add(unres, result, UNRES_EMPTYCONT)) {
1066 goto error;
1067 }
Radek Krejci0c0086a2016-03-24 15:20:28 +01001068 }
1069
Radek Krejci5449d472015-10-26 14:35:56 +01001070 } else if (schema->nodetype == LYS_LIST) {
1071 if (data[len] != '[') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001072 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing begin-array)");
Radek Krejci5449d472015-10-26 14:35:56 +01001073 goto error;
1074 }
1075
1076 list = result;
1077 do {
1078 len++;
1079 len += skip_ws(&data[len]);
Radek Krejci23238922015-10-27 17:13:34 +01001080
Radek Krejcic4831272015-11-01 19:26:34 +01001081 if (data[len] != '{') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001082 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result,
Radek Krejciadb57612016-02-16 13:34:34 +01001083 "JSON data (missing list instance's begin-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001084 goto error;
1085 }
Radek Krejcic4831272015-11-01 19:26:34 +01001086 diter = NULL;
1087 attrs_aux = NULL;
1088 do {
1089 len++;
1090 len += skip_ws(&data[len]);
1091
Radek Krejcibd930122016-08-10 13:28:26 +02001092 r = json_parse_data(ctx, &data[len], NULL, &list, list->child, diter, &attrs_aux, options, unres);
Radek Krejcic4831272015-11-01 19:26:34 +01001093 if (!r) {
1094 goto error;
1095 }
1096 len += r;
1097
Radek Krejci52934692015-11-01 20:08:15 +01001098 if (list->child) {
Radek Krejcic4831272015-11-01 19:26:34 +01001099 diter = list->child->prev;
1100 }
1101 } while(data[len] == ',');
1102
1103 /* store attributes */
Radek Krejci52934692015-11-01 20:08:15 +01001104 if (store_attrs(ctx, attrs_aux, list->child)) {
Radek Krejcic4831272015-11-01 19:26:34 +01001105 goto error;
1106 }
1107
1108 if (data[len] != '}') {
1109 /* expecting end-object */
Radek Krejci48464ed2016-03-17 15:44:09 +01001110 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result,
Radek Krejciadb57612016-02-16 13:34:34 +01001111 "JSON data (missing list instance's end-object)");
Radek Krejcic4831272015-11-01 19:26:34 +01001112 goto error;
1113 }
1114 len++;
Radek Krejci5449d472015-10-26 14:35:56 +01001115 len += skip_ws(&data[len]);
1116
1117 if (data[len] == ',') {
Radek Krejci93fab982016-02-03 15:58:19 +01001118 /* various validation checks */
1119 ly_errno = 0;
Radek Krejci2d5525d2016-04-04 15:43:30 +02001120 if (!(options & LYD_OPT_TRUSTED) &&
1121 (lyv_data_content(list, options, unres) ||
Radek Krejci76fed2b2016-04-11 14:55:23 +02001122 lyv_multicases(list, NULL, first_sibling == list ? NULL : first_sibling, 0, NULL))) {
Radek Krejci93fab982016-02-03 15:58:19 +01001123 if (ly_errno) {
1124 goto error;
1125 }
1126 }
1127 /* validation successful */
1128 list->validity = LYD_VAL_OK;
1129
Radek Krejci5449d472015-10-26 14:35:56 +01001130 /* another instance of the list */
1131 new = calloc(1, sizeof *new);
Michal Vasko253035f2015-12-17 16:58:13 +01001132 if (!new) {
1133 goto error;
1134 }
Radek Krejci5449d472015-10-26 14:35:56 +01001135 new->parent = list->parent;
1136 new->prev = list;
1137 list->next = new;
1138
1139 /* fix the "last" pointer */
Radek Krejci2d5525d2016-04-04 15:43:30 +02001140 first_sibling->prev = new;
Radek Krejci5449d472015-10-26 14:35:56 +01001141
1142 new->schema = list->schema;
Radek Krejci5449d472015-10-26 14:35:56 +01001143 list = new;
1144 }
1145 } while (data[len] == ',');
Michal Vaskod171d4e2016-06-06 13:33:19 +02001146 result = first_sibling;
Radek Krejci5449d472015-10-26 14:35:56 +01001147
1148 if (data[len] != ']') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001149 LOGVAL(LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing end-array)");
Radek Krejci5449d472015-10-26 14:35:56 +01001150 goto error;
1151 }
1152 len++;
1153 len += skip_ws(&data[len]);
1154 }
1155
1156 /* various validation checks */
Michal Vasko10e586f2016-05-18 13:25:30 +02001157 if (!(options & LYD_OPT_TRUSTED) && lyv_data_context(result, options, unres)) {
1158 goto error;
1159 }
1160
Radek Krejci5449d472015-10-26 14:35:56 +01001161 ly_errno = 0;
Radek Krejci2d5525d2016-04-04 15:43:30 +02001162 if (!(options & LYD_OPT_TRUSTED) &&
1163 (lyv_data_content(result, options, unres) ||
Radek Krejci76fed2b2016-04-11 14:55:23 +02001164 lyv_multicases(result, NULL, first_sibling == result ? NULL : first_sibling, 0, NULL))) {
Radek Krejci5449d472015-10-26 14:35:56 +01001165 if (ly_errno) {
1166 goto error;
1167 }
1168 }
1169
Radek Krejcica7efb72016-01-18 13:06:01 +01001170 /* validation successful */
Radek Krejci63b79c82016-08-10 10:09:33 +02001171 if (result->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
1172 /* postpone checking when there will be all list/leaflist instances */
1173 result->validity = LYD_VAL_UNIQUE;
1174 } else {
1175 result->validity = LYD_VAL_OK;
1176 }
Radek Krejcica7efb72016-01-18 13:06:01 +01001177
Radek Krejci88f29302015-10-30 15:42:33 +01001178 if (!(*parent)) {
1179 *parent = result;
1180 }
1181
Radek Krejcide9d92c2015-10-30 15:59:59 +01001182 free(str);
Radek Krejci5449d472015-10-26 14:35:56 +01001183 return len;
1184
1185error:
Radek Krejci0c0086a2016-03-24 15:20:28 +01001186 len = 0;
Radek Krejci0c0086a2016-03-24 15:20:28 +01001187 /* cleanup */
1188 for (i = unres->count - 1; i >= 0; i--) {
1189 /* remove unres items connected with the node being removed */
1190 if (unres->node[i] == result) {
1191 unres_data_del(unres, i);
1192 }
Radek Krejci88f29302015-10-30 15:42:33 +01001193 }
1194 while (*attrs) {
Radek Krejcic4831272015-11-01 19:26:34 +01001195 attrs_aux = *attrs;
Radek Krejci88f29302015-10-30 15:42:33 +01001196 *attrs = (*attrs)->next;
1197
Radek Krejcic4831272015-11-01 19:26:34 +01001198 lyd_free_attr(ctx, NULL, attrs_aux->attr, 1);
1199 free(attrs_aux);
Radek Krejci88f29302015-10-30 15:42:33 +01001200 }
1201
Radek Krejci5449d472015-10-26 14:35:56 +01001202 lyd_free(result);
Radek Krejci88f29302015-10-30 15:42:33 +01001203 free(str);
1204
Radek Krejci0c0086a2016-03-24 15:20:28 +01001205 return len;
Radek Krejci5449d472015-10-26 14:35:56 +01001206}
1207
1208struct lyd_node *
Michal Vasko36ef6932015-12-01 14:30:17 +01001209lyd_parse_json(struct ly_ctx *ctx, const struct lys_node *parent, const char *data, int options)
Radek Krejci5449d472015-10-26 14:35:56 +01001210{
Radek Krejcic4831272015-11-01 19:26:34 +01001211 struct lyd_node *result = NULL, *next = NULL, *iter = NULL;
Radek Krejci5449d472015-10-26 14:35:56 +01001212 struct unres_data *unres = NULL;
Radek Krejcic4831272015-11-01 19:26:34 +01001213 unsigned int len = 0, r;
Radek Krejci63b79c82016-08-10 10:09:33 +02001214 int i;
Radek Krejcic4831272015-11-01 19:26:34 +01001215 struct attr_cont *attrs = NULL;
Radek Krejci63b79c82016-08-10 10:09:33 +02001216 struct ly_set *set;
Radek Krejci5449d472015-10-26 14:35:56 +01001217
Radek Krejci2342cf62016-01-29 16:48:23 +01001218 ly_errno = LY_SUCCESS;
1219
Michal Vasko0a073da2016-05-10 15:48:40 +02001220 if (!ctx || !data || (options & LYD_OPT_RPCREPLY)) {
Radek Krejci5449d472015-10-26 14:35:56 +01001221 LOGERR(LY_EINVAL, "%s: Invalid parameter.", __func__);
1222 return NULL;
1223 }
1224
Radek Krejcic4831272015-11-01 19:26:34 +01001225 /* skip leading whitespaces */
1226 len += skip_ws(&data[len]);
1227
Michal Vasko24d982f2016-04-18 15:13:58 +02001228 /* no data (or whitespaces only) are fine */
1229 if (!data[len]) {
1230 lyd_validate(&result, options, ctx);
1231 return result;
1232 }
1233
Radek Krejcic4831272015-11-01 19:26:34 +01001234 /* expect top-level { */
1235 if (data[len] != '{') {
Radek Krejci48464ed2016-03-17 15:44:09 +01001236 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top level begin-object)");
Michal Vasko24d982f2016-04-18 15:13:58 +02001237 return NULL;
1238 }
1239
1240 unres = calloc(1, sizeof *unres);
1241 if (!unres) {
1242 LOGMEM;
1243 return NULL;
Radek Krejcic4831272015-11-01 19:26:34 +01001244 }
1245
1246 do {
1247 len++;
1248 len += skip_ws(&data[len]);
1249
Radek Krejcibd930122016-08-10 13:28:26 +02001250 r = json_parse_data(ctx, &data[len], parent, &next, result, iter, &attrs, options, unres);
Radek Krejcic4831272015-11-01 19:26:34 +01001251 if (!r) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001252 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001253 }
1254 len += r;
1255
1256 if (!result) {
1257 result = next;
1258 }
1259 if (next) {
1260 iter = next;
1261 }
1262 next = NULL;
1263 } while(data[len] == ',');
1264
1265 if (data[len] != '}') {
1266 /* expecting end-object */
Radek Krejci48464ed2016-03-17 15:44:09 +01001267 LOGVAL(LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top-level end-object)");
Michal Vasko24d982f2016-04-18 15:13:58 +02001268 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001269 }
1270 len++;
1271 len += skip_ws(&data[len]);
1272
1273 /* store attributes */
1274 if (store_attrs(ctx, attrs, result)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001275 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001276 }
Radek Krejci5449d472015-10-26 14:35:56 +01001277
Michal Vaskoc1cf86f2015-11-04 09:54:51 +01001278 if (!result) {
1279 LOGERR(LY_EVALID, "Model for the data to be linked with not found.");
Michal Vasko24d982f2016-04-18 15:13:58 +02001280 goto error;
Michal Vaskoc1cf86f2015-11-04 09:54:51 +01001281 }
1282
Radek Krejci63b79c82016-08-10 10:09:33 +02001283 /* check for uniquness of top-level lists/leaflists because
1284 * only the inner instances were tested in lyv_data_content() */
1285 set = ly_set_new();
1286 LY_TREE_FOR(result, iter) {
1287 if (!(iter->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(iter->validity & LYD_VAL_UNIQUE)) {
1288 continue;
1289 }
1290
1291 /* check each list/leaflist only once */
1292 i = set->number;
1293 if (ly_set_add(set, iter->schema, 0) != i) {
1294 /* already checked */
1295 continue;
1296 }
1297
1298 if (lyv_data_unique(iter, result)) {
1299 ly_set_free(set);
1300 goto error;
1301 }
1302 }
1303 ly_set_free(set);
1304
Michal Vasko24d982f2016-04-18 15:13:58 +02001305 /* check for missing top level mandatory nodes */
Michal Vasko587bdc32016-07-21 09:12:55 +02001306 if (!(options & LYD_OPT_TRUSTED) && lyd_check_topmandatory(result, ctx, options)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001307 goto error;
Radek Krejci5c162452016-03-23 13:36:01 +01001308 }
1309
Michal Vasko24d982f2016-04-18 15:13:58 +02001310 /* add/validate default values, unres */
Michal Vaskocd5dbe12016-05-12 10:56:38 +02001311 if (lyd_defaults_add_unres(&result, options, ctx, unres)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001312 goto error;
Radek Krejci5c162452016-03-23 13:36:01 +01001313 }
1314
Radek Krejci5449d472015-10-26 14:35:56 +01001315 free(unres->node);
1316 free(unres->type);
Radek Krejci5449d472015-10-26 14:35:56 +01001317 free(unres);
1318
1319 return result;
Michal Vasko24d982f2016-04-18 15:13:58 +02001320
1321error:
1322 lyd_free_withsiblings(result);
1323 free(unres->node);
1324 free(unres->type);
1325 free(unres);
1326
1327 return NULL;
Radek Krejci5449d472015-10-26 14:35:56 +01001328}