blob: 22012697ab20210bbfae5d51d1126fde6a2623a1 [file] [log] [blame]
Michal Vasko60ea6352020-06-29 13:39:39 +02001/**
2 * @file parser_lyb.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief LYB data parser for libyang
5 *
Michal Vasko78041d12022-11-29 14:11:07 +01006 * Copyright (c) 2020 - 2022 CESNET, z.s.p.o.
Michal Vasko60ea6352020-06-29 13:39:39 +02007 *
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 "lyb.h"
16
17#include <assert.h>
Radek Krejciad97c5f2020-06-30 09:19:28 +020018#include <stdint.h>
Michal Vasko60ea6352020-06-29 13:39:39 +020019#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
23#include "common.h"
24#include "compat.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020025#include "context.h"
26#include "dict.h"
Radek Krejci47fab892020-11-05 17:02:41 +010027#include "hash_table.h"
28#include "in.h"
Michal Vaskoafac7822020-10-20 14:22:26 +020029#include "in_internal.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020030#include "log.h"
Radek Krejci7931b192020-06-25 17:05:03 +020031#include "parser_data.h"
32#include "parser_internal.h"
Michal Vasko9883a3e2022-03-31 12:16:00 +020033#include "plugins_exts.h"
Michal Vaskob4750962022-10-06 15:33:35 +020034#include "plugins_exts/metadata.h"
Radek Krejci77114102021-03-10 15:21:57 +010035#include "set.h"
Radek Krejciad97c5f2020-06-30 09:19:28 +020036#include "tree.h"
Radek Krejci47fab892020-11-05 17:02:41 +010037#include "tree_data.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020038#include "tree_data_internal.h"
Radek Krejci859a15a2021-03-05 20:56:59 +010039#include "tree_edit.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020040#include "tree_schema.h"
41#include "validation.h"
Michal Vasko6b5cb2a2020-11-11 19:11:21 +010042#include "xml.h"
Michal Vasko60ea6352020-06-29 13:39:39 +020043
Michal Vasko02ed9d82021-07-15 14:58:04 +020044static LY_ERR _lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
45 struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
46 struct ly_set *parsed, struct lyd_ctx **lydctx_p);
47
Michal Vasko78041d12022-11-29 14:11:07 +010048static LY_ERR lyb_parse_siblings(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node **first_p,
49 struct ly_set *parsed);
aPiecek821cf732021-09-09 15:37:28 +020050
Radek Krejci1798aae2020-07-14 13:26:06 +020051void
52lylyb_ctx_free(struct lylyb_ctx *ctx)
53{
54 LY_ARRAY_COUNT_TYPE u;
55
aPiecek570d7ed2021-09-10 07:15:35 +020056 LY_ARRAY_FREE(ctx->siblings);
Radek Krejci1798aae2020-07-14 13:26:06 +020057 LY_ARRAY_FREE(ctx->models);
58
59 LY_ARRAY_FOR(ctx->sib_hts, u) {
60 lyht_free(ctx->sib_hts[u].ht);
61 }
62 LY_ARRAY_FREE(ctx->sib_hts);
63
64 free(ctx);
65}
66
67void
68lyd_lyb_ctx_free(struct lyd_ctx *lydctx)
69{
70 struct lyd_lyb_ctx *ctx = (struct lyd_lyb_ctx *)lydctx;
71
72 lyd_ctx_free(lydctx);
73 lylyb_ctx_free(ctx->lybctx);
74 free(ctx);
75}
76
Michal Vasko60ea6352020-06-29 13:39:39 +020077/**
aPiecek6828a312021-09-17 15:53:18 +020078 * @brief Read metadata about siblings.
79 *
80 * @param[out] sib Structure in which the metadata will be stored.
81 * @param[in] lybctx LYB context.
82 */
83static void
84lyb_read_sibling_meta(struct lyd_lyb_sibling *sib, struct lylyb_ctx *lybctx)
85{
86 uint8_t meta_buf[LYB_META_BYTES];
87 uint64_t num = 0;
88
89 ly_in_read(lybctx->in, meta_buf, LYB_META_BYTES);
90
91 memcpy(&num, meta_buf, LYB_SIZE_BYTES);
92 sib->written = le64toh(num);
93 memcpy(&num, meta_buf + LYB_SIZE_BYTES, LYB_INCHUNK_BYTES);
94 sib->inner_chunks = le64toh(num);
95
96 /* remember whether there is a following chunk or not */
97 sib->position = (sib->written == LYB_SIZE_MAX ? 1 : 0);
98}
99
100/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200101 * @brief Read YANG data from LYB input. Metadata are handled transparently and not returned.
102 *
103 * @param[in] buf Destination buffer.
104 * @param[in] count Number of bytes to read.
105 * @param[in] lybctx LYB context.
106 */
107static void
Radek Krejci1798aae2020-07-14 13:26:06 +0200108lyb_read(uint8_t *buf, size_t count, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200109{
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200110 LY_ARRAY_COUNT_TYPE u;
aPiecek570d7ed2021-09-10 07:15:35 +0200111 struct lyd_lyb_sibling *empty;
Michal Vasko60ea6352020-06-29 13:39:39 +0200112 size_t to_read;
Michal Vasko60ea6352020-06-29 13:39:39 +0200113
114 assert(lybctx);
115
116 while (1) {
117 /* check for fully-read (empty) data chunks */
118 to_read = count;
119 empty = NULL;
aPiecek570d7ed2021-09-10 07:15:35 +0200120 LY_ARRAY_FOR(lybctx->siblings, u) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200121 /* we want the innermost chunks resolved first, so replace previous empty chunks,
122 * also ignore chunks that are completely finished, there is nothing for us to do */
aPiecek570d7ed2021-09-10 07:15:35 +0200123 if ((lybctx->siblings[u].written <= to_read) && lybctx->siblings[u].position) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200124 /* empty chunk, do not read more */
aPiecek570d7ed2021-09-10 07:15:35 +0200125 to_read = lybctx->siblings[u].written;
126 empty = &lybctx->siblings[u];
Michal Vasko60ea6352020-06-29 13:39:39 +0200127 }
128 }
129
130 if (!empty && !count) {
131 break;
132 }
133
134 /* we are actually reading some data, not just finishing another chunk */
135 if (to_read) {
136 if (buf) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200137 ly_in_read(lybctx->in, buf, to_read);
138 } else {
139 ly_in_skip(lybctx->in, to_read);
Michal Vasko60ea6352020-06-29 13:39:39 +0200140 }
141
aPiecek570d7ed2021-09-10 07:15:35 +0200142 LY_ARRAY_FOR(lybctx->siblings, u) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200143 /* decrease all written counters */
aPiecek570d7ed2021-09-10 07:15:35 +0200144 lybctx->siblings[u].written -= to_read;
145 assert(lybctx->siblings[u].written <= LYB_SIZE_MAX);
Michal Vasko60ea6352020-06-29 13:39:39 +0200146 }
147 /* decrease count/buf */
148 count -= to_read;
149 if (buf) {
150 buf += to_read;
151 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200152 }
153
154 if (empty) {
155 /* read the next chunk meta information */
aPiecek6828a312021-09-17 15:53:18 +0200156 lyb_read_sibling_meta(empty, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200157 }
158 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200159}
160
161/**
162 * @brief Read a number.
163 *
164 * @param[in] num Destination buffer.
165 * @param[in] num_size Size of @p num.
166 * @param[in] bytes Number of bytes to read.
167 * @param[in] lybctx LYB context.
168 */
169static void
Radek Krejci1798aae2020-07-14 13:26:06 +0200170lyb_read_number(void *num, size_t num_size, size_t bytes, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200171{
172 uint64_t buf = 0;
173
174 lyb_read((uint8_t *)&buf, bytes, lybctx);
175
176 /* correct byte order */
177 buf = le64toh(buf);
178
179 switch (num_size) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100180 case sizeof(uint8_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200181 *((uint8_t *)num) = buf;
182 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100183 case sizeof(uint16_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200184 *((uint16_t *)num) = buf;
185 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100186 case sizeof(uint32_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200187 *((uint32_t *)num) = buf;
188 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100189 case sizeof(uint64_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200190 *((uint64_t *)num) = buf;
191 break;
192 default:
193 LOGINT(lybctx->ctx);
194 }
195}
196
197/**
198 * @brief Read a string.
199 *
200 * @param[in] str Destination buffer, is allocated.
aPieceke99345d2021-09-30 12:49:59 +0200201 * @param[in] len_size Number of bytes on which the length of the string is written.
Michal Vasko60ea6352020-06-29 13:39:39 +0200202 * @param[in] lybctx LYB context.
203 * @return LY_ERR value.
204 */
205static LY_ERR
aPieceke99345d2021-09-30 12:49:59 +0200206lyb_read_string(char **str, uint8_t len_size, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200207{
aPieceke99345d2021-09-30 12:49:59 +0200208 uint64_t len = 0;
209
210 assert((len_size == 1) || (len_size == 2) || (len_size == 4) || (len_size == 8));
Michal Vasko60ea6352020-06-29 13:39:39 +0200211
212 *str = NULL;
213
aPieceke99345d2021-09-30 12:49:59 +0200214 lyb_read_number(&len, sizeof len, len_size, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200215
216 *str = malloc((len + 1) * sizeof **str);
217 LY_CHECK_ERR_RET(!*str, LOGMEM(lybctx->ctx), LY_EMEM);
218
219 lyb_read((uint8_t *)*str, len, lybctx);
220
Michal Vaskocebbae52021-05-31 11:11:36 +0200221 (*str)[len] = '\0';
Michal Vasko60ea6352020-06-29 13:39:39 +0200222 return LY_SUCCESS;
223}
224
225/**
aPiecekd5796f92021-09-30 13:39:37 +0200226 * @brief Skip string.
227 *
228 * @param[in] len_size Number of bytes on which the length of the string is written.
229 * @param[in] lybctx LYB context.
230 */
231static void
232lyb_skip_string(uint8_t len_size, struct lylyb_ctx *lybctx)
233{
234 size_t len = 0;
235
236 lyb_read_number(&len, sizeof len, len_size, lybctx);
237
238 lyb_read(NULL, len, lybctx);
239}
240
241/**
aPiecek91eec232021-09-09 15:42:37 +0200242 * @brief Read value of term node.
aPiecekea304e32021-08-18 09:13:47 +0200243 *
aPiecekaa5b70a2021-08-30 08:33:25 +0200244 * @param[in] term Compiled term node.
aPiecekea304e32021-08-18 09:13:47 +0200245 * @param[out] term_value Set to term node value in dynamically
246 * allocated memory. The caller must release it.
247 * @param[out] term_value_len Value length in bytes. The zero byte is
248 * always included and is not counted.
249 * @param[in,out] lybctx LYB context.
250 * @return LY_ERR value.
251 */
252static LY_ERR
aPieceke99345d2021-09-30 12:49:59 +0200253lyb_read_term_value(const struct lysc_node_leaf *term, uint8_t **term_value, uint64_t *term_value_len,
aPiecek91eec232021-09-09 15:42:37 +0200254 struct lylyb_ctx *lybctx)
aPiecekea304e32021-08-18 09:13:47 +0200255{
256 uint32_t allocated_size;
aPiecekaa5b70a2021-08-30 08:33:25 +0200257 int32_t lyb_data_len;
258 struct lysc_type_leafref *type_lf;
aPiecekea304e32021-08-18 09:13:47 +0200259
aPiecekaa5b70a2021-08-30 08:33:25 +0200260 assert(term && term_value && term_value_len && lybctx);
aPiecekea304e32021-08-18 09:13:47 +0200261
aPiecekaa5b70a2021-08-30 08:33:25 +0200262 /* Find out the size from @ref howtoDataLYB. */
263 if (term->type->basetype == LY_TYPE_LEAFREF) {
264 /* Leafref itself is ignored, the target is loaded directly. */
265 type_lf = (struct lysc_type_leafref *)term->type;
266 lyb_data_len = type_lf->realtype->plugin->lyb_data_len;
267 } else {
268 lyb_data_len = term->type->plugin->lyb_data_len;
269 }
270
271 if (lyb_data_len < 0) {
272 /* Parse value size. */
273 lyb_read_number(term_value_len, sizeof *term_value_len,
274 sizeof *term_value_len, lybctx);
275 } else {
276 /* Data size is fixed. */
277 *term_value_len = lyb_data_len;
278 }
aPiecekea304e32021-08-18 09:13:47 +0200279
280 /* Allocate memory. */
281 allocated_size = *term_value_len + 1;
282 *term_value = malloc(allocated_size * sizeof **term_value);
283 LY_CHECK_ERR_RET(!*term_value, LOGMEM(lybctx->ctx), LY_EMEM);
284
285 if (*term_value_len > 0) {
286 /* Parse value. */
287 lyb_read(*term_value, *term_value_len, lybctx);
288 }
289
290 /* Add extra zero byte regardless of whether it is string or not. */
291 (*term_value)[allocated_size - 1] = 0;
292
293 return LY_SUCCESS;
294}
295
296/**
aPiecek570d7ed2021-09-10 07:15:35 +0200297 * @brief Stop the current "siblings" - change LYB context state.
Michal Vasko60ea6352020-06-29 13:39:39 +0200298 *
299 * @param[in] lybctx LYB context.
300 * @return LY_ERR value.
301 */
302static LY_ERR
aPiecek570d7ed2021-09-10 07:15:35 +0200303lyb_read_stop_siblings(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200304{
aPiecek570d7ed2021-09-10 07:15:35 +0200305 if (LYB_LAST_SIBLING(lybctx).written) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200306 LOGINT_RET(lybctx->ctx);
307 }
308
aPiecek570d7ed2021-09-10 07:15:35 +0200309 LY_ARRAY_DECREMENT(lybctx->siblings);
Michal Vasko60ea6352020-06-29 13:39:39 +0200310 return LY_SUCCESS;
311}
312
313/**
aPiecek570d7ed2021-09-10 07:15:35 +0200314 * @brief Start a new "siblings" - change LYB context state but also read the expected metadata.
Michal Vasko60ea6352020-06-29 13:39:39 +0200315 *
316 * @param[in] lybctx LYB context.
317 * @return LY_ERR value.
318 */
319static LY_ERR
aPiecek570d7ed2021-09-10 07:15:35 +0200320lyb_read_start_siblings(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200321{
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200322 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200323
aPiecek570d7ed2021-09-10 07:15:35 +0200324 u = LY_ARRAY_COUNT(lybctx->siblings);
325 if (u == lybctx->sibling_size) {
326 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->siblings, u + LYB_SIBLING_STEP, LY_EMEM);
327 lybctx->sibling_size = u + LYB_SIBLING_STEP;
Michal Vasko60ea6352020-06-29 13:39:39 +0200328 }
329
aPiecek570d7ed2021-09-10 07:15:35 +0200330 LY_ARRAY_INCREMENT(lybctx->siblings);
aPiecek6828a312021-09-17 15:53:18 +0200331 lyb_read_sibling_meta(&LYB_LAST_SIBLING(lybctx), lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200332
Michal Vasko60ea6352020-06-29 13:39:39 +0200333 return LY_SUCCESS;
334}
335
336/**
Michal Vasko9883a3e2022-03-31 12:16:00 +0200337 * @brief Read YANG model info.
Michal Vasko60ea6352020-06-29 13:39:39 +0200338 *
339 * @param[in] lybctx LYB context.
Michal Vasko9883a3e2022-03-31 12:16:00 +0200340 * @param[out] mod_name Module name, if any.
341 * @param[out] mod_rev Module revision, "" if none.
Michal Vasko78041d12022-11-29 14:11:07 +0100342 * @param[in,out] feat_set Set to add the names of enabled features to. If not set, enabled features are not parsed.
Michal Vasko60ea6352020-06-29 13:39:39 +0200343 * @return LY_ERR value.
344 */
345static LY_ERR
Michal Vasko78041d12022-11-29 14:11:07 +0100346lyb_read_model(struct lylyb_ctx *lybctx, char **mod_name, char mod_rev[], struct ly_set *feat_set)
Michal Vasko60ea6352020-06-29 13:39:39 +0200347{
Michal Vasko78041d12022-11-29 14:11:07 +0100348 uint16_t i, rev, length;
349 char *str;
Michal Vasko60ea6352020-06-29 13:39:39 +0200350
Michal Vasko9883a3e2022-03-31 12:16:00 +0200351 *mod_name = NULL;
352 mod_rev[0] = '\0';
aPiecek339bdc32021-09-10 08:42:36 +0200353
Michal Vasko9883a3e2022-03-31 12:16:00 +0200354 lyb_read_number(&length, 2, 2, lybctx);
355 if (!length) {
356 return LY_SUCCESS;
aPiecek570d7ed2021-09-10 07:15:35 +0200357 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200358
Michal Vasko9883a3e2022-03-31 12:16:00 +0200359 /* module name */
Michal Vasko0d156b92022-04-01 12:27:04 +0200360 *mod_name = malloc(length + 1);
Michal Vasko9883a3e2022-03-31 12:16:00 +0200361 LY_CHECK_ERR_RET(!*mod_name, LOGMEM(lybctx->ctx), LY_EMEM);
362 lyb_read(((uint8_t *)*mod_name), length, lybctx);
363 (*mod_name)[length] = '\0';
364
365 /* module revision */
Michal Vasko60ea6352020-06-29 13:39:39 +0200366 lyb_read_number(&rev, sizeof rev, 2, lybctx);
367
Michal Vasko60ea6352020-06-29 13:39:39 +0200368 if (rev) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100369 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & LYB_REV_YEAR_MASK) >> LYB_REV_YEAR_SHIFT) + LYB_REV_YEAR_OFFSET,
370 (rev & LYB_REV_MONTH_MASK) >> LYB_REV_MONTH_SHIFT, rev & LYB_REV_DAY_MASK);
Michal Vasko9883a3e2022-03-31 12:16:00 +0200371 }
372
Michal Vasko78041d12022-11-29 14:11:07 +0100373 if (!feat_set) {
374 /* enabled features not printed */
375 return LY_SUCCESS;
376 }
377
378 /* enabled feature count */
379 lyb_read_number(&length, sizeof length, sizeof length, lybctx);
380 if (!length) {
381 return LY_SUCCESS;
382 }
383
384 /* enabled features */
385 for (i = 0; i < length; ++i) {
386 lyb_read_string(&str, sizeof length, lybctx);
387 ly_set_add(feat_set, str, 1, NULL);
388 }
389
Michal Vasko9883a3e2022-03-31 12:16:00 +0200390 return LY_SUCCESS;
391}
392
393/**
394 * @brief Parse YANG model info.
395 *
396 * @param[in] lybctx LYB context.
397 * @param[in] parse_options Flag with options for parsing.
Michal Vasko78041d12022-11-29 14:11:07 +0100398 * @param[in] with_features Whether the enabled features were also printed and should be read.
Michal Vasko9883a3e2022-03-31 12:16:00 +0200399 * @param[out] mod Parsed module.
400 * @return LY_ERR value.
401 */
402static LY_ERR
Michal Vasko78041d12022-11-29 14:11:07 +0100403lyb_parse_model(struct lylyb_ctx *lybctx, uint32_t parse_options, ly_bool with_features, const struct lys_module **mod)
Michal Vasko9883a3e2022-03-31 12:16:00 +0200404{
405 LY_ERR ret = LY_SUCCESS;
406 const struct lys_module *m = NULL;
407 char *mod_name = NULL, mod_rev[LY_REV_SIZE];
Michal Vasko78041d12022-11-29 14:11:07 +0100408 struct ly_set feat_set = {0};
409 struct lysp_feature *f = NULL;
410 uint32_t i, idx = 0;
411 ly_bool enabled;
Michal Vasko9883a3e2022-03-31 12:16:00 +0200412
413 /* read module info */
Michal Vasko78041d12022-11-29 14:11:07 +0100414 if ((ret = lyb_read_model(lybctx, &mod_name, mod_rev, with_features ? &feat_set : NULL))) {
Michal Vasko9883a3e2022-03-31 12:16:00 +0200415 goto cleanup;
416 }
417
418 /* get the module */
419 if (mod_rev[0]) {
420 m = ly_ctx_get_module(lybctx->ctx, mod_name, mod_rev);
421 if ((parse_options & LYD_PARSE_LYB_MOD_UPDATE) && !m) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200422 /* try to use an updated module */
Michal Vasko9883a3e2022-03-31 12:16:00 +0200423 m = ly_ctx_get_module_implemented(lybctx->ctx, mod_name);
424 if (m && (!m->revision || (strcmp(m->revision, mod_rev) < 0))) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200425 /* not an implemented module in a newer revision */
Michal Vasko9883a3e2022-03-31 12:16:00 +0200426 m = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200427 }
428 }
429 } else {
Michal Vasko9883a3e2022-03-31 12:16:00 +0200430 m = ly_ctx_get_module_latest(lybctx->ctx, mod_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200431 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200432
Michal Vasko9883a3e2022-03-31 12:16:00 +0200433 if (!m || !m->implemented) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200434 if (parse_options & LYD_PARSE_STRICT) {
Michal Vasko9883a3e2022-03-31 12:16:00 +0200435 if (!m) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200436 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
Michal Vasko9883a3e2022-03-31 12:16:00 +0200437 mod_name, mod_rev[0] ? "@" : "", mod_rev[0] ? mod_rev : "");
438 } else if (!m->implemented) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200439 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",
Michal Vasko9883a3e2022-03-31 12:16:00 +0200440 mod_name, mod_rev[0] ? "@" : "", mod_rev[0] ? mod_rev : "");
Michal Vasko60ea6352020-06-29 13:39:39 +0200441 }
442 ret = LY_EINVAL;
443 goto cleanup;
444 }
445
Michal Vasko78041d12022-11-29 14:11:07 +0100446 goto cleanup;
Michal Vasko60ea6352020-06-29 13:39:39 +0200447 }
448
Michal Vasko78041d12022-11-29 14:11:07 +0100449 if (with_features) {
450 /* check features */
451 while ((f = lysp_feature_next(f, m->parsed, &idx))) {
452 enabled = 0;
453 for (i = 0; i < feat_set.count; ++i) {
454 if (!strcmp(feat_set.objs[i], f->name)) {
455 enabled = 1;
456 break;
457 }
458 }
459
460 if (enabled && !(f->flags & LYS_FENABLED)) {
461 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s\" has \"%s\" feature disabled.",
462 mod_name, f->name);
463 ret = LY_EINVAL;
464 goto cleanup;
465 } else if (!enabled && (f->flags & LYS_FENABLED)) {
466 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s\" has \"%s\" feature enabled.",
467 mod_name, f->name);
468 ret = LY_EINVAL;
469 goto cleanup;
470 }
471 }
Michal Vasko85d9edc2021-04-22 09:15:05 +0200472 }
Michal Vasko11f76c82021-04-15 14:36:14 +0200473
Michal Vasko78041d12022-11-29 14:11:07 +0100474 /* fill cached hashes, if not already */
475 lyb_cache_module_hash(m);
476
Michal Vasko60ea6352020-06-29 13:39:39 +0200477cleanup:
Michal Vasko9883a3e2022-03-31 12:16:00 +0200478 *mod = m;
Michal Vasko60ea6352020-06-29 13:39:39 +0200479 free(mod_name);
Michal Vasko78041d12022-11-29 14:11:07 +0100480 ly_set_erase(&feat_set, free);
Michal Vasko60ea6352020-06-29 13:39:39 +0200481 return ret;
482}
483
484/**
485 * @brief Parse YANG node metadata.
486 *
487 * @param[in] lybctx LYB context.
Michal Vaskoddd76592022-01-17 13:34:48 +0100488 * @param[in] sparent Schema parent node of the metadata.
Michal Vasko60ea6352020-06-29 13:39:39 +0200489 * @param[out] meta Parsed metadata.
490 * @return LY_ERR value.
491 */
492static LY_ERR
Michal Vaskoddd76592022-01-17 13:34:48 +0100493lyb_parse_metadata(struct lyd_lyb_ctx *lybctx, const struct lysc_node *sparent, struct lyd_meta **meta)
Michal Vasko60ea6352020-06-29 13:39:39 +0200494{
495 LY_ERR ret = LY_SUCCESS;
Radek Krejci857189e2020-09-01 13:26:36 +0200496 ly_bool dynamic;
Michal Vasko60ea6352020-06-29 13:39:39 +0200497 uint8_t i, count = 0;
Michal Vasko1e5d5612020-07-03 13:29:26 +0200498 char *meta_name = NULL, *meta_value;
Michal Vasko60ea6352020-06-29 13:39:39 +0200499 const struct lys_module *mod;
500
501 /* read number of attributes stored */
Radek Krejci1798aae2020-07-14 13:26:06 +0200502 lyb_read(&count, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200503
504 /* read attributes */
505 for (i = 0; i < count; ++i) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200506 /* find model */
Michal Vasko78041d12022-11-29 14:11:07 +0100507 ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, 0, &mod);
Michal Vasko60ea6352020-06-29 13:39:39 +0200508 LY_CHECK_GOTO(ret, cleanup);
509
510 if (!mod) {
aPiecekd5796f92021-09-30 13:39:37 +0200511 /* skip meta name */
512 lyb_skip_string(sizeof(uint16_t), lybctx->lybctx);
513
514 /* skip meta value */
515 lyb_skip_string(sizeof(uint16_t), lybctx->lybctx);
516 continue;
Michal Vasko60ea6352020-06-29 13:39:39 +0200517 }
518
519 /* meta name */
aPieceke99345d2021-09-30 12:49:59 +0200520 ret = lyb_read_string(&meta_name, sizeof(uint16_t), lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200521 LY_CHECK_GOTO(ret, cleanup);
522
523 /* meta value */
aPieceke99345d2021-09-30 12:49:59 +0200524 ret = lyb_read_string(&meta_value, sizeof(uint64_t), lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200525 LY_CHECK_GOTO(ret, cleanup);
526 dynamic = 1;
527
528 /* create metadata */
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200529 ret = lyd_parser_create_meta((struct lyd_ctx *)lybctx, NULL, meta, mod, meta_name, strlen(meta_name), meta_value,
Michal Vaskoddd76592022-01-17 13:34:48 +0100530 ly_strlen(meta_value), &dynamic, LY_VALUE_JSON, NULL, LYD_HINT_DATA, sparent);
Michal Vasko60ea6352020-06-29 13:39:39 +0200531
532 /* free strings */
533 free(meta_name);
534 meta_name = NULL;
535 if (dynamic) {
536 free(meta_value);
537 dynamic = 0;
538 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200539
Radek Krejci1798aae2020-07-14 13:26:06 +0200540 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200541 }
542
543cleanup:
544 free(meta_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200545 if (ret) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200546 lyd_free_meta_siblings(*meta);
Michal Vasko60ea6352020-06-29 13:39:39 +0200547 *meta = NULL;
548 }
549 return ret;
550}
551
552/**
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100553 * @brief Parse format-specific prefix data.
Michal Vasko60ea6352020-06-29 13:39:39 +0200554 *
555 * @param[in] lybctx LYB context.
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100556 * @param[in] format Prefix data format.
557 * @param[out] prefix_data Parsed prefix data.
Michal Vasko60ea6352020-06-29 13:39:39 +0200558 * @return LY_ERR value.
559 */
560static LY_ERR
Radek Krejci8df109d2021-04-23 12:19:08 +0200561lyb_parse_prefix_data(struct lylyb_ctx *lybctx, LY_VALUE_FORMAT format, void **prefix_data)
Michal Vasko60ea6352020-06-29 13:39:39 +0200562{
563 LY_ERR ret = LY_SUCCESS;
564 uint8_t count, i;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100565 struct ly_set *set = NULL;
566 struct lyxml_ns *ns = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200567
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100568 switch (format) {
Radek Krejci8df109d2021-04-23 12:19:08 +0200569 case LY_VALUE_XML:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100570 /* read count */
571 lyb_read(&count, 1, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200572
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100573 /* read all NS elements */
574 LY_CHECK_GOTO(ret = ly_set_new(&set), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200575
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100576 for (i = 0; i < count; ++i) {
577 ns = calloc(1, sizeof *ns);
Michal Vasko60ea6352020-06-29 13:39:39 +0200578
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100579 /* prefix */
aPieceke99345d2021-09-30 12:49:59 +0200580 LY_CHECK_GOTO(ret = lyb_read_string(&ns->prefix, sizeof(uint16_t), lybctx), cleanup);
Michal Vaskoa3494b42022-02-28 13:58:34 +0100581 if (!strlen(ns->prefix)) {
582 free(ns->prefix);
583 ns->prefix = NULL;
584 }
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100585
586 /* namespace */
aPieceke99345d2021-09-30 12:49:59 +0200587 LY_CHECK_GOTO(ret = lyb_read_string(&ns->uri, sizeof(uint16_t), lybctx), cleanup);
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100588
589 LY_CHECK_GOTO(ret = ly_set_add(set, ns, 1, NULL), cleanup);
590 ns = NULL;
591 }
592
593 *prefix_data = set;
594 break;
Radek Krejci8df109d2021-04-23 12:19:08 +0200595 case LY_VALUE_JSON:
Radek Krejcif9943642021-04-26 10:18:21 +0200596 case LY_VALUE_LYB:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100597 /* nothing stored */
598 break;
599 default:
600 LOGINT(lybctx->ctx);
601 ret = LY_EINT;
602 break;
Michal Vasko60ea6352020-06-29 13:39:39 +0200603 }
604
605cleanup:
606 if (ret) {
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100607 ly_free_prefix_data(format, set);
608 if (ns) {
609 free(ns->prefix);
610 free(ns->uri);
611 free(ns);
612 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200613 }
614 return ret;
615}
616
617/**
618 * @brief Parse opaque attributes.
619 *
620 * @param[in] lybctx LYB context.
621 * @param[out] attr Parsed attributes.
622 * @return LY_ERR value.
623 */
624static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200625lyb_parse_attributes(struct lylyb_ctx *lybctx, struct lyd_attr **attr)
Michal Vasko60ea6352020-06-29 13:39:39 +0200626{
627 LY_ERR ret = LY_SUCCESS;
628 uint8_t count, i;
Michal Vasko486e4f92021-07-01 13:12:32 +0200629 struct lyd_attr *attr2 = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200630 char *prefix = NULL, *module_name = NULL, *name = NULL, *value = NULL;
Radek Krejci857189e2020-09-01 13:26:36 +0200631 ly_bool dynamic = 0;
Radek Krejci8df109d2021-04-23 12:19:08 +0200632 LY_VALUE_FORMAT format = 0;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100633 void *val_prefix_data = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200634
635 /* read count */
636 lyb_read(&count, 1, lybctx);
637
638 /* read attributes */
639 for (i = 0; i < count; ++i) {
Michal Vasko0fdcd242020-11-11 19:12:30 +0100640 /* prefix, may be empty */
aPieceke99345d2021-09-30 12:49:59 +0200641 ret = lyb_read_string(&prefix, sizeof(uint16_t), lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200642 LY_CHECK_GOTO(ret, cleanup);
643 if (!prefix[0]) {
644 free(prefix);
645 prefix = NULL;
646 }
647
648 /* namespace, may be empty */
aPieceke99345d2021-09-30 12:49:59 +0200649 ret = lyb_read_string(&module_name, sizeof(uint16_t), lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200650 LY_CHECK_GOTO(ret, cleanup);
Radek Krejci1798aae2020-07-14 13:26:06 +0200651 if (!module_name[0]) {
652 free(module_name);
653 module_name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200654 }
655
656 /* name */
aPieceke99345d2021-09-30 12:49:59 +0200657 ret = lyb_read_string(&name, sizeof(uint16_t), lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200658 LY_CHECK_GOTO(ret, cleanup);
659
Michal Vasko60ea6352020-06-29 13:39:39 +0200660 /* format */
Michal Vasko403beac2021-08-24 08:27:52 +0200661 lyb_read_number(&format, sizeof format, 1, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200662
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100663 /* value prefixes */
664 ret = lyb_parse_prefix_data(lybctx, format, &val_prefix_data);
665 LY_CHECK_GOTO(ret, cleanup);
666
Michal Vasko60ea6352020-06-29 13:39:39 +0200667 /* value */
aPieceke99345d2021-09-30 12:49:59 +0200668 ret = lyb_read_string(&value, sizeof(uint64_t), lybctx);
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100669 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200670 dynamic = 1;
671
672 /* attr2 is always changed to the created attribute */
Michal Vasko501af032020-11-11 20:27:44 +0100673 ret = lyd_create_attr(NULL, &attr2, lybctx->ctx, name, strlen(name), prefix, ly_strlen(prefix), module_name,
Michal Vaskobb512792021-07-01 13:12:49 +0200674 ly_strlen(module_name), value, ly_strlen(value), &dynamic, format, val_prefix_data, LYD_HINT_DATA);
Michal Vasko60ea6352020-06-29 13:39:39 +0200675 LY_CHECK_GOTO(ret, cleanup);
676
677 free(prefix);
678 prefix = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200679 free(module_name);
680 module_name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200681 free(name);
682 name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200683 assert(!dynamic);
684 value = NULL;
685
686 if (!*attr) {
687 *attr = attr2;
688 }
689
Michal Vasko60ea6352020-06-29 13:39:39 +0200690 LY_CHECK_GOTO(ret, cleanup);
691 }
692
693cleanup:
694 free(prefix);
Radek Krejci1798aae2020-07-14 13:26:06 +0200695 free(module_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200696 free(name);
697 if (dynamic) {
698 free(value);
699 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200700 if (ret) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200701 lyd_free_attr_siblings(lybctx->ctx, *attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200702 *attr = NULL;
703 }
704 return ret;
705}
706
707/**
aPiecek619350d2021-09-09 16:06:59 +0200708 * @brief Fill @p hash with hash values.
709 *
710 * @param[in] lybctx LYB context.
711 * @param[in,out] hash Pointer to the array in which the hash values are to be written.
712 * @param[out] hash_count Number of hashes in @p hash.
713 * @return LY_ERR value.
714 */
715static LY_ERR
716lyb_read_hashes(struct lylyb_ctx *lybctx, LYB_HASH *hash, uint8_t *hash_count)
717{
718 uint8_t i = 0, j;
719
720 /* read the first hash */
721 lyb_read(&hash[0], sizeof *hash, lybctx);
722
723 if (!hash[0]) {
724 *hash_count = i + 1;
725 return LY_SUCCESS;
726 }
727
728 /* based on the first hash read all the other ones, if any */
729 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
730 if (i > LYB_HASH_BITS) {
731 LOGINT_RET(lybctx->ctx);
732 }
733 }
734
735 /* move the first hash on its accurate position */
736 hash[i] = hash[0];
737
738 /* read the rest of hashes */
739 for (j = i; j; --j) {
740 lyb_read(&hash[j - 1], sizeof *hash, lybctx);
741
742 /* correct collision ID */
743 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
744 /* preceded with zeros */
745 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
746 }
747
748 *hash_count = i + 1;
749
750 return LY_SUCCESS;
751}
752
753/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200754 * @brief Check whether a schema node matches a hash(es).
755 *
756 * @param[in] sibling Schema node to check.
757 * @param[in] hash Hash array to check.
758 * @param[in] hash_count Number of hashes in @p hash.
759 * @return non-zero if matches,
760 * @return 0 if not.
761 */
762static int
763lyb_is_schema_hash_match(struct lysc_node *sibling, LYB_HASH *hash, uint8_t hash_count)
764{
765 LYB_HASH sibling_hash;
766 uint8_t i;
767
768 /* compare all the hashes starting from collision ID 0 */
769 for (i = 0; i < hash_count; ++i) {
Michal Vasko11f76c82021-04-15 14:36:14 +0200770 sibling_hash = lyb_get_hash(sibling, i);
Michal Vasko60ea6352020-06-29 13:39:39 +0200771 if (sibling_hash != hash[i]) {
772 return 0;
773 }
774 }
775
776 return 1;
777}
778
779/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200780 * @brief Parse schema node hash.
781 *
782 * @param[in] lybctx LYB context.
783 * @param[in] sparent Schema parent, must be set if @p mod is not.
784 * @param[in] mod Module of the top-level node, must be set if @p sparent is not.
785 * @param[out] snode Parsed found schema node, may be NULL if opaque.
786 * @return LY_ERR value.
787 */
788static LY_ERR
789lyb_parse_schema_hash(struct lyd_lyb_ctx *lybctx, const struct lysc_node *sparent, const struct lys_module *mod,
Radek Krejci0f969882020-08-21 16:56:47 +0200790 const struct lysc_node **snode)
Michal Vasko60ea6352020-06-29 13:39:39 +0200791{
792 LY_ERR ret;
Michal Vasko60ea6352020-06-29 13:39:39 +0200793 const struct lysc_node *sibling;
794 LYB_HASH hash[LYB_HASH_BITS - 1];
Radek Krejci1deb5be2020-08-26 16:43:36 +0200795 uint32_t getnext_opts;
aPiecek619350d2021-09-09 16:06:59 +0200796 uint8_t hash_count;
Michal Vasko60ea6352020-06-29 13:39:39 +0200797
aPiecek570d7ed2021-09-10 07:15:35 +0200798 *snode = NULL;
799
aPiecek619350d2021-09-09 16:06:59 +0200800 ret = lyb_read_hashes(lybctx->lybctx, hash, &hash_count);
801 LY_CHECK_RET(ret);
Michal Vasko60ea6352020-06-29 13:39:39 +0200802
803 if (!hash[0]) {
804 /* opaque node */
805 return LY_SUCCESS;
806 }
807
aPiecek619350d2021-09-09 16:06:59 +0200808 getnext_opts = lybctx->int_opts & LYD_INTOPT_REPLY ? LYS_GETNEXT_OUTPUT : 0;
Michal Vasko60ea6352020-06-29 13:39:39 +0200809
810 /* find our node with matching hashes */
811 sibling = NULL;
Radek Krejcif16e2542021-02-17 15:39:23 +0100812 while (1) {
813 if (!sparent && lybctx->ext) {
814 sibling = lys_getnext_ext(sibling, sparent, lybctx->ext, getnext_opts);
815 } else {
816 sibling = lys_getnext(sibling, sparent, mod ? mod->compiled : NULL, getnext_opts);
817 }
818 if (!sibling) {
819 break;
820 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200821 /* skip schema nodes from models not present during printing */
Michal Vasko9883a3e2022-03-31 12:16:00 +0200822 if (((sibling->module->ctx != lybctx->lybctx->ctx) || lyb_has_schema_model(sibling, lybctx->lybctx->models)) &&
aPiecek619350d2021-09-09 16:06:59 +0200823 lyb_is_schema_hash_match((struct lysc_node *)sibling, hash, hash_count)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200824 /* match found */
825 break;
826 }
827 }
828
Michal Vaskoe0665742021-02-11 11:08:44 +0100829 if (!sibling && (lybctx->parse_opts & LYD_PARSE_STRICT)) {
Radek Krejcif16e2542021-02-17 15:39:23 +0100830 if (lybctx->ext) {
831 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a node from \"%s\" extension instance node.",
832 lybctx->ext->def->name);
833 } else if (mod) {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100834 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a top-level node"
Michal Vasko69730152020-10-09 16:30:07 +0200835 " from \"%s\".", mod->name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200836 } else {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100837 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a child node"
Michal Vasko69730152020-10-09 16:30:07 +0200838 " of \"%s\".", sparent->name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200839 }
840 return LY_EVALID;
Radek Krejci1798aae2020-07-14 13:26:06 +0200841 } else if (sibling && (ret = lyd_parser_check_schema((struct lyd_ctx *)lybctx, sibling))) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200842 return ret;
843 }
844
845 *snode = sibling;
846 return LY_SUCCESS;
847}
848
849/**
Michal Vasko9883a3e2022-03-31 12:16:00 +0200850 * @brief Parse schema node name of a nested extension data node.
851 *
852 * @param[in] lybctx LYB context.
853 * @param[in] parent Data parent.
854 * @param[in] mod_name Module name of the node.
855 * @param[out] snode Parsed found schema node of a nested extension.
856 * @return LY_ERR value.
857 */
858static LY_ERR
859lyb_parse_schema_nested_ext(struct lyd_lyb_ctx *lybctx, const struct lyd_node *parent, const char *mod_name,
860 const struct lysc_node **snode)
861{
862 LY_ERR rc = LY_SUCCESS, r;
863 char *name = NULL;
864 struct lysc_ext_instance *ext;
865
866 assert(parent);
867
868 /* read schema node name */
869 LY_CHECK_GOTO(rc = lyb_read_string(&name, sizeof(uint16_t), lybctx->lybctx), cleanup);
870
871 /* check for extension data */
872 r = ly_nested_ext_schema(parent, NULL, mod_name, mod_name ? strlen(mod_name) : 0, LY_VALUE_JSON, NULL, name,
873 strlen(name), snode, &ext);
874 if (r == LY_ENOT) {
875 /* failed to parse */
876 LOGERR(lybctx->lybctx->ctx, LY_EINVAL, "Failed to parse node \"%s\" as nested extension instance data.", name);
877 rc = LY_EINVAL;
878 goto cleanup;
879 } else if (r) {
880 /* error */
881 rc = r;
882 goto cleanup;
883 }
884
885 /* fill cached hashes in the module, it may be from a different context */
886 lyb_cache_module_hash((*snode)->module);
887
888cleanup:
889 free(name);
890 return rc;
891}
892
893/**
aPiecek570d7ed2021-09-10 07:15:35 +0200894 * @brief Read until the end of the current siblings.
Michal Vasko60ea6352020-06-29 13:39:39 +0200895 *
896 * @param[in] lybctx LYB context.
897 */
898static void
aPiecek570d7ed2021-09-10 07:15:35 +0200899lyb_skip_siblings(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200900{
Michal Vasko60ea6352020-06-29 13:39:39 +0200901 do {
902 /* first skip any meta information inside */
aPiecek570d7ed2021-09-10 07:15:35 +0200903 ly_in_skip(lybctx->in, LYB_LAST_SIBLING(lybctx).inner_chunks * LYB_META_BYTES);
Michal Vasko60ea6352020-06-29 13:39:39 +0200904
905 /* then read data */
aPiecek570d7ed2021-09-10 07:15:35 +0200906 lyb_read(NULL, LYB_LAST_SIBLING(lybctx).written, lybctx);
907 } while (LYB_LAST_SIBLING(lybctx).written);
Michal Vasko60ea6352020-06-29 13:39:39 +0200908}
909
910/**
Michal Vasko02ed9d82021-07-15 14:58:04 +0200911 * @brief Parse the context of anydata/anyxml node.
912 *
913 * @param[in] ctx libyang context.
914 * @param[in] data LYB data to parse.
915 * @param[out] tree Parsed tree.
916 * @return LY_ERR value.
917 */
918static LY_ERR
919lyb_parse_any_content(const struct ly_ctx *ctx, const char *data, struct lyd_node **tree)
920{
921 LY_ERR ret;
922 uint32_t prev_lo;
923 struct ly_in *in;
924 struct lyd_ctx *lydctx = NULL;
925
926 *tree = NULL;
927
928 LY_CHECK_RET(ly_in_new_memory(data, &in));
929
930 /* turn logging off */
931 prev_lo = ly_log_options(0);
932
Michal Vasko56d88602021-07-15 16:37:59 +0200933 ret = _lyd_parse_lyb(ctx, NULL, NULL, tree, in, LYD_PARSE_ONLY | LYD_PARSE_OPAQ | LYD_PARSE_STRICT, 0,
Michal Vasko02ed9d82021-07-15 14:58:04 +0200934 LYD_INTOPT_ANY | LYD_INTOPT_WITH_SIBLINGS, NULL, &lydctx);
935
936 /* turn logging on again */
937 ly_log_options(prev_lo);
938
939 ly_in_free(in, 0);
Michal Vasko1391e792021-08-23 12:15:44 +0200940 if (lydctx) {
941 lydctx->free(lydctx);
942 }
Michal Vasko02ed9d82021-07-15 14:58:04 +0200943 if (ret) {
944 lyd_free_siblings(*tree);
945 *tree = NULL;
946 }
947 return ret;
948}
949
950/**
aPiecek37c493b2021-09-09 12:52:30 +0200951 * @brief Insert new node to @p parsed set.
952 *
953 * Also if needed, correct @p first_p.
954 *
955 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +0200956 * @param[in] parent Data parent of the sibling, must be set if @p first_p is not.
aPiecek37c493b2021-09-09 12:52:30 +0200957 * @param[in,out] node Parsed node to insertion.
958 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
959 * @param[out] parsed Set of all successfully parsed nodes.
960 * @return LY_ERR value.
961 */
962static void
963lyb_insert_node(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node *node, struct lyd_node **first_p,
964 struct ly_set *parsed)
965{
966 /* insert, keep first pointer correct */
Michal Vasko9883a3e2022-03-31 12:16:00 +0200967 if (parent && (LYD_CTX(parent) != LYD_CTX(node))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200968 lyplg_ext_insert(parent, node);
Michal Vasko9883a3e2022-03-31 12:16:00 +0200969 } else {
970 lyd_insert_node(parent, first_p, node, lybctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0);
971 }
aPiecek37c493b2021-09-09 12:52:30 +0200972 while (!parent && (*first_p)->prev->next) {
973 *first_p = (*first_p)->prev;
974 }
975
976 /* rememeber a successfully parsed node */
977 if (parsed) {
978 ly_set_add(parsed, node, 1, NULL);
979 }
980}
981
982/**
983 * @brief Finish parsing the opaq node.
984 *
985 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +0200986 * @param[in] parent Data parent of the sibling, must be set if @p first_p is not.
aPiecek37c493b2021-09-09 12:52:30 +0200987 * @param[in] flags Node flags to set.
988 * @param[in,out] attr Attributes to be attached. Finally set to NULL.
989 * @param[in,out] node Parsed opaq node to finish.
990 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
991 * @param[out] parsed Set of all successfully parsed nodes.
992 * @return LY_ERR value.
993 */
994static void
995lyb_finish_opaq(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, uint32_t flags, struct lyd_attr **attr,
996 struct lyd_node **node, struct lyd_node **first_p, struct ly_set *parsed)
997{
998 struct lyd_attr *iter;
999
1000 /* set flags */
1001 (*node)->flags = flags;
1002
1003 /* add attributes */
1004 assert(!(*node)->schema);
1005 LY_LIST_FOR(*attr, iter) {
1006 iter->parent = (struct lyd_node_opaq *)*node;
1007 }
1008 ((struct lyd_node_opaq *)*node)->attr = *attr;
1009 *attr = NULL;
1010
1011 lyb_insert_node(lybctx, parent, *node, first_p, parsed);
1012 *node = NULL;
1013}
1014
1015/**
1016 * @brief Finish parsing the node.
1017 *
1018 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +02001019 * @param[in] parent Data parent of the sibling, must be set if @p first_p is not.
aPiecek37c493b2021-09-09 12:52:30 +02001020 * @param[in] flags Node flags to set.
1021 * @param[in,out] meta Metadata to be attached. Finally set to NULL.
1022 * @param[in,out] node Parsed node to finish.
1023 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
1024 * @param[out] parsed Set of all successfully parsed nodes.
1025 * @return LY_ERR value.
1026 */
1027static void
1028lyb_finish_node(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, uint32_t flags, struct lyd_meta **meta,
1029 struct lyd_node **node, struct lyd_node **first_p, struct ly_set *parsed)
1030{
1031 struct lyd_meta *m;
1032
1033 /* set flags */
1034 (*node)->flags = flags;
1035
1036 /* add metadata */
1037 LY_LIST_FOR(*meta, m) {
1038 m->parent = *node;
1039 }
1040 (*node)->meta = *meta;
1041 *meta = NULL;
1042
Michal Vasko135719f2022-08-25 12:18:17 +02001043 /* insert into parent */
aPiecek37c493b2021-09-09 12:52:30 +02001044 lyb_insert_node(lybctx, parent, *node, first_p, parsed);
Michal Vasko135719f2022-08-25 12:18:17 +02001045
Michal Vaskoeba23112022-08-26 08:35:41 +02001046 if (!(lybctx->parse_opts & LYD_PARSE_ONLY)) {
1047 /* store for ext instance node validation, if needed */
1048 (void)lyd_validate_node_ext(*node, &lybctx->ext_node);
1049 }
Michal Vasko135719f2022-08-25 12:18:17 +02001050
aPiecek37c493b2021-09-09 12:52:30 +02001051 *node = NULL;
1052}
1053
1054/**
aPiecek6fdac2f2021-09-10 11:21:10 +02001055 * @brief Parse header for non-opaq node.
1056 *
1057 * @param[in] lybctx LYB context.
Michal Vaskoddd76592022-01-17 13:34:48 +01001058 * @param[in] sparent Schema parent node of the metadata.
aPiecek6fdac2f2021-09-10 11:21:10 +02001059 * @param[out] flags Parsed node flags.
1060 * @param[out] meta Parsed metadata of the node.
1061 * @return LY_ERR value.
1062 */
1063static LY_ERR
Michal Vaskoddd76592022-01-17 13:34:48 +01001064lyb_parse_node_header(struct lyd_lyb_ctx *lybctx, const struct lysc_node *sparent, uint32_t *flags, struct lyd_meta **meta)
aPiecek6fdac2f2021-09-10 11:21:10 +02001065{
1066 LY_ERR ret;
1067
1068 /* create and read metadata */
Michal Vaskoddd76592022-01-17 13:34:48 +01001069 ret = lyb_parse_metadata(lybctx, sparent, meta);
aPiecek6fdac2f2021-09-10 11:21:10 +02001070 LY_CHECK_RET(ret);
1071
1072 /* read flags */
1073 lyb_read_number(flags, sizeof *flags, sizeof *flags, lybctx->lybctx);
1074
1075 return ret;
1076}
1077
1078/**
aPiecek33fc6b02021-09-09 15:45:37 +02001079 * @brief Create term node and fill it with value.
1080 *
1081 * @param[in] lybctx LYB context.
1082 * @param[in] snode Schema of the term node.
1083 * @param[out] node Created term node.
1084 * @return LY_ERR value.
1085 */
1086static LY_ERR
1087lyb_create_term(struct lyd_lyb_ctx *lybctx, const struct lysc_node *snode, struct lyd_node **node)
1088{
1089 LY_ERR ret;
1090 ly_bool dynamic;
1091 uint8_t *term_value;
aPieceke99345d2021-09-30 12:49:59 +02001092 uint64_t term_value_len;
aPiecek33fc6b02021-09-09 15:45:37 +02001093
1094 ret = lyb_read_term_value((struct lysc_node_leaf *)snode, &term_value, &term_value_len, lybctx->lybctx);
1095 LY_CHECK_RET(ret);
1096
1097 dynamic = 1;
1098 /* create node */
1099 ret = lyd_parser_create_term((struct lyd_ctx *)lybctx, snode,
1100 term_value, term_value_len, &dynamic, LY_VALUE_LYB,
1101 NULL, LYD_HINT_DATA, node);
1102 if (dynamic) {
1103 free(term_value);
1104 }
1105 if (ret) {
1106 lyd_free_tree(*node);
1107 *node = NULL;
1108 }
1109
1110 return ret;
1111}
1112
1113/**
aPiecek0e2e1052021-09-09 15:48:27 +02001114 * @brief Validate inner node, autodelete default values nad create implicit nodes.
1115 *
1116 * @param[in,out] lybctx LYB context.
1117 * @param[in] snode Schema of the inner node.
1118 * @param[in] node Parsed inner node.
1119 * @return LY_ERR value.
1120 */
1121static LY_ERR
1122lyb_validate_node_inner(struct lyd_lyb_ctx *lybctx, const struct lysc_node *snode, struct lyd_node *node)
1123{
1124 LY_ERR ret = LY_SUCCESS;
1125 uint32_t impl_opts;
1126
1127 if (!(lybctx->parse_opts & LYD_PARSE_ONLY)) {
1128 /* new node validation, autodelete CANNOT occur, all nodes are new */
1129 ret = lyd_validate_new(lyd_node_child_p(node), snode, NULL, NULL);
1130 LY_CHECK_RET(ret);
1131
1132 /* add any missing default children */
1133 impl_opts = (lybctx->val_opts & LYD_VALIDATE_NO_STATE) ? LYD_IMPLICIT_NO_STATE : 0;
Michal Vaskoddd76592022-01-17 13:34:48 +01001134 ret = lyd_new_implicit_r(node, lyd_node_child_p(node), NULL, NULL, &lybctx->node_when, &lybctx->node_types,
Michal Vaskofcbd78f2022-08-26 08:34:15 +02001135 &lybctx->ext_node, impl_opts, NULL);
aPiecek0e2e1052021-09-09 15:48:27 +02001136 LY_CHECK_RET(ret);
1137 }
1138
1139 return ret;
1140}
1141
1142/**
aPiecek821cf732021-09-09 15:37:28 +02001143 * @brief Parse opaq node.
1144 *
1145 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +02001146 * @param[in] parent Data parent of the sibling.
aPiecek821cf732021-09-09 15:37:28 +02001147 * @param[in,out] first_p First top-level sibling.
1148 * @param[out] parsed Set of all successfully parsed nodes.
1149 * @return LY_ERR value.
1150 */
1151static LY_ERR
1152lyb_parse_node_opaq(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node **first_p, struct ly_set *parsed)
1153{
1154 LY_ERR ret;
1155 struct lyd_node *node = NULL;
1156 struct lyd_attr *attr = NULL;
1157 char *value = NULL, *name = NULL, *prefix = NULL, *module_key = NULL;
1158 ly_bool dynamic = 0;
1159 LY_VALUE_FORMAT format = 0;
1160 void *val_prefix_data = NULL;
1161 const struct ly_ctx *ctx = lybctx->lybctx->ctx;
1162 uint32_t flags;
1163
aPiecek821cf732021-09-09 15:37:28 +02001164 /* parse opaq node attributes */
1165 ret = lyb_parse_attributes(lybctx->lybctx, &attr);
1166 LY_CHECK_GOTO(ret, cleanup);
1167
1168 /* read flags */
1169 lyb_read_number(&flags, sizeof flags, sizeof flags, lybctx->lybctx);
1170
1171 /* parse prefix */
aPieceke99345d2021-09-30 12:49:59 +02001172 ret = lyb_read_string(&prefix, sizeof(uint16_t), lybctx->lybctx);
aPiecek821cf732021-09-09 15:37:28 +02001173 LY_CHECK_GOTO(ret, cleanup);
1174
1175 /* parse module key */
aPieceke99345d2021-09-30 12:49:59 +02001176 ret = lyb_read_string(&module_key, sizeof(uint16_t), lybctx->lybctx);
aPiecek821cf732021-09-09 15:37:28 +02001177 LY_CHECK_GOTO(ret, cleanup);
1178
1179 /* parse name */
aPieceke99345d2021-09-30 12:49:59 +02001180 ret = lyb_read_string(&name, sizeof(uint16_t), lybctx->lybctx);
aPiecek821cf732021-09-09 15:37:28 +02001181 LY_CHECK_GOTO(ret, cleanup);
1182
1183 /* parse value */
aPieceke99345d2021-09-30 12:49:59 +02001184 ret = lyb_read_string(&value, sizeof(uint64_t), lybctx->lybctx);
aPiecek821cf732021-09-09 15:37:28 +02001185 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
1186 dynamic = 1;
1187
1188 /* parse format */
1189 lyb_read_number(&format, sizeof format, 1, lybctx->lybctx);
1190
1191 /* parse value prefixes */
1192 ret = lyb_parse_prefix_data(lybctx->lybctx, format, &val_prefix_data);
1193 LY_CHECK_GOTO(ret, cleanup);
1194
aPiecek570d7ed2021-09-10 07:15:35 +02001195 if (!(lybctx->parse_opts & LYD_PARSE_OPAQ)) {
Michal Vaskoefa96e62021-11-02 12:19:14 +01001196 /* skip children */
1197 ret = lyb_read_start_siblings(lybctx->lybctx);
1198 LY_CHECK_GOTO(ret, cleanup);
1199 lyb_skip_siblings(lybctx->lybctx);
1200 ret = lyb_read_stop_siblings(lybctx->lybctx);
1201 LY_CHECK_GOTO(ret, cleanup);
aPiecek570d7ed2021-09-10 07:15:35 +02001202 goto cleanup;
1203 }
1204
aPiecek821cf732021-09-09 15:37:28 +02001205 /* create node */
1206 ret = lyd_create_opaq(ctx, name, strlen(name), prefix, ly_strlen(prefix), module_key, ly_strlen(module_key),
1207 value, strlen(value), &dynamic, format, val_prefix_data, 0, &node);
1208 LY_CHECK_GOTO(ret, cleanup);
1209
1210 /* process children */
aPiecek570d7ed2021-09-10 07:15:35 +02001211 ret = lyb_parse_siblings(lybctx, node, NULL, NULL);
1212 LY_CHECK_GOTO(ret, cleanup);
aPiecek821cf732021-09-09 15:37:28 +02001213
1214 /* register parsed opaq node */
1215 lyb_finish_opaq(lybctx, parent, flags, &attr, &node, first_p, parsed);
1216 assert(!attr && !node);
1217
1218cleanup:
1219 free(prefix);
1220 free(module_key);
1221 free(name);
1222 if (dynamic) {
1223 free(value);
1224 }
1225 lyd_free_attr_siblings(ctx, attr);
1226 lyd_free_tree(node);
1227
1228 return ret;
1229}
1230
aPiecek18457d72021-09-09 15:52:20 +02001231/**
1232 * @brief Parse anydata or anyxml node.
1233 *
1234 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +02001235 * @param[in] parent Data parent of the sibling.
aPiecek18457d72021-09-09 15:52:20 +02001236 * @param[in] snode Schema of the node to be parsed.
1237 * @param[in,out] first_p First top-level sibling.
1238 * @param[out] parsed Set of all successfully parsed nodes.
1239 * @return LY_ERR value.
1240 */
1241static LY_ERR
1242lyb_parse_node_any(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const struct lysc_node *snode,
1243 struct lyd_node **first_p, struct ly_set *parsed)
1244{
1245 LY_ERR ret;
1246 struct lyd_node *node = NULL, *tree;
1247 struct lyd_meta *meta = NULL;
1248 LYD_ANYDATA_VALUETYPE value_type;
1249 char *value = NULL;
aPiecek18457d72021-09-09 15:52:20 +02001250 uint32_t flags;
1251 const struct ly_ctx *ctx = lybctx->lybctx->ctx;
1252
1253 /* read necessary basic data */
Michal Vaskoddd76592022-01-17 13:34:48 +01001254 ret = lyb_parse_node_header(lybctx, snode, &flags, &meta);
Michal Vaskoedd4f252021-09-23 08:37:40 +02001255 LY_CHECK_GOTO(ret, error);
aPiecek18457d72021-09-09 15:52:20 +02001256
1257 /* parse value type */
1258 lyb_read_number(&value_type, sizeof value_type, sizeof value_type, lybctx->lybctx);
1259 if (value_type == LYD_ANYDATA_DATATREE) {
1260 /* invalid situation */
1261 LOGINT(ctx);
1262 ret = LY_EINT;
1263 goto error;
1264 }
1265
1266 /* read anydata content */
aPieceke99345d2021-09-30 12:49:59 +02001267 ret = lyb_read_string(&value, sizeof(uint64_t), lybctx->lybctx);
aPiecek18457d72021-09-09 15:52:20 +02001268 LY_CHECK_GOTO(ret, error);
1269
1270 if (value_type == LYD_ANYDATA_LYB) {
1271 /* try to parse LYB into a data tree */
1272 if (!lyb_parse_any_content(ctx, value, &tree)) {
1273 /* successfully parsed */
1274 free(value);
1275 value = (char *)tree;
1276 value_type = LYD_ANYDATA_DATATREE;
1277 }
1278 }
1279
1280 /* create the node */
1281 switch (value_type) {
1282 case LYD_ANYDATA_LYB:
1283 case LYD_ANYDATA_DATATREE:
aPiecek18457d72021-09-09 15:52:20 +02001284 case LYD_ANYDATA_STRING:
1285 case LYD_ANYDATA_XML:
1286 case LYD_ANYDATA_JSON:
Michal Vasko742a5b12022-02-24 16:07:27 +01001287 /* use the value directly */
1288 ret = lyd_create_any(snode, value, value_type, 1, &node);
aPiecek18457d72021-09-09 15:52:20 +02001289 LY_CHECK_GOTO(ret, error);
aPiecek18457d72021-09-09 15:52:20 +02001290 break;
1291 default:
1292 LOGINT(ctx);
1293 ret = LY_EINT;
1294 goto error;
1295 }
1296
1297 /* register parsed anydata node */
1298 lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);
1299
1300 return LY_SUCCESS;
1301
1302error:
1303 free(value);
1304 lyd_free_meta_siblings(meta);
1305 lyd_free_tree(node);
1306 return ret;
1307}
aPiecek821cf732021-09-09 15:37:28 +02001308
1309/**
aPiecek5777f122021-09-10 10:26:23 +02001310 * @brief Parse inner node.
aPiecek37c493b2021-09-09 12:52:30 +02001311 *
1312 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +02001313 * @param[in] parent Data parent of the sibling, must be set if @p first is not.
1314 * @param[in] snode Schema of the node to be parsed.
aPiecekfc7cf7e2021-09-09 11:20:27 +02001315 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
1316 * @param[out] parsed Set of all successfully parsed nodes.
Michal Vasko60ea6352020-06-29 13:39:39 +02001317 * @return LY_ERR value.
1318 */
1319static LY_ERR
aPiecek5777f122021-09-10 10:26:23 +02001320lyb_parse_node_inner(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const struct lysc_node *snode,
aPiecek570d7ed2021-09-10 07:15:35 +02001321 struct lyd_node **first_p, struct ly_set *parsed)
Michal Vasko60ea6352020-06-29 13:39:39 +02001322{
1323 LY_ERR ret = LY_SUCCESS;
aPiecek18457d72021-09-09 15:52:20 +02001324 struct lyd_node *node = NULL;
aPiecek37c493b2021-09-09 12:52:30 +02001325 struct lyd_meta *meta = NULL;
aPiecek33fc6b02021-09-09 15:45:37 +02001326 uint32_t flags;
Michal Vasko60ea6352020-06-29 13:39:39 +02001327
aPiecek307f0772021-09-10 09:09:47 +02001328 /* read necessary basic data */
Michal Vaskoddd76592022-01-17 13:34:48 +01001329 ret = lyb_parse_node_header(lybctx, snode, &flags, &meta);
aPiecek307f0772021-09-10 09:09:47 +02001330 LY_CHECK_GOTO(ret, error);
aPiecek37c493b2021-09-09 12:52:30 +02001331
aPiecek5777f122021-09-10 10:26:23 +02001332 /* create node */
1333 ret = lyd_create_inner(snode, &node);
1334 LY_CHECK_GOTO(ret, error);
Michal Vasko60ea6352020-06-29 13:39:39 +02001335
aPiecek5777f122021-09-10 10:26:23 +02001336 /* process children */
1337 ret = lyb_parse_siblings(lybctx, node, NULL, NULL);
1338 LY_CHECK_GOTO(ret, error);
Michal Vasko60ea6352020-06-29 13:39:39 +02001339
aPiecek5777f122021-09-10 10:26:23 +02001340 /* additional procedure for inner node */
1341 ret = lyb_validate_node_inner(lybctx, snode, node);
1342 LY_CHECK_GOTO(ret, error);
Michal Vasko60ea6352020-06-29 13:39:39 +02001343
aPiecek5777f122021-09-10 10:26:23 +02001344 if (snode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1345 /* rememeber the RPC/action/notification */
1346 lybctx->op_node = node;
Michal Vasko60ea6352020-06-29 13:39:39 +02001347 }
1348
aPiecek307f0772021-09-10 09:09:47 +02001349 /* register parsed node */
1350 lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);
1351
1352 return LY_SUCCESS;
1353
1354error:
Michal Vasko3a41dff2020-07-15 14:30:28 +02001355 lyd_free_meta_siblings(meta);
Michal Vasko60ea6352020-06-29 13:39:39 +02001356 lyd_free_tree(node);
1357 return ret;
1358}
1359
1360/**
aPiecek8a555d72021-09-10 10:15:26 +02001361 * @brief Parse leaf node.
1362 *
1363 * @param[in] lybctx LYB context.
1364 * @param[in] parent Data parent of the sibling.
1365 * @param[in] snode Schema of the node to be parsed.
1366 * @param[in,out] first_p First top-level sibling.
1367 * @param[out] parsed Set of all successfully parsed nodes.
1368 * @return LY_ERR value.
1369 */
1370static LY_ERR
1371lyb_parse_node_leaf(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const struct lysc_node *snode,
1372 struct lyd_node **first_p, struct ly_set *parsed)
1373{
1374 LY_ERR ret;
1375 struct lyd_node *node = NULL;
1376 struct lyd_meta *meta = NULL;
1377 uint32_t flags;
1378
1379 /* read necessary basic data */
Michal Vaskoddd76592022-01-17 13:34:48 +01001380 ret = lyb_parse_node_header(lybctx, snode, &flags, &meta);
aPiecek8a555d72021-09-10 10:15:26 +02001381 LY_CHECK_GOTO(ret, error);
1382
1383 /* read value of term node and create it */
1384 ret = lyb_create_term(lybctx, snode, &node);
1385 LY_CHECK_GOTO(ret, error);
1386
1387 lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);
1388
1389 return LY_SUCCESS;
1390
1391error:
1392 lyd_free_meta_siblings(meta);
1393 lyd_free_tree(node);
1394 return ret;
1395}
1396
1397/**
aPiecek5777f122021-09-10 10:26:23 +02001398 * @brief Parse all leaflist nodes which belong to same schema.
1399 *
1400 * @param[in] lybctx LYB context.
1401 * @param[in] parent Data parent of the sibling.
1402 * @param[in] snode Schema of the nodes to be parsed.
1403 * @param[in,out] first_p First top-level sibling.
1404 * @param[out] parsed Set of all successfully parsed nodes.
1405 * @return LY_ERR value.
1406 */
1407static LY_ERR
1408lyb_parse_node_leaflist(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const struct lysc_node *snode,
1409 struct lyd_node **first_p, struct ly_set *parsed)
1410{
1411 LY_ERR ret;
1412
1413 /* register a new sibling */
1414 ret = lyb_read_start_siblings(lybctx->lybctx);
1415 LY_CHECK_RET(ret);
1416
1417 /* process all siblings */
1418 while (LYB_LAST_SIBLING(lybctx->lybctx).written) {
1419 ret = lyb_parse_node_leaf(lybctx, parent, snode, first_p, parsed);
1420 LY_CHECK_RET(ret);
1421 }
1422
1423 /* end the sibling */
1424 ret = lyb_read_stop_siblings(lybctx->lybctx);
1425 LY_CHECK_RET(ret);
1426
1427 return ret;
1428}
1429
1430/**
aPiecek77d3e962021-09-10 10:33:59 +02001431 * @brief Parse all list nodes which belong to same schema.
1432 *
1433 * @param[in] lybctx LYB context.
1434 * @param[in] parent Data parent of the sibling.
1435 * @param[in] snode Schema of the nodes to be parsed.
1436 * @param[in,out] first_p First top-level sibling.
1437 * @param[out] parsed Set of all successfully parsed nodes.
1438 * @return LY_ERR value.
1439 */
1440static LY_ERR
1441lyb_parse_node_list(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const struct lysc_node *snode,
1442 struct lyd_node **first_p, struct ly_set *parsed)
1443{
1444 LY_ERR ret;
1445 struct lyd_node *node = NULL;
1446 struct lyd_meta *meta = NULL;
1447 uint32_t flags;
1448
1449 /* register a new sibling */
1450 ret = lyb_read_start_siblings(lybctx->lybctx);
1451 LY_CHECK_RET(ret);
1452
1453 while (LYB_LAST_SIBLING(lybctx->lybctx).written) {
1454 /* read necessary basic data */
Michal Vaskoddd76592022-01-17 13:34:48 +01001455 ret = lyb_parse_node_header(lybctx, snode, &flags, &meta);
Michal Vaskoedd4f252021-09-23 08:37:40 +02001456 LY_CHECK_GOTO(ret, error);
aPiecek77d3e962021-09-10 10:33:59 +02001457
1458 /* create list node */
1459 ret = lyd_create_inner(snode, &node);
1460 LY_CHECK_GOTO(ret, error);
1461
1462 /* process children */
1463 ret = lyb_parse_siblings(lybctx, node, NULL, NULL);
1464 LY_CHECK_GOTO(ret, error);
1465
1466 /* additional procedure for inner node */
1467 ret = lyb_validate_node_inner(lybctx, snode, node);
1468 LY_CHECK_GOTO(ret, error);
1469
1470 if (snode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1471 /* rememeber the RPC/action/notification */
1472 lybctx->op_node = node;
1473 }
1474
1475 /* register parsed list node */
1476 lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);
1477 }
1478
1479 /* end the sibling */
1480 ret = lyb_read_stop_siblings(lybctx->lybctx);
1481 LY_CHECK_RET(ret);
1482
1483 return LY_SUCCESS;
1484
1485error:
1486 lyd_free_meta_siblings(meta);
1487 lyd_free_tree(node);
1488 return ret;
1489}
1490
1491/**
Michal Vasko9883a3e2022-03-31 12:16:00 +02001492 * @brief Parse a node.
aPiecek17737b52021-09-21 12:29:52 +02001493 *
aPiecek17737b52021-09-21 12:29:52 +02001494 * @param[in] lybctx LYB context.
Michal Vasko9883a3e2022-03-31 12:16:00 +02001495 * @param[in] parent Data parent of the sibling, must be set if @p first_p is not.
1496 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
1497 * @param[in,out] parsed Set of all successfully parsed nodes to add to.
aPiecek17737b52021-09-21 12:29:52 +02001498 * @return LY_ERR value.
1499 */
1500static LY_ERR
1501lyb_parse_node(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node **first_p,
1502 struct ly_set *parsed)
1503{
1504 LY_ERR ret;
1505 const struct lysc_node *snode;
1506 const struct lys_module *mod;
Michal Vasko9883a3e2022-03-31 12:16:00 +02001507 enum lylyb_node_type lyb_type;
1508 char *mod_name = NULL, mod_rev[LY_REV_SIZE];
aPiecek17737b52021-09-21 12:29:52 +02001509
Michal Vasko9883a3e2022-03-31 12:16:00 +02001510 /* read node type */
1511 lyb_read_number(&lyb_type, sizeof lyb_type, 1, lybctx->lybctx);
1512
1513 switch (lyb_type) {
1514 case LYB_NODE_TOP:
1515 /* top-level, read module name */
Michal Vasko78041d12022-11-29 14:11:07 +01001516 LY_CHECK_GOTO(ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, 0, &mod), cleanup);
aPiecek17737b52021-09-21 12:29:52 +02001517
1518 /* read hash, find the schema node starting from mod */
Michal Vasko9883a3e2022-03-31 12:16:00 +02001519 LY_CHECK_GOTO(ret = lyb_parse_schema_hash(lybctx, NULL, mod, &snode), cleanup);
1520 break;
1521 case LYB_NODE_CHILD:
1522 case LYB_NODE_OPAQ:
1523 /* read hash, find the schema node starting from parent schema, if any */
1524 LY_CHECK_GOTO(ret = lyb_parse_schema_hash(lybctx, parent ? parent->schema : NULL, NULL, &snode), cleanup);
1525 break;
1526 case LYB_NODE_EXT:
1527 /* ext, read module name */
Michal Vasko78041d12022-11-29 14:11:07 +01001528 LY_CHECK_GOTO(ret = lyb_read_model(lybctx->lybctx, &mod_name, mod_rev, NULL), cleanup);
Michal Vasko9883a3e2022-03-31 12:16:00 +02001529
1530 /* read schema node name, find the nexted ext schema node */
1531 LY_CHECK_GOTO(ret = lyb_parse_schema_nested_ext(lybctx, parent, mod_name, &snode), cleanup);
1532 break;
aPiecek17737b52021-09-21 12:29:52 +02001533 }
aPiecek17737b52021-09-21 12:29:52 +02001534
1535 if (!snode) {
1536 ret = lyb_parse_node_opaq(lybctx, parent, first_p, parsed);
1537 } else if (snode->nodetype & LYS_LEAFLIST) {
1538 ret = lyb_parse_node_leaflist(lybctx, parent, snode, first_p, parsed);
1539 } else if (snode->nodetype == LYS_LIST) {
1540 ret = lyb_parse_node_list(lybctx, parent, snode, first_p, parsed);
1541 } else if (snode->nodetype & LYD_NODE_ANY) {
1542 ret = lyb_parse_node_any(lybctx, parent, snode, first_p, parsed);
1543 } else if (snode->nodetype & LYD_NODE_INNER) {
1544 ret = lyb_parse_node_inner(lybctx, parent, snode, first_p, parsed);
1545 } else {
1546 ret = lyb_parse_node_leaf(lybctx, parent, snode, first_p, parsed);
1547 }
Michal Vasko9883a3e2022-03-31 12:16:00 +02001548 LY_CHECK_GOTO(ret, cleanup);
aPiecek17737b52021-09-21 12:29:52 +02001549
Michal Vasko9883a3e2022-03-31 12:16:00 +02001550cleanup:
1551 free(mod_name);
aPiecek17737b52021-09-21 12:29:52 +02001552 return ret;
1553}
1554
1555/**
aPiecek570d7ed2021-09-10 07:15:35 +02001556 * @brief Parse siblings (@ref lyb_print_siblings()).
1557 *
1558 * @param[in] lybctx LYB context.
1559 * @param[in] parent Data parent of the sibling, must be set if @p first_p is not.
1560 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
1561 * @param[out] parsed Set of all successfully parsed nodes.
1562 * @return LY_ERR value.
1563 */
1564static LY_ERR
1565lyb_parse_siblings(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node **first_p,
1566 struct ly_set *parsed)
1567{
aPiecek570d7ed2021-09-10 07:15:35 +02001568 ly_bool top_level;
aPiecek570d7ed2021-09-10 07:15:35 +02001569
1570 top_level = !LY_ARRAY_COUNT(lybctx->lybctx->siblings);
1571
1572 /* register a new siblings */
Michal Vasko9883a3e2022-03-31 12:16:00 +02001573 LY_CHECK_RET(lyb_read_start_siblings(lybctx->lybctx));
aPiecek570d7ed2021-09-10 07:15:35 +02001574
1575 while (LYB_LAST_SIBLING(lybctx->lybctx).written) {
Michal Vasko9883a3e2022-03-31 12:16:00 +02001576 LY_CHECK_RET(lyb_parse_node(lybctx, parent, first_p, parsed));
aPiecek570d7ed2021-09-10 07:15:35 +02001577
1578 if (top_level && !(lybctx->int_opts & LYD_INTOPT_WITH_SIBLINGS)) {
1579 break;
1580 }
1581 }
1582
1583 /* end the siblings */
Michal Vasko9883a3e2022-03-31 12:16:00 +02001584 LY_CHECK_RET(lyb_read_stop_siblings(lybctx->lybctx));
aPiecek570d7ed2021-09-10 07:15:35 +02001585
Michal Vasko9883a3e2022-03-31 12:16:00 +02001586 return LY_SUCCESS;
aPiecek570d7ed2021-09-10 07:15:35 +02001587}
1588
1589/**
Michal Vasko60ea6352020-06-29 13:39:39 +02001590 * @brief Parse used YANG data models.
1591 *
1592 * @param[in] lybctx LYB context.
aPiecekfc7cf7e2021-09-09 11:20:27 +02001593 * @param[in] parse_options Flag with options for parsing.
Michal Vasko60ea6352020-06-29 13:39:39 +02001594 * @return LY_ERR value.
1595 */
1596static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001597lyb_parse_data_models(struct lylyb_ctx *lybctx, uint32_t parse_options)
Michal Vasko60ea6352020-06-29 13:39:39 +02001598{
1599 LY_ERR ret;
1600 uint32_t count;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001601 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +02001602
1603 /* read model count */
1604 lyb_read_number(&count, sizeof count, 2, lybctx);
1605
1606 if (count) {
1607 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->models, count, LY_EMEM);
1608
1609 /* read modules */
1610 for (u = 0; u < count; ++u) {
Michal Vasko78041d12022-11-29 14:11:07 +01001611 ret = lyb_parse_model(lybctx, parse_options, 1, &lybctx->models[u]);
Michal Vasko60ea6352020-06-29 13:39:39 +02001612 LY_CHECK_RET(ret);
1613 LY_ARRAY_INCREMENT(lybctx->models);
1614 }
1615 }
1616
1617 return LY_SUCCESS;
1618}
1619
1620/**
1621 * @brief Parse LYB magic number.
1622 *
1623 * @param[in] lybctx LYB context.
1624 * @return LY_ERR value.
1625 */
1626static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001627lyb_parse_magic_number(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001628{
1629 char magic_byte = 0;
1630
1631 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1632 if (magic_byte != 'l') {
1633 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
1634 return LY_EINVAL;
1635 }
1636
1637 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1638 if (magic_byte != 'y') {
1639 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
1640 return LY_EINVAL;
1641 }
1642
1643 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1644 if (magic_byte != 'b') {
1645 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
1646 return LY_EINVAL;
1647 }
1648
1649 return LY_SUCCESS;
1650}
1651
1652/**
1653 * @brief Parse LYB header.
1654 *
1655 * @param[in] lybctx LYB context.
1656 * @return LY_ERR value.
1657 */
1658static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001659lyb_parse_header(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001660{
1661 uint8_t byte = 0;
1662
1663 /* version, future flags */
1664 lyb_read((uint8_t *)&byte, sizeof byte, lybctx);
1665
1666 if ((byte & LYB_VERSION_MASK) != LYB_VERSION_NUM) {
1667 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid LYB format version \"0x%02x\", expected \"0x%02x\".",
Michal Vasko69730152020-10-09 16:30:07 +02001668 byte & LYB_VERSION_MASK, LYB_VERSION_NUM);
Michal Vasko60ea6352020-06-29 13:39:39 +02001669 return LY_EINVAL;
1670 }
1671
1672 return LY_SUCCESS;
1673}
1674
Michal Vasko02ed9d82021-07-15 14:58:04 +02001675static LY_ERR
1676_lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1677 struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, uint32_t int_opts,
Radek Krejcif16e2542021-02-17 15:39:23 +01001678 struct ly_set *parsed, struct lyd_ctx **lydctx_p)
Michal Vasko60ea6352020-06-29 13:39:39 +02001679{
Michal Vaskoe0665742021-02-11 11:08:44 +01001680 LY_ERR rc = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001681 struct lyd_lyb_ctx *lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001682
Michal Vaskoe0665742021-02-11 11:08:44 +01001683 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1684 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
Radek Krejci7931b192020-06-25 17:05:03 +02001685
Radek Krejci1798aae2020-07-14 13:26:06 +02001686 lybctx = calloc(1, sizeof *lybctx);
1687 LY_CHECK_ERR_RET(!lybctx, LOGMEM(ctx), LY_EMEM);
1688 lybctx->lybctx = calloc(1, sizeof *lybctx->lybctx);
Michal Vaskoe0665742021-02-11 11:08:44 +01001689 LY_CHECK_ERR_GOTO(!lybctx->lybctx, LOGMEM(ctx); rc = LY_EMEM, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001690
Radek Krejci1798aae2020-07-14 13:26:06 +02001691 lybctx->lybctx->in = in;
1692 lybctx->lybctx->ctx = ctx;
Michal Vaskoe0665742021-02-11 11:08:44 +01001693 lybctx->parse_opts = parse_opts;
1694 lybctx->val_opts = val_opts;
Michal Vaskoe0665742021-02-11 11:08:44 +01001695 lybctx->int_opts = int_opts;
Michal Vasko02ed9d82021-07-15 14:58:04 +02001696 lybctx->free = lyd_lyb_ctx_free;
Radek Krejcif16e2542021-02-17 15:39:23 +01001697 lybctx->ext = ext;
Michal Vaskoe0665742021-02-11 11:08:44 +01001698
1699 /* find the operation node if it exists already */
1700 LY_CHECK_GOTO(rc = lyd_parser_find_operation(parent, int_opts, &lybctx->op_node), cleanup);
1701
Michal Vasko60ea6352020-06-29 13:39:39 +02001702 /* read magic number */
Michal Vaskoe0665742021-02-11 11:08:44 +01001703 rc = lyb_parse_magic_number(lybctx->lybctx);
1704 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001705
1706 /* read header */
Michal Vaskoe0665742021-02-11 11:08:44 +01001707 rc = lyb_parse_header(lybctx->lybctx);
1708 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001709
1710 /* read used models */
Michal Vaskoe0665742021-02-11 11:08:44 +01001711 rc = lyb_parse_data_models(lybctx->lybctx, lybctx->parse_opts);
1712 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001713
aPiecek570d7ed2021-09-10 07:15:35 +02001714 /* read sibling(s) */
1715 rc = lyb_parse_siblings(lybctx, parent, first_p, parsed);
1716 LY_CHECK_GOTO(rc, cleanup);
Michal Vaskoe0665742021-02-11 11:08:44 +01001717
1718 if ((int_opts & LYD_INTOPT_NO_SIBLINGS) && lybctx->lybctx->in->current[0]) {
1719 LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling node.");
1720 rc = LY_EVALID;
1721 goto cleanup;
1722 }
1723 if ((int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY)) && !lybctx->op_node) {
1724 LOGVAL(ctx, LYVE_DATA, "Missing the operation node.");
1725 rc = LY_EVALID;
1726 goto cleanup;
Michal Vasko60ea6352020-06-29 13:39:39 +02001727 }
1728
1729 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001730 ly_in_skip(lybctx->lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001731
Michal Vasko60ea6352020-06-29 13:39:39 +02001732cleanup:
Michal Vaskoe0665742021-02-11 11:08:44 +01001733 /* there should be no unres stored if validation should be skipped */
1734 assert(!(parse_opts & LYD_PARSE_ONLY) || (!lybctx->node_types.count && !lybctx->meta_types.count &&
1735 !lybctx->node_when.count));
1736
1737 if (rc) {
Radek Krejci1798aae2020-07-14 13:26:06 +02001738 lyd_lyb_ctx_free((struct lyd_ctx *)lybctx);
Radek Krejci1798aae2020-07-14 13:26:06 +02001739 } else {
Michal Vaskoe0665742021-02-11 11:08:44 +01001740 *lydctx_p = (struct lyd_ctx *)lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001741 }
Michal Vaskoe0665742021-02-11 11:08:44 +01001742 return rc;
Michal Vasko60ea6352020-06-29 13:39:39 +02001743}
1744
Michal Vasko02ed9d82021-07-15 14:58:04 +02001745LY_ERR
1746lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1747 struct lyd_node **first_p, struct ly_in *in, uint32_t parse_opts, uint32_t val_opts, enum lyd_type data_type,
Michal Vaskoddd76592022-01-17 13:34:48 +01001748 struct ly_set *parsed, ly_bool *subtree_sibling, struct lyd_ctx **lydctx_p)
Michal Vasko02ed9d82021-07-15 14:58:04 +02001749{
1750 uint32_t int_opts;
1751
1752 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1753 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
1754
Michal Vaskoddd76592022-01-17 13:34:48 +01001755 LY_CHECK_ARG_RET(ctx, !(parse_opts & LYD_PARSE_SUBTREE), LY_EINVAL);
1756
Michal Vasko02ed9d82021-07-15 14:58:04 +02001757 switch (data_type) {
1758 case LYD_TYPE_DATA_YANG:
1759 int_opts = LYD_INTOPT_WITH_SIBLINGS;
1760 break;
1761 case LYD_TYPE_RPC_YANG:
1762 int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
1763 break;
1764 case LYD_TYPE_NOTIF_YANG:
1765 int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
1766 break;
1767 case LYD_TYPE_REPLY_YANG:
1768 int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
1769 break;
1770 default:
1771 LOGINT(ctx);
1772 return LY_EINT;
1773 }
1774
Michal Vaskoddd76592022-01-17 13:34:48 +01001775 if (subtree_sibling) {
1776 *subtree_sibling = 0;
1777 }
Michal Vasko02ed9d82021-07-15 14:58:04 +02001778 return _lyd_parse_lyb(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, parsed, lydctx_p);
1779}
1780
Jan Kundrátc53a7ec2021-12-09 16:01:19 +01001781LIBYANG_API_DEF int
Michal Vasko60ea6352020-06-29 13:39:39 +02001782lyd_lyb_data_length(const char *data)
1783{
1784 LY_ERR ret = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001785 struct lylyb_ctx *lybctx;
Michal Vasko78041d12022-11-29 14:11:07 +01001786 uint32_t count, feat_count, len = 0, i, j;
Michal Vasko60ea6352020-06-29 13:39:39 +02001787 uint8_t buf[LYB_SIZE_MAX];
aPiecek6828a312021-09-17 15:53:18 +02001788 uint8_t zero[LYB_SIZE_BYTES] = {0};
Michal Vasko60ea6352020-06-29 13:39:39 +02001789
1790 if (!data) {
1791 return -1;
1792 }
1793
Radek Krejci1798aae2020-07-14 13:26:06 +02001794 lybctx = calloc(1, sizeof *lybctx);
1795 LY_CHECK_ERR_RET(!lybctx, LOGMEM(NULL), LY_EMEM);
1796 ret = ly_in_new_memory(data, &lybctx->in);
Michal Vasko63f3d842020-07-08 10:10:14 +02001797 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001798
1799 /* read magic number */
Radek Krejci1798aae2020-07-14 13:26:06 +02001800 ret = lyb_parse_magic_number(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001801 LY_CHECK_GOTO(ret, cleanup);
1802
1803 /* read header */
Radek Krejci1798aae2020-07-14 13:26:06 +02001804 ret = lyb_parse_header(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001805 LY_CHECK_GOTO(ret, cleanup);
1806
1807 /* read model count */
Radek Krejci1798aae2020-07-14 13:26:06 +02001808 lyb_read_number(&count, sizeof count, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001809
1810 /* read all models */
1811 for (i = 0; i < count; ++i) {
1812 /* module name length */
Radek Krejci1798aae2020-07-14 13:26:06 +02001813 lyb_read_number(&len, sizeof len, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001814
1815 /* model name */
Radek Krejci1798aae2020-07-14 13:26:06 +02001816 lyb_read(buf, len, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001817
1818 /* revision */
Radek Krejci1798aae2020-07-14 13:26:06 +02001819 lyb_read(buf, 2, lybctx);
Michal Vasko78041d12022-11-29 14:11:07 +01001820
1821 /* enabled feature count */
1822 lyb_read_number(&feat_count, sizeof feat_count, 2, lybctx);
1823
1824 /* enabled features */
1825 for (j = 0; j < feat_count; ++j) {
1826 /* feature name length */
1827 lyb_read_number(&len, sizeof len, 2, lybctx);
1828
1829 /* feature name */
1830 lyb_read(buf, len, lybctx);
1831 }
Michal Vasko60ea6352020-06-29 13:39:39 +02001832 }
1833
aPiecek6828a312021-09-17 15:53:18 +02001834 if (memcmp(zero, lybctx->in->current, LYB_SIZE_BYTES)) {
aPiecek570d7ed2021-09-10 07:15:35 +02001835 /* register a new sibling */
1836 ret = lyb_read_start_siblings(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001837 LY_CHECK_GOTO(ret, cleanup);
1838
1839 /* skip it */
aPiecek570d7ed2021-09-10 07:15:35 +02001840 lyb_skip_siblings(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001841
aPiecek570d7ed2021-09-10 07:15:35 +02001842 /* sibling finished */
1843 ret = lyb_read_stop_siblings(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001844 LY_CHECK_GOTO(ret, cleanup);
aPiecek570d7ed2021-09-10 07:15:35 +02001845 } else {
aPiecek6828a312021-09-17 15:53:18 +02001846 lyb_read(NULL, LYB_SIZE_BYTES, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001847 }
1848
1849 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001850 ly_in_skip(lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001851
1852cleanup:
Radek Krejci1798aae2020-07-14 13:26:06 +02001853 count = lybctx->in->current - lybctx->in->start;
Michal Vasko63f3d842020-07-08 10:10:14 +02001854
Radek Krejci1798aae2020-07-14 13:26:06 +02001855 ly_in_free(lybctx->in, 0);
1856 lylyb_ctx_free(lybctx);
1857
Michal Vasko78041d12022-11-29 14:11:07 +01001858 return ret ? -1 : (int)count;
Michal Vasko60ea6352020-06-29 13:39:39 +02001859}