blob: a5c221f1ee66721bc36483634b463aa2e078e27a [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 *
Michal Vasko53b7da02018-02-13 15:28:42 +010060lyjson_parse_text(struct ly_ctx *ctx, const char *data, unsigned int *len)
Radek Krejci5449d472015-10-26 14:35:56 +010061{
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);
Michal Vasko53b7da02018-02-13 15:28:42 +010076 LY_CHECK_ERR_RETURN(!aux, LOGMEM(ctx), NULL);
Radek Krejci5449d472015-10-26 14:35:56 +010077 result = aux;
78 } else {
79 size = o;
80 result = malloc((size + 1) * sizeof *result);
Michal Vasko53b7da02018-02-13 15:28:42 +010081 LY_CHECK_ERR_RETURN(!result, LOGMEM(ctx), NULL);
Radek Krejci5449d472015-10-26 14:35:56 +010082 }
83 memcpy(&result[size - o], buf, o);
84
85 /* write again into the beginning of the buffer */
86 o = 0;
87 }
88
89 if (data[*len] == '\\') {
90 /* parse escape sequence */
91 (*len)++;
92 i = 1;
93 switch (data[(*len)]) {
94 case '"':
95 /* quotation mark */
96 value = 0x22;
97 break;
98 case '\\':
99 /* reverse solidus */
100 value = 0x5c;
101 break;
102 case '/':
103 /* solidus */
104 value = 0x2f;
105 break;
106 case 'b':
107 /* backspace */
108 value = 0x08;
109 break;
110 case 'f':
111 /* form feed */
112 value = 0x0c;
113 break;
114 case 'n':
115 /* line feed */
116 value = 0x0a;
117 break;
118 case 'r':
119 /* carriage return */
120 value = 0x0d;
121 break;
122 case 't':
123 /* tab */
124 value = 0x09;
125 break;
126 case 'u':
127 /* Basic Multilingual Plane character \uXXXX */
128 (*len)++;
129 for (value = i = 0; i < 4; i++) {
130 if (isdigit(data[(*len) + i])) {
131 r = (data[(*len) + i] - '0');
132 } else if (data[(*len) + i] > 'F') {
133 r = 10 + (data[(*len) + i] - 'a');
134 } else {
135 r = 10 + (data[(*len) + i] - 'A');
136 }
137 value = (16 * value) + r;
138 }
139 break;
140 default:
141 /* invalid escape sequence */
Michal Vasko53b7da02018-02-13 15:28:42 +0100142 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "character escape sequence");
Radek Krejci5449d472015-10-26 14:35:56 +0100143 goto error;
144
145 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100146 r = pututf8(ctx, &buf[o], value);
Radek Krejci5449d472015-10-26 14:35:56 +0100147 if (!r) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100148 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "character UTF8 character");
Radek Krejci5449d472015-10-26 14:35:56 +0100149 goto error;
150 }
151 o += r - 1; /* o is ++ in for loop */
152 (*len) += i; /* number of read characters */
Jan Kundrátf5cbb962018-08-24 14:17:35 +0200153 } else if ((unsigned char)(data[*len]) < 0x20) {
154 /* In C, char != unsigned char != signed char, so let's work with ASCII explicitly */
Radek Krejci5449d472015-10-26 14:35:56 +0100155 /* control characters must be escaped */
Michal Vasko53b7da02018-02-13 15:28:42 +0100156 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "control character (unescaped)");
Radek Krejci5449d472015-10-26 14:35:56 +0100157 goto error;
158 } else {
159 /* unescaped character */
Michal Vasko53b7da02018-02-13 15:28:42 +0100160 r = copyutf8(ctx, &buf[o], &data[*len]);
Radek Krejcideee60e2016-09-23 15:21:14 +0200161 if (!r) {
162 goto error;
163 }
164
165 o += r - 1; /* o is ++ in for loop */
166 (*len) += r;
Radek Krejci5449d472015-10-26 14:35:56 +0100167 }
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);
Michal Vasko53b7da02018-02-13 15:28:42 +0100176 LY_CHECK_ERR_RETURN(!aux, LOGMEM(ctx), NULL);
Radek Krejci5449d472015-10-26 14:35:56 +0100177 result = aux;
178 } else {
179 size = o;
180 result = malloc((size + 1) * sizeof *result);
Michal Vasko53b7da02018-02-13 15:28:42 +0100181 LY_CHECK_ERR_RETURN(!result, LOGMEM(ctx), NULL);
Radek Krejci5449d472015-10-26 14:35:56 +0100182 }
183 memcpy(&result[size - o], buf, o);
184 }
185 if (result) {
186 result[size] = '\0';
187 } else {
188 size = 0;
189 result = strdup("");
Michal Vasko53b7da02018-02-13 15:28:42 +0100190 LY_CHECK_ERR_RETURN(!result, LOGMEM(ctx), NULL);
Radek Krejci5449d472015-10-26 14:35:56 +0100191 }
192
193 return result;
194
195error:
196 free(result);
197 return NULL;
198}
199
200static unsigned int
Michal Vasko53b7da02018-02-13 15:28:42 +0100201lyjson_parse_number(struct ly_ctx *ctx, const char *data)
Radek Krejci5449d472015-10-26 14:35:56 +0100202{
Michal Vasko8f32c112016-05-18 13:22:59 +0200203 unsigned int len = 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100204
Michal Vasko8f32c112016-05-18 13:22:59 +0200205 if (data[len] == '-') {
206 ++len;
207 }
Radek Krejci5449d472015-10-26 14:35:56 +0100208
Michal Vasko8f32c112016-05-18 13:22:59 +0200209 if (data[len] == '0') {
210 ++len;
211 } else if (isdigit(data[len])) {
212 ++len;
213 while (isdigit(data[len])) {
214 ++len;
215 }
216 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100217 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value ('%c').", data[len]);
Michal Vasko8f32c112016-05-18 13:22:59 +0200218 return 0;
219 }
220
221 if (data[len] == '.') {
222 ++len;
223 if (!isdigit(data[len])) {
224 if (data[len]) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100225 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value ('%c').", data[len]);
Michal Vasko8f32c112016-05-18 13:22:59 +0200226 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100227 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value (EOF).");
Radek Krejci5449d472015-10-26 14:35:56 +0100228 }
Radek Krejci5449d472015-10-26 14:35:56 +0100229 return 0;
230 }
Michal Vasko8f32c112016-05-18 13:22:59 +0200231 while (isdigit(data[len])) {
232 ++len;
233 }
234 }
235
Michal Vasko1e676ca2016-06-24 15:23:54 +0200236 if ((data[len] == 'e') || (data[len] == 'E')) {
237 ++len;
238 if ((data[len] == '+') || (data[len] == '-')) {
239 ++len;
240 }
241 while (isdigit(data[len])) {
242 ++len;
243 }
244 }
245
Michal Vasko8f32c112016-05-18 13:22:59 +0200246 if (data[len] && (data[len] != ',') && (data[len] != ']') && (data[len] != '}') && !lyjson_isspace(data[len])) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100247 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid character in JSON Number value ('%c').", data[len]);
Michal Vasko8f32c112016-05-18 13:22:59 +0200248 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100249 }
250
251 return len;
252}
253
Michal Vasko1e676ca2016-06-24 15:23:54 +0200254static char *
Michal Vasko53b7da02018-02-13 15:28:42 +0100255lyjson_convert_enumber(struct ly_ctx *ctx, const char *number, unsigned int num_len, char *e_ptr)
Michal Vasko1e676ca2016-06-24 15:23:54 +0200256{
257 char *ptr, *num;
258 const char *number_ptr;
259 long int e_val;
260 int dot_pos, chars_to_dot, minus;
261 unsigned int num_len_no_e;
262
263 if (*number == '-') {
264 minus = 1;
265 ++number;
266 --num_len;
267 } else {
268 minus = 0;
269 }
270
271 num_len_no_e = e_ptr - number;
272
273 errno = 0;
274 ++e_ptr;
275 e_val = strtol(e_ptr, &ptr, 10);
276 if (errno) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100277 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Exponent out-of-bounds in a JSON Number value (%.*s).",
Michal Vasko1e676ca2016-06-24 15:23:54 +0200278 num_len - (e_ptr - number), e_ptr);
279 return NULL;
280 } else if (ptr != number + num_len) {
281 /* we checked this already */
Michal Vasko53b7da02018-02-13 15:28:42 +0100282 LOGINT(ctx);
Michal Vasko1e676ca2016-06-24 15:23:54 +0200283 return NULL;
284 }
285
286 if ((ptr = strnchr(number, '.', num_len_no_e))) {
287 dot_pos = ptr - number;
288 } else {
289 dot_pos = num_len_no_e;
290 }
291
292 dot_pos += e_val;
293
294 /* allocate enough memory */
295 if (dot_pos < 1) {
296 /* (.XXX)XXX[.]XXXX */
297 num = malloc((minus ? 1 : 0) + -dot_pos + 2 + (num_len_no_e - (ptr ? 1 : 0)) + 1);
298 } else if (dot_pos < (signed)num_len_no_e) {
299 /* XXXX(.)XX.XXX */
300 num = malloc((minus ? 1 : 0) + num_len_no_e + (ptr ? 0 : 1) + 1);
301 } else {
302 /* XXX[.]XXXX(XXX.) */
303 num = malloc((minus ? 1 : 0) + (dot_pos - (ptr ? 2 : 1)) + 1);
304 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100305 LY_CHECK_ERR_RETURN(!num, LOGMEM(ctx), NULL);
Michal Vasko1e676ca2016-06-24 15:23:54 +0200306 if (minus) {
307 strcpy(num, "-");
308 } else {
309 num[0] = '\0';
310 }
311
312 if (dot_pos < 1) {
313 strcat(num, "0.");
314 }
315 if (dot_pos < 0) {
316 sprintf(num + strlen(num), "%0*d", -dot_pos, 0);
317 }
318
319 chars_to_dot = dot_pos;
Michal Vasko9d1593d2016-09-30 12:33:34 +0200320 for (ptr = num + strlen(num), number_ptr = number; (unsigned)(number_ptr - number) < num_len_no_e; ) {
Michal Vasko1e676ca2016-06-24 15:23:54 +0200321 if (!chars_to_dot) {
322 *ptr = '.';
323 ++ptr;
324 chars_to_dot = -1;
325 } else if (isdigit(*number_ptr)) {
326 *ptr = *number_ptr;
327 ++ptr;
328 ++number_ptr;
329 if (chars_to_dot > 0) {
330 --chars_to_dot;
331 }
332 } else if (*number_ptr == '.') {
333 ++number_ptr;
334 } else {
Michal Vasko53b7da02018-02-13 15:28:42 +0100335 LOGINT(ctx);
Michal Vasko1e676ca2016-06-24 15:23:54 +0200336 free(num);
337 return NULL;
338 }
339 }
340 *ptr = '\0';
341
342 if (dot_pos > (signed)num_len_no_e) {
343 sprintf(num + strlen(num), "%0*d", dot_pos - num_len_no_e, 0);
344 }
345
346 return num;
347}
348
Radek Krejci5449d472015-10-26 14:35:56 +0100349static unsigned int
Michal Vasko53b7da02018-02-13 15:28:42 +0100350lyjson_parse_boolean(struct ly_ctx *ctx, const char *data)
Radek Krejci5449d472015-10-26 14:35:56 +0100351{
Radek Krejci6b47b502015-10-30 15:52:41 +0100352 unsigned int len = 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100353
354 if (!strncmp(data, "false", 5)) {
355 len = 5;
356 } else if (!strncmp(data, "true", 4)) {
357 len = 4;
358 }
359
360 if (data[len] && data[len] != ',' && data[len] != ']' && data[len] != '}' && !lyjson_isspace(data[len])) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100361 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON literal value (expected true or false)");
Radek Krejci5449d472015-10-26 14:35:56 +0100362 return 0;
363 }
364
365 return len;
366}
367
368static unsigned int
Radek Krejci4ae82942016-09-19 16:41:06 +0200369json_get_anydata(struct lyd_node_anydata *any, const char *data)
Radek Krejci5449d472015-10-26 14:35:56 +0100370{
Michal Vasko53b7da02018-02-13 15:28:42 +0100371 struct ly_ctx *ctx = any->schema->module->ctx;
Michal Vasko9696e4d2018-05-28 08:28:31 +0200372 unsigned int len = 0, c = 0;
Radek Krejcia7177672016-11-17 14:53:03 +0900373 char *str;
Radek Krejci5449d472015-10-26 14:35:56 +0100374
Michal Vasko9696e4d2018-05-28 08:28:31 +0200375 if (data[len] == '"') {
Radek Krejcia7177672016-11-17 14:53:03 +0900376 len = 1;
Michal Vasko53b7da02018-02-13 15:28:42 +0100377 str = lyjson_parse_text(ctx, &data[len], &c);
Radek Krejcia7177672016-11-17 14:53:03 +0900378 if (!str) {
379 return 0;
380 }
381 if (data[len + c] != '"') {
Radek Krejci7d6d2842016-11-28 11:21:38 +0100382 free(str);
Michal Vasko53b7da02018-02-13 15:28:42 +0100383 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, any,
Radek Krejcia7177672016-11-17 14:53:03 +0900384 "JSON data (missing quotation-mark at the end of string)");
385 return 0;
386 }
387
Michal Vasko53b7da02018-02-13 15:28:42 +0100388 any->value.str = lydict_insert_zc(ctx, str);
Radek Krejcia7177672016-11-17 14:53:03 +0900389 any->value_type = LYD_ANYDATA_CONSTSTRING;
390 return len + c + 1;
391 } else if (data[len] != '{') {
Michal Vasko9696e4d2018-05-28 08:28:31 +0200392 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, any, "anydata/anyxml content (not an object nor string)");
Michal Vaskoa19f7d72016-05-18 13:24:08 +0200393 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100394 }
395
Radek Krejcia7177672016-11-17 14:53:03 +0900396 /* count opening '{' and closing '}' brackets to get the end of the object without its parsing */
Michal Vasko9696e4d2018-05-28 08:28:31 +0200397 c = len = 0;
398 do {
Radek Krejci4ae82942016-09-19 16:41:06 +0200399 switch (data[len]) {
400 case '{':
401 c++;
402 break;
403 case '}':
404 c--;
405 break;
406 default:
Michal Vasko9696e4d2018-05-28 08:28:31 +0200407 break;
Radek Krejci4ae82942016-09-19 16:41:06 +0200408 }
409 len++;
Michal Vasko9696e4d2018-05-28 08:28:31 +0200410 } while (data[len] && c);
Radek Krejci4ae82942016-09-19 16:41:06 +0200411 if (c) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100412 LOGVAL(ctx, LYE_EOF, LY_VLOG_LYD, any);
Radek Krejci4ae82942016-09-19 16:41:06 +0200413 return 0;
414 }
Michal Vasko9696e4d2018-05-28 08:28:31 +0200415
Radek Krejci4ae82942016-09-19 16:41:06 +0200416 any->value_type = LYD_ANYDATA_JSON;
Michal Vasko9696e4d2018-05-28 08:28:31 +0200417 any->value.str = lydict_insert(ctx, data, len);
Radek Krejci4ae82942016-09-19 16:41:06 +0200418
Michal Vaskoa19f7d72016-05-18 13:24:08 +0200419 return len;
Radek Krejci5449d472015-10-26 14:35:56 +0100420}
421
422static unsigned int
Radek Krejci45f41dd2017-02-09 14:11:09 +0100423json_get_value(struct lyd_node_leaf_list *leaf, struct lyd_node **first_sibling, const char *data, int options,
424 struct unres_data *unres)
Radek Krejci5449d472015-10-26 14:35:56 +0100425{
Radek Krejcibd930122016-08-10 13:28:26 +0200426 struct lyd_node_leaf_list *new;
Radek Krejci37b756f2016-01-18 10:15:03 +0100427 struct lys_type *stype;
Radek Krejci5449d472015-10-26 14:35:56 +0100428 struct ly_ctx *ctx;
429 unsigned int len = 0, r;
Radek Krejci5449d472015-10-26 14:35:56 +0100430 char *str;
431
Radek Krejci0b7704f2016-03-18 12:16:14 +0100432 assert(leaf && data);
Radek Krejci5449d472015-10-26 14:35:56 +0100433 ctx = leaf->schema->module->ctx;
434
435 stype = &((struct lys_node_leaf *)leaf->schema)->type;
Radek Krejci23238922015-10-27 17:13:34 +0100436
Radek Krejci5449d472015-10-26 14:35:56 +0100437 if (leaf->schema->nodetype == LYS_LEAFLIST) {
438 /* expecting begin-array */
439 if (data[len++] != '[') {
Michal Vasko53b7da02018-02-13 15:28:42 +0100440 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expected begin-array)");
Radek Krejci5449d472015-10-26 14:35:56 +0100441 return 0;
442 }
443
444repeat:
445 len += skip_ws(&data[len]);
446 }
447
448 /* will be changed in case of union */
449 leaf->value_type = stype->base;
450
451 if (data[len] == '"') {
452 /* string representations */
Michal Vasko6baed1c2016-05-18 13:24:44 +0200453 ++len;
Michal Vasko53b7da02018-02-13 15:28:42 +0100454 str = lyjson_parse_text(ctx, &data[len], &r);
Radek Krejci23238922015-10-27 17:13:34 +0100455 if (!str) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100456 LOGPATH(ctx, LY_VLOG_LYD, leaf);
Radek Krejci5449d472015-10-26 14:35:56 +0100457 return 0;
458 }
459 leaf->value_str = lydict_insert_zc(ctx, str);
460 if (data[len + r] != '"') {
Michal Vasko53b7da02018-02-13 15:28:42 +0100461 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, leaf,
Radek Krejciadb57612016-02-16 13:34:34 +0100462 "JSON data (missing quotation-mark at the end of string)");
Radek Krejci5449d472015-10-26 14:35:56 +0100463 return 0;
464 }
465 len += r + 1;
466 } else if (data[len] == '-' || isdigit(data[len])) {
467 /* numeric type */
Michal Vasko53b7da02018-02-13 15:28:42 +0100468 r = lyjson_parse_number(ctx, &data[len]);
Radek Krejci5449d472015-10-26 14:35:56 +0100469 if (!r) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100470 LOGPATH(ctx, LY_VLOG_LYD, leaf);
Radek Krejci5449d472015-10-26 14:35:56 +0100471 return 0;
472 }
Michal Vasko1e676ca2016-06-24 15:23:54 +0200473 /* if it's a number with 'e' or 'E', get rid of it first */
474 if ((str = strnchr(&data[len], 'e', r)) || (str = strnchr(&data[len], 'E', r))) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100475 str = lyjson_convert_enumber(ctx, &data[len], r, str);
Michal Vasko1e676ca2016-06-24 15:23:54 +0200476 if (!str) {
477 return 0;
478 }
479 leaf->value_str = lydict_insert_zc(ctx, str);
480 } else {
481 leaf->value_str = lydict_insert(ctx, &data[len], r);
482 }
Radek Krejci5449d472015-10-26 14:35:56 +0100483 len += r;
484 } else if (data[len] == 'f' || data[len] == 't') {
485 /* boolean */
Michal Vasko53b7da02018-02-13 15:28:42 +0100486 r = lyjson_parse_boolean(ctx, &data[len]);
Radek Krejci5449d472015-10-26 14:35:56 +0100487 if (!r) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100488 LOGPATH(ctx, LY_VLOG_LYD, leaf);
Radek Krejci5449d472015-10-26 14:35:56 +0100489 return 0;
490 }
491 leaf->value_str = lydict_insert(ctx, &data[len], r);
492 len += r;
493 } else if (!strncmp(&data[len], "[null]", 6)) {
494 /* empty */
Michal Vasko44913842016-04-13 14:20:41 +0200495 leaf->value_str = lydict_insert(ctx, "", 0);
Radek Krejci5449d472015-10-26 14:35:56 +0100496 len += 6;
497 } else {
498 /* error */
Michal Vasko53b7da02018-02-13 15:28:42 +0100499 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (unexpected value)");
Radek Krejci5449d472015-10-26 14:35:56 +0100500 return 0;
501 }
502
Radek Krejci1899d6a2016-11-03 13:48:07 +0100503 /* the value is here converted to a JSON format if needed in case of LY_TYPE_IDENT and LY_TYPE_INST or to a
504 * canonical form of the value */
Michal Vasko35f46a82018-05-30 10:44:11 +0200505 if (!lyp_parse_value(&((struct lys_node_leaf *)leaf->schema)->type, &leaf->value_str, NULL, leaf, NULL, NULL,
506 1, 0, options & LYD_OPT_TRUSTED)) {
Radek Krejci23238922015-10-27 17:13:34 +0100507 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100508 }
509
Michal Vasko24affa02018-04-03 09:06:06 +0200510#ifdef LY_ENABLED_CACHE
511 /* calculate the hash and insert it into parent */
512 lyd_hash((struct lyd_node *)leaf);
513 lyd_insert_hash((struct lyd_node *)leaf);
514#endif
515
Radek Krejci5449d472015-10-26 14:35:56 +0100516 if (leaf->schema->nodetype == LYS_LEAFLIST) {
517 /* repeat until end-array */
518 len += skip_ws(&data[len]);
519 if (data[len] == ',') {
Radek Krejci45f41dd2017-02-09 14:11:09 +0100520 /* various validation checks */
fanchanghucdb16a12018-09-18 10:54:05 +0800521 if (lyv_data_context((struct lyd_node*)leaf, options | LYD_OPT_TRUSTED, unres) ||
Michal Vasko53b7da02018-02-13 15:28:42 +0100522 lyv_data_content((struct lyd_node*)leaf, options, unres) ||
523 lyv_multicases((struct lyd_node*)leaf, NULL, first_sibling, 0, NULL)) {
Radek Krejci45f41dd2017-02-09 14:11:09 +0100524 return 0;
525 }
526
Radek Krejci5449d472015-10-26 14:35:56 +0100527 /* another instance of the leaf-list */
528 new = calloc(1, sizeof(struct lyd_node_leaf_list));
Michal Vasko53b7da02018-02-13 15:28:42 +0100529 LY_CHECK_ERR_RETURN(!new, LOGMEM(ctx), 0);
Radek Krejcia8d111f2017-05-31 13:57:37 +0200530
Radek Krejci5449d472015-10-26 14:35:56 +0100531 new->parent = leaf->parent;
532 new->prev = (struct lyd_node *)leaf;
533 leaf->next = (struct lyd_node *)new;
534
Radek Krejcie1794882017-02-08 13:23:38 +0100535 /* copy the validity and when flags */
536 new->validity = leaf->validity;
537 new->when_status = leaf->when_status;
538
Radek Krejci5449d472015-10-26 14:35:56 +0100539 /* fix the "last" pointer */
Radek Krejci45f41dd2017-02-09 14:11:09 +0100540 (*first_sibling)->prev = (struct lyd_node *)new;
Radek Krejci5449d472015-10-26 14:35:56 +0100541
542 new->schema = leaf->schema;
543
544 /* repeat value parsing */
545 leaf = new;
546 len++;
547 goto repeat;
548 } else if (data[len] == ']') {
549 len++;
550 len += skip_ws(&data[len]);
551 } else {
552 /* something unexpected */
Michal Vasko53b7da02018-02-13 15:28:42 +0100553 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, leaf, "JSON data (expecting value-separator or end-array)");
Radek Krejci5449d472015-10-26 14:35:56 +0100554 return 0;
555 }
556 }
557
558 len += skip_ws(&data[len]);
559 return len;
560}
561
562static unsigned int
Radek Krejci532e5e92017-02-22 12:59:24 +0100563json_parse_attr(struct lys_module *parent_module, struct lyd_attr **attr, const char *data, int options)
Radek Krejci88f29302015-10-30 15:42:33 +0100564{
Michal Vasko53b7da02018-02-13 15:28:42 +0100565 struct ly_ctx *ctx = parent_module->ctx;
Radek Krejci88f29302015-10-30 15:42:33 +0100566 unsigned int len = 0, r;
Radek Krejci532e5e92017-02-22 12:59:24 +0100567 char *str = NULL, *name, *prefix = NULL, *value;
Radek Krejci88f29302015-10-30 15:42:33 +0100568 struct lys_module *module = parent_module;
569 struct lyd_attr *attr_new, *attr_last = NULL;
Michal Vasko7675c622017-03-02 10:50:07 +0100570 int ret;
Radek Krejci88f29302015-10-30 15:42:33 +0100571
Radek Krejcide9d92c2015-10-30 15:59:59 +0100572 *attr = NULL;
573
Radek Krejci88f29302015-10-30 15:42:33 +0100574 if (data[len] != '{') {
575 if (!strncmp(&data[len], "null", 4)) {
Radek Krejci88f29302015-10-30 15:42:33 +0100576 len += 4;
577 len += skip_ws(&data[len]);
578 return len;
579 }
Michal Vasko53b7da02018-02-13 15:28:42 +0100580 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing begin-object)");
Radek Krejci88f29302015-10-30 15:42:33 +0100581 goto error;
582 }
583
584repeat:
Radek Krejci6a6326d2017-02-27 13:00:52 +0100585 prefix = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100586 len++;
587 len += skip_ws(&data[len]);
588
589 if (data[len] != '"') {
David Lamparter18f74812018-11-09 14:55:59 +0100590 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing quotation-mark at the beginning of string)");
Radek Krejci88f29302015-10-30 15:42:33 +0100591 return 0;
592 }
593 len++;
Michal Vasko53b7da02018-02-13 15:28:42 +0100594 str = lyjson_parse_text(ctx, &data[len], &r);
Radek Krejci88f29302015-10-30 15:42:33 +0100595 if (!r) {
596 goto error;
597 } else if (data[len + r] != '"') {
Michal Vasko53b7da02018-02-13 15:28:42 +0100598 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing quotation-mark at the end of string)");
Radek Krejci88f29302015-10-30 15:42:33 +0100599 goto error;
600 }
601 if ((name = strchr(str, ':'))) {
602 *name = '\0';
603 name++;
604 prefix = str;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200605 module = (struct lys_module *)ly_ctx_get_module(parent_module->ctx, prefix, NULL, 0);
Radek Krejci88f29302015-10-30 15:42:33 +0100606 if (!module) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100607 LOGVAL(ctx, LYE_INELEM, LY_VLOG_NONE, NULL, name);
Radek Krejci88f29302015-10-30 15:42:33 +0100608 goto error;
609 }
610 } else {
611 name = str;
612 }
613
614 /* prepare data for parsing node content */
615 len += r + 1;
616 len += skip_ws(&data[len]);
617 if (data[len] != ':') {
Michal Vasko53b7da02018-02-13 15:28:42 +0100618 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing name-separator)");
Radek Krejci88f29302015-10-30 15:42:33 +0100619 goto error;
620 }
621 len++;
622 len += skip_ws(&data[len]);
623
624 if (data[len] != '"') {
Michal Vasko53b7da02018-02-13 15:28:42 +0100625 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing quotation-mark at the beginning of string)");
Radek Krejcide9d92c2015-10-30 15:59:59 +0100626 goto error;
Radek Krejci88f29302015-10-30 15:42:33 +0100627 }
628 len++;
Michal Vasko53b7da02018-02-13 15:28:42 +0100629 value = lyjson_parse_text(ctx, &data[len], &r);
Radek Krejci88f29302015-10-30 15:42:33 +0100630 if (!r) {
631 goto error;
632 } else if (data[len + r] != '"') {
Michal Vasko53b7da02018-02-13 15:28:42 +0100633 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing quotation-mark at the end of string)");
Radek Krejcide9d92c2015-10-30 15:59:59 +0100634 free(value);
Radek Krejci88f29302015-10-30 15:42:33 +0100635 goto error;
636 }
637 len += r + 1;
638 len += skip_ws(&data[len]);
639
Michal Vasko35f46a82018-05-30 10:44:11 +0200640 ret = lyp_fill_attr(parent_module->ctx, NULL, NULL, prefix, name, value, NULL, options, &attr_new);
Michal Vasko7675c622017-03-02 10:50:07 +0100641 if (ret == -1) {
Radek Krejci532e5e92017-02-22 12:59:24 +0100642 free(value);
Michal Vasko253035f2015-12-17 16:58:13 +0100643 goto error;
Michal Vasko7675c622017-03-02 10:50:07 +0100644 } else if (ret == 1) {
645 if (options & LYD_OPT_STRICT) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100646 LOGVAL(ctx, LYE_INMETA, LY_VLOG_NONE, NULL, prefix, name, value);
Michal Vasko7675c622017-03-02 10:50:07 +0100647 free(value);
648 goto error;
649 }
Radek Krejci532e5e92017-02-22 12:59:24 +0100650
Michal Vasko53b7da02018-02-13 15:28:42 +0100651 LOGWRN(ctx, "Unknown \"%s:%s\" metadata with value \"%s\", ignoring.",
Michal Vasko7675c622017-03-02 10:50:07 +0100652 (prefix ? prefix : "<none>"), name, value);
653 free(value);
654 goto next;
Radek Krejci532e5e92017-02-22 12:59:24 +0100655 }
Michal Vasko7675c622017-03-02 10:50:07 +0100656 free(value);
Radek Krejcia571d942017-02-24 09:26:49 +0100657
Radek Krejci88f29302015-10-30 15:42:33 +0100658 if (!attr_last) {
659 *attr = attr_last = attr_new;
660 } else {
661 attr_last->next = attr_new;
662 attr_last = attr_new;
663 }
664
Radek Krejci532e5e92017-02-22 12:59:24 +0100665next:
Radek Krejci88f29302015-10-30 15:42:33 +0100666 free(str);
Radek Krejcide9d92c2015-10-30 15:59:59 +0100667 str = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100668
669 if (data[len] == ',') {
670 goto repeat;
671 } else if (data[len] != '}') {
Michal Vasko53b7da02018-02-13 15:28:42 +0100672 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing end-object)");
Radek Krejcide9d92c2015-10-30 15:59:59 +0100673 goto error;
Radek Krejci88f29302015-10-30 15:42:33 +0100674 }
675 len++;
676 len += skip_ws(&data[len]);
677
678 return len;
679
680error:
681 free(str);
Radek Krejcide9d92c2015-10-30 15:59:59 +0100682 if (*attr) {
Radek Krejci532e5e92017-02-22 12:59:24 +0100683 lyd_free_attr(module->ctx, NULL, *attr, 1);
Radek Krejcide9d92c2015-10-30 15:59:59 +0100684 *attr = NULL;
685 }
Radek Krejci88f29302015-10-30 15:42:33 +0100686 return 0;
687}
688
689struct attr_cont {
690 struct attr_cont *next;
691 struct lyd_attr *attr;
692 struct lys_node *schema;
693 unsigned int index; /** non-zero only in case of leaf-list */
694};
695
Radek Krejcic4831272015-11-01 19:26:34 +0100696static int
Michal Vasko7675c622017-03-02 10:50:07 +0100697store_attrs(struct ly_ctx *ctx, struct attr_cont *attrs, struct lyd_node *first, int options)
Radek Krejcic4831272015-11-01 19:26:34 +0100698{
699 struct lyd_node *diter;
700 struct attr_cont *iter;
Radek Krejci532e5e92017-02-22 12:59:24 +0100701 struct lyd_attr *aiter;
Radek Krejcic4831272015-11-01 19:26:34 +0100702 unsigned int flag_leaflist = 0;
703
704 while (attrs) {
705 iter = attrs;
706 attrs = attrs->next;
707
708 if (iter->index) {
709 flag_leaflist = 1;
710 }
711
712 LY_TREE_FOR(first, diter) {
713 if (iter->schema != diter->schema) {
714 continue;
715 }
716
717 if (flag_leaflist && flag_leaflist != iter->index) {
718 flag_leaflist++;
719 continue;
720 }
721
722 /* we have match */
723 if (diter->attr) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100724 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, diter,
Radek Krejciadb57612016-02-16 13:34:34 +0100725 "attribute (multiple attribute definitions belong to a single element)");
Radek Krejcic4831272015-11-01 19:26:34 +0100726 free(iter);
727 goto error;
728 }
729
730 diter->attr = iter->attr;
Radek Krejci532e5e92017-02-22 12:59:24 +0100731 for (aiter = iter->attr; aiter; aiter = aiter->next) {
732 aiter->parent = diter;
733 }
Michal Vasko7675c622017-03-02 10:50:07 +0100734
Radek Krejcic4831272015-11-01 19:26:34 +0100735 break;
736 }
737
738 if (!diter) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100739 LOGVAL(ctx, LYE_XML_MISS, LY_VLOG_NONE, NULL, "element for the specified attribute", iter->attr->name);
Radek Krejcic4831272015-11-01 19:26:34 +0100740 lyd_free_attr(iter->schema->module->ctx, NULL, iter->attr, 1);
741 free(iter);
742 goto error;
743 }
744 free(iter);
Michal Vasko7675c622017-03-02 10:50:07 +0100745
746 /* check edit-config attribute correctness */
747 if ((options & LYD_OPT_EDIT) && lyp_check_edit_attr(ctx, diter->attr, diter, NULL)) {
748 goto error;
749 }
Radek Krejcic4831272015-11-01 19:26:34 +0100750 }
751
752 return 0;
753
754error:
755
756 while (attrs) {
757 iter = attrs;
758 attrs = attrs->next;
759
760 lyd_free_attr(ctx, NULL, iter->attr, 1);
761 free(iter);
762 }
763
764 return -1;
765}
766
Radek Krejci88f29302015-10-30 15:42:33 +0100767static unsigned int
Michal Vasko36ef6932015-12-01 14:30:17 +0100768json_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 +0200769 struct lyd_node *first_sibling, struct lyd_node *prev, struct attr_cont **attrs, int options,
PavolVican832f5432018-02-21 00:54:45 +0100770 struct unres_data *unres, struct lyd_node **act_notif, const char *yang_data_name)
Radek Krejci5449d472015-10-26 14:35:56 +0100771{
772 unsigned int len = 0;
773 unsigned int r;
Radek Krejcic4831272015-11-01 19:26:34 +0100774 unsigned int flag_leaflist = 0;
Radek Krejci65aca412018-01-24 11:23:06 +0100775 int i;
776 uint8_t pos;
Radek Krejci88f29302015-10-30 15:42:33 +0100777 char *name, *prefix = NULL, *str = NULL;
Michal Vasko1e62a092015-12-01 12:27:20 +0100778 const struct lys_module *module = NULL;
Radek Krejci5449d472015-10-26 14:35:56 +0100779 struct lys_node *schema = NULL;
PavolVican832f5432018-02-21 00:54:45 +0100780 const struct lys_node *sparent = NULL;
Radek Krejcibd930122016-08-10 13:28:26 +0200781 struct lyd_node *result = NULL, *new, *list, *diter = NULL;
Radek Krejci88f29302015-10-30 15:42:33 +0100782 struct lyd_attr *attr;
Radek Krejcic4831272015-11-01 19:26:34 +0100783 struct attr_cont *attrs_aux;
Radek Krejci5449d472015-10-26 14:35:56 +0100784
785 /* each YANG data node representation starts with string (node identifier) */
786 if (data[len] != '"') {
Michal Vasko53b7da02018-02-13 15:28:42 +0100787 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, (*parent),
Radek Krejciadb57612016-02-16 13:34:34 +0100788 "JSON data (missing quotation-mark at the beginning of string)");
Radek Krejci88f29302015-10-30 15:42:33 +0100789 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +0100790 }
791 len++;
792
Michal Vasko53b7da02018-02-13 15:28:42 +0100793 str = lyjson_parse_text(ctx, &data[len], &r);
Radek Krejci5449d472015-10-26 14:35:56 +0100794 if (!r) {
795 goto error;
796 } else if (data[len + r] != '"') {
Michal Vasko53b7da02018-02-13 15:28:42 +0100797 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, (*parent),
Radek Krejciadb57612016-02-16 13:34:34 +0100798 "JSON data (missing quotation-mark at the end of string)");
Radek Krejci5449d472015-10-26 14:35:56 +0100799 goto error;
800 }
Radek Krejci23238922015-10-27 17:13:34 +0100801 if ((name = strchr(str, ':'))) {
802 *name = '\0';
803 name++;
804 prefix = str;
Radek Krejci88f29302015-10-30 15:42:33 +0100805 if (prefix[0] == '@') {
806 prefix++;
807 }
Radek Krejci23238922015-10-27 17:13:34 +0100808 } else {
809 name = str;
Radek Krejci88f29302015-10-30 15:42:33 +0100810 if (name[0] == '@') {
811 name++;
812 }
Radek Krejci5449d472015-10-26 14:35:56 +0100813 }
814
Radek Krejci5449d472015-10-26 14:35:56 +0100815 /* prepare data for parsing node content */
816 len += r + 1;
817 len += skip_ws(&data[len]);
818 if (data[len] != ':') {
Michal Vasko53b7da02018-02-13 15:28:42 +0100819 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "JSON data (missing name-separator)");
Radek Krejci5449d472015-10-26 14:35:56 +0100820 goto error;
821 }
822 len++;
823 len += skip_ws(&data[len]);
824
Radek Krejci88f29302015-10-30 15:42:33 +0100825 if (str[0] == '@' && !str[1]) {
826 /* process attribute of the parent object (container or list) */
Radek Krejci2a0efef2016-03-24 15:10:40 +0100827 if (!(*parent)) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100828 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "attribute with no corresponding element to belongs to");
Radek Krejci88f29302015-10-30 15:42:33 +0100829 goto error;
830 }
831
Radek Krejci532e5e92017-02-22 12:59:24 +0100832 r = json_parse_attr((*parent)->schema->module, &attr, &data[len], options);
Radek Krejci88f29302015-10-30 15:42:33 +0100833 if (!r) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100834 LOGPATH(ctx, LY_VLOG_LYD, *parent);
Radek Krejci88f29302015-10-30 15:42:33 +0100835 goto error;
836 }
837 len += r;
838
839 if ((*parent)->attr) {
840 lyd_free_attr(ctx, NULL, attr, 1);
841 } else {
842 (*parent)->attr = attr;
Radek Krejci532e5e92017-02-22 12:59:24 +0100843 for (; attr; attr = attr->next) {
844 attr->parent = *parent;
845 }
Radek Krejci88f29302015-10-30 15:42:33 +0100846 }
Michal Vasko7675c622017-03-02 10:50:07 +0100847
848 /* check edit-config attribute correctness */
849 if ((options & LYD_OPT_EDIT) && lyp_check_edit_attr(ctx, (*parent)->attr, *parent, NULL)) {
850 goto error;
851 }
852
Radek Krejcic4831272015-11-01 19:26:34 +0100853 free(str);
854 return len;
Radek Krejci88f29302015-10-30 15:42:33 +0100855 }
856
Radek Krejci5449d472015-10-26 14:35:56 +0100857 /* find schema node */
858 if (!(*parent)) {
859 /* starting in root */
860 /* get the proper schema */
Michal Vasko03b0a672018-06-15 09:58:30 +0200861 module = ly_ctx_get_module(ctx, prefix, NULL, 0);
Michal Vaskof53187d2017-01-13 13:23:14 +0100862 if (ctx->data_clb) {
863 if (!module) {
864 module = ctx->data_clb(ctx, prefix, NULL, 0, ctx->data_clb_data);
865 } else if (!module->implemented) {
866 module = ctx->data_clb(ctx, module->name, module->ns, LY_MODCLB_NOT_IMPLEMENTED, ctx->data_clb_data);
867 }
868 }
869 if (module && module->implemented) {
PavolVican832f5432018-02-21 00:54:45 +0100870 if (yang_data_name) {
871 sparent = lyp_get_yang_data_template(module, yang_data_name, strlen(yang_data_name));
872 schema = NULL;
873 if (sparent) {
874 /* get the proper schema node */
875 while ((schema = (struct lys_node *) lys_getnext(schema, sparent, module, 0))) {
876 if (!strcmp(schema->name, name)) {
877 break;
878 }
879 }
880 }
881 } else {
882 /* get the proper schema node */
883 while ((schema = (struct lys_node *) lys_getnext(schema, NULL, module, 0))) {
884 if (!strcmp(schema->name, name)) {
885 break;
886 }
Radek Krejci5449d472015-10-26 14:35:56 +0100887 }
888 }
889 }
890 } else {
Radek Krejci5449d472015-10-26 14:35:56 +0100891 if (prefix) {
Michal Vaskof53187d2017-01-13 13:23:14 +0100892 /* get the proper module to give the chance to load/implement it */
Radek Krejcidfb00d62017-09-06 09:39:35 +0200893 module = ly_ctx_get_module(ctx, prefix, NULL, 1);
Michal Vaskof53187d2017-01-13 13:23:14 +0100894 if (ctx->data_clb) {
895 if (!module) {
Michal Vaskoad43c182017-01-23 09:55:28 +0100896 ctx->data_clb(ctx, prefix, NULL, 0, ctx->data_clb_data);
Michal Vaskof53187d2017-01-13 13:23:14 +0100897 } else if (!module->implemented) {
Michal Vaskoad43c182017-01-23 09:55:28 +0100898 ctx->data_clb(ctx, module->name, module->ns, LY_MODCLB_NOT_IMPLEMENTED, ctx->data_clb_data);
Michal Vaskof53187d2017-01-13 13:23:14 +0100899 }
Radek Krejci5449d472015-10-26 14:35:56 +0100900 }
901 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100902
903 /* go through RPC's input/output following the options' data type */
fanchanghu4236af32018-09-15 10:06:57 +0800904 if ((*parent)->schema->nodetype == LYS_RPC || (*parent)->schema->nodetype == LYS_ACTION) {
Michal Vaskof53187d2017-01-13 13:23:14 +0100905 while ((schema = (struct lys_node *)lys_getnext(schema, (*parent)->schema, NULL, LYS_GETNEXT_WITHINOUT))) {
Michal Vaskoafa7a642016-10-18 15:11:38 +0200906 if ((options & LYD_OPT_RPC) && (schema->nodetype == LYS_INPUT)) {
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100907 break;
Michal Vaskoafa7a642016-10-18 15:11:38 +0200908 } else if ((options & LYD_OPT_RPCREPLY) && (schema->nodetype == LYS_OUTPUT)) {
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100909 break;
910 }
911 }
Radek Krejci4a49bdf2016-01-12 17:17:01 +0100912 schema_parent = schema;
913 schema = NULL;
914 }
915
Michal Vasko36ef6932015-12-01 14:30:17 +0100916 if (schema_parent) {
Michal Vaskof53187d2017-01-13 13:23:14 +0100917 while ((schema = (struct lys_node *)lys_getnext(schema, schema_parent, NULL, 0))) {
918 if (!strcmp(schema->name, name)
919 && ((prefix && !strcmp(lys_node_module(schema)->name, prefix))
920 || (!prefix && (lys_node_module(schema) == lys_node_module(schema_parent))))) {
Michal Vasko36ef6932015-12-01 14:30:17 +0100921 break;
922 }
923 }
924 } else {
Michal Vaskof53187d2017-01-13 13:23:14 +0100925 while ((schema = (struct lys_node *)lys_getnext(schema, (*parent)->schema, NULL, 0))) {
926 if (!strcmp(schema->name, name)
927 && ((prefix && !strcmp(lys_node_module(schema)->name, prefix))
928 || (!prefix && (lys_node_module(schema) == lyd_node_module(*parent))))) {
Michal Vasko36ef6932015-12-01 14:30:17 +0100929 break;
930 }
Radek Krejci5449d472015-10-26 14:35:56 +0100931 }
932 }
933 }
Michal Vaskof53187d2017-01-13 13:23:14 +0100934
935 module = lys_node_module(schema);
936 if (!module || !module->implemented || module->disabled) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100937 LOGVAL(ctx, LYE_INELEM, (*parent ? LY_VLOG_LYD : LY_VLOG_NONE), (*parent), name);
Radek Krejci88f29302015-10-30 15:42:33 +0100938 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +0100939 }
Radek Krejci88f29302015-10-30 15:42:33 +0100940
941 if (str[0] == '@') {
Radek Krejci88f29302015-10-30 15:42:33 +0100942 /* attribute for some sibling node */
943 if (data[len] == '[') {
944 flag_leaflist = 1;
945 len++;
946 len += skip_ws(&data[len]);
947 }
948
949attr_repeat:
Radek Krejci532e5e92017-02-22 12:59:24 +0100950 r = json_parse_attr((struct lys_module *)module, &attr, &data[len], options);
Radek Krejci88f29302015-10-30 15:42:33 +0100951 if (!r) {
Michal Vasko53b7da02018-02-13 15:28:42 +0100952 LOGPATH(ctx, LY_VLOG_LYD, (*parent));
Radek Krejci88f29302015-10-30 15:42:33 +0100953 goto error;
954 }
955 len += r;
956
957 if (attr) {
Radek Krejcic4831272015-11-01 19:26:34 +0100958 attrs_aux = malloc(sizeof *attrs_aux);
Michal Vasko53b7da02018-02-13 15:28:42 +0100959 LY_CHECK_ERR_GOTO(!attrs_aux, LOGMEM(ctx), error);
Radek Krejcic4831272015-11-01 19:26:34 +0100960 attrs_aux->attr = attr;
961 attrs_aux->index = flag_leaflist;
962 attrs_aux->schema = schema;
963 attrs_aux->next = *attrs;
964 *attrs = attrs_aux;
Radek Krejci88f29302015-10-30 15:42:33 +0100965 }
966
967 if (flag_leaflist) {
968 if (data[len] == ',') {
969 len++;
970 len += skip_ws(&data[len]);
971 flag_leaflist++;
972 goto attr_repeat;
973 } else if (data[len] != ']') {
Michal Vasko53b7da02018-02-13 15:28:42 +0100974 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, (*parent), "JSON data (missing end-array)");
Radek Krejci88f29302015-10-30 15:42:33 +0100975 goto error;
976 }
977 len++;
978 len += skip_ws(&data[len]);
979 }
980
Radek Krejcic4831272015-11-01 19:26:34 +0100981 free(str);
982 return len;
Radek Krejci88f29302015-10-30 15:42:33 +0100983 }
984
Radek Krejci5449d472015-10-26 14:35:56 +0100985 switch (schema->nodetype) {
986 case LYS_CONTAINER:
987 case LYS_LIST:
988 case LYS_NOTIF:
989 case LYS_RPC:
Michal Vaskoafa7a642016-10-18 15:11:38 +0200990 case LYS_ACTION:
Radek Krejci5449d472015-10-26 14:35:56 +0100991 result = calloc(1, sizeof *result);
992 break;
993 case LYS_LEAF:
994 case LYS_LEAFLIST:
995 result = calloc(1, sizeof(struct lyd_node_leaf_list));
996 break;
997 case LYS_ANYXML:
Radek Krejcibf2abff2016-08-23 15:51:52 +0200998 case LYS_ANYDATA:
999 result = calloc(1, sizeof(struct lyd_node_anydata));
Radek Krejci5449d472015-10-26 14:35:56 +01001000 break;
1001 default:
Michal Vasko53b7da02018-02-13 15:28:42 +01001002 LOGINT(ctx);
Radek Krejci595060f2015-10-30 16:29:58 +01001003 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +01001004 }
Michal Vasko53b7da02018-02-13 15:28:42 +01001005 LY_CHECK_ERR_GOTO(!result, LOGMEM(ctx), error);
Michal Vasko253035f2015-12-17 16:58:13 +01001006
Radek Krejci61767ca2016-09-19 14:21:55 +02001007 result->prev = result;
Radek Krejci5449d472015-10-26 14:35:56 +01001008 result->schema = schema;
Radek Krejci61767ca2016-09-19 14:21:55 +02001009 result->parent = *parent;
1010 diter = NULL;
Radek Krejci65aca412018-01-24 11:23:06 +01001011 if (schema->nodetype == LYS_LEAF && lys_is_key((struct lys_node_leaf *)schema, &pos)) {
Michal Vasko80389542018-02-08 14:35:32 +01001012 /* it is key and we need to insert it into a correct place (we must have parent then, a key cannot be top-level) */
1013 assert(*parent);
Radek Krejci61767ca2016-09-19 14:21:55 +02001014 for (i = 0, diter = (*parent)->child;
Radek Krejci65aca412018-01-24 11:23:06 +01001015 diter && i < pos && diter->schema->nodetype == LYS_LEAF && lys_is_key((struct lys_node_leaf *)diter->schema, NULL);
Radek Krejci61767ca2016-09-19 14:21:55 +02001016 i++, diter = diter->next);
1017 if (diter) {
1018 /* out of order insertion - insert list's key to the correct position, before the diter */
1019 if ((*parent)->child == diter) {
1020 (*parent)->child = result;
1021 /* update first_sibling */
1022 first_sibling = result;
1023 }
1024 if (diter->prev->next) {
1025 diter->prev->next = result;
1026 }
1027 result->prev = diter->prev;
1028 diter->prev = result;
1029 result->next = diter;
1030 }
1031 }
1032 if (!diter) {
1033 /* simplified (faster) insert as the last node */
1034 if (*parent && !(*parent)->child) {
1035 (*parent)->child = result;
1036 }
1037 if (prev) {
1038 result->prev = prev;
1039 prev->next = result;
1040
1041 /* fix the "last" pointer */
1042 first_sibling->prev = result;
1043 } else {
1044 result->prev = result;
1045 first_sibling = result;
1046 }
1047 }
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001048 result->validity = ly_new_node_validity(result->schema);
Radek Krejci46165822016-08-26 14:06:27 +02001049 if (resolve_applies_when(schema, 0, NULL)) {
Radek Krejci0b7704f2016-03-18 12:16:14 +01001050 result->when_status = LYD_WHEN;
1051 }
Radek Krejci5449d472015-10-26 14:35:56 +01001052
Radek Krejci5449d472015-10-26 14:35:56 +01001053 /* type specific processing */
Michal Vasko24affa02018-04-03 09:06:06 +02001054 switch (schema->nodetype) {
1055 case LYS_LEAF:
1056 case LYS_LEAFLIST:
Radek Krejci5449d472015-10-26 14:35:56 +01001057 /* type detection and assigning the value */
Radek Krejci45f41dd2017-02-09 14:11:09 +01001058 r = json_get_value((struct lyd_node_leaf_list *)result, &first_sibling, &data[len], options, unres);
Radek Krejci5449d472015-10-26 14:35:56 +01001059 if (!r) {
1060 goto error;
1061 }
Michal Vasko33cbf422018-09-13 15:18:15 +02001062 /* only for leaf-list */
1063 while (result->next && (result->next->schema == result->schema)) {
Radek Krejci88f29302015-10-30 15:42:33 +01001064 result = result->next;
1065 }
1066
Radek Krejci5449d472015-10-26 14:35:56 +01001067 len += r;
1068 len += skip_ws(&data[len]);
Michal Vasko24affa02018-04-03 09:06:06 +02001069 break;
1070 case LYS_ANYDATA:
1071 case LYS_ANYXML:
Radek Krejci4ae82942016-09-19 16:41:06 +02001072 r = json_get_anydata((struct lyd_node_anydata *)result, &data[len]);
Radek Krejci5449d472015-10-26 14:35:56 +01001073 if (!r) {
1074 goto error;
1075 }
Michal Vasko24affa02018-04-03 09:06:06 +02001076
1077#ifdef LY_ENABLED_CACHE
1078 /* calculate the hash and insert it into parent */
1079 lyd_hash(result);
1080 lyd_insert_hash(result);
1081#endif
1082
Radek Krejci5449d472015-10-26 14:35:56 +01001083 len += r;
1084 len += skip_ws(&data[len]);
Michal Vasko24affa02018-04-03 09:06:06 +02001085 break;
1086 case LYS_CONTAINER:
1087 case LYS_RPC:
1088 case LYS_ACTION:
1089 case LYS_NOTIF:
Michal Vaskoafa7a642016-10-18 15:11:38 +02001090 if (schema->nodetype & (LYS_RPC | LYS_ACTION)) {
1091 if (!(options & LYD_OPT_RPC) || *act_notif) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001092 LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, result, schema->name);
1093 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Unexpected %s node \"%s\".",
Michal Vaskoafa7a642016-10-18 15:11:38 +02001094 (schema->nodetype == LYS_RPC ? "rpc" : "action"), schema->name);
1095 goto error;
1096 }
1097 *act_notif = result;
1098 } else if (schema->nodetype == LYS_NOTIF) {
1099 if (!(options & LYD_OPT_NOTIF) || *act_notif) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001100 LOGVAL(ctx, LYE_INELEM, LY_VLOG_LYD, result, schema->name);
1101 LOGVAL(ctx, LYE_SPEC, LY_VLOG_PREV, NULL, "Unexpected notification node \"%s\".", schema->name);
Michal Vaskoafa7a642016-10-18 15:11:38 +02001102 goto error;
1103 }
1104 *act_notif = result;
1105 }
1106
Michal Vasko24affa02018-04-03 09:06:06 +02001107#ifdef LY_ENABLED_CACHE
1108 /* calculate the hash and insert it into parent */
1109 lyd_hash(result);
1110 lyd_insert_hash(result);
1111#endif
1112
Radek Krejci5449d472015-10-26 14:35:56 +01001113 if (data[len] != '{') {
Michal Vasko53b7da02018-02-13 15:28:42 +01001114 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing begin-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001115 goto error;
1116 }
1117 len++;
1118 len += skip_ws(&data[len]);
1119
1120 if (data[len] != '}') {
1121 /* non-empty container */
Radek Krejcic4831272015-11-01 19:26:34 +01001122 len--;
1123 diter = NULL;
1124 attrs_aux = NULL;
1125 do {
1126 len++;
1127 len += skip_ws(&data[len]);
1128
PavolVican832f5432018-02-21 00:54:45 +01001129 r = json_parse_data(ctx, &data[len], NULL, &result, result->child, diter, &attrs_aux, options, unres, act_notif, yang_data_name);
Radek Krejcic4831272015-11-01 19:26:34 +01001130 if (!r) {
1131 goto error;
1132 }
1133 len += r;
1134
1135 if (result->child) {
1136 diter = result->child->prev;
1137 }
1138 } while(data[len] == ',');
1139
1140 /* store attributes */
Michal Vasko7675c622017-03-02 10:50:07 +01001141 if (store_attrs(ctx, attrs_aux, result->child, options)) {
Radek Krejci5449d472015-10-26 14:35:56 +01001142 goto error;
1143 }
Radek Krejci5449d472015-10-26 14:35:56 +01001144 }
1145
1146 if (data[len] != '}') {
Michal Vasko53b7da02018-02-13 15:28:42 +01001147 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing end-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001148 goto error;
1149 }
1150 len++;
1151 len += skip_ws(&data[len]);
1152
Radek Krejcifb7156e2016-10-27 13:39:56 +02001153 /* if we have empty non-presence container, mark it as default */
Radek Krejci2537fd32016-09-07 16:22:41 +02001154 if (schema->nodetype == LYS_CONTAINER && !result->child &&
Radek Krejcid3e73722016-05-23 12:24:55 +02001155 !result->attr && !((struct lys_node_container *)schema)->presence) {
Radek Krejcifb7156e2016-10-27 13:39:56 +02001156 result->dflt = 1;
Radek Krejci0c0086a2016-03-24 15:20:28 +01001157 }
Michal Vasko24affa02018-04-03 09:06:06 +02001158 break;
1159 case LYS_LIST:
Radek Krejci5449d472015-10-26 14:35:56 +01001160 if (data[len] != '[') {
Michal Vasko53b7da02018-02-13 15:28:42 +01001161 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing begin-array)");
Radek Krejci5449d472015-10-26 14:35:56 +01001162 goto error;
1163 }
1164
1165 list = result;
1166 do {
1167 len++;
1168 len += skip_ws(&data[len]);
Radek Krejci23238922015-10-27 17:13:34 +01001169
Radek Krejcic4831272015-11-01 19:26:34 +01001170 if (data[len] != '{') {
Michal Vasko53b7da02018-02-13 15:28:42 +01001171 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, result,
Radek Krejciadb57612016-02-16 13:34:34 +01001172 "JSON data (missing list instance's begin-object)");
Radek Krejci5449d472015-10-26 14:35:56 +01001173 goto error;
1174 }
Radek Krejcic4831272015-11-01 19:26:34 +01001175 diter = NULL;
1176 attrs_aux = NULL;
1177 do {
1178 len++;
1179 len += skip_ws(&data[len]);
1180
PavolVican832f5432018-02-21 00:54:45 +01001181 r = json_parse_data(ctx, &data[len], NULL, &list, list->child, diter, &attrs_aux, options, unres, act_notif, yang_data_name);
Radek Krejcic4831272015-11-01 19:26:34 +01001182 if (!r) {
1183 goto error;
1184 }
1185 len += r;
1186
Radek Krejci52934692015-11-01 20:08:15 +01001187 if (list->child) {
Radek Krejcic4831272015-11-01 19:26:34 +01001188 diter = list->child->prev;
1189 }
Michal Vasko24affa02018-04-03 09:06:06 +02001190 } while (data[len] == ',');
1191
1192#ifdef LY_ENABLED_CACHE
1193 /* calculate the hash and insert it into parent */
1194 if (!((struct lys_node_list *)list->schema)->keys_size) {
1195 lyd_hash(list);
1196 lyd_insert_hash(list);
1197 }
1198#endif
Radek Krejcic4831272015-11-01 19:26:34 +01001199
1200 /* store attributes */
Michal Vasko7675c622017-03-02 10:50:07 +01001201 if (store_attrs(ctx, attrs_aux, list->child, options)) {
Radek Krejcic4831272015-11-01 19:26:34 +01001202 goto error;
1203 }
1204
1205 if (data[len] != '}') {
1206 /* expecting end-object */
Michal Vasko53b7da02018-02-13 15:28:42 +01001207 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, result,
Radek Krejciadb57612016-02-16 13:34:34 +01001208 "JSON data (missing list instance's end-object)");
Radek Krejcic4831272015-11-01 19:26:34 +01001209 goto error;
1210 }
1211 len++;
Radek Krejci5449d472015-10-26 14:35:56 +01001212 len += skip_ws(&data[len]);
1213
1214 if (data[len] == ',') {
Radek Krejci93fab982016-02-03 15:58:19 +01001215 /* various validation checks */
fanchanghucdb16a12018-09-18 10:54:05 +08001216 if (lyv_data_context(list, options | LYD_OPT_TRUSTED, unres) ||
Michal Vasko53b7da02018-02-13 15:28:42 +01001217 lyv_data_content(list, options, unres) ||
1218 lyv_multicases(list, NULL, prev ? &first_sibling : NULL, 0, NULL)) {
Radek Krejci45f41dd2017-02-09 14:11:09 +01001219 goto error;
1220 }
1221
Radek Krejci5449d472015-10-26 14:35:56 +01001222 /* another instance of the list */
1223 new = calloc(1, sizeof *new);
Michal Vasko53b7da02018-02-13 15:28:42 +01001224 LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx), error);
Radek Krejci5449d472015-10-26 14:35:56 +01001225 new->parent = list->parent;
1226 new->prev = list;
1227 list->next = new;
1228
Radek Krejcie1794882017-02-08 13:23:38 +01001229 /* copy the validity and when flags */
1230 new->validity = list->validity;
1231 new->when_status = list->when_status;
1232
Radek Krejci5449d472015-10-26 14:35:56 +01001233 /* fix the "last" pointer */
Radek Krejci2d5525d2016-04-04 15:43:30 +02001234 first_sibling->prev = new;
Radek Krejci5449d472015-10-26 14:35:56 +01001235
1236 new->schema = list->schema;
Radek Krejci5449d472015-10-26 14:35:56 +01001237 list = new;
1238 }
1239 } while (data[len] == ',');
Radek Krejcib915fb92017-02-08 14:12:40 +01001240 result = list;
Radek Krejci5449d472015-10-26 14:35:56 +01001241
1242 if (data[len] != ']') {
Michal Vasko53b7da02018-02-13 15:28:42 +01001243 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_LYD, result, "JSON data (missing end-array)");
Radek Krejci5449d472015-10-26 14:35:56 +01001244 goto error;
1245 }
1246 len++;
1247 len += skip_ws(&data[len]);
Michal Vasko24affa02018-04-03 09:06:06 +02001248 break;
1249 default:
1250 LOGINT(ctx);
1251 goto error;
Radek Krejci5449d472015-10-26 14:35:56 +01001252 }
1253
Michal Vasko4d504152018-09-11 08:42:51 +02001254 /* various validation checks (LYD_OPT_TRUSTED is used just so that the order of elements is not checked) */
1255 if (lyv_data_context(result, options | LYD_OPT_TRUSTED, unres) ||
Michal Vasko53b7da02018-02-13 15:28:42 +01001256 lyv_data_content(result, options, unres) ||
1257 lyv_multicases(result, NULL, prev ? &first_sibling : NULL, 0, NULL)) {
Michal Vasko10e586f2016-05-18 13:25:30 +02001258 goto error;
1259 }
1260
Radek Krejcica7efb72016-01-18 13:06:01 +01001261 /* validation successful */
Radek Krejci63b79c82016-08-10 10:09:33 +02001262 if (result->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
Michal Vaskoe3886bb2017-01-02 11:33:28 +01001263 /* postpone checking of unique when there will be all list/leaflist instances */
Michal Vasko185b5272018-09-13 14:26:12 +02001264 result->validity |= LYD_VAL_DUP;
Radek Krejci63b79c82016-08-10 10:09:33 +02001265 }
Radek Krejcica7efb72016-01-18 13:06:01 +01001266
Radek Krejci88f29302015-10-30 15:42:33 +01001267 if (!(*parent)) {
1268 *parent = result;
1269 }
1270
Radek Krejcide9d92c2015-10-30 15:59:59 +01001271 free(str);
Radek Krejci5449d472015-10-26 14:35:56 +01001272 return len;
1273
1274error:
Radek Krejci0c0086a2016-03-24 15:20:28 +01001275 /* cleanup */
1276 for (i = unres->count - 1; i >= 0; i--) {
1277 /* remove unres items connected with the node being removed */
1278 if (unres->node[i] == result) {
1279 unres_data_del(unres, i);
1280 }
Radek Krejci88f29302015-10-30 15:42:33 +01001281 }
1282 while (*attrs) {
Radek Krejcic4831272015-11-01 19:26:34 +01001283 attrs_aux = *attrs;
Radek Krejci88f29302015-10-30 15:42:33 +01001284 *attrs = (*attrs)->next;
1285
Radek Krejcic4831272015-11-01 19:26:34 +01001286 lyd_free_attr(ctx, NULL, attrs_aux->attr, 1);
1287 free(attrs_aux);
Radek Krejci88f29302015-10-30 15:42:33 +01001288 }
1289
Radek Krejci5449d472015-10-26 14:35:56 +01001290 lyd_free(result);
Radek Krejci88f29302015-10-30 15:42:33 +01001291 free(str);
1292
Michal Vasko53b7da02018-02-13 15:28:42 +01001293 return 0;
Radek Krejci5449d472015-10-26 14:35:56 +01001294}
1295
1296struct lyd_node *
Michal Vasko945b96b2016-10-18 11:49:12 +02001297lyd_parse_json(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *rpc_act,
PavolVican832f5432018-02-21 00:54:45 +01001298 const struct lyd_node *data_tree, const char *yang_data_name)
Radek Krejci5449d472015-10-26 14:35:56 +01001299{
Michal Vaskoafa7a642016-10-18 15:11:38 +02001300 struct lyd_node *result = NULL, *next, *iter, *reply_parent = NULL, *reply_top = NULL, *act_notif = NULL;
Radek Krejci5449d472015-10-26 14:35:56 +01001301 struct unres_data *unres = NULL;
Radek Krejcic4831272015-11-01 19:26:34 +01001302 unsigned int len = 0, r;
Michal Vasko185b5272018-09-13 14:26:12 +02001303 int act_cont = 0;
Radek Krejcic4831272015-11-01 19:26:34 +01001304 struct attr_cont *attrs = NULL;
Radek Krejci5449d472015-10-26 14:35:56 +01001305
Michal Vaskoafa7a642016-10-18 15:11:38 +02001306 if (!ctx || !data) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001307 LOGARG;
Radek Krejci5449d472015-10-26 14:35:56 +01001308 return NULL;
1309 }
1310
Radek Krejcic4831272015-11-01 19:26:34 +01001311 /* skip leading whitespaces */
1312 len += skip_ws(&data[len]);
1313
1314 /* expect top-level { */
1315 if (data[len] != '{') {
Michal Vasko53b7da02018-02-13 15:28:42 +01001316 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top level begin-object)");
Michal Vasko24d982f2016-04-18 15:13:58 +02001317 return NULL;
1318 }
1319
Michal Vasko85c63f42018-01-02 10:43:45 +01001320 /* check for empty object */
1321 r = len + 1;
1322 r += skip_ws(&data[r]);
1323 if (data[r] == '}') {
Michal Vasko7d15c3a2018-11-22 15:27:46 +01001324 if (options & LYD_OPT_DATA_ADD_YANGLIB) {
1325 result = ly_ctx_info(ctx);
1326 }
1327 lyd_validate(&result, options, ctx);
1328 return result;
Michal Vasko85c63f42018-01-02 10:43:45 +01001329 }
1330
Michal Vasko24d982f2016-04-18 15:13:58 +02001331 unres = calloc(1, sizeof *unres);
Michal Vasko53b7da02018-02-13 15:28:42 +01001332 LY_CHECK_ERR_RETURN(!unres, LOGMEM(ctx), NULL);
Radek Krejcic4831272015-11-01 19:26:34 +01001333
Michal Vaskoafa7a642016-10-18 15:11:38 +02001334 /* create RPC/action reply part that is not in the parsed data */
1335 if (rpc_act) {
1336 assert(options & LYD_OPT_RPCREPLY);
1337 if (rpc_act->schema->nodetype == LYS_RPC) {
1338 /* RPC request */
1339 reply_top = reply_parent = _lyd_new(NULL, rpc_act->schema, 0);
1340 } else {
1341 /* action request */
1342 reply_top = lyd_dup(rpc_act, 1);
1343 LY_TREE_DFS_BEGIN(reply_top, iter, reply_parent) {
1344 if (reply_parent->schema->nodetype == LYS_ACTION) {
1345 break;
1346 }
1347 LY_TREE_DFS_END(reply_top, iter, reply_parent);
1348 }
1349 if (!reply_parent) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001350 LOGERR(ctx, LY_EINVAL, "%s: invalid variable parameter (const struct lyd_node *rpc_act).", __func__);
Michal Vaskoafa7a642016-10-18 15:11:38 +02001351 goto error;
1352 }
1353 lyd_free_withsiblings(reply_parent->child);
1354 }
1355 }
1356
1357 iter = NULL;
1358 next = reply_parent;
Radek Krejcic4831272015-11-01 19:26:34 +01001359 do {
1360 len++;
1361 len += skip_ws(&data[len]);
1362
Michal Vaskoafa7a642016-10-18 15:11:38 +02001363 if (!act_cont) {
1364 if (!strncmp(&data[len], "\"yang:action\"", 13)) {
1365 len += 13;
1366 len += skip_ws(&data[len]);
1367 if (data[len] != ':') {
Michal Vasko53b7da02018-02-13 15:28:42 +01001368 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top-level begin-object)");
Michal Vaskoafa7a642016-10-18 15:11:38 +02001369 goto error;
1370 }
1371 ++len;
1372 len += skip_ws(&data[len]);
1373 if (data[len] != '{') {
Michal Vasko53b7da02018-02-13 15:28:42 +01001374 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top level yang:action object)");
Michal Vaskoafa7a642016-10-18 15:11:38 +02001375 goto error;
1376 }
1377 ++len;
1378 len += skip_ws(&data[len]);
1379
1380 act_cont = 1;
1381 } else {
1382 act_cont = -1;
1383 }
1384 }
1385
PavolVican832f5432018-02-21 00:54:45 +01001386 r = json_parse_data(ctx, &data[len], NULL, &next, result, iter, &attrs, options, unres, &act_notif, yang_data_name);
Radek Krejcic4831272015-11-01 19:26:34 +01001387 if (!r) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001388 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001389 }
1390 len += r;
1391
1392 if (!result) {
Radek Krejcie4f9dcd2017-10-27 15:22:41 +02001393 if (reply_parent) {
1394 result = next->child;
Michal Vaskodc176ef2018-10-31 10:44:49 +01001395 iter = next->child ? next->child->prev : NULL;
Radek Krejcie4f9dcd2017-10-27 15:22:41 +02001396 } else {
1397 for (iter = next; iter && iter->prev->next; iter = iter->prev);
1398 result = iter;
1399 if (iter && (options & LYD_OPT_DATA_ADD_YANGLIB) && iter->schema->module == ctx->models.list[ctx->internal_module_count - 1]) {
1400 /* ietf-yang-library data present, so ignore the option to add them */
1401 options &= ~LYD_OPT_DATA_ADD_YANGLIB;
1402 }
1403 iter = next;
Radek Krejci06f8bb92017-08-02 15:36:25 +02001404 }
Radek Krejcie4f9dcd2017-10-27 15:22:41 +02001405 } else {
1406 iter = result->prev;
Radek Krejcic4831272015-11-01 19:26:34 +01001407 }
Radek Krejcie4f9dcd2017-10-27 15:22:41 +02001408 if (!reply_parent) {
1409 next = NULL;
Radek Krejcic4831272015-11-01 19:26:34 +01001410 }
Michal Vaskoafa7a642016-10-18 15:11:38 +02001411 } while (data[len] == ',');
Radek Krejcic4831272015-11-01 19:26:34 +01001412
1413 if (data[len] != '}') {
1414 /* expecting end-object */
Michal Vasko53b7da02018-02-13 15:28:42 +01001415 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top-level end-object)");
Michal Vasko24d982f2016-04-18 15:13:58 +02001416 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001417 }
1418 len++;
1419 len += skip_ws(&data[len]);
1420
Michal Vaskoafa7a642016-10-18 15:11:38 +02001421 if (act_cont == 1) {
1422 if (data[len] != '}') {
Michal Vasko53b7da02018-02-13 15:28:42 +01001423 LOGVAL(ctx, LYE_XML_INVAL, LY_VLOG_NONE, NULL, "JSON data (missing top-level end-object)");
Michal Vaskoafa7a642016-10-18 15:11:38 +02001424 goto error;
1425 }
1426 len++;
1427 len += skip_ws(&data[len]);
1428 }
1429
Radek Krejcic4831272015-11-01 19:26:34 +01001430 /* store attributes */
Michal Vasko7675c622017-03-02 10:50:07 +01001431 if (store_attrs(ctx, attrs, result, options)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001432 goto error;
Radek Krejcic4831272015-11-01 19:26:34 +01001433 }
Radek Krejci5449d472015-10-26 14:35:56 +01001434
Michal Vaskoafa7a642016-10-18 15:11:38 +02001435 if (reply_top) {
1436 result = reply_top;
1437 }
1438
Michal Vaskoc1cf86f2015-11-04 09:54:51 +01001439 if (!result) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001440 LOGERR(ctx, LY_EVALID, "Model for the data to be linked with not found.");
Michal Vasko24d982f2016-04-18 15:13:58 +02001441 goto error;
Michal Vaskoc1cf86f2015-11-04 09:54:51 +01001442 }
1443
Michal Vaskodfcd4f62018-09-11 10:21:10 +02001444 /* order the elements by hand as it is not required of the JSON input */
fanchanghud20b9042018-09-17 14:16:26 +08001445 if ((options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY))) {
Michal Vaskodfcd4f62018-09-11 10:21:10 +02001446 if (lyd_schema_sort(result, 1)) {
1447 goto error;
1448 }
1449 }
1450
Michal Vaskoafa7a642016-10-18 15:11:38 +02001451 if ((options & LYD_OPT_RPCREPLY) && (rpc_act->schema->nodetype != LYS_RPC)) {
1452 /* action reply */
1453 act_notif = reply_parent;
1454 } else if ((options & (LYD_OPT_RPC | LYD_OPT_NOTIF)) && !act_notif) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001455 LOGVAL(ctx, LYE_MISSELEM, LY_VLOG_LYD, result, (options & LYD_OPT_RPC ? "action" : "notification"), result->schema->name);
Michal Vaskoafa7a642016-10-18 15:11:38 +02001456 goto error;
1457 }
1458
Radek Krejci06f8bb92017-08-02 15:36:25 +02001459 /* add missing ietf-yang-library if requested */
1460 if (options & LYD_OPT_DATA_ADD_YANGLIB) {
Radek Krejcib1ed7e52017-08-09 12:42:35 +02001461 if (lyd_merge(result, ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
Michal Vasko53b7da02018-02-13 15:28:42 +01001462 LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
Radek Krejci06f8bb92017-08-02 15:36:25 +02001463 goto error;
1464 }
1465 }
1466
Radek Krejci63b79c82016-08-10 10:09:33 +02001467 /* check for uniquness of top-level lists/leaflists because
1468 * only the inner instances were tested in lyv_data_content() */
Radek Krejci63b79c82016-08-10 10:09:33 +02001469 LY_TREE_FOR(result, iter) {
Michal Vasko185b5272018-09-13 14:26:12 +02001470 if (!(iter->schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) || !(iter->validity & LYD_VAL_DUP)) {
Radek Krejci63b79c82016-08-10 10:09:33 +02001471 continue;
1472 }
1473
Michal Vasko185b5272018-09-13 14:26:12 +02001474 if (lyv_data_dup(iter, result)) {
Radek Krejci63b79c82016-08-10 10:09:33 +02001475 goto error;
1476 }
1477 }
Radek Krejci63b79c82016-08-10 10:09:33 +02001478
Radek Krejci46165822016-08-26 14:06:27 +02001479 /* add/validate default values, unres */
Michal Vasko228431e2018-07-10 15:47:11 +02001480 if (lyd_defaults_add_unres(&result, options, ctx, data_tree, act_notif, unres, 1)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001481 goto error;
Radek Krejci5c162452016-03-23 13:36:01 +01001482 }
1483
Radek Krejci46165822016-08-26 14:06:27 +02001484 /* check for missing top level mandatory nodes */
Michal Vaskoad2e44a2017-01-03 10:31:35 +01001485 if (!(options & (LYD_OPT_TRUSTED | LYD_OPT_NOTIF_FILTER))
1486 && lyd_check_mandatory_tree((act_notif ? act_notif : result), ctx, options)) {
Michal Vasko24d982f2016-04-18 15:13:58 +02001487 goto error;
Radek Krejci5c162452016-03-23 13:36:01 +01001488 }
1489
Radek Krejci5449d472015-10-26 14:35:56 +01001490 free(unres->node);
1491 free(unres->type);
Radek Krejci5449d472015-10-26 14:35:56 +01001492 free(unres);
1493
1494 return result;
Michal Vasko24d982f2016-04-18 15:13:58 +02001495
1496error:
1497 lyd_free_withsiblings(result);
Radek Krejci1fe41792017-10-27 14:47:05 +02001498 if (reply_top && result != reply_top) {
1499 lyd_free_withsiblings(reply_top);
1500 }
Michal Vasko24d982f2016-04-18 15:13:58 +02001501 free(unres->node);
1502 free(unres->type);
1503 free(unres);
1504
1505 return NULL;
Radek Krejci5449d472015-10-26 14:35:56 +01001506}