blob: f37a81ee957b956da3663ebe7187fab822df71fa [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);
Michal Vaskodcaf7222018-08-08 16:27:00 +0200292 } else if (any->value_type == LYD_ANYDATA_LYB) {
293 ret += (r = lyb_read_string(data, &any->value.mem, 0, lybs));
294 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200295 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200296 ret += (r = lyb_read_string(data, &str, 0, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200297 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200298
299 /* add to dictionary */
300 any->value.str = lydict_insert_zc(node->schema->module->ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200301 }
302
303 return ret;
304}
305
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200306/* generally, fill lyd_val value union */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200307static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200308lyb_parse_val_1(struct ly_ctx *ctx, struct lys_type *type, LY_DATA_TYPE value_type, uint8_t value_flags, const char *data,
309 const char **value_str, lyd_val *value, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200310{
Michal Vasko228431e2018-07-10 15:47:11 +0200311 int r, ret;
312 size_t i;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200313 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200314 uint8_t byte;
Michal Vasko228431e2018-07-10 15:47:11 +0200315 uint64_t num;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200316
Michal Vasko42132c52018-07-24 16:09:21 +0200317 if (value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200318 /* just read value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200319 ret = lyb_read_string(data, &str, 0, lybs);
320 if (ret > -1) {
321 *value_str = lydict_insert_zc(ctx, str);
322 }
323 return ret;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200324 }
325
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200326 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200327 case LY_TYPE_INST:
328 case LY_TYPE_IDENT:
329 case LY_TYPE_UNION:
330 /* we do not actually fill value now, but value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200331 ret = lyb_read_string(data, &str, 0, lybs);
332 if (ret > -1) {
333 *value_str = lydict_insert_zc(ctx, str);
334 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200335 break;
336 case LY_TYPE_BINARY:
337 case LY_TYPE_STRING:
338 case LY_TYPE_UNKNOWN:
339 /* read string */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200340 ret = lyb_read_string(data, &str, 0, lybs);
341 if (ret > -1) {
342 value->string = lydict_insert_zc(ctx, str);
343 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200344 break;
345 case LY_TYPE_BITS:
346 /* find the correct structure */
347 for (; !type->info.bits.count; type = &type->der->type);
348
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200349 value->bit = calloc(type->info.bits.count, sizeof *value->bit);
350 LY_CHECK_ERR_RETURN(!value->bit, LOGMEM(ctx), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200351
352 /* read values */
Michal Vasko228431e2018-07-10 15:47:11 +0200353 ret = 0;
354 for (i = 0; i < type->info.bits.count; ++i) {
355 if (i % 8 == 0) {
356 /* read another byte */
357 ret += (r = lyb_read(data, &byte, sizeof byte, lybs));
358 if (r < 0) {
359 return -1;
360 }
361 }
362
363 if (byte & (0x01 << (i % 8))) {
364 /* bit is set */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200365 value->bit[i] = &type->info.bits.bit[i];
Michal Vasko228431e2018-07-10 15:47:11 +0200366 }
367 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200368 break;
369 case LY_TYPE_BOOL:
370 /* read byte */
371 ret = lyb_read(data, &byte, sizeof byte, lybs);
372 if ((ret > 0) && byte) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200373 value->bln = 1;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200374 }
375 break;
376 case LY_TYPE_EMPTY:
377 /* nothing to read */
378 ret = 0;
379 break;
380 case LY_TYPE_ENUM:
381 /* find the correct structure */
Michal Vasko228431e2018-07-10 15:47:11 +0200382 for (; !type->info.enums.count; type = &type->der->type);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200383
Michal Vasko228431e2018-07-10 15:47:11 +0200384 num = 0;
Michal Vaskob7400232018-07-11 15:35:57 +0200385 ret = lyb_read_number(&num, type->info.enums.count, data, lybs);
386 if (ret > 0) {
387 assert(num < type->info.enums.count);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200388 value->enm = &type->info.enums.enm[num];
Michal Vasko228431e2018-07-10 15:47:11 +0200389 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200390 break;
391 case LY_TYPE_INT8:
392 case LY_TYPE_UINT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200393 ret = lyb_read_number((uint64_t *)&value->uint8, UINT8_MAX, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200394 break;
395 case LY_TYPE_INT16:
396 case LY_TYPE_UINT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200397 ret = lyb_read_number((uint64_t *)&value->uint16, UINT16_MAX, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200398 break;
399 case LY_TYPE_INT32:
400 case LY_TYPE_UINT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200401 ret = lyb_read_number((uint64_t *)&value->uint32, UINT32_MAX, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200402 break;
403 case LY_TYPE_DEC64:
404 case LY_TYPE_INT64:
405 case LY_TYPE_UINT64:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200406 ret = lyb_read_number((uint64_t *)&value->uint64, UINT64_MAX, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200407 break;
408 default:
409 return -1;
410 }
411
412 return ret;
413}
414
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200415/* generally, fill value_str */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200416static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200417lyb_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 +0200418{
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200419 struct ly_ctx *ctx;
420 struct lys_module *mod;
Michal Vasko228431e2018-07-10 15:47:11 +0200421 char num_str[22], *str;
Michal Vasko27e5e682018-07-23 14:22:57 +0200422 int64_t frac;
Michal Vasko228431e2018-07-10 15:47:11 +0200423 uint32_t i, str_len;
Michal Vaskob0c3d9e2018-07-23 14:35:17 +0200424 uint8_t *value_flags, dig;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200425 const char **value_str;
426 LY_DATA_TYPE value_type;
427 lyd_val *value;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200428
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200429 if (leaf) {
430 ctx = leaf->schema->module->ctx;
431 mod = lys_node_module(leaf->schema);
432
433 value = &leaf->value;
434 value_str = &leaf->value_str;
435 value_flags = &leaf->value_flags;
436 value_type = leaf->value_type;
437 } else {
438 ctx = attr->annotation->module->ctx;
439 mod = lys_main_module(attr->annotation->module);
440
441 value = &attr->value;
442 value_str = &attr->value_str;
443 value_flags = &attr->value_flags;
444 value_type = attr->value_type;
445 }
446
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200447 if (*value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200448 /* unfortunately, we need to also fill the value properly, so just parse it again */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200449 *value_flags &= ~LY_VALUE_USER;
450 if (!lyp_parse_value(type, value_str, NULL, leaf, attr, NULL, 1, (leaf ? leaf->dflt : 0), 1)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200451 return -1;
452 }
453
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200454 if (!(*value_flags & LY_VALUE_USER)) {
455 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 +0200456 }
457 return 0;
458 }
459
Michal Vaskob7400232018-07-11 15:35:57 +0200460 /* we are parsing leafref/ptr union stored as the target type,
461 * so we first parse it into string and then resolve the leafref/ptr union */
Michal Vasko42132c52018-07-24 16:09:21 +0200462 if (!(*value_flags & LY_VALUE_UNRES) && ((type->base == LY_TYPE_LEAFREF)
463 || (type->base == LY_TYPE_INST) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type))) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200464 if ((value_type == LY_TYPE_INST) || (value_type == LY_TYPE_IDENT) || (value_type == LY_TYPE_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200465 /* we already have a string */
466 goto parse_reference;
467 }
468 }
469
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200470 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200471 case LY_TYPE_IDENT:
472 /* fill the identity pointer now */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200473 value->ident = resolve_identref(type, *value_str, (struct lyd_node *)leaf, mod, (leaf ? leaf->dflt : 0));
474 if (!value->ident) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200475 return -1;
476 }
477 break;
Michal Vasko56670362018-08-08 16:27:21 +0200478 case LY_TYPE_INST:
479 /* unresolved instance-identifier, keep value NULL */
480 value->instance = NULL;
481 break;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200482 case LY_TYPE_BINARY:
483 case LY_TYPE_STRING:
484 case LY_TYPE_UNKNOWN:
485 /* just re-assign it */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200486 *value_str = value->string;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200487 break;
488 case LY_TYPE_BITS:
Michal Vasko228431e2018-07-10 15:47:11 +0200489 for (; !type->info.bits.count; type = &type->der->type);
490
491 /* print the set bits */
492 str = malloc(1);
493 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
494 str[0] = '\0';
Michal Vaskob7400232018-07-11 15:35:57 +0200495 str_len = 0;
Michal Vasko228431e2018-07-10 15:47:11 +0200496 for (i = 0; i < type->info.bits.count; ++i) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200497 if (value->bit[i]) {
498 str = ly_realloc(str, str_len + strlen(value->bit[i]->name) + (str_len ? 1 : 0) + 1);
Michal Vasko228431e2018-07-10 15:47:11 +0200499 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
500
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200501 str_len += sprintf(str + str_len, "%s%s", str_len ? " " : "", value->bit[i]->name);
Michal Vasko228431e2018-07-10 15:47:11 +0200502 }
503 }
504
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200505 *value_str = lydict_insert_zc(ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200506 break;
507 case LY_TYPE_BOOL:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200508 *value_str = lydict_insert(ctx, (value->bln ? "true" : "false"), 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200509 break;
510 case LY_TYPE_EMPTY:
Michal Vasko27e5e682018-07-23 14:22:57 +0200511 *value_str = lydict_insert(ctx, "", 0);
512 break;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200513 case LY_TYPE_UNION:
Michal Vasko27e5e682018-07-23 14:22:57 +0200514 if (attr) {
515 /* we do not support union type attribute */
516 LOGINT(ctx);
517 return -1;
518 }
519
520 if (resolve_union(leaf, type, 1, 2, NULL)) {
521 return -1;
522 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200523 break;
524 case LY_TYPE_ENUM:
Michal Vasko228431e2018-07-10 15:47:11 +0200525 /* print the value */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200526 *value_str = lydict_insert(ctx, value->enm->name, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200527 break;
528 case LY_TYPE_INT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200529 sprintf(num_str, "%d", value->int8);
530 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200531 break;
532 case LY_TYPE_UINT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200533 sprintf(num_str, "%u", value->uint8);
534 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200535 break;
536 case LY_TYPE_INT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200537 sprintf(num_str, "%d", value->int16);
538 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200539 break;
540 case LY_TYPE_UINT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200541 sprintf(num_str, "%u", value->uint16);
542 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200543 break;
544 case LY_TYPE_INT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200545 sprintf(num_str, "%d", value->int32);
546 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200547 break;
548 case LY_TYPE_UINT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200549 sprintf(num_str, "%u", value->uint32);
550 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200551 break;
552 case LY_TYPE_INT64:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200553 sprintf(num_str, "%ld", value->int64);
554 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200555 break;
556 case LY_TYPE_UINT64:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200557 sprintf(num_str, "%lu", value->uint64);
558 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200559 break;
560 case LY_TYPE_DEC64:
Michal Vasko27e5e682018-07-23 14:22:57 +0200561 frac = value->dec64 % type->info.dec64.div;
Michal Vaskob0c3d9e2018-07-23 14:35:17 +0200562 dig = type->info.dec64.dig;
563 /* remove trailing zeros */
564 while ((dig > 1) && !(frac % 10)) {
565 frac /= 10;
566 --dig;
567 }
568
569 sprintf(num_str, "%ld.%.*ld", value->dec64 / (int64_t)type->info.dec64.div, dig, frac);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200570 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200571 break;
572 default:
573 return -1;
574 }
575
Michal Vasko56670362018-08-08 16:27:21 +0200576 if (!(*value_flags & LY_VALUE_UNRES) && ((type->base == LY_TYPE_LEAFREF)
577 || (type->base == LY_TYPE_INST) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type))) {
Michal Vaskob7400232018-07-11 15:35:57 +0200578parse_reference:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200579 assert(*value_str);
Michal Vaskob7400232018-07-11 15:35:57 +0200580
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200581 if (attr) {
582 /* we do not support reference types of attributes */
583 LOGINT(ctx);
584 return -1;
585 }
586
587 if (type->base == LY_TYPE_INST) {
588 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_INSTID)) {
589 return -1;
590 }
591 } else if (type->base == LY_TYPE_LEAFREF) {
592 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_LEAFREF)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200593 return -1;
594 }
595 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200596 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200597 return -1;
598 }
599 }
600 }
601
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200602 return 0;
603}
604
605static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200606lyb_parse_value(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, const char *data,
607 struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200608{
609 int r, ret = 0;
610 uint8_t start_byte;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200611
612 struct ly_ctx *ctx;
613 const char **value_str;
614 lyd_val *value;
615 LY_DATA_TYPE *value_type;
616 uint8_t *value_flags;
617
618 assert((leaf || attr) && (!leaf || !attr));
619
620 if (leaf) {
621 ctx = leaf->schema->module->ctx;
622 value_str = &leaf->value_str;
623 value = &leaf->value;
624 value_type = &leaf->value_type;
625 value_flags = &leaf->value_flags;
626 } else {
627 ctx = attr->annotation->module->ctx;
628 value_str = &attr->value_str;
629 value = &attr->value;
630 value_type = &attr->value_type;
631 value_flags = &attr->value_flags;
632 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200633
634 /* read value type and flags on the first byte */
635 ret += (r = lyb_read(data, &start_byte, sizeof start_byte, lybs));
636 LYB_HAVE_READ_RETURN(r, data, -1);
637
638 /* fill value type, flags */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200639 *value_type = start_byte & 0x1F;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200640 if (start_byte & 0x80) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200641 assert(leaf);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200642 leaf->dflt = 1;
643 }
644 if (start_byte & 0x40) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200645 *value_flags |= LY_VALUE_USER;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200646 }
647 if (start_byte & 0x20) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200648 *value_flags |= LY_VALUE_UNRES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200649 }
650
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200651 ret += (r = lyb_parse_val_1(ctx, type, *value_type, *value_flags, data, value_str, value, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200652 LYB_HAVE_READ_RETURN(r, data, -1);
653
Michal Vasko27e5e682018-07-23 14:22:57 +0200654 /* union is handled specially */
655 if (type->base == LY_TYPE_UNION) {
656 assert(*value_type == LY_TYPE_STRING);
657
658 *value_str = value->string;
659 value->string = NULL;
660 *value_type = LY_TYPE_UNION;
661 }
662
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200663 ret += (r = lyb_parse_val_2(type, leaf, attr, unres));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200664 LYB_HAVE_READ_RETURN(r, data, -1);
665
666 return ret;
667}
668
669static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200670lyb_parse_attr_name(const struct lys_module *mod, const char *data, struct lys_ext_instance_complex **ext, int options,
671 struct lyb_state *lybs)
672{
673 int r, ret = 0, pos, i, j, k;
674 const struct lys_submodule *submod = NULL;
675 char *attr_name = NULL;
676
677 /* attr name */
678 ret += (r = lyb_read_string(data, &attr_name, 1, lybs));
679 LYB_HAVE_READ_RETURN(r, data, -1);
680
681 /* search module */
682 pos = -1;
683 for (i = 0, j = 0; i < mod->ext_size; i = i + j + 1) {
684 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &mod->ext[i], mod->ext_size - i);
685 if (j == -1) {
686 break;
687 }
688 if (ly_strequal(mod->ext[i + j]->arg_value, attr_name, 0)) {
689 pos = i + j;
690 break;
691 }
692 }
693
694 /* try submodules */
695 if (pos == -1) {
696 for (k = 0; k < mod->inc_size; ++k) {
697 submod = mod->inc[k].submodule;
698 for (i = 0, j = 0; i < submod->ext_size; i = i + j + 1) {
699 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &submod->ext[i], submod->ext_size - i);
700 if (j == -1) {
701 break;
702 }
703 if (ly_strequal(submod->ext[i + j]->arg_value, attr_name, 0)) {
704 pos = i + j;
705 break;
706 }
707 }
708 }
709 }
710
711 if (pos == -1) {
712 *ext = NULL;
713 } else {
714 *ext = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] : (struct lys_ext_instance_complex *)mod->ext[pos];
715 }
716
717 if (!*ext && (options & LYD_OPT_STRICT)) {
718 LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find annotation \"%s\" in \"%s\".", attr_name, mod->name);
719 free(attr_name);
720 return -1;
721 }
722
723 free(attr_name);
724 return ret;
725}
726
727static int
728lyb_parse_attributes(struct lyd_node *node, const char *data, int options, struct unres_data *unres, struct lyb_state *lybs)
729{
730 int r, ret = 0;
731 uint8_t i, count = 0;
732 const struct lys_module *mod;
733 struct lys_type *type;
734 struct lyd_attr *attr = NULL;
735 struct lys_ext_instance_complex *ext;
736 struct ly_ctx *ctx = node->schema->module->ctx;
737
738 /* read number of attributes stored */
739 ret += (r = lyb_read(data, &count, 1, lybs));
740 LYB_HAVE_READ_GOTO(r, data, error);
741
742 /* read attributes */
743 for (i = 0; i < count; ++i) {
744 ret += (r = lyb_read_start_subtree(data, lybs));
745 LYB_HAVE_READ_GOTO(r, data, error);
746
747 /* find model */
748 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
749 LYB_HAVE_READ_GOTO(r, data, error);
750
Michal Vasko53830662018-07-24 16:09:49 +0200751 if (mod) {
752 /* annotation name */
753 ret += (r = lyb_parse_attr_name(mod, data, &ext, options, lybs));
754 LYB_HAVE_READ_GOTO(r, data, error);
755 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200756
Michal Vasko53830662018-07-24 16:09:49 +0200757 if (!mod || !ext) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200758 /* unknown attribute, skip it */
759 do {
760 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200761 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200762 } while (lybs->written[lybs->used - 1]);
763 goto stop_subtree;
764 }
765
766 /* allocate new attribute */
767 if (!attr) {
768 assert(!node->attr);
769
770 attr = calloc(1, sizeof *attr);
771 LY_CHECK_ERR_GOTO(!attr, LOGMEM(ctx), error);
772
773 node->attr = attr;
774 } else {
775 attr->next = calloc(1, sizeof *attr);
776 LY_CHECK_ERR_GOTO(!attr->next, LOGMEM(ctx), error);
777
778 attr = attr->next;
779 }
780
781 /* attribute annotation */
782 attr->annotation = ext;
783
784 /* attribute name */
785 attr->name = lydict_insert(ctx, attr->annotation->arg_value, 0);
786
787 /* get the type */
788 type = *(struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, attr->annotation, NULL);
789
790 /* attribute value */
791 ret += (r = lyb_parse_value(type, NULL, attr, data, unres, lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200792 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200793
794stop_subtree:
795 lyb_read_stop_subtree(lybs);
796 }
797
798 return ret;
799
800error:
801 lyd_free_attr(ctx, node, node->attr, 1);
802 return -1;
803}
804
805static int
Michal Vaskob7400232018-07-11 15:35:57 +0200806lyb_is_schema_hash_match(struct lys_node *sibling, LYB_HASH *hash, uint8_t hash_count)
Michal Vasko228431e2018-07-10 15:47:11 +0200807{
808 LYB_HASH sibling_hash;
Michal Vaskob7400232018-07-11 15:35:57 +0200809 uint8_t i;
Michal Vasko228431e2018-07-10 15:47:11 +0200810
Michal Vaskob7400232018-07-11 15:35:57 +0200811 /* compare all the hashes starting from collision ID 0 */
812 for (i = 0; i < hash_count; ++i) {
813 sibling_hash = lyb_hash(sibling, i);
814 if (sibling_hash != hash[i]) {
815 return 0;
816 }
817 }
Michal Vasko228431e2018-07-10 15:47:11 +0200818
Michal Vaskob7400232018-07-11 15:35:57 +0200819 return 1;
Michal Vasko228431e2018-07-10 15:47:11 +0200820}
821
822static int
823lyb_parse_schema_hash(const struct lys_node *sparent, const struct lys_module *mod, const char *data, const char *yang_data_name,
824 int options, struct lys_node **snode, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200825{
826 int r, ret = 0;
Michal Vaskob7400232018-07-11 15:35:57 +0200827 uint8_t i, j;
828 struct lys_node *sibling;
829 LYB_HASH hash[LYB_HASH_BITS - 1];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200830 struct ly_ctx *ctx;
831
832 assert((sparent || mod) && (!sparent || !mod));
833 ctx = (sparent ? sparent->module->ctx : mod->ctx);
834
Michal Vaskob7400232018-07-11 15:35:57 +0200835 /* read the first hash */
836 ret += (r = lyb_read(data, &hash[0], sizeof *hash, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200837 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskob7400232018-07-11 15:35:57 +0200838
839 /* based on the first hash read all the other ones, if any */
840 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i);
841
842 /* move the first hash on its accurate position */
843 hash[i] = hash[0];
844
845 /* read the rest of hashes */
846 for (j = i; j; --j) {
847 ret += (r = lyb_read(data, &hash[j - 1], sizeof *hash, lybs));
848 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200849
Michal Vasko365849c2018-08-07 11:31:30 +0200850 /* correct collision ID */
851 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
852 /* preceded with zeros */
853 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
Michal Vasko228431e2018-07-10 15:47:11 +0200854 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200855
Michal Vaskoe3880e62018-07-11 16:18:34 +0200856 /* handle yang data templates */
857 if ((options & LYD_OPT_DATA_TEMPLATE) && yang_data_name && mod) {
858 sparent = lyp_get_yang_data_template(mod, yang_data_name, strlen(yang_data_name));
859 if (!sparent) {
860 sibling = NULL;
861 goto finish;
862 }
863 }
864
865 /* handle RPC/action input/output */
Michal Vaskob7400232018-07-11 15:35:57 +0200866 if (sparent && (sparent->nodetype & (LYS_RPC | LYS_ACTION))) {
867 sibling = NULL;
868 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, NULL, LYS_GETNEXT_WITHINOUT))) {
869 if ((sibling->nodetype == LYS_INPUT) && (options & LYD_OPT_RPC)) {
870 break;
871 }
872 if ((sibling->nodetype == LYS_OUTPUT) && (options & LYD_OPT_RPCREPLY)) {
873 break;
874 }
875 }
876 if (!sibling) {
877 /* fail */
878 goto finish;
879 }
880
881 /* use only input/output children nodes */
882 sparent = sibling;
883 }
884
885 /* find our node with matching hashes */
886 sibling = NULL;
Michal Vasko228431e2018-07-10 15:47:11 +0200887 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, mod, 0))) {
888 /* skip schema nodes from models not present during printing */
Michal Vaskob7400232018-07-11 15:35:57 +0200889 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 +0200890 /* match found */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200891 break;
892 }
893 }
894
Michal Vaskob7400232018-07-11 15:35:57 +0200895finish:
Michal Vasko228431e2018-07-10 15:47:11 +0200896 *snode = sibling;
897 if (!sibling && (options & LYD_OPT_STRICT)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200898 if (mod) {
899 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find matching hash for a top-level node from \"%s\".", mod->name);
900 } else {
901 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, sparent, "Failed to find matching hash for a child of \"%s\".", sparent->name);
902 }
903 return -1;
904 }
905
906 return ret;
907}
908
909static int
910lyb_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 +0200911 const char *yang_data_name, int options, struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200912{
913 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200914 struct lyd_node *node = NULL, *iter;
915 const struct lys_module *mod;
Michal Vaskoe3880e62018-07-11 16:18:34 +0200916 struct lys_node *snode;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200917
918 assert((parent && !first_sibling) || (!parent && first_sibling));
919
920 /* register a new subtree */
921 ret += (r = lyb_read_start_subtree(data, lybs));
922 LYB_HAVE_READ_GOTO(r, data, error);
923
924 if (!parent) {
925 /* top-level, read module name */
926 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
927 LYB_HAVE_READ_GOTO(r, data, error);
928
Michal Vasko53830662018-07-24 16:09:49 +0200929 if (mod) {
930 /* read hash, find the schema node starting from mod, possibly yang_data_name */
931 r = lyb_parse_schema_hash(NULL, mod, data, yang_data_name, options, &snode, lybs);
932 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200933 } else {
Michal Vasko53830662018-07-24 16:09:49 +0200934 mod = lyd_node_module(parent);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200935
Michal Vaskoe3880e62018-07-11 16:18:34 +0200936 /* read hash, find the schema node starting from parent schema */
937 r = lyb_parse_schema_hash(parent->schema, NULL, data, NULL, options, &snode, lybs);
938 }
939 ret += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200940 LYB_HAVE_READ_GOTO(r, data, error);
941
Michal Vasko53830662018-07-24 16:09:49 +0200942 if (!mod || !snode) {
Michal Vasko997071e2018-07-10 15:56:14 +0200943 /* unknown data subtree, skip it whole */
944 do {
945 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vaskoa9852522018-08-08 16:24:45 +0200946 /* also skip the meta information inside */
947 ret += (r = lyb_read(data, NULL, lybs->inner_chunks[lybs->used - 1] * LYB_META_BYTES, lybs));
Michal Vasko997071e2018-07-10 15:56:14 +0200948 } while (lybs->written[lybs->used - 1]);
Michal Vasko228431e2018-07-10 15:47:11 +0200949 goto stop_subtree;
950 }
951
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200952 /*
953 * read the node
954 */
955 node = lyb_new_node(snode);
956 if (!node) {
957 goto error;
958 }
959
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200960 ret += (r = lyb_parse_attributes(node, data, options, unres, lybs));
961 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200962
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200963 /* read node content */
964 switch (snode->nodetype) {
965 case LYS_CONTAINER:
966 case LYS_LIST:
Michal Vaskob7400232018-07-11 15:35:57 +0200967 case LYS_NOTIF:
968 case LYS_RPC:
969 case LYS_ACTION:
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200970 /* nothing to read */
971 break;
972 case LYS_LEAF:
973 case LYS_LEAFLIST:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200974 ret += (r = lyb_parse_value(&((struct lys_node_leaf *)node->schema)->type, (struct lyd_node_leaf_list *)node,
975 NULL, data, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200976 LYB_HAVE_READ_GOTO(r, data, error);
977 break;
978 case LYS_ANYXML:
979 case LYS_ANYDATA:
980 ret += (r = lyb_parse_anydata(node, data, lybs));
981 LYB_HAVE_READ_GOTO(r, data, error);
982 break;
983 default:
984 goto error;
985 }
986
987 /* insert into data tree, manually */
988 if (parent) {
989 if (!parent->child) {
990 /* only child */
991 parent->child = node;
992 } else {
993 /* last child */
994 parent->child->prev->next = node;
995 node->prev = parent->child->prev;
996 parent->child->prev = node;
997 }
998 node->parent = parent;
999 } else if (*first_sibling) {
1000 /* last sibling */
1001 (*first_sibling)->prev->next = node;
1002 node->prev = (*first_sibling)->prev;
1003 (*first_sibling)->prev = node;
1004 } else {
1005 /* only sibling */
1006 *first_sibling = node;
1007 }
1008
1009 /* read all descendants */
1010 while (lybs->written[lybs->used - 1]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001011 ret += (r = lyb_parse_subtree(ctx, data, node, NULL, NULL, options, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001012 LYB_HAVE_READ_GOTO(r, data, error);
1013 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001014
1015 /* make containers default if should be */
1016 if (node->schema->nodetype == LYS_CONTAINER) {
1017 LY_TREE_FOR(node->child, iter) {
1018 if (!iter->dflt) {
1019 break;
1020 }
1021 }
1022
1023 if (!iter) {
1024 node->dflt = 1;
1025 }
1026 }
1027
Michal Vaskofe43d042018-07-24 09:43:46 +02001028#ifdef LY_ENABLED_CACHE
1029 /* calculate the hash and insert it into parent (list with keys is handled when its keys are inserted) */
1030 if ((node->schema->nodetype != LYS_LIST) || !((struct lys_node_list *)node->schema)->keys_size) {
1031 lyd_hash(node);
1032 lyd_insert_hash(node);
1033 }
1034#endif
1035
Michal Vasko228431e2018-07-10 15:47:11 +02001036stop_subtree:
1037 /* end the subtree */
1038 lyb_read_stop_subtree(lybs);
1039
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001040 return ret;
1041
1042error:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001043 lyd_free(node);
Michal Vaskob7400232018-07-11 15:35:57 +02001044 if (first_sibling && (*first_sibling == node)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001045 *first_sibling = NULL;
1046 }
1047 return -1;
1048}
1049
1050static int
Michal Vasko228431e2018-07-10 15:47:11 +02001051lyb_parse_data_models(struct ly_ctx *ctx, const char *data, struct lyb_state *lybs)
1052{
1053 int i, r, ret = 0;
1054
1055 /* read model count */
1056 ret += (r = lyb_read(data, (uint8_t *)&lybs->mod_count, 2, lybs));
1057 LYB_HAVE_READ_RETURN(r, data, -1);
1058
1059 lybs->models = malloc(lybs->mod_count * sizeof *lybs->models);
1060 LY_CHECK_ERR_RETURN(!lybs->models, LOGMEM(NULL), -1);
1061
1062 /* read modules */
1063 for (i = 0; i < lybs->mod_count; ++i) {
1064 ret += (r = lyb_parse_model(ctx, data, &lybs->models[i], lybs));
1065 LYB_HAVE_READ_RETURN(r, data, -1);
1066 }
1067
1068 return ret;
1069}
1070
1071static int
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001072lyb_parse_header(const char *data, struct lyb_state *lybs)
1073{
1074 int ret = 0;
1075 uint8_t byte = 0;
1076
Michal Vasko228431e2018-07-10 15:47:11 +02001077 /* TODO version, any flags? */
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001078 ret += lyb_read(data, (uint8_t *)&byte, sizeof byte, lybs);
1079
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001080 return ret;
1081}
1082
1083struct lyd_node *
Michal Vasko228431e2018-07-10 15:47:11 +02001084lyd_parse_lyb(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *data_tree,
1085 const char *yang_data_name, int *parsed)
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001086{
1087 int r, ret = 0;
Michal Vasko228431e2018-07-10 15:47:11 +02001088 struct lyd_node *node = NULL, *next, *act_notif = NULL;
1089 struct unres_data *unres = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001090 struct lyb_state lybs;
1091
1092 if (!ctx || !data) {
1093 LOGARG;
1094 return NULL;
1095 }
1096
1097 lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
1098 lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001099 lybs.inner_chunks = malloc(LYB_STATE_STEP * sizeof *lybs.inner_chunks);
1100 LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position || !lybs.inner_chunks, LOGMEM(ctx), finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001101 lybs.used = 0;
1102 lybs.size = LYB_STATE_STEP;
Michal Vasko228431e2018-07-10 15:47:11 +02001103 lybs.models = NULL;
1104 lybs.mod_count = 0;
1105
1106 unres = calloc(1, sizeof *unres);
1107 LY_CHECK_ERR_GOTO(!unres, LOGMEM(ctx), finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001108
1109 /* read header */
1110 ret += (r = lyb_parse_header(data, &lybs));
1111 LYB_HAVE_READ_GOTO(r, data, finish);
1112
Michal Vasko228431e2018-07-10 15:47:11 +02001113 /* read used models */
1114 ret += (r = lyb_parse_data_models(ctx, data, &lybs));
1115 LYB_HAVE_READ_GOTO(r, data, finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001116
1117 /* read subtree(s) */
1118 while (data[0]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001119 ret += (r = lyb_parse_subtree(ctx, data, NULL, &node, yang_data_name, options, unres, &lybs));
1120 if (r < 0) {
1121 lyd_free_withsiblings(node);
1122 node = NULL;
1123 goto finish;
1124 }
1125 data += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001126 }
1127
1128 /* read the last zero, parsing finished */
1129 ++ret;
1130 r = ret;
1131
Michal Vasko228431e2018-07-10 15:47:11 +02001132 if (options & LYD_OPT_DATA_ADD_YANGLIB) {
1133 if (lyd_merge(node, ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
1134 LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
1135 lyd_free_withsiblings(node);
1136 node = NULL;
1137 goto finish;
1138 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001139 }
Michal Vasko228431e2018-07-10 15:47:11 +02001140
1141 /* resolve any unresolved instance-identifiers */
1142 if (unres->count) {
1143 if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
1144 LY_TREE_DFS_BEGIN(node, next, act_notif) {
1145 if (act_notif->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1146 break;
1147 }
1148 LY_TREE_DFS_END(node, next, act_notif);
1149 }
1150 }
1151 if (lyd_defaults_add_unres(&node, options, ctx, data_tree, act_notif, unres, 0)) {
1152 lyd_free_withsiblings(node);
1153 node = NULL;
1154 goto finish;
1155 }
1156 }
1157
1158finish:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001159 free(lybs.written);
1160 free(lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001161 free(lybs.inner_chunks);
Michal Vasko228431e2018-07-10 15:47:11 +02001162 free(lybs.models);
1163 if (unres) {
1164 free(unres->node);
1165 free(unres->type);
1166 free(unres);
1167 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001168
1169 if (parsed) {
1170 *parsed = r;
1171 }
1172 return node;
1173}