blob: ef3eeadc55c12fe9b97bf43cd2b9306201c4ad13 [file] [log] [blame]
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001/**
2 * @file parser_lyb.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief LYB data parser for libyang
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * 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
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#include <assert.h>
16#include <errno.h>
17#include <stdlib.h>
18#include <string.h>
19
20#include "libyang.h"
21#include "common.h"
22#include "context.h"
23#include "parser.h"
24#include "tree_internal.h"
25
26#define LYB_HAVE_READ_GOTO(r, d, go) if (r < 0) goto go; d += r;
27#define LYB_HAVE_READ_RETURN(r, d, ret) if (r < 0) return ret; d += r;
28
29static int
30lyb_read(const char *data, uint8_t *buf, size_t count, struct lyb_state *lybs)
31{
32 int ret = 0, i, empty_chunk_i;
33 size_t to_read;
Michal Vaskoa9852522018-08-08 16:24:45 +020034 LYB_META meta;
Michal Vasko1e82a3b2018-07-03 12:16:58 +020035
36 assert(data && lybs);
37
38 while (1) {
39 /* check for fully-read (empty) data chunks */
40 to_read = count;
41 empty_chunk_i = -1;
42 for (i = 0; i < lybs->used; ++i) {
43 /* we want the innermost chunks resolved first, so replace previous empty chunks,
44 * also ignore chunks that are completely finished, there is nothing for us to do */
Michal Vaskoae4b7d32018-07-13 12:21:01 +020045 if ((lybs->written[i] <= to_read) && lybs->position[i]) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +020046 /* empty chunk, do not read more */
47 to_read = lybs->written[i];
48 empty_chunk_i = i;
49 }
50 }
51
52 if ((empty_chunk_i == -1) && !count) {
53 break;
54 }
55
56 /* we are actually reading some data, not just finishing another chunk */
57 if (to_read) {
Michal Vasko228431e2018-07-10 15:47:11 +020058 if (buf) {
59 memcpy(buf, data + ret, to_read);
60 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +020061
62 for (i = 0; i < lybs->used; ++i) {
63 /* decrease all written counters */
64 lybs->written[i] -= to_read;
Michal Vaskoae4b7d32018-07-13 12:21:01 +020065 assert(lybs->written[i] <= LYB_SIZE_MAX);
Michal Vasko1e82a3b2018-07-03 12:16:58 +020066 }
67 /* decrease count/buf */
68 count -= to_read;
Michal Vasko228431e2018-07-10 15:47:11 +020069 if (buf) {
70 buf += to_read;
71 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +020072
73 ret += to_read;
74 }
75
76 if (empty_chunk_i > -1) {
Michal Vaskoa9852522018-08-08 16:24:45 +020077 /* read the next chunk meta information */
78 memcpy(&meta, data + ret, LYB_META_BYTES);
79 lybs->written[empty_chunk_i] = 0;
80 lybs->inner_chunks[empty_chunk_i] = 0;
81
82 memcpy(&lybs->written[empty_chunk_i], &meta, LYB_SIZE_BYTES);
83 memcpy(&lybs->inner_chunks[empty_chunk_i], ((uint8_t *)&meta) + LYB_SIZE_BYTES, LYB_INCHUNK_BYTES);
84
Michal Vasko1e82a3b2018-07-03 12:16:58 +020085 /* remember whether there is a following chunk or not */
86 lybs->position[empty_chunk_i] = (lybs->written[empty_chunk_i] == LYB_SIZE_MAX ? 1 : 0);
87
Michal Vaskoa9852522018-08-08 16:24:45 +020088 ret += LYB_META_BYTES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +020089 }
90 }
91
92 return ret;
93}
94
95static int
96lyb_read_number(uint64_t *num, uint64_t max_num, const char *data, struct lyb_state *lybs)
97{
98 int max_bits, max_bytes, i, r, ret = 0;
Michal Vasko228431e2018-07-10 15:47:11 +020099 uint8_t byte;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200100
101 for (max_bits = 0; max_num; max_num >>= 1, ++max_bits);
102 max_bytes = max_bits / 8 + (max_bits % 8 ? 1 : 0);
103
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200104 for (i = 0; i < max_bytes; ++i) {
Michal Vasko228431e2018-07-10 15:47:11 +0200105 ret += (r = lyb_read(data, &byte, 1, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200106 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vasko228431e2018-07-10 15:47:11 +0200107
108 *(((uint8_t *)num) + i) = byte;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200109 }
110
111 return ret;
112}
113
114static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200115lyb_read_string(const char *data, char **str, int with_length, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200116{
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200117 int next_chunk = 0, r, ret = 0;
118 size_t len = 0, cur_len;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200119
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200120 if (with_length) {
121 ret += (r = lyb_read(data, (uint8_t *)&len, 2, lybs));
122 LYB_HAVE_READ_GOTO(r, data, error);
123 } else {
124 /* read until the end of this subtree */
125 len = lybs->written[lybs->used - 1];
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200126 if (lybs->position[lybs->used - 1]) {
127 next_chunk = 1;
128 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200129 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200130
131 *str = malloc((len + 1) * sizeof **str);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200132 LY_CHECK_ERR_RETURN(!*str, LOGMEM(NULL), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200133
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200134 ret += (r = lyb_read(data, (uint8_t *)*str, len, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200135 LYB_HAVE_READ_GOTO(ret, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200136
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200137 while (next_chunk) {
138 cur_len = lybs->written[lybs->used - 1];
139 if (lybs->position[lybs->used - 1]) {
140 next_chunk = 1;
141 } else {
142 next_chunk = 0;
143 }
144
145 *str = ly_realloc(*str, (len + cur_len + 1) * sizeof **str);
146 LY_CHECK_ERR_RETURN(!*str, LOGMEM(NULL), -1);
147
148 ret += (r = lyb_read(data, ((uint8_t *)*str) + len, cur_len, lybs));
149 LYB_HAVE_READ_GOTO(ret, data, error);
150
151 len += cur_len;
152 }
153
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200154 ((char *)*str)[len] = '\0';
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200155 return ret;
156
157error:
158 free((char *)*str);
159 *str = NULL;
160 return -1;
161}
162
163static void
164lyb_read_stop_subtree(struct lyb_state *lybs)
165{
166 if (lybs->written[lybs->used - 1]) {
167 LOGINT(NULL);
168 }
169
170 --lybs->used;
171}
172
173static int
174lyb_read_start_subtree(const char *data, struct lyb_state *lybs)
175{
Michal Vaskoa9852522018-08-08 16:24:45 +0200176 LYB_META meta;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200177
178 if (lybs->used == lybs->size) {
179 lybs->size += LYB_STATE_STEP;
180 lybs->written = ly_realloc(lybs->written, lybs->size * sizeof *lybs->written);
181 lybs->position = ly_realloc(lybs->position, lybs->size * sizeof *lybs->position);
Michal Vaskoa9852522018-08-08 16:24:45 +0200182 lybs->inner_chunks = ly_realloc(lybs->inner_chunks, lybs->size * sizeof *lybs->inner_chunks);
183 LY_CHECK_ERR_RETURN(!lybs->written || !lybs->position || !lybs->inner_chunks, LOGMEM(NULL), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200184 }
185
Michal Vaskoa9852522018-08-08 16:24:45 +0200186 memcpy(&meta, data, LYB_META_BYTES);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200187
188 ++lybs->used;
Michal Vaskoa9852522018-08-08 16:24:45 +0200189 lybs->written[lybs->used - 1] = 0;
190 lybs->inner_chunks[lybs->used - 1] = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200191
Michal Vaskoa9852522018-08-08 16:24:45 +0200192 memcpy(&lybs->written[lybs->used - 1], &meta, LYB_SIZE_BYTES);
193 memcpy(&lybs->inner_chunks[lybs->used - 1], ((uint8_t *)&meta) + LYB_SIZE_BYTES, LYB_INCHUNK_BYTES);
194 lybs->position[lybs->used - 1] = (lybs->written[lybs->used - 1] == LYB_SIZE_MAX ? 1 : 0);
195
196 return LYB_META_BYTES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200197}
198
199static int
200lyb_parse_model(struct ly_ctx *ctx, const char *data, const struct lys_module **mod, struct lyb_state *lybs)
201{
202 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200203 char *mod_name = NULL, mod_rev[11];
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200204 uint16_t rev = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200205
206 /* model name */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200207 ret += (r = lyb_read_string(data, &mod_name, 1, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200208 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200209
210 /* revision */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200211 ret += (r = lyb_read(data, (uint8_t *)&rev, sizeof rev, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200212 LYB_HAVE_READ_GOTO(r, data, error);
213
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200214 if (rev) {
215 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & 0xFE00) >> 9) + 2000, (rev & 0x01E0) >> 5, (rev & 0x001F));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200216 *mod = ly_ctx_get_module(ctx, mod_name, mod_rev, 0);
217 } else {
218 *mod = ly_ctx_get_module(ctx, mod_name, NULL, 0);
219 }
Michal Vasko18c3b6d2018-07-24 16:08:57 +0200220 if (ctx->data_clb) {
221 if (!*mod) {
222 *mod = ctx->data_clb(ctx, mod_name, NULL, 0, ctx->data_clb_data);
223 } else if (!(*mod)->implemented) {
224 *mod = ctx->data_clb(ctx, mod_name, (*mod)->ns, LY_MODCLB_NOT_IMPLEMENTED, ctx->data_clb_data);
225 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200226 }
227
228 free(mod_name);
229 return ret;
230
231error:
232 free(mod_name);
233 return -1;
234}
235
236static struct lyd_node *
237lyb_new_node(const struct lys_node *schema)
238{
239 struct lyd_node *node;
240
241 switch (schema->nodetype) {
242 case LYS_CONTAINER:
243 case LYS_LIST:
244 case LYS_NOTIF:
245 case LYS_RPC:
246 case LYS_ACTION:
247 node = calloc(sizeof(struct lyd_node), 1);
248 break;
249 case LYS_LEAF:
250 case LYS_LEAFLIST:
251 node = calloc(sizeof(struct lyd_node_leaf_list), 1);
Michal Vaskob7400232018-07-11 15:35:57 +0200252
253 if (((struct lys_node_leaf *)schema)->type.base == LY_TYPE_LEAFREF) {
254 node->validity |= LYD_VAL_LEAFREF;
255 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200256 break;
257 case LYS_ANYDATA:
258 case LYS_ANYXML:
259 node = calloc(sizeof(struct lyd_node_anydata), 1);
260 break;
261 default:
262 return NULL;
263 }
264 LY_CHECK_ERR_RETURN(!node, LOGMEM(schema->module->ctx), NULL);
265
266 /* fill basic info */
267 node->schema = (struct lys_node *)schema;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200268 if (resolve_applies_when(schema, 0, NULL)) {
269 node->when_status = LYD_WHEN;
270 }
271 node->prev = node;
272
273 return node;
274}
275
276static int
277lyb_parse_anydata(struct lyd_node *node, const char *data, struct lyb_state *lybs)
278{
279 int r, ret = 0;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200280 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200281 struct lyd_node_anydata *any = (struct lyd_node_anydata *)node;
282
283 /* read value type */
284 ret += (r = lyb_read(data, (uint8_t *)&any->value_type, sizeof any->value_type, lybs));
285 LYB_HAVE_READ_RETURN(r, data, -1);
286
287 /* read anydata content */
288 if (any->value_type == LYD_ANYDATA_DATATREE) {
Michal Vasko228431e2018-07-10 15:47:11 +0200289 any->value.tree = lyd_parse_lyb(node->schema->module->ctx, data, 0, NULL, NULL, &r);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200290 ret += r;
291 LYB_HAVE_READ_RETURN(r, data, -1);
292 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200293 ret += (r = lyb_read_string(data, &str, 0, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200294 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200295
296 /* add to dictionary */
297 any->value.str = lydict_insert_zc(node->schema->module->ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200298 }
299
300 return ret;
301}
302
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200303/* generally, fill lyd_val value union */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200304static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200305lyb_parse_val_1(struct ly_ctx *ctx, struct lys_type *type, LY_DATA_TYPE value_type, uint8_t value_flags, const char *data,
306 const char **value_str, lyd_val *value, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200307{
Michal Vasko228431e2018-07-10 15:47:11 +0200308 int r, ret;
309 size_t i;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200310 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200311 uint8_t byte;
Michal Vasko228431e2018-07-10 15:47:11 +0200312 uint64_t num;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200313
Michal Vasko42132c52018-07-24 16:09:21 +0200314 if (value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200315 /* just read value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200316 ret = lyb_read_string(data, &str, 0, lybs);
317 if (ret > -1) {
318 *value_str = lydict_insert_zc(ctx, str);
319 }
320 return ret;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200321 }
322
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200323 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200324 case LY_TYPE_INST:
325 case LY_TYPE_IDENT:
326 case LY_TYPE_UNION:
327 /* we do not actually fill value now, but value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200328 ret = lyb_read_string(data, &str, 0, lybs);
329 if (ret > -1) {
330 *value_str = lydict_insert_zc(ctx, str);
331 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200332 break;
333 case LY_TYPE_BINARY:
334 case LY_TYPE_STRING:
335 case LY_TYPE_UNKNOWN:
336 /* read string */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200337 ret = lyb_read_string(data, &str, 0, lybs);
338 if (ret > -1) {
339 value->string = lydict_insert_zc(ctx, str);
340 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200341 break;
342 case LY_TYPE_BITS:
343 /* find the correct structure */
344 for (; !type->info.bits.count; type = &type->der->type);
345
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200346 value->bit = calloc(type->info.bits.count, sizeof *value->bit);
347 LY_CHECK_ERR_RETURN(!value->bit, LOGMEM(ctx), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200348
349 /* read values */
Michal Vasko228431e2018-07-10 15:47:11 +0200350 ret = 0;
351 for (i = 0; i < type->info.bits.count; ++i) {
352 if (i % 8 == 0) {
353 /* read another byte */
354 ret += (r = lyb_read(data, &byte, sizeof byte, lybs));
355 if (r < 0) {
356 return -1;
357 }
358 }
359
360 if (byte & (0x01 << (i % 8))) {
361 /* bit is set */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200362 value->bit[i] = &type->info.bits.bit[i];
Michal Vasko228431e2018-07-10 15:47:11 +0200363 }
364 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200365 break;
366 case LY_TYPE_BOOL:
367 /* read byte */
368 ret = lyb_read(data, &byte, sizeof byte, lybs);
369 if ((ret > 0) && byte) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200370 value->bln = 1;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200371 }
372 break;
373 case LY_TYPE_EMPTY:
374 /* nothing to read */
375 ret = 0;
376 break;
377 case LY_TYPE_ENUM:
378 /* find the correct structure */
Michal Vasko228431e2018-07-10 15:47:11 +0200379 for (; !type->info.enums.count; type = &type->der->type);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200380
Michal Vasko228431e2018-07-10 15:47:11 +0200381 num = 0;
Michal Vaskob7400232018-07-11 15:35:57 +0200382 ret = lyb_read_number(&num, type->info.enums.count, data, lybs);
383 if (ret > 0) {
384 assert(num < type->info.enums.count);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200385 value->enm = &type->info.enums.enm[num];
Michal Vasko228431e2018-07-10 15:47:11 +0200386 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200387 break;
388 case LY_TYPE_INT8:
389 case LY_TYPE_UINT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200390 ret = lyb_read_number((uint64_t *)&value->uint8, UINT8_MAX, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200391 break;
392 case LY_TYPE_INT16:
393 case LY_TYPE_UINT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200394 ret = lyb_read_number((uint64_t *)&value->uint16, UINT16_MAX, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200395 break;
396 case LY_TYPE_INT32:
397 case LY_TYPE_UINT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200398 ret = lyb_read_number((uint64_t *)&value->uint32, UINT32_MAX, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200399 break;
400 case LY_TYPE_DEC64:
401 case LY_TYPE_INT64:
402 case LY_TYPE_UINT64:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200403 ret = lyb_read_number((uint64_t *)&value->uint64, UINT64_MAX, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200404 break;
405 default:
406 return -1;
407 }
408
409 return ret;
410}
411
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200412/* generally, fill value_str */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200413static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200414lyb_parse_val_2(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, struct unres_data *unres)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200415{
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200416 struct ly_ctx *ctx;
417 struct lys_module *mod;
Michal Vasko228431e2018-07-10 15:47:11 +0200418 char num_str[22], *str;
Michal Vasko27e5e682018-07-23 14:22:57 +0200419 int64_t frac;
Michal Vasko228431e2018-07-10 15:47:11 +0200420 uint32_t i, str_len;
Michal Vaskob0c3d9e2018-07-23 14:35:17 +0200421 uint8_t *value_flags, dig;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200422 const char **value_str;
423 LY_DATA_TYPE value_type;
424 lyd_val *value;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200425
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200426 if (leaf) {
427 ctx = leaf->schema->module->ctx;
428 mod = lys_node_module(leaf->schema);
429
430 value = &leaf->value;
431 value_str = &leaf->value_str;
432 value_flags = &leaf->value_flags;
433 value_type = leaf->value_type;
434 } else {
435 ctx = attr->annotation->module->ctx;
436 mod = lys_main_module(attr->annotation->module);
437
438 value = &attr->value;
439 value_str = &attr->value_str;
440 value_flags = &attr->value_flags;
441 value_type = attr->value_type;
442 }
443
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200444 if (*value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200445 /* unfortunately, we need to also fill the value properly, so just parse it again */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200446 *value_flags &= ~LY_VALUE_USER;
447 if (!lyp_parse_value(type, value_str, NULL, leaf, attr, NULL, 1, (leaf ? leaf->dflt : 0), 1)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200448 return -1;
449 }
450
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200451 if (!(*value_flags & LY_VALUE_USER)) {
452 LOGWRN(ctx, "Value \"%s\" was stored as a user type, but it is not in the current context.", value_str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200453 }
454 return 0;
455 }
456
Michal Vaskob7400232018-07-11 15:35:57 +0200457 /* we are parsing leafref/ptr union stored as the target type,
458 * so we first parse it into string and then resolve the leafref/ptr union */
Michal Vasko42132c52018-07-24 16:09:21 +0200459 if (!(*value_flags & LY_VALUE_UNRES) && ((type->base == LY_TYPE_LEAFREF)
460 || (type->base == LY_TYPE_INST) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type))) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200461 if ((value_type == LY_TYPE_INST) || (value_type == LY_TYPE_IDENT) || (value_type == LY_TYPE_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200462 /* we already have a string */
463 goto parse_reference;
464 }
465 }
466
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200467 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200468 case LY_TYPE_IDENT:
469 /* fill the identity pointer now */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200470 value->ident = resolve_identref(type, *value_str, (struct lyd_node *)leaf, mod, (leaf ? leaf->dflt : 0));
471 if (!value->ident) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200472 return -1;
473 }
474 break;
475 case LY_TYPE_BINARY:
476 case LY_TYPE_STRING:
477 case LY_TYPE_UNKNOWN:
478 /* just re-assign it */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200479 *value_str = value->string;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200480 break;
481 case LY_TYPE_BITS:
Michal Vasko228431e2018-07-10 15:47:11 +0200482 for (; !type->info.bits.count; type = &type->der->type);
483
484 /* print the set bits */
485 str = malloc(1);
486 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
487 str[0] = '\0';
Michal Vaskob7400232018-07-11 15:35:57 +0200488 str_len = 0;
Michal Vasko228431e2018-07-10 15:47:11 +0200489 for (i = 0; i < type->info.bits.count; ++i) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200490 if (value->bit[i]) {
491 str = ly_realloc(str, str_len + strlen(value->bit[i]->name) + (str_len ? 1 : 0) + 1);
Michal Vasko228431e2018-07-10 15:47:11 +0200492 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
493
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200494 str_len += sprintf(str + str_len, "%s%s", str_len ? " " : "", value->bit[i]->name);
Michal Vasko228431e2018-07-10 15:47:11 +0200495 }
496 }
497
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200498 *value_str = lydict_insert_zc(ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200499 break;
500 case LY_TYPE_BOOL:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200501 *value_str = lydict_insert(ctx, (value->bln ? "true" : "false"), 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200502 break;
503 case LY_TYPE_EMPTY:
Michal Vasko27e5e682018-07-23 14:22:57 +0200504 *value_str = lydict_insert(ctx, "", 0);
505 break;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200506 case LY_TYPE_UNION:
Michal Vasko27e5e682018-07-23 14:22:57 +0200507 if (attr) {
508 /* we do not support union type attribute */
509 LOGINT(ctx);
510 return -1;
511 }
512
513 if (resolve_union(leaf, type, 1, 2, NULL)) {
514 return -1;
515 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200516 break;
517 case LY_TYPE_ENUM:
Michal Vasko228431e2018-07-10 15:47:11 +0200518 /* print the value */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200519 *value_str = lydict_insert(ctx, value->enm->name, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200520 break;
521 case LY_TYPE_INT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200522 sprintf(num_str, "%d", value->int8);
523 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200524 break;
525 case LY_TYPE_UINT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200526 sprintf(num_str, "%u", value->uint8);
527 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200528 break;
529 case LY_TYPE_INT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200530 sprintf(num_str, "%d", value->int16);
531 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200532 break;
533 case LY_TYPE_UINT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200534 sprintf(num_str, "%u", value->uint16);
535 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200536 break;
537 case LY_TYPE_INT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200538 sprintf(num_str, "%d", value->int32);
539 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200540 break;
541 case LY_TYPE_UINT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200542 sprintf(num_str, "%u", value->uint32);
543 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200544 break;
545 case LY_TYPE_INT64:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200546 sprintf(num_str, "%ld", value->int64);
547 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200548 break;
549 case LY_TYPE_UINT64:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200550 sprintf(num_str, "%lu", value->uint64);
551 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200552 break;
553 case LY_TYPE_DEC64:
Michal Vasko27e5e682018-07-23 14:22:57 +0200554 frac = value->dec64 % type->info.dec64.div;
Michal Vaskob0c3d9e2018-07-23 14:35:17 +0200555 dig = type->info.dec64.dig;
556 /* remove trailing zeros */
557 while ((dig > 1) && !(frac % 10)) {
558 frac /= 10;
559 --dig;
560 }
561
562 sprintf(num_str, "%ld.%.*ld", value->dec64 / (int64_t)type->info.dec64.div, dig, frac);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200563 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200564 break;
565 default:
566 return -1;
567 }
568
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200569 if ((type->base == LY_TYPE_LEAFREF) || (type->base == LY_TYPE_INST) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200570parse_reference:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200571 assert(*value_str);
Michal Vaskob7400232018-07-11 15:35:57 +0200572
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200573 if (attr) {
574 /* we do not support reference types of attributes */
575 LOGINT(ctx);
576 return -1;
577 }
578
579 if (type->base == LY_TYPE_INST) {
580 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_INSTID)) {
581 return -1;
582 }
583 } else if (type->base == LY_TYPE_LEAFREF) {
584 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_LEAFREF)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200585 return -1;
586 }
587 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200588 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200589 return -1;
590 }
591 }
592 }
593
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200594 return 0;
595}
596
597static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200598lyb_parse_value(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, const char *data,
599 struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200600{
601 int r, ret = 0;
602 uint8_t start_byte;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200603
604 struct ly_ctx *ctx;
605 const char **value_str;
606 lyd_val *value;
607 LY_DATA_TYPE *value_type;
608 uint8_t *value_flags;
609
610 assert((leaf || attr) && (!leaf || !attr));
611
612 if (leaf) {
613 ctx = leaf->schema->module->ctx;
614 value_str = &leaf->value_str;
615 value = &leaf->value;
616 value_type = &leaf->value_type;
617 value_flags = &leaf->value_flags;
618 } else {
619 ctx = attr->annotation->module->ctx;
620 value_str = &attr->value_str;
621 value = &attr->value;
622 value_type = &attr->value_type;
623 value_flags = &attr->value_flags;
624 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200625
626 /* read value type and flags on the first byte */
627 ret += (r = lyb_read(data, &start_byte, sizeof start_byte, lybs));
628 LYB_HAVE_READ_RETURN(r, data, -1);
629
630 /* fill value type, flags */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200631 *value_type = start_byte & 0x1F;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200632 if (start_byte & 0x80) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200633 assert(leaf);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200634 leaf->dflt = 1;
635 }
636 if (start_byte & 0x40) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200637 *value_flags |= LY_VALUE_USER;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200638 }
639 if (start_byte & 0x20) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200640 *value_flags |= LY_VALUE_UNRES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200641 }
642
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200643 ret += (r = lyb_parse_val_1(ctx, type, *value_type, *value_flags, data, value_str, value, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200644 LYB_HAVE_READ_RETURN(r, data, -1);
645
Michal Vasko27e5e682018-07-23 14:22:57 +0200646 /* union is handled specially */
647 if (type->base == LY_TYPE_UNION) {
648 assert(*value_type == LY_TYPE_STRING);
649
650 *value_str = value->string;
651 value->string = NULL;
652 *value_type = LY_TYPE_UNION;
653 }
654
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200655 ret += (r = lyb_parse_val_2(type, leaf, attr, unres));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200656 LYB_HAVE_READ_RETURN(r, data, -1);
657
658 return ret;
659}
660
661static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200662lyb_parse_attr_name(const struct lys_module *mod, const char *data, struct lys_ext_instance_complex **ext, int options,
663 struct lyb_state *lybs)
664{
665 int r, ret = 0, pos, i, j, k;
666 const struct lys_submodule *submod = NULL;
667 char *attr_name = NULL;
668
669 /* attr name */
670 ret += (r = lyb_read_string(data, &attr_name, 1, lybs));
671 LYB_HAVE_READ_RETURN(r, data, -1);
672
673 /* search module */
674 pos = -1;
675 for (i = 0, j = 0; i < mod->ext_size; i = i + j + 1) {
676 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &mod->ext[i], mod->ext_size - i);
677 if (j == -1) {
678 break;
679 }
680 if (ly_strequal(mod->ext[i + j]->arg_value, attr_name, 0)) {
681 pos = i + j;
682 break;
683 }
684 }
685
686 /* try submodules */
687 if (pos == -1) {
688 for (k = 0; k < mod->inc_size; ++k) {
689 submod = mod->inc[k].submodule;
690 for (i = 0, j = 0; i < submod->ext_size; i = i + j + 1) {
691 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &submod->ext[i], submod->ext_size - i);
692 if (j == -1) {
693 break;
694 }
695 if (ly_strequal(submod->ext[i + j]->arg_value, attr_name, 0)) {
696 pos = i + j;
697 break;
698 }
699 }
700 }
701 }
702
703 if (pos == -1) {
704 *ext = NULL;
705 } else {
706 *ext = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] : (struct lys_ext_instance_complex *)mod->ext[pos];
707 }
708
709 if (!*ext && (options & LYD_OPT_STRICT)) {
710 LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find annotation \"%s\" in \"%s\".", attr_name, mod->name);
711 free(attr_name);
712 return -1;
713 }
714
715 free(attr_name);
716 return ret;
717}
718
719static int
720lyb_parse_attributes(struct lyd_node *node, const char *data, int options, struct unres_data *unres, struct lyb_state *lybs)
721{
722 int r, ret = 0;
723 uint8_t i, count = 0;
724 const struct lys_module *mod;
725 struct lys_type *type;
726 struct lyd_attr *attr = NULL;
727 struct lys_ext_instance_complex *ext;
728 struct ly_ctx *ctx = node->schema->module->ctx;
729
730 /* read number of attributes stored */
731 ret += (r = lyb_read(data, &count, 1, lybs));
732 LYB_HAVE_READ_GOTO(r, data, error);
733
734 /* read attributes */
735 for (i = 0; i < count; ++i) {
736 ret += (r = lyb_read_start_subtree(data, lybs));
737 LYB_HAVE_READ_GOTO(r, data, error);
738
739 /* find model */
740 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
741 LYB_HAVE_READ_GOTO(r, data, error);
742
Michal Vasko53830662018-07-24 16:09:49 +0200743 if (mod) {
744 /* annotation name */
745 ret += (r = lyb_parse_attr_name(mod, data, &ext, options, lybs));
746 LYB_HAVE_READ_GOTO(r, data, error);
747 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200748
Michal Vasko53830662018-07-24 16:09:49 +0200749 if (!mod || !ext) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200750 /* unknown attribute, skip it */
751 do {
752 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200753 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200754 } while (lybs->written[lybs->used - 1]);
755 goto stop_subtree;
756 }
757
758 /* allocate new attribute */
759 if (!attr) {
760 assert(!node->attr);
761
762 attr = calloc(1, sizeof *attr);
763 LY_CHECK_ERR_GOTO(!attr, LOGMEM(ctx), error);
764
765 node->attr = attr;
766 } else {
767 attr->next = calloc(1, sizeof *attr);
768 LY_CHECK_ERR_GOTO(!attr->next, LOGMEM(ctx), error);
769
770 attr = attr->next;
771 }
772
773 /* attribute annotation */
774 attr->annotation = ext;
775
776 /* attribute name */
777 attr->name = lydict_insert(ctx, attr->annotation->arg_value, 0);
778
779 /* get the type */
780 type = *(struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, attr->annotation, NULL);
781
782 /* attribute value */
783 ret += (r = lyb_parse_value(type, NULL, attr, data, unres, lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200784 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200785
786stop_subtree:
787 lyb_read_stop_subtree(lybs);
788 }
789
790 return ret;
791
792error:
793 lyd_free_attr(ctx, node, node->attr, 1);
794 return -1;
795}
796
797static int
Michal Vaskob7400232018-07-11 15:35:57 +0200798lyb_is_schema_hash_match(struct lys_node *sibling, LYB_HASH *hash, uint8_t hash_count)
Michal Vasko228431e2018-07-10 15:47:11 +0200799{
800 LYB_HASH sibling_hash;
Michal Vaskob7400232018-07-11 15:35:57 +0200801 uint8_t i;
Michal Vasko228431e2018-07-10 15:47:11 +0200802
Michal Vaskob7400232018-07-11 15:35:57 +0200803 /* compare all the hashes starting from collision ID 0 */
804 for (i = 0; i < hash_count; ++i) {
805 sibling_hash = lyb_hash(sibling, i);
806 if (sibling_hash != hash[i]) {
807 return 0;
808 }
809 }
Michal Vasko228431e2018-07-10 15:47:11 +0200810
Michal Vaskob7400232018-07-11 15:35:57 +0200811 return 1;
Michal Vasko228431e2018-07-10 15:47:11 +0200812}
813
814static int
815lyb_parse_schema_hash(const struct lys_node *sparent, const struct lys_module *mod, const char *data, const char *yang_data_name,
816 int options, struct lys_node **snode, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200817{
818 int r, ret = 0;
Michal Vaskob7400232018-07-11 15:35:57 +0200819 uint8_t i, j;
820 struct lys_node *sibling;
821 LYB_HASH hash[LYB_HASH_BITS - 1];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200822 struct ly_ctx *ctx;
823
824 assert((sparent || mod) && (!sparent || !mod));
825 ctx = (sparent ? sparent->module->ctx : mod->ctx);
826
Michal Vaskob7400232018-07-11 15:35:57 +0200827 /* read the first hash */
828 ret += (r = lyb_read(data, &hash[0], sizeof *hash, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200829 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskob7400232018-07-11 15:35:57 +0200830
831 /* based on the first hash read all the other ones, if any */
832 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i);
833
834 /* move the first hash on its accurate position */
835 hash[i] = hash[0];
836
837 /* read the rest of hashes */
838 for (j = i; j; --j) {
839 ret += (r = lyb_read(data, &hash[j - 1], sizeof *hash, lybs));
840 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200841
Michal Vasko365849c2018-08-07 11:31:30 +0200842 /* correct collision ID */
843 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
844 /* preceded with zeros */
845 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
Michal Vasko228431e2018-07-10 15:47:11 +0200846 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200847
Michal Vaskoe3880e62018-07-11 16:18:34 +0200848 /* handle yang data templates */
849 if ((options & LYD_OPT_DATA_TEMPLATE) && yang_data_name && mod) {
850 sparent = lyp_get_yang_data_template(mod, yang_data_name, strlen(yang_data_name));
851 if (!sparent) {
852 sibling = NULL;
853 goto finish;
854 }
855 }
856
857 /* handle RPC/action input/output */
Michal Vaskob7400232018-07-11 15:35:57 +0200858 if (sparent && (sparent->nodetype & (LYS_RPC | LYS_ACTION))) {
859 sibling = NULL;
860 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, NULL, LYS_GETNEXT_WITHINOUT))) {
861 if ((sibling->nodetype == LYS_INPUT) && (options & LYD_OPT_RPC)) {
862 break;
863 }
864 if ((sibling->nodetype == LYS_OUTPUT) && (options & LYD_OPT_RPCREPLY)) {
865 break;
866 }
867 }
868 if (!sibling) {
869 /* fail */
870 goto finish;
871 }
872
873 /* use only input/output children nodes */
874 sparent = sibling;
875 }
876
877 /* find our node with matching hashes */
878 sibling = NULL;
Michal Vasko228431e2018-07-10 15:47:11 +0200879 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, mod, 0))) {
880 /* skip schema nodes from models not present during printing */
Michal Vaskob7400232018-07-11 15:35:57 +0200881 if (lyb_has_schema_model(sibling, lybs->models, lybs->mod_count) && lyb_is_schema_hash_match(sibling, hash, i + 1)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200882 /* match found */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200883 break;
884 }
885 }
886
Michal Vaskob7400232018-07-11 15:35:57 +0200887finish:
Michal Vasko228431e2018-07-10 15:47:11 +0200888 *snode = sibling;
889 if (!sibling && (options & LYD_OPT_STRICT)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200890 if (mod) {
891 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find matching hash for a top-level node from \"%s\".", mod->name);
892 } else {
893 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, sparent, "Failed to find matching hash for a child of \"%s\".", sparent->name);
894 }
895 return -1;
896 }
897
898 return ret;
899}
900
901static int
902lyb_parse_subtree(struct ly_ctx *ctx, const char *data, struct lyd_node *parent, struct lyd_node **first_sibling,
Michal Vasko228431e2018-07-10 15:47:11 +0200903 const char *yang_data_name, int options, struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200904{
905 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200906 struct lyd_node *node = NULL, *iter;
907 const struct lys_module *mod;
Michal Vaskoe3880e62018-07-11 16:18:34 +0200908 struct lys_node *snode;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200909
910 assert((parent && !first_sibling) || (!parent && first_sibling));
911
912 /* register a new subtree */
913 ret += (r = lyb_read_start_subtree(data, lybs));
914 LYB_HAVE_READ_GOTO(r, data, error);
915
916 if (!parent) {
917 /* top-level, read module name */
918 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
919 LYB_HAVE_READ_GOTO(r, data, error);
920
Michal Vasko53830662018-07-24 16:09:49 +0200921 if (mod) {
922 /* read hash, find the schema node starting from mod, possibly yang_data_name */
923 r = lyb_parse_schema_hash(NULL, mod, data, yang_data_name, options, &snode, lybs);
924 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200925 } else {
Michal Vasko53830662018-07-24 16:09:49 +0200926 mod = lyd_node_module(parent);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200927
Michal Vaskoe3880e62018-07-11 16:18:34 +0200928 /* read hash, find the schema node starting from parent schema */
929 r = lyb_parse_schema_hash(parent->schema, NULL, data, NULL, options, &snode, lybs);
930 }
931 ret += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200932 LYB_HAVE_READ_GOTO(r, data, error);
933
Michal Vasko53830662018-07-24 16:09:49 +0200934 if (!mod || !snode) {
Michal Vasko997071e2018-07-10 15:56:14 +0200935 /* unknown data subtree, skip it whole */
936 do {
937 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vaskoa9852522018-08-08 16:24:45 +0200938 /* also skip the meta information inside */
939 ret += (r = lyb_read(data, NULL, lybs->inner_chunks[lybs->used - 1] * LYB_META_BYTES, lybs));
Michal Vasko997071e2018-07-10 15:56:14 +0200940 } while (lybs->written[lybs->used - 1]);
Michal Vasko228431e2018-07-10 15:47:11 +0200941 goto stop_subtree;
942 }
943
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200944 /*
945 * read the node
946 */
947 node = lyb_new_node(snode);
948 if (!node) {
949 goto error;
950 }
951
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200952 ret += (r = lyb_parse_attributes(node, data, options, unres, lybs));
953 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200954
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200955 /* read node content */
956 switch (snode->nodetype) {
957 case LYS_CONTAINER:
958 case LYS_LIST:
Michal Vaskob7400232018-07-11 15:35:57 +0200959 case LYS_NOTIF:
960 case LYS_RPC:
961 case LYS_ACTION:
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200962 /* nothing to read */
963 break;
964 case LYS_LEAF:
965 case LYS_LEAFLIST:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200966 ret += (r = lyb_parse_value(&((struct lys_node_leaf *)node->schema)->type, (struct lyd_node_leaf_list *)node,
967 NULL, data, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200968 LYB_HAVE_READ_GOTO(r, data, error);
969 break;
970 case LYS_ANYXML:
971 case LYS_ANYDATA:
972 ret += (r = lyb_parse_anydata(node, data, lybs));
973 LYB_HAVE_READ_GOTO(r, data, error);
974 break;
975 default:
976 goto error;
977 }
978
979 /* insert into data tree, manually */
980 if (parent) {
981 if (!parent->child) {
982 /* only child */
983 parent->child = node;
984 } else {
985 /* last child */
986 parent->child->prev->next = node;
987 node->prev = parent->child->prev;
988 parent->child->prev = node;
989 }
990 node->parent = parent;
991 } else if (*first_sibling) {
992 /* last sibling */
993 (*first_sibling)->prev->next = node;
994 node->prev = (*first_sibling)->prev;
995 (*first_sibling)->prev = node;
996 } else {
997 /* only sibling */
998 *first_sibling = node;
999 }
1000
1001 /* read all descendants */
1002 while (lybs->written[lybs->used - 1]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001003 ret += (r = lyb_parse_subtree(ctx, data, node, NULL, NULL, options, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001004 LYB_HAVE_READ_GOTO(r, data, error);
1005 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001006
1007 /* make containers default if should be */
1008 if (node->schema->nodetype == LYS_CONTAINER) {
1009 LY_TREE_FOR(node->child, iter) {
1010 if (!iter->dflt) {
1011 break;
1012 }
1013 }
1014
1015 if (!iter) {
1016 node->dflt = 1;
1017 }
1018 }
1019
Michal Vaskofe43d042018-07-24 09:43:46 +02001020#ifdef LY_ENABLED_CACHE
1021 /* calculate the hash and insert it into parent (list with keys is handled when its keys are inserted) */
1022 if ((node->schema->nodetype != LYS_LIST) || !((struct lys_node_list *)node->schema)->keys_size) {
1023 lyd_hash(node);
1024 lyd_insert_hash(node);
1025 }
1026#endif
1027
Michal Vasko228431e2018-07-10 15:47:11 +02001028stop_subtree:
1029 /* end the subtree */
1030 lyb_read_stop_subtree(lybs);
1031
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001032 return ret;
1033
1034error:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001035 lyd_free(node);
Michal Vaskob7400232018-07-11 15:35:57 +02001036 if (first_sibling && (*first_sibling == node)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001037 *first_sibling = NULL;
1038 }
1039 return -1;
1040}
1041
1042static int
Michal Vasko228431e2018-07-10 15:47:11 +02001043lyb_parse_data_models(struct ly_ctx *ctx, const char *data, struct lyb_state *lybs)
1044{
1045 int i, r, ret = 0;
1046
1047 /* read model count */
1048 ret += (r = lyb_read(data, (uint8_t *)&lybs->mod_count, 2, lybs));
1049 LYB_HAVE_READ_RETURN(r, data, -1);
1050
1051 lybs->models = malloc(lybs->mod_count * sizeof *lybs->models);
1052 LY_CHECK_ERR_RETURN(!lybs->models, LOGMEM(NULL), -1);
1053
1054 /* read modules */
1055 for (i = 0; i < lybs->mod_count; ++i) {
1056 ret += (r = lyb_parse_model(ctx, data, &lybs->models[i], lybs));
1057 LYB_HAVE_READ_RETURN(r, data, -1);
1058 }
1059
1060 return ret;
1061}
1062
1063static int
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001064lyb_parse_header(const char *data, struct lyb_state *lybs)
1065{
1066 int ret = 0;
1067 uint8_t byte = 0;
1068
Michal Vasko228431e2018-07-10 15:47:11 +02001069 /* TODO version, any flags? */
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001070 ret += lyb_read(data, (uint8_t *)&byte, sizeof byte, lybs);
1071
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001072 return ret;
1073}
1074
1075struct lyd_node *
Michal Vasko228431e2018-07-10 15:47:11 +02001076lyd_parse_lyb(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *data_tree,
1077 const char *yang_data_name, int *parsed)
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001078{
1079 int r, ret = 0;
Michal Vasko228431e2018-07-10 15:47:11 +02001080 struct lyd_node *node = NULL, *next, *act_notif = NULL;
1081 struct unres_data *unres = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001082 struct lyb_state lybs;
1083
1084 if (!ctx || !data) {
1085 LOGARG;
1086 return NULL;
1087 }
1088
1089 lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
1090 lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001091 lybs.inner_chunks = malloc(LYB_STATE_STEP * sizeof *lybs.inner_chunks);
1092 LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position || !lybs.inner_chunks, LOGMEM(ctx), finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001093 lybs.used = 0;
1094 lybs.size = LYB_STATE_STEP;
Michal Vasko228431e2018-07-10 15:47:11 +02001095 lybs.models = NULL;
1096 lybs.mod_count = 0;
1097
1098 unres = calloc(1, sizeof *unres);
1099 LY_CHECK_ERR_GOTO(!unres, LOGMEM(ctx), finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001100
1101 /* read header */
1102 ret += (r = lyb_parse_header(data, &lybs));
1103 LYB_HAVE_READ_GOTO(r, data, finish);
1104
Michal Vasko228431e2018-07-10 15:47:11 +02001105 /* read used models */
1106 ret += (r = lyb_parse_data_models(ctx, data, &lybs));
1107 LYB_HAVE_READ_GOTO(r, data, finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001108
1109 /* read subtree(s) */
1110 while (data[0]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001111 ret += (r = lyb_parse_subtree(ctx, data, NULL, &node, yang_data_name, options, unres, &lybs));
1112 if (r < 0) {
1113 lyd_free_withsiblings(node);
1114 node = NULL;
1115 goto finish;
1116 }
1117 data += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001118 }
1119
1120 /* read the last zero, parsing finished */
1121 ++ret;
1122 r = ret;
1123
Michal Vasko228431e2018-07-10 15:47:11 +02001124 if (options & LYD_OPT_DATA_ADD_YANGLIB) {
1125 if (lyd_merge(node, ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
1126 LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
1127 lyd_free_withsiblings(node);
1128 node = NULL;
1129 goto finish;
1130 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001131 }
Michal Vasko228431e2018-07-10 15:47:11 +02001132
1133 /* resolve any unresolved instance-identifiers */
1134 if (unres->count) {
1135 if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
1136 LY_TREE_DFS_BEGIN(node, next, act_notif) {
1137 if (act_notif->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1138 break;
1139 }
1140 LY_TREE_DFS_END(node, next, act_notif);
1141 }
1142 }
1143 if (lyd_defaults_add_unres(&node, options, ctx, data_tree, act_notif, unres, 0)) {
1144 lyd_free_withsiblings(node);
1145 node = NULL;
1146 goto finish;
1147 }
1148 }
1149
1150finish:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001151 free(lybs.written);
1152 free(lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001153 free(lybs.inner_chunks);
Michal Vasko228431e2018-07-10 15:47:11 +02001154 free(lybs.models);
1155 if (unres) {
1156 free(unres->node);
1157 free(unres->type);
1158 free(unres);
1159 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001160
1161 if (parsed) {
1162 *parsed = r;
1163 }
1164 return node;
1165}