blob: 3daed88d4509d89fec9745f5b46f332427208534 [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 *
6 * Copyright (c) 2020 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 "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
aPiecek570d7ed2021-09-10 07:15:35 +020048static LY_ERR lyb_parse_siblings(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node **first_p, struct ly_set *parsed);
aPiecek821cf732021-09-09 15:37:28 +020049
Radek Krejci1798aae2020-07-14 13:26:06 +020050void
51lylyb_ctx_free(struct lylyb_ctx *ctx)
52{
53 LY_ARRAY_COUNT_TYPE u;
54
aPiecek570d7ed2021-09-10 07:15:35 +020055 LY_ARRAY_FREE(ctx->siblings);
Radek Krejci1798aae2020-07-14 13:26:06 +020056 LY_ARRAY_FREE(ctx->models);
57
58 LY_ARRAY_FOR(ctx->sib_hts, u) {
59 lyht_free(ctx->sib_hts[u].ht);
60 }
61 LY_ARRAY_FREE(ctx->sib_hts);
62
63 free(ctx);
64}
65
66void
67lyd_lyb_ctx_free(struct lyd_ctx *lydctx)
68{
69 struct lyd_lyb_ctx *ctx = (struct lyd_lyb_ctx *)lydctx;
70
71 lyd_ctx_free(lydctx);
72 lylyb_ctx_free(ctx->lybctx);
73 free(ctx);
74}
75
Michal Vasko60ea6352020-06-29 13:39:39 +020076/**
aPiecek6828a312021-09-17 15:53:18 +020077 * @brief Read metadata about siblings.
78 *
79 * @param[out] sib Structure in which the metadata will be stored.
80 * @param[in] lybctx LYB context.
81 */
82static void
83lyb_read_sibling_meta(struct lyd_lyb_sibling *sib, struct lylyb_ctx *lybctx)
84{
85 uint8_t meta_buf[LYB_META_BYTES];
86 uint64_t num = 0;
87
88 ly_in_read(lybctx->in, meta_buf, LYB_META_BYTES);
89
90 memcpy(&num, meta_buf, LYB_SIZE_BYTES);
91 sib->written = le64toh(num);
92 memcpy(&num, meta_buf + LYB_SIZE_BYTES, LYB_INCHUNK_BYTES);
93 sib->inner_chunks = le64toh(num);
94
95 /* remember whether there is a following chunk or not */
96 sib->position = (sib->written == LYB_SIZE_MAX ? 1 : 0);
97}
98
99/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200100 * @brief Read YANG data from LYB input. Metadata are handled transparently and not returned.
101 *
102 * @param[in] buf Destination buffer.
103 * @param[in] count Number of bytes to read.
104 * @param[in] lybctx LYB context.
105 */
106static void
Radek Krejci1798aae2020-07-14 13:26:06 +0200107lyb_read(uint8_t *buf, size_t count, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200108{
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200109 LY_ARRAY_COUNT_TYPE u;
aPiecek570d7ed2021-09-10 07:15:35 +0200110 struct lyd_lyb_sibling *empty;
Michal Vasko60ea6352020-06-29 13:39:39 +0200111 size_t to_read;
Michal Vasko60ea6352020-06-29 13:39:39 +0200112
113 assert(lybctx);
114
115 while (1) {
116 /* check for fully-read (empty) data chunks */
117 to_read = count;
118 empty = NULL;
aPiecek570d7ed2021-09-10 07:15:35 +0200119 LY_ARRAY_FOR(lybctx->siblings, u) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200120 /* we want the innermost chunks resolved first, so replace previous empty chunks,
121 * also ignore chunks that are completely finished, there is nothing for us to do */
aPiecek570d7ed2021-09-10 07:15:35 +0200122 if ((lybctx->siblings[u].written <= to_read) && lybctx->siblings[u].position) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200123 /* empty chunk, do not read more */
aPiecek570d7ed2021-09-10 07:15:35 +0200124 to_read = lybctx->siblings[u].written;
125 empty = &lybctx->siblings[u];
Michal Vasko60ea6352020-06-29 13:39:39 +0200126 }
127 }
128
129 if (!empty && !count) {
130 break;
131 }
132
133 /* we are actually reading some data, not just finishing another chunk */
134 if (to_read) {
135 if (buf) {
Michal Vasko63f3d842020-07-08 10:10:14 +0200136 ly_in_read(lybctx->in, buf, to_read);
137 } else {
138 ly_in_skip(lybctx->in, to_read);
Michal Vasko60ea6352020-06-29 13:39:39 +0200139 }
140
aPiecek570d7ed2021-09-10 07:15:35 +0200141 LY_ARRAY_FOR(lybctx->siblings, u) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200142 /* decrease all written counters */
aPiecek570d7ed2021-09-10 07:15:35 +0200143 lybctx->siblings[u].written -= to_read;
144 assert(lybctx->siblings[u].written <= LYB_SIZE_MAX);
Michal Vasko60ea6352020-06-29 13:39:39 +0200145 }
146 /* decrease count/buf */
147 count -= to_read;
148 if (buf) {
149 buf += to_read;
150 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200151 }
152
153 if (empty) {
154 /* read the next chunk meta information */
aPiecek6828a312021-09-17 15:53:18 +0200155 lyb_read_sibling_meta(empty, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200156 }
157 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200158}
159
160/**
161 * @brief Read a number.
162 *
163 * @param[in] num Destination buffer.
164 * @param[in] num_size Size of @p num.
165 * @param[in] bytes Number of bytes to read.
166 * @param[in] lybctx LYB context.
167 */
168static void
Radek Krejci1798aae2020-07-14 13:26:06 +0200169lyb_read_number(void *num, size_t num_size, size_t bytes, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200170{
171 uint64_t buf = 0;
172
173 lyb_read((uint8_t *)&buf, bytes, lybctx);
174
175 /* correct byte order */
176 buf = le64toh(buf);
177
178 switch (num_size) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100179 case sizeof(uint8_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200180 *((uint8_t *)num) = buf;
181 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100182 case sizeof(uint16_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200183 *((uint16_t *)num) = buf;
184 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100185 case sizeof(uint32_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200186 *((uint32_t *)num) = buf;
187 break;
Radek Krejcif13b87b2020-12-01 22:02:17 +0100188 case sizeof(uint64_t):
Michal Vasko60ea6352020-06-29 13:39:39 +0200189 *((uint64_t *)num) = buf;
190 break;
191 default:
192 LOGINT(lybctx->ctx);
193 }
194}
195
196/**
197 * @brief Read a string.
198 *
199 * @param[in] str Destination buffer, is allocated.
aPieceke99345d2021-09-30 12:49:59 +0200200 * @param[in] len_size Number of bytes on which the length of the string is written.
Michal Vasko60ea6352020-06-29 13:39:39 +0200201 * @param[in] lybctx LYB context.
202 * @return LY_ERR value.
203 */
204static LY_ERR
aPieceke99345d2021-09-30 12:49:59 +0200205lyb_read_string(char **str, uint8_t len_size, struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200206{
aPieceke99345d2021-09-30 12:49:59 +0200207 uint64_t len = 0;
208
209 assert((len_size == 1) || (len_size == 2) || (len_size == 4) || (len_size == 8));
Michal Vasko60ea6352020-06-29 13:39:39 +0200210
211 *str = NULL;
212
aPieceke99345d2021-09-30 12:49:59 +0200213 lyb_read_number(&len, sizeof len, len_size, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200214
215 *str = malloc((len + 1) * sizeof **str);
216 LY_CHECK_ERR_RET(!*str, LOGMEM(lybctx->ctx), LY_EMEM);
217
218 lyb_read((uint8_t *)*str, len, lybctx);
219
Michal Vaskocebbae52021-05-31 11:11:36 +0200220 (*str)[len] = '\0';
Michal Vasko60ea6352020-06-29 13:39:39 +0200221 return LY_SUCCESS;
222}
223
224/**
aPiecekd5796f92021-09-30 13:39:37 +0200225 * @brief Skip string.
226 *
227 * @param[in] len_size Number of bytes on which the length of the string is written.
228 * @param[in] lybctx LYB context.
229 */
230static void
231lyb_skip_string(uint8_t len_size, struct lylyb_ctx *lybctx)
232{
233 size_t len = 0;
234
235 lyb_read_number(&len, sizeof len, len_size, lybctx);
236
237 lyb_read(NULL, len, lybctx);
238}
239
240/**
aPiecek91eec232021-09-09 15:42:37 +0200241 * @brief Read value of term node.
aPiecekea304e32021-08-18 09:13:47 +0200242 *
aPiecekaa5b70a2021-08-30 08:33:25 +0200243 * @param[in] term Compiled term node.
aPiecekea304e32021-08-18 09:13:47 +0200244 * @param[out] term_value Set to term node value in dynamically
245 * allocated memory. The caller must release it.
246 * @param[out] term_value_len Value length in bytes. The zero byte is
247 * always included and is not counted.
248 * @param[in,out] lybctx LYB context.
249 * @return LY_ERR value.
250 */
251static LY_ERR
aPieceke99345d2021-09-30 12:49:59 +0200252lyb_read_term_value(const struct lysc_node_leaf *term, uint8_t **term_value, uint64_t *term_value_len,
aPiecek91eec232021-09-09 15:42:37 +0200253 struct lylyb_ctx *lybctx)
aPiecekea304e32021-08-18 09:13:47 +0200254{
255 uint32_t allocated_size;
aPiecekaa5b70a2021-08-30 08:33:25 +0200256 int32_t lyb_data_len;
257 struct lysc_type_leafref *type_lf;
aPiecekea304e32021-08-18 09:13:47 +0200258
aPiecekaa5b70a2021-08-30 08:33:25 +0200259 assert(term && term_value && term_value_len && lybctx);
aPiecekea304e32021-08-18 09:13:47 +0200260
aPiecekaa5b70a2021-08-30 08:33:25 +0200261 /* Find out the size from @ref howtoDataLYB. */
262 if (term->type->basetype == LY_TYPE_LEAFREF) {
263 /* Leafref itself is ignored, the target is loaded directly. */
264 type_lf = (struct lysc_type_leafref *)term->type;
265 lyb_data_len = type_lf->realtype->plugin->lyb_data_len;
266 } else {
267 lyb_data_len = term->type->plugin->lyb_data_len;
268 }
269
270 if (lyb_data_len < 0) {
271 /* Parse value size. */
272 lyb_read_number(term_value_len, sizeof *term_value_len,
273 sizeof *term_value_len, lybctx);
274 } else {
275 /* Data size is fixed. */
276 *term_value_len = lyb_data_len;
277 }
aPiecekea304e32021-08-18 09:13:47 +0200278
279 /* Allocate memory. */
280 allocated_size = *term_value_len + 1;
281 *term_value = malloc(allocated_size * sizeof **term_value);
282 LY_CHECK_ERR_RET(!*term_value, LOGMEM(lybctx->ctx), LY_EMEM);
283
284 if (*term_value_len > 0) {
285 /* Parse value. */
286 lyb_read(*term_value, *term_value_len, lybctx);
287 }
288
289 /* Add extra zero byte regardless of whether it is string or not. */
290 (*term_value)[allocated_size - 1] = 0;
291
292 return LY_SUCCESS;
293}
294
295/**
aPiecek570d7ed2021-09-10 07:15:35 +0200296 * @brief Stop the current "siblings" - change LYB context state.
Michal Vasko60ea6352020-06-29 13:39:39 +0200297 *
298 * @param[in] lybctx LYB context.
299 * @return LY_ERR value.
300 */
301static LY_ERR
aPiecek570d7ed2021-09-10 07:15:35 +0200302lyb_read_stop_siblings(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200303{
aPiecek570d7ed2021-09-10 07:15:35 +0200304 if (LYB_LAST_SIBLING(lybctx).written) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200305 LOGINT_RET(lybctx->ctx);
306 }
307
aPiecek570d7ed2021-09-10 07:15:35 +0200308 LY_ARRAY_DECREMENT(lybctx->siblings);
Michal Vasko60ea6352020-06-29 13:39:39 +0200309 return LY_SUCCESS;
310}
311
312/**
aPiecek570d7ed2021-09-10 07:15:35 +0200313 * @brief Start a new "siblings" - change LYB context state but also read the expected metadata.
Michal Vasko60ea6352020-06-29 13:39:39 +0200314 *
315 * @param[in] lybctx LYB context.
316 * @return LY_ERR value.
317 */
318static LY_ERR
aPiecek570d7ed2021-09-10 07:15:35 +0200319lyb_read_start_siblings(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200320{
Michal Vaskofd69e1d2020-07-03 11:57:17 +0200321 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +0200322
aPiecek570d7ed2021-09-10 07:15:35 +0200323 u = LY_ARRAY_COUNT(lybctx->siblings);
324 if (u == lybctx->sibling_size) {
325 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->siblings, u + LYB_SIBLING_STEP, LY_EMEM);
326 lybctx->sibling_size = u + LYB_SIBLING_STEP;
Michal Vasko60ea6352020-06-29 13:39:39 +0200327 }
328
aPiecek570d7ed2021-09-10 07:15:35 +0200329 LY_ARRAY_INCREMENT(lybctx->siblings);
aPiecek6828a312021-09-17 15:53:18 +0200330 lyb_read_sibling_meta(&LYB_LAST_SIBLING(lybctx), lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200331
Michal Vasko60ea6352020-06-29 13:39:39 +0200332 return LY_SUCCESS;
333}
334
335/**
Michal Vasko9883a3e2022-03-31 12:16:00 +0200336 * @brief Read YANG model info.
Michal Vasko60ea6352020-06-29 13:39:39 +0200337 *
338 * @param[in] lybctx LYB context.
Michal Vasko9883a3e2022-03-31 12:16:00 +0200339 * @param[out] mod_name Module name, if any.
340 * @param[out] mod_rev Module revision, "" if none.
Michal Vasko60ea6352020-06-29 13:39:39 +0200341 * @return LY_ERR value.
342 */
343static LY_ERR
Michal Vasko9883a3e2022-03-31 12:16:00 +0200344lyb_read_model(struct lylyb_ctx *lybctx, char **mod_name, char mod_rev[])
Michal Vasko60ea6352020-06-29 13:39:39 +0200345{
aPiecek570d7ed2021-09-10 07:15:35 +0200346 uint16_t rev, length;
Michal Vasko60ea6352020-06-29 13:39:39 +0200347
Michal Vasko9883a3e2022-03-31 12:16:00 +0200348 *mod_name = NULL;
349 mod_rev[0] = '\0';
aPiecek339bdc32021-09-10 08:42:36 +0200350
Michal Vasko9883a3e2022-03-31 12:16:00 +0200351 lyb_read_number(&length, 2, 2, lybctx);
352 if (!length) {
353 return LY_SUCCESS;
aPiecek570d7ed2021-09-10 07:15:35 +0200354 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200355
Michal Vasko9883a3e2022-03-31 12:16:00 +0200356 /* module name */
Michal Vasko0d156b92022-04-01 12:27:04 +0200357 *mod_name = malloc(length + 1);
Michal Vasko9883a3e2022-03-31 12:16:00 +0200358 LY_CHECK_ERR_RET(!*mod_name, LOGMEM(lybctx->ctx), LY_EMEM);
359 lyb_read(((uint8_t *)*mod_name), length, lybctx);
360 (*mod_name)[length] = '\0';
361
362 /* module revision */
Michal Vasko60ea6352020-06-29 13:39:39 +0200363 lyb_read_number(&rev, sizeof rev, 2, lybctx);
364
Michal Vasko60ea6352020-06-29 13:39:39 +0200365 if (rev) {
Radek Krejcif13b87b2020-12-01 22:02:17 +0100366 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & LYB_REV_YEAR_MASK) >> LYB_REV_YEAR_SHIFT) + LYB_REV_YEAR_OFFSET,
367 (rev & LYB_REV_MONTH_MASK) >> LYB_REV_MONTH_SHIFT, rev & LYB_REV_DAY_MASK);
Michal Vasko9883a3e2022-03-31 12:16:00 +0200368 }
369
370 return LY_SUCCESS;
371}
372
373/**
374 * @brief Parse YANG model info.
375 *
376 * @param[in] lybctx LYB context.
377 * @param[in] parse_options Flag with options for parsing.
378 * @param[out] mod Parsed module.
379 * @return LY_ERR value.
380 */
381static LY_ERR
382lyb_parse_model(struct lylyb_ctx *lybctx, uint32_t parse_options, const struct lys_module **mod)
383{
384 LY_ERR ret = LY_SUCCESS;
385 const struct lys_module *m = NULL;
386 char *mod_name = NULL, mod_rev[LY_REV_SIZE];
387
388 /* read module info */
389 if ((ret = lyb_read_model(lybctx, &mod_name, mod_rev))) {
390 goto cleanup;
391 }
392
393 /* get the module */
394 if (mod_rev[0]) {
395 m = ly_ctx_get_module(lybctx->ctx, mod_name, mod_rev);
396 if ((parse_options & LYD_PARSE_LYB_MOD_UPDATE) && !m) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200397 /* try to use an updated module */
Michal Vasko9883a3e2022-03-31 12:16:00 +0200398 m = ly_ctx_get_module_implemented(lybctx->ctx, mod_name);
399 if (m && (!m->revision || (strcmp(m->revision, mod_rev) < 0))) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200400 /* not an implemented module in a newer revision */
Michal Vasko9883a3e2022-03-31 12:16:00 +0200401 m = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200402 }
403 }
404 } else {
Michal Vasko9883a3e2022-03-31 12:16:00 +0200405 m = ly_ctx_get_module_latest(lybctx->ctx, mod_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200406 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200407
Michal Vasko9883a3e2022-03-31 12:16:00 +0200408 if (!m || !m->implemented) {
Radek Krejci1798aae2020-07-14 13:26:06 +0200409 if (parse_options & LYD_PARSE_STRICT) {
Michal Vasko9883a3e2022-03-31 12:16:00 +0200410 if (!m) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200411 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
Michal Vasko9883a3e2022-03-31 12:16:00 +0200412 mod_name, mod_rev[0] ? "@" : "", mod_rev[0] ? mod_rev : "");
413 } else if (!m->implemented) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200414 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",
Michal Vasko9883a3e2022-03-31 12:16:00 +0200415 mod_name, mod_rev[0] ? "@" : "", mod_rev[0] ? mod_rev : "");
Michal Vasko60ea6352020-06-29 13:39:39 +0200416 }
417 ret = LY_EINVAL;
418 goto cleanup;
419 }
420
421 }
422
Michal Vasko9883a3e2022-03-31 12:16:00 +0200423 if (m) {
Michal Vasko85d9edc2021-04-22 09:15:05 +0200424 /* fill cached hashes, if not already */
Michal Vasko9883a3e2022-03-31 12:16:00 +0200425 lyb_cache_module_hash(m);
Michal Vasko85d9edc2021-04-22 09:15:05 +0200426 }
Michal Vasko11f76c82021-04-15 14:36:14 +0200427
Michal Vasko60ea6352020-06-29 13:39:39 +0200428cleanup:
Michal Vasko9883a3e2022-03-31 12:16:00 +0200429 *mod = m;
Michal Vasko60ea6352020-06-29 13:39:39 +0200430 free(mod_name);
431 return ret;
432}
433
434/**
435 * @brief Parse YANG node metadata.
436 *
437 * @param[in] lybctx LYB context.
Michal Vaskoddd76592022-01-17 13:34:48 +0100438 * @param[in] sparent Schema parent node of the metadata.
Michal Vasko60ea6352020-06-29 13:39:39 +0200439 * @param[out] meta Parsed metadata.
440 * @return LY_ERR value.
441 */
442static LY_ERR
Michal Vaskoddd76592022-01-17 13:34:48 +0100443lyb_parse_metadata(struct lyd_lyb_ctx *lybctx, const struct lysc_node *sparent, struct lyd_meta **meta)
Michal Vasko60ea6352020-06-29 13:39:39 +0200444{
445 LY_ERR ret = LY_SUCCESS;
Radek Krejci857189e2020-09-01 13:26:36 +0200446 ly_bool dynamic;
Michal Vasko60ea6352020-06-29 13:39:39 +0200447 uint8_t i, count = 0;
Michal Vasko1e5d5612020-07-03 13:29:26 +0200448 char *meta_name = NULL, *meta_value;
Michal Vasko60ea6352020-06-29 13:39:39 +0200449 const struct lys_module *mod;
450
451 /* read number of attributes stored */
Radek Krejci1798aae2020-07-14 13:26:06 +0200452 lyb_read(&count, 1, lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200453
454 /* read attributes */
455 for (i = 0; i < count; ++i) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200456 /* find model */
Michal Vaskoe0665742021-02-11 11:08:44 +0100457 ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, &mod);
Michal Vasko60ea6352020-06-29 13:39:39 +0200458 LY_CHECK_GOTO(ret, cleanup);
459
460 if (!mod) {
aPiecekd5796f92021-09-30 13:39:37 +0200461 /* skip meta name */
462 lyb_skip_string(sizeof(uint16_t), lybctx->lybctx);
463
464 /* skip meta value */
465 lyb_skip_string(sizeof(uint16_t), lybctx->lybctx);
466 continue;
Michal Vasko60ea6352020-06-29 13:39:39 +0200467 }
468
469 /* meta name */
aPieceke99345d2021-09-30 12:49:59 +0200470 ret = lyb_read_string(&meta_name, sizeof(uint16_t), lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200471 LY_CHECK_GOTO(ret, cleanup);
472
473 /* meta value */
aPieceke99345d2021-09-30 12:49:59 +0200474 ret = lyb_read_string(&meta_value, sizeof(uint64_t), lybctx->lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200475 LY_CHECK_GOTO(ret, cleanup);
476 dynamic = 1;
477
478 /* create metadata */
Michal Vaskoc8a230d2020-08-14 12:17:10 +0200479 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 +0100480 ly_strlen(meta_value), &dynamic, LY_VALUE_JSON, NULL, LYD_HINT_DATA, sparent);
Michal Vasko60ea6352020-06-29 13:39:39 +0200481
482 /* free strings */
483 free(meta_name);
484 meta_name = NULL;
485 if (dynamic) {
486 free(meta_value);
487 dynamic = 0;
488 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200489
Radek Krejci1798aae2020-07-14 13:26:06 +0200490 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200491 }
492
493cleanup:
494 free(meta_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200495 if (ret) {
Michal Vasko3a41dff2020-07-15 14:30:28 +0200496 lyd_free_meta_siblings(*meta);
Michal Vasko60ea6352020-06-29 13:39:39 +0200497 *meta = NULL;
498 }
499 return ret;
500}
501
502/**
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100503 * @brief Parse format-specific prefix data.
Michal Vasko60ea6352020-06-29 13:39:39 +0200504 *
505 * @param[in] lybctx LYB context.
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100506 * @param[in] format Prefix data format.
507 * @param[out] prefix_data Parsed prefix data.
Michal Vasko60ea6352020-06-29 13:39:39 +0200508 * @return LY_ERR value.
509 */
510static LY_ERR
Radek Krejci8df109d2021-04-23 12:19:08 +0200511lyb_parse_prefix_data(struct lylyb_ctx *lybctx, LY_VALUE_FORMAT format, void **prefix_data)
Michal Vasko60ea6352020-06-29 13:39:39 +0200512{
513 LY_ERR ret = LY_SUCCESS;
514 uint8_t count, i;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100515 struct ly_set *set = NULL;
516 struct lyxml_ns *ns = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200517
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100518 switch (format) {
Radek Krejci8df109d2021-04-23 12:19:08 +0200519 case LY_VALUE_XML:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100520 /* read count */
521 lyb_read(&count, 1, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200522
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100523 /* read all NS elements */
524 LY_CHECK_GOTO(ret = ly_set_new(&set), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200525
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100526 for (i = 0; i < count; ++i) {
527 ns = calloc(1, sizeof *ns);
Michal Vasko60ea6352020-06-29 13:39:39 +0200528
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100529 /* prefix */
aPieceke99345d2021-09-30 12:49:59 +0200530 LY_CHECK_GOTO(ret = lyb_read_string(&ns->prefix, sizeof(uint16_t), lybctx), cleanup);
Michal Vaskoa3494b42022-02-28 13:58:34 +0100531 if (!strlen(ns->prefix)) {
532 free(ns->prefix);
533 ns->prefix = NULL;
534 }
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100535
536 /* namespace */
aPieceke99345d2021-09-30 12:49:59 +0200537 LY_CHECK_GOTO(ret = lyb_read_string(&ns->uri, sizeof(uint16_t), lybctx), cleanup);
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100538
539 LY_CHECK_GOTO(ret = ly_set_add(set, ns, 1, NULL), cleanup);
540 ns = NULL;
541 }
542
543 *prefix_data = set;
544 break;
Radek Krejci8df109d2021-04-23 12:19:08 +0200545 case LY_VALUE_JSON:
Radek Krejcif9943642021-04-26 10:18:21 +0200546 case LY_VALUE_LYB:
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100547 /* nothing stored */
548 break;
549 default:
550 LOGINT(lybctx->ctx);
551 ret = LY_EINT;
552 break;
Michal Vasko60ea6352020-06-29 13:39:39 +0200553 }
554
555cleanup:
556 if (ret) {
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100557 ly_free_prefix_data(format, set);
558 if (ns) {
559 free(ns->prefix);
560 free(ns->uri);
561 free(ns);
562 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200563 }
564 return ret;
565}
566
567/**
568 * @brief Parse opaque attributes.
569 *
570 * @param[in] lybctx LYB context.
571 * @param[out] attr Parsed attributes.
572 * @return LY_ERR value.
573 */
574static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +0200575lyb_parse_attributes(struct lylyb_ctx *lybctx, struct lyd_attr **attr)
Michal Vasko60ea6352020-06-29 13:39:39 +0200576{
577 LY_ERR ret = LY_SUCCESS;
578 uint8_t count, i;
Michal Vasko486e4f92021-07-01 13:12:32 +0200579 struct lyd_attr *attr2 = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200580 char *prefix = NULL, *module_name = NULL, *name = NULL, *value = NULL;
Radek Krejci857189e2020-09-01 13:26:36 +0200581 ly_bool dynamic = 0;
Radek Krejci8df109d2021-04-23 12:19:08 +0200582 LY_VALUE_FORMAT format = 0;
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100583 void *val_prefix_data = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200584
585 /* read count */
586 lyb_read(&count, 1, lybctx);
587
588 /* read attributes */
589 for (i = 0; i < count; ++i) {
Michal Vasko0fdcd242020-11-11 19:12:30 +0100590 /* prefix, may be empty */
aPieceke99345d2021-09-30 12:49:59 +0200591 ret = lyb_read_string(&prefix, sizeof(uint16_t), lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200592 LY_CHECK_GOTO(ret, cleanup);
593 if (!prefix[0]) {
594 free(prefix);
595 prefix = NULL;
596 }
597
598 /* namespace, may be empty */
aPieceke99345d2021-09-30 12:49:59 +0200599 ret = lyb_read_string(&module_name, sizeof(uint16_t), lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200600 LY_CHECK_GOTO(ret, cleanup);
Radek Krejci1798aae2020-07-14 13:26:06 +0200601 if (!module_name[0]) {
602 free(module_name);
603 module_name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200604 }
605
606 /* name */
aPieceke99345d2021-09-30 12:49:59 +0200607 ret = lyb_read_string(&name, sizeof(uint16_t), lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200608 LY_CHECK_GOTO(ret, cleanup);
609
Michal Vasko60ea6352020-06-29 13:39:39 +0200610 /* format */
Michal Vasko403beac2021-08-24 08:27:52 +0200611 lyb_read_number(&format, sizeof format, 1, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +0200612
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100613 /* value prefixes */
614 ret = lyb_parse_prefix_data(lybctx, format, &val_prefix_data);
615 LY_CHECK_GOTO(ret, cleanup);
616
Michal Vasko60ea6352020-06-29 13:39:39 +0200617 /* value */
aPieceke99345d2021-09-30 12:49:59 +0200618 ret = lyb_read_string(&value, sizeof(uint64_t), lybctx);
Michal Vasko6b5cb2a2020-11-11 19:11:21 +0100619 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +0200620 dynamic = 1;
621
622 /* attr2 is always changed to the created attribute */
Michal Vasko501af032020-11-11 20:27:44 +0100623 ret = lyd_create_attr(NULL, &attr2, lybctx->ctx, name, strlen(name), prefix, ly_strlen(prefix), module_name,
Michal Vaskobb512792021-07-01 13:12:49 +0200624 ly_strlen(module_name), value, ly_strlen(value), &dynamic, format, val_prefix_data, LYD_HINT_DATA);
Michal Vasko60ea6352020-06-29 13:39:39 +0200625 LY_CHECK_GOTO(ret, cleanup);
626
627 free(prefix);
628 prefix = NULL;
Radek Krejci1798aae2020-07-14 13:26:06 +0200629 free(module_name);
630 module_name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200631 free(name);
632 name = NULL;
Michal Vasko60ea6352020-06-29 13:39:39 +0200633 assert(!dynamic);
634 value = NULL;
635
636 if (!*attr) {
637 *attr = attr2;
638 }
639
Michal Vasko60ea6352020-06-29 13:39:39 +0200640 LY_CHECK_GOTO(ret, cleanup);
641 }
642
643cleanup:
644 free(prefix);
Radek Krejci1798aae2020-07-14 13:26:06 +0200645 free(module_name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200646 free(name);
647 if (dynamic) {
648 free(value);
649 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200650 if (ret) {
Radek Krejci011e4aa2020-09-04 15:22:31 +0200651 lyd_free_attr_siblings(lybctx->ctx, *attr);
Michal Vasko60ea6352020-06-29 13:39:39 +0200652 *attr = NULL;
653 }
654 return ret;
655}
656
657/**
aPiecek619350d2021-09-09 16:06:59 +0200658 * @brief Fill @p hash with hash values.
659 *
660 * @param[in] lybctx LYB context.
661 * @param[in,out] hash Pointer to the array in which the hash values are to be written.
662 * @param[out] hash_count Number of hashes in @p hash.
663 * @return LY_ERR value.
664 */
665static LY_ERR
666lyb_read_hashes(struct lylyb_ctx *lybctx, LYB_HASH *hash, uint8_t *hash_count)
667{
668 uint8_t i = 0, j;
669
670 /* read the first hash */
671 lyb_read(&hash[0], sizeof *hash, lybctx);
672
673 if (!hash[0]) {
674 *hash_count = i + 1;
675 return LY_SUCCESS;
676 }
677
678 /* based on the first hash read all the other ones, if any */
679 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
680 if (i > LYB_HASH_BITS) {
681 LOGINT_RET(lybctx->ctx);
682 }
683 }
684
685 /* move the first hash on its accurate position */
686 hash[i] = hash[0];
687
688 /* read the rest of hashes */
689 for (j = i; j; --j) {
690 lyb_read(&hash[j - 1], sizeof *hash, lybctx);
691
692 /* correct collision ID */
693 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
694 /* preceded with zeros */
695 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
696 }
697
698 *hash_count = i + 1;
699
700 return LY_SUCCESS;
701}
702
703/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200704 * @brief Check whether a schema node matches a hash(es).
705 *
706 * @param[in] sibling Schema node to check.
707 * @param[in] hash Hash array to check.
708 * @param[in] hash_count Number of hashes in @p hash.
709 * @return non-zero if matches,
710 * @return 0 if not.
711 */
712static int
713lyb_is_schema_hash_match(struct lysc_node *sibling, LYB_HASH *hash, uint8_t hash_count)
714{
715 LYB_HASH sibling_hash;
716 uint8_t i;
717
718 /* compare all the hashes starting from collision ID 0 */
719 for (i = 0; i < hash_count; ++i) {
Michal Vasko11f76c82021-04-15 14:36:14 +0200720 sibling_hash = lyb_get_hash(sibling, i);
Michal Vasko60ea6352020-06-29 13:39:39 +0200721 if (sibling_hash != hash[i]) {
722 return 0;
723 }
724 }
725
726 return 1;
727}
728
729/**
Michal Vasko60ea6352020-06-29 13:39:39 +0200730 * @brief Parse schema node hash.
731 *
732 * @param[in] lybctx LYB context.
733 * @param[in] sparent Schema parent, must be set if @p mod is not.
734 * @param[in] mod Module of the top-level node, must be set if @p sparent is not.
735 * @param[out] snode Parsed found schema node, may be NULL if opaque.
736 * @return LY_ERR value.
737 */
738static LY_ERR
739lyb_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 +0200740 const struct lysc_node **snode)
Michal Vasko60ea6352020-06-29 13:39:39 +0200741{
742 LY_ERR ret;
Michal Vasko60ea6352020-06-29 13:39:39 +0200743 const struct lysc_node *sibling;
744 LYB_HASH hash[LYB_HASH_BITS - 1];
Radek Krejci1deb5be2020-08-26 16:43:36 +0200745 uint32_t getnext_opts;
aPiecek619350d2021-09-09 16:06:59 +0200746 uint8_t hash_count;
Michal Vasko60ea6352020-06-29 13:39:39 +0200747
aPiecek570d7ed2021-09-10 07:15:35 +0200748 *snode = NULL;
749
aPiecek619350d2021-09-09 16:06:59 +0200750 ret = lyb_read_hashes(lybctx->lybctx, hash, &hash_count);
751 LY_CHECK_RET(ret);
Michal Vasko60ea6352020-06-29 13:39:39 +0200752
753 if (!hash[0]) {
754 /* opaque node */
755 return LY_SUCCESS;
756 }
757
aPiecek619350d2021-09-09 16:06:59 +0200758 getnext_opts = lybctx->int_opts & LYD_INTOPT_REPLY ? LYS_GETNEXT_OUTPUT : 0;
Michal Vasko60ea6352020-06-29 13:39:39 +0200759
760 /* find our node with matching hashes */
761 sibling = NULL;
Radek Krejcif16e2542021-02-17 15:39:23 +0100762 while (1) {
763 if (!sparent && lybctx->ext) {
764 sibling = lys_getnext_ext(sibling, sparent, lybctx->ext, getnext_opts);
765 } else {
766 sibling = lys_getnext(sibling, sparent, mod ? mod->compiled : NULL, getnext_opts);
767 }
768 if (!sibling) {
769 break;
770 }
Michal Vasko60ea6352020-06-29 13:39:39 +0200771 /* skip schema nodes from models not present during printing */
Michal Vasko9883a3e2022-03-31 12:16:00 +0200772 if (((sibling->module->ctx != lybctx->lybctx->ctx) || lyb_has_schema_model(sibling, lybctx->lybctx->models)) &&
aPiecek619350d2021-09-09 16:06:59 +0200773 lyb_is_schema_hash_match((struct lysc_node *)sibling, hash, hash_count)) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200774 /* match found */
775 break;
776 }
777 }
778
Michal Vaskoe0665742021-02-11 11:08:44 +0100779 if (!sibling && (lybctx->parse_opts & LYD_PARSE_STRICT)) {
Radek Krejcif16e2542021-02-17 15:39:23 +0100780 if (lybctx->ext) {
781 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a node from \"%s\" extension instance node.",
782 lybctx->ext->def->name);
783 } else if (mod) {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100784 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a top-level node"
Michal Vasko69730152020-10-09 16:30:07 +0200785 " from \"%s\".", mod->name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200786 } else {
Radek Krejci2efc45b2020-12-22 16:25:44 +0100787 LOGVAL(lybctx->lybctx->ctx, LYVE_REFERENCE, "Failed to find matching hash for a child node"
Michal Vasko69730152020-10-09 16:30:07 +0200788 " of \"%s\".", sparent->name);
Michal Vasko60ea6352020-06-29 13:39:39 +0200789 }
790 return LY_EVALID;
Radek Krejci1798aae2020-07-14 13:26:06 +0200791 } else if (sibling && (ret = lyd_parser_check_schema((struct lyd_ctx *)lybctx, sibling))) {
Michal Vasko60ea6352020-06-29 13:39:39 +0200792 return ret;
793 }
794
795 *snode = sibling;
796 return LY_SUCCESS;
797}
798
799/**
Michal Vasko9883a3e2022-03-31 12:16:00 +0200800 * @brief Parse schema node name of a nested extension data node.
801 *
802 * @param[in] lybctx LYB context.
803 * @param[in] parent Data parent.
804 * @param[in] mod_name Module name of the node.
805 * @param[out] snode Parsed found schema node of a nested extension.
806 * @return LY_ERR value.
807 */
808static LY_ERR
809lyb_parse_schema_nested_ext(struct lyd_lyb_ctx *lybctx, const struct lyd_node *parent, const char *mod_name,
810 const struct lysc_node **snode)
811{
812 LY_ERR rc = LY_SUCCESS, r;
813 char *name = NULL;
814 struct lysc_ext_instance *ext;
815
816 assert(parent);
817
818 /* read schema node name */
819 LY_CHECK_GOTO(rc = lyb_read_string(&name, sizeof(uint16_t), lybctx->lybctx), cleanup);
820
821 /* check for extension data */
822 r = ly_nested_ext_schema(parent, NULL, mod_name, mod_name ? strlen(mod_name) : 0, LY_VALUE_JSON, NULL, name,
823 strlen(name), snode, &ext);
824 if (r == LY_ENOT) {
825 /* failed to parse */
826 LOGERR(lybctx->lybctx->ctx, LY_EINVAL, "Failed to parse node \"%s\" as nested extension instance data.", name);
827 rc = LY_EINVAL;
828 goto cleanup;
829 } else if (r) {
830 /* error */
831 rc = r;
832 goto cleanup;
833 }
834
835 /* fill cached hashes in the module, it may be from a different context */
836 lyb_cache_module_hash((*snode)->module);
837
838cleanup:
839 free(name);
840 return rc;
841}
842
843/**
aPiecek570d7ed2021-09-10 07:15:35 +0200844 * @brief Read until the end of the current siblings.
Michal Vasko60ea6352020-06-29 13:39:39 +0200845 *
846 * @param[in] lybctx LYB context.
847 */
848static void
aPiecek570d7ed2021-09-10 07:15:35 +0200849lyb_skip_siblings(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +0200850{
Michal Vasko60ea6352020-06-29 13:39:39 +0200851 do {
852 /* first skip any meta information inside */
aPiecek570d7ed2021-09-10 07:15:35 +0200853 ly_in_skip(lybctx->in, LYB_LAST_SIBLING(lybctx).inner_chunks * LYB_META_BYTES);
Michal Vasko60ea6352020-06-29 13:39:39 +0200854
855 /* then read data */
aPiecek570d7ed2021-09-10 07:15:35 +0200856 lyb_read(NULL, LYB_LAST_SIBLING(lybctx).written, lybctx);
857 } while (LYB_LAST_SIBLING(lybctx).written);
Michal Vasko60ea6352020-06-29 13:39:39 +0200858}
859
860/**
Michal Vasko02ed9d82021-07-15 14:58:04 +0200861 * @brief Parse the context of anydata/anyxml node.
862 *
863 * @param[in] ctx libyang context.
864 * @param[in] data LYB data to parse.
865 * @param[out] tree Parsed tree.
866 * @return LY_ERR value.
867 */
868static LY_ERR
869lyb_parse_any_content(const struct ly_ctx *ctx, const char *data, struct lyd_node **tree)
870{
871 LY_ERR ret;
872 uint32_t prev_lo;
873 struct ly_in *in;
874 struct lyd_ctx *lydctx = NULL;
875
876 *tree = NULL;
877
878 LY_CHECK_RET(ly_in_new_memory(data, &in));
879
880 /* turn logging off */
881 prev_lo = ly_log_options(0);
882
Michal Vasko56d88602021-07-15 16:37:59 +0200883 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 +0200884 LYD_INTOPT_ANY | LYD_INTOPT_WITH_SIBLINGS, NULL, &lydctx);
885
886 /* turn logging on again */
887 ly_log_options(prev_lo);
888
889 ly_in_free(in, 0);
Michal Vasko1391e792021-08-23 12:15:44 +0200890 if (lydctx) {
891 lydctx->free(lydctx);
892 }
Michal Vasko02ed9d82021-07-15 14:58:04 +0200893 if (ret) {
894 lyd_free_siblings(*tree);
895 *tree = NULL;
896 }
897 return ret;
898}
899
900/**
aPiecek37c493b2021-09-09 12:52:30 +0200901 * @brief Insert new node to @p parsed set.
902 *
903 * Also if needed, correct @p first_p.
904 *
905 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +0200906 * @param[in] parent Data parent of the sibling, must be set if @p first_p is not.
aPiecek37c493b2021-09-09 12:52:30 +0200907 * @param[in,out] node Parsed node to insertion.
908 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
909 * @param[out] parsed Set of all successfully parsed nodes.
910 * @return LY_ERR value.
911 */
912static void
913lyb_insert_node(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node *node, struct lyd_node **first_p,
914 struct ly_set *parsed)
915{
916 /* insert, keep first pointer correct */
Michal Vasko9883a3e2022-03-31 12:16:00 +0200917 if (parent && (LYD_CTX(parent) != LYD_CTX(node))) {
Michal Vasko193dacd2022-10-13 08:43:05 +0200918 lyplg_ext_insert(parent, node);
Michal Vasko9883a3e2022-03-31 12:16:00 +0200919 } else {
920 lyd_insert_node(parent, first_p, node, lybctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0);
921 }
aPiecek37c493b2021-09-09 12:52:30 +0200922 while (!parent && (*first_p)->prev->next) {
923 *first_p = (*first_p)->prev;
924 }
925
926 /* rememeber a successfully parsed node */
927 if (parsed) {
928 ly_set_add(parsed, node, 1, NULL);
929 }
930}
931
932/**
933 * @brief Finish parsing the opaq node.
934 *
935 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +0200936 * @param[in] parent Data parent of the sibling, must be set if @p first_p is not.
aPiecek37c493b2021-09-09 12:52:30 +0200937 * @param[in] flags Node flags to set.
938 * @param[in,out] attr Attributes to be attached. Finally set to NULL.
939 * @param[in,out] node Parsed opaq node to finish.
940 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
941 * @param[out] parsed Set of all successfully parsed nodes.
942 * @return LY_ERR value.
943 */
944static void
945lyb_finish_opaq(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, uint32_t flags, struct lyd_attr **attr,
946 struct lyd_node **node, struct lyd_node **first_p, struct ly_set *parsed)
947{
948 struct lyd_attr *iter;
949
950 /* set flags */
951 (*node)->flags = flags;
952
953 /* add attributes */
954 assert(!(*node)->schema);
955 LY_LIST_FOR(*attr, iter) {
956 iter->parent = (struct lyd_node_opaq *)*node;
957 }
958 ((struct lyd_node_opaq *)*node)->attr = *attr;
959 *attr = NULL;
960
961 lyb_insert_node(lybctx, parent, *node, first_p, parsed);
962 *node = NULL;
963}
964
965/**
966 * @brief Finish parsing the node.
967 *
968 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +0200969 * @param[in] parent Data parent of the sibling, must be set if @p first_p is not.
aPiecek37c493b2021-09-09 12:52:30 +0200970 * @param[in] flags Node flags to set.
971 * @param[in,out] meta Metadata to be attached. Finally set to NULL.
972 * @param[in,out] node Parsed node to finish.
973 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
974 * @param[out] parsed Set of all successfully parsed nodes.
975 * @return LY_ERR value.
976 */
977static void
978lyb_finish_node(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, uint32_t flags, struct lyd_meta **meta,
979 struct lyd_node **node, struct lyd_node **first_p, struct ly_set *parsed)
980{
981 struct lyd_meta *m;
982
983 /* set flags */
984 (*node)->flags = flags;
985
986 /* add metadata */
987 LY_LIST_FOR(*meta, m) {
988 m->parent = *node;
989 }
990 (*node)->meta = *meta;
991 *meta = NULL;
992
Michal Vasko135719f2022-08-25 12:18:17 +0200993 /* insert into parent */
aPiecek37c493b2021-09-09 12:52:30 +0200994 lyb_insert_node(lybctx, parent, *node, first_p, parsed);
Michal Vasko135719f2022-08-25 12:18:17 +0200995
Michal Vaskoeba23112022-08-26 08:35:41 +0200996 if (!(lybctx->parse_opts & LYD_PARSE_ONLY)) {
997 /* store for ext instance node validation, if needed */
998 (void)lyd_validate_node_ext(*node, &lybctx->ext_node);
999 }
Michal Vasko135719f2022-08-25 12:18:17 +02001000
aPiecek37c493b2021-09-09 12:52:30 +02001001 *node = NULL;
1002}
1003
1004/**
aPiecek6fdac2f2021-09-10 11:21:10 +02001005 * @brief Parse header for non-opaq node.
1006 *
1007 * @param[in] lybctx LYB context.
Michal Vaskoddd76592022-01-17 13:34:48 +01001008 * @param[in] sparent Schema parent node of the metadata.
aPiecek6fdac2f2021-09-10 11:21:10 +02001009 * @param[out] flags Parsed node flags.
1010 * @param[out] meta Parsed metadata of the node.
1011 * @return LY_ERR value.
1012 */
1013static LY_ERR
Michal Vaskoddd76592022-01-17 13:34:48 +01001014lyb_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 +02001015{
1016 LY_ERR ret;
1017
1018 /* create and read metadata */
Michal Vaskoddd76592022-01-17 13:34:48 +01001019 ret = lyb_parse_metadata(lybctx, sparent, meta);
aPiecek6fdac2f2021-09-10 11:21:10 +02001020 LY_CHECK_RET(ret);
1021
1022 /* read flags */
1023 lyb_read_number(flags, sizeof *flags, sizeof *flags, lybctx->lybctx);
1024
1025 return ret;
1026}
1027
1028/**
aPiecek33fc6b02021-09-09 15:45:37 +02001029 * @brief Create term node and fill it with value.
1030 *
1031 * @param[in] lybctx LYB context.
1032 * @param[in] snode Schema of the term node.
1033 * @param[out] node Created term node.
1034 * @return LY_ERR value.
1035 */
1036static LY_ERR
1037lyb_create_term(struct lyd_lyb_ctx *lybctx, const struct lysc_node *snode, struct lyd_node **node)
1038{
1039 LY_ERR ret;
1040 ly_bool dynamic;
1041 uint8_t *term_value;
aPieceke99345d2021-09-30 12:49:59 +02001042 uint64_t term_value_len;
aPiecek33fc6b02021-09-09 15:45:37 +02001043
1044 ret = lyb_read_term_value((struct lysc_node_leaf *)snode, &term_value, &term_value_len, lybctx->lybctx);
1045 LY_CHECK_RET(ret);
1046
1047 dynamic = 1;
1048 /* create node */
1049 ret = lyd_parser_create_term((struct lyd_ctx *)lybctx, snode,
1050 term_value, term_value_len, &dynamic, LY_VALUE_LYB,
1051 NULL, LYD_HINT_DATA, node);
1052 if (dynamic) {
1053 free(term_value);
1054 }
1055 if (ret) {
1056 lyd_free_tree(*node);
1057 *node = NULL;
1058 }
1059
1060 return ret;
1061}
1062
1063/**
aPiecek0e2e1052021-09-09 15:48:27 +02001064 * @brief Validate inner node, autodelete default values nad create implicit nodes.
1065 *
1066 * @param[in,out] lybctx LYB context.
1067 * @param[in] snode Schema of the inner node.
1068 * @param[in] node Parsed inner node.
1069 * @return LY_ERR value.
1070 */
1071static LY_ERR
1072lyb_validate_node_inner(struct lyd_lyb_ctx *lybctx, const struct lysc_node *snode, struct lyd_node *node)
1073{
1074 LY_ERR ret = LY_SUCCESS;
1075 uint32_t impl_opts;
1076
1077 if (!(lybctx->parse_opts & LYD_PARSE_ONLY)) {
1078 /* new node validation, autodelete CANNOT occur, all nodes are new */
1079 ret = lyd_validate_new(lyd_node_child_p(node), snode, NULL, NULL);
1080 LY_CHECK_RET(ret);
1081
1082 /* add any missing default children */
1083 impl_opts = (lybctx->val_opts & LYD_VALIDATE_NO_STATE) ? LYD_IMPLICIT_NO_STATE : 0;
Michal Vaskoddd76592022-01-17 13:34:48 +01001084 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 +02001085 &lybctx->ext_node, impl_opts, NULL);
aPiecek0e2e1052021-09-09 15:48:27 +02001086 LY_CHECK_RET(ret);
1087 }
1088
1089 return ret;
1090}
1091
1092/**
aPiecek821cf732021-09-09 15:37:28 +02001093 * @brief Parse opaq node.
1094 *
1095 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +02001096 * @param[in] parent Data parent of the sibling.
aPiecek821cf732021-09-09 15:37:28 +02001097 * @param[in,out] first_p First top-level sibling.
1098 * @param[out] parsed Set of all successfully parsed nodes.
1099 * @return LY_ERR value.
1100 */
1101static LY_ERR
1102lyb_parse_node_opaq(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node **first_p, struct ly_set *parsed)
1103{
1104 LY_ERR ret;
1105 struct lyd_node *node = NULL;
1106 struct lyd_attr *attr = NULL;
1107 char *value = NULL, *name = NULL, *prefix = NULL, *module_key = NULL;
1108 ly_bool dynamic = 0;
1109 LY_VALUE_FORMAT format = 0;
1110 void *val_prefix_data = NULL;
1111 const struct ly_ctx *ctx = lybctx->lybctx->ctx;
1112 uint32_t flags;
1113
aPiecek821cf732021-09-09 15:37:28 +02001114 /* parse opaq node attributes */
1115 ret = lyb_parse_attributes(lybctx->lybctx, &attr);
1116 LY_CHECK_GOTO(ret, cleanup);
1117
1118 /* read flags */
1119 lyb_read_number(&flags, sizeof flags, sizeof flags, lybctx->lybctx);
1120
1121 /* parse prefix */
aPieceke99345d2021-09-30 12:49:59 +02001122 ret = lyb_read_string(&prefix, sizeof(uint16_t), lybctx->lybctx);
aPiecek821cf732021-09-09 15:37:28 +02001123 LY_CHECK_GOTO(ret, cleanup);
1124
1125 /* parse module key */
aPieceke99345d2021-09-30 12:49:59 +02001126 ret = lyb_read_string(&module_key, sizeof(uint16_t), lybctx->lybctx);
aPiecek821cf732021-09-09 15:37:28 +02001127 LY_CHECK_GOTO(ret, cleanup);
1128
1129 /* parse name */
aPieceke99345d2021-09-30 12:49:59 +02001130 ret = lyb_read_string(&name, sizeof(uint16_t), lybctx->lybctx);
aPiecek821cf732021-09-09 15:37:28 +02001131 LY_CHECK_GOTO(ret, cleanup);
1132
1133 /* parse value */
aPieceke99345d2021-09-30 12:49:59 +02001134 ret = lyb_read_string(&value, sizeof(uint64_t), lybctx->lybctx);
aPiecek821cf732021-09-09 15:37:28 +02001135 LY_CHECK_ERR_GOTO(ret, ly_free_prefix_data(format, val_prefix_data), cleanup);
1136 dynamic = 1;
1137
1138 /* parse format */
1139 lyb_read_number(&format, sizeof format, 1, lybctx->lybctx);
1140
1141 /* parse value prefixes */
1142 ret = lyb_parse_prefix_data(lybctx->lybctx, format, &val_prefix_data);
1143 LY_CHECK_GOTO(ret, cleanup);
1144
aPiecek570d7ed2021-09-10 07:15:35 +02001145 if (!(lybctx->parse_opts & LYD_PARSE_OPAQ)) {
Michal Vaskoefa96e62021-11-02 12:19:14 +01001146 /* skip children */
1147 ret = lyb_read_start_siblings(lybctx->lybctx);
1148 LY_CHECK_GOTO(ret, cleanup);
1149 lyb_skip_siblings(lybctx->lybctx);
1150 ret = lyb_read_stop_siblings(lybctx->lybctx);
1151 LY_CHECK_GOTO(ret, cleanup);
aPiecek570d7ed2021-09-10 07:15:35 +02001152 goto cleanup;
1153 }
1154
aPiecek821cf732021-09-09 15:37:28 +02001155 /* create node */
1156 ret = lyd_create_opaq(ctx, name, strlen(name), prefix, ly_strlen(prefix), module_key, ly_strlen(module_key),
1157 value, strlen(value), &dynamic, format, val_prefix_data, 0, &node);
1158 LY_CHECK_GOTO(ret, cleanup);
1159
1160 /* process children */
aPiecek570d7ed2021-09-10 07:15:35 +02001161 ret = lyb_parse_siblings(lybctx, node, NULL, NULL);
1162 LY_CHECK_GOTO(ret, cleanup);
aPiecek821cf732021-09-09 15:37:28 +02001163
1164 /* register parsed opaq node */
1165 lyb_finish_opaq(lybctx, parent, flags, &attr, &node, first_p, parsed);
1166 assert(!attr && !node);
1167
1168cleanup:
1169 free(prefix);
1170 free(module_key);
1171 free(name);
1172 if (dynamic) {
1173 free(value);
1174 }
1175 lyd_free_attr_siblings(ctx, attr);
1176 lyd_free_tree(node);
1177
1178 return ret;
1179}
1180
aPiecek18457d72021-09-09 15:52:20 +02001181/**
1182 * @brief Parse anydata or anyxml node.
1183 *
1184 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +02001185 * @param[in] parent Data parent of the sibling.
aPiecek18457d72021-09-09 15:52:20 +02001186 * @param[in] snode Schema of the node to be parsed.
1187 * @param[in,out] first_p First top-level sibling.
1188 * @param[out] parsed Set of all successfully parsed nodes.
1189 * @return LY_ERR value.
1190 */
1191static LY_ERR
1192lyb_parse_node_any(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const struct lysc_node *snode,
1193 struct lyd_node **first_p, struct ly_set *parsed)
1194{
1195 LY_ERR ret;
1196 struct lyd_node *node = NULL, *tree;
1197 struct lyd_meta *meta = NULL;
1198 LYD_ANYDATA_VALUETYPE value_type;
1199 char *value = NULL;
aPiecek18457d72021-09-09 15:52:20 +02001200 uint32_t flags;
1201 const struct ly_ctx *ctx = lybctx->lybctx->ctx;
1202
1203 /* read necessary basic data */
Michal Vaskoddd76592022-01-17 13:34:48 +01001204 ret = lyb_parse_node_header(lybctx, snode, &flags, &meta);
Michal Vaskoedd4f252021-09-23 08:37:40 +02001205 LY_CHECK_GOTO(ret, error);
aPiecek18457d72021-09-09 15:52:20 +02001206
1207 /* parse value type */
1208 lyb_read_number(&value_type, sizeof value_type, sizeof value_type, lybctx->lybctx);
1209 if (value_type == LYD_ANYDATA_DATATREE) {
1210 /* invalid situation */
1211 LOGINT(ctx);
1212 ret = LY_EINT;
1213 goto error;
1214 }
1215
1216 /* read anydata content */
aPieceke99345d2021-09-30 12:49:59 +02001217 ret = lyb_read_string(&value, sizeof(uint64_t), lybctx->lybctx);
aPiecek18457d72021-09-09 15:52:20 +02001218 LY_CHECK_GOTO(ret, error);
1219
1220 if (value_type == LYD_ANYDATA_LYB) {
1221 /* try to parse LYB into a data tree */
1222 if (!lyb_parse_any_content(ctx, value, &tree)) {
1223 /* successfully parsed */
1224 free(value);
1225 value = (char *)tree;
1226 value_type = LYD_ANYDATA_DATATREE;
1227 }
1228 }
1229
1230 /* create the node */
1231 switch (value_type) {
1232 case LYD_ANYDATA_LYB:
1233 case LYD_ANYDATA_DATATREE:
aPiecek18457d72021-09-09 15:52:20 +02001234 case LYD_ANYDATA_STRING:
1235 case LYD_ANYDATA_XML:
1236 case LYD_ANYDATA_JSON:
Michal Vasko742a5b12022-02-24 16:07:27 +01001237 /* use the value directly */
1238 ret = lyd_create_any(snode, value, value_type, 1, &node);
aPiecek18457d72021-09-09 15:52:20 +02001239 LY_CHECK_GOTO(ret, error);
aPiecek18457d72021-09-09 15:52:20 +02001240 break;
1241 default:
1242 LOGINT(ctx);
1243 ret = LY_EINT;
1244 goto error;
1245 }
1246
1247 /* register parsed anydata node */
1248 lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);
1249
1250 return LY_SUCCESS;
1251
1252error:
1253 free(value);
1254 lyd_free_meta_siblings(meta);
1255 lyd_free_tree(node);
1256 return ret;
1257}
aPiecek821cf732021-09-09 15:37:28 +02001258
1259/**
aPiecek5777f122021-09-10 10:26:23 +02001260 * @brief Parse inner node.
aPiecek37c493b2021-09-09 12:52:30 +02001261 *
1262 * @param[in] lybctx LYB context.
aPiecek570d7ed2021-09-10 07:15:35 +02001263 * @param[in] parent Data parent of the sibling, must be set if @p first is not.
1264 * @param[in] snode Schema of the node to be parsed.
aPiecekfc7cf7e2021-09-09 11:20:27 +02001265 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
1266 * @param[out] parsed Set of all successfully parsed nodes.
Michal Vasko60ea6352020-06-29 13:39:39 +02001267 * @return LY_ERR value.
1268 */
1269static LY_ERR
aPiecek5777f122021-09-10 10:26:23 +02001270lyb_parse_node_inner(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const struct lysc_node *snode,
aPiecek570d7ed2021-09-10 07:15:35 +02001271 struct lyd_node **first_p, struct ly_set *parsed)
Michal Vasko60ea6352020-06-29 13:39:39 +02001272{
1273 LY_ERR ret = LY_SUCCESS;
aPiecek18457d72021-09-09 15:52:20 +02001274 struct lyd_node *node = NULL;
aPiecek37c493b2021-09-09 12:52:30 +02001275 struct lyd_meta *meta = NULL;
aPiecek33fc6b02021-09-09 15:45:37 +02001276 uint32_t flags;
Michal Vasko60ea6352020-06-29 13:39:39 +02001277
aPiecek307f0772021-09-10 09:09:47 +02001278 /* read necessary basic data */
Michal Vaskoddd76592022-01-17 13:34:48 +01001279 ret = lyb_parse_node_header(lybctx, snode, &flags, &meta);
aPiecek307f0772021-09-10 09:09:47 +02001280 LY_CHECK_GOTO(ret, error);
aPiecek37c493b2021-09-09 12:52:30 +02001281
aPiecek5777f122021-09-10 10:26:23 +02001282 /* create node */
1283 ret = lyd_create_inner(snode, &node);
1284 LY_CHECK_GOTO(ret, error);
Michal Vasko60ea6352020-06-29 13:39:39 +02001285
aPiecek5777f122021-09-10 10:26:23 +02001286 /* process children */
1287 ret = lyb_parse_siblings(lybctx, node, NULL, NULL);
1288 LY_CHECK_GOTO(ret, error);
Michal Vasko60ea6352020-06-29 13:39:39 +02001289
aPiecek5777f122021-09-10 10:26:23 +02001290 /* additional procedure for inner node */
1291 ret = lyb_validate_node_inner(lybctx, snode, node);
1292 LY_CHECK_GOTO(ret, error);
Michal Vasko60ea6352020-06-29 13:39:39 +02001293
aPiecek5777f122021-09-10 10:26:23 +02001294 if (snode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1295 /* rememeber the RPC/action/notification */
1296 lybctx->op_node = node;
Michal Vasko60ea6352020-06-29 13:39:39 +02001297 }
1298
aPiecek307f0772021-09-10 09:09:47 +02001299 /* register parsed node */
1300 lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);
1301
1302 return LY_SUCCESS;
1303
1304error:
Michal Vasko3a41dff2020-07-15 14:30:28 +02001305 lyd_free_meta_siblings(meta);
Michal Vasko60ea6352020-06-29 13:39:39 +02001306 lyd_free_tree(node);
1307 return ret;
1308}
1309
1310/**
aPiecek8a555d72021-09-10 10:15:26 +02001311 * @brief Parse leaf node.
1312 *
1313 * @param[in] lybctx LYB context.
1314 * @param[in] parent Data parent of the sibling.
1315 * @param[in] snode Schema of the node to be parsed.
1316 * @param[in,out] first_p First top-level sibling.
1317 * @param[out] parsed Set of all successfully parsed nodes.
1318 * @return LY_ERR value.
1319 */
1320static LY_ERR
1321lyb_parse_node_leaf(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const struct lysc_node *snode,
1322 struct lyd_node **first_p, struct ly_set *parsed)
1323{
1324 LY_ERR ret;
1325 struct lyd_node *node = NULL;
1326 struct lyd_meta *meta = NULL;
1327 uint32_t flags;
1328
1329 /* read necessary basic data */
Michal Vaskoddd76592022-01-17 13:34:48 +01001330 ret = lyb_parse_node_header(lybctx, snode, &flags, &meta);
aPiecek8a555d72021-09-10 10:15:26 +02001331 LY_CHECK_GOTO(ret, error);
1332
1333 /* read value of term node and create it */
1334 ret = lyb_create_term(lybctx, snode, &node);
1335 LY_CHECK_GOTO(ret, error);
1336
1337 lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);
1338
1339 return LY_SUCCESS;
1340
1341error:
1342 lyd_free_meta_siblings(meta);
1343 lyd_free_tree(node);
1344 return ret;
1345}
1346
1347/**
aPiecek5777f122021-09-10 10:26:23 +02001348 * @brief Parse all leaflist nodes which belong to same schema.
1349 *
1350 * @param[in] lybctx LYB context.
1351 * @param[in] parent Data parent of the sibling.
1352 * @param[in] snode Schema of the nodes to be parsed.
1353 * @param[in,out] first_p First top-level sibling.
1354 * @param[out] parsed Set of all successfully parsed nodes.
1355 * @return LY_ERR value.
1356 */
1357static LY_ERR
1358lyb_parse_node_leaflist(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const struct lysc_node *snode,
1359 struct lyd_node **first_p, struct ly_set *parsed)
1360{
1361 LY_ERR ret;
1362
1363 /* register a new sibling */
1364 ret = lyb_read_start_siblings(lybctx->lybctx);
1365 LY_CHECK_RET(ret);
1366
1367 /* process all siblings */
1368 while (LYB_LAST_SIBLING(lybctx->lybctx).written) {
1369 ret = lyb_parse_node_leaf(lybctx, parent, snode, first_p, parsed);
1370 LY_CHECK_RET(ret);
1371 }
1372
1373 /* end the sibling */
1374 ret = lyb_read_stop_siblings(lybctx->lybctx);
1375 LY_CHECK_RET(ret);
1376
1377 return ret;
1378}
1379
1380/**
aPiecek77d3e962021-09-10 10:33:59 +02001381 * @brief Parse all list nodes which belong to same schema.
1382 *
1383 * @param[in] lybctx LYB context.
1384 * @param[in] parent Data parent of the sibling.
1385 * @param[in] snode Schema of the nodes to be parsed.
1386 * @param[in,out] first_p First top-level sibling.
1387 * @param[out] parsed Set of all successfully parsed nodes.
1388 * @return LY_ERR value.
1389 */
1390static LY_ERR
1391lyb_parse_node_list(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const struct lysc_node *snode,
1392 struct lyd_node **first_p, struct ly_set *parsed)
1393{
1394 LY_ERR ret;
1395 struct lyd_node *node = NULL;
1396 struct lyd_meta *meta = NULL;
1397 uint32_t flags;
1398
1399 /* register a new sibling */
1400 ret = lyb_read_start_siblings(lybctx->lybctx);
1401 LY_CHECK_RET(ret);
1402
1403 while (LYB_LAST_SIBLING(lybctx->lybctx).written) {
1404 /* read necessary basic data */
Michal Vaskoddd76592022-01-17 13:34:48 +01001405 ret = lyb_parse_node_header(lybctx, snode, &flags, &meta);
Michal Vaskoedd4f252021-09-23 08:37:40 +02001406 LY_CHECK_GOTO(ret, error);
aPiecek77d3e962021-09-10 10:33:59 +02001407
1408 /* create list node */
1409 ret = lyd_create_inner(snode, &node);
1410 LY_CHECK_GOTO(ret, error);
1411
1412 /* process children */
1413 ret = lyb_parse_siblings(lybctx, node, NULL, NULL);
1414 LY_CHECK_GOTO(ret, error);
1415
1416 /* additional procedure for inner node */
1417 ret = lyb_validate_node_inner(lybctx, snode, node);
1418 LY_CHECK_GOTO(ret, error);
1419
1420 if (snode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1421 /* rememeber the RPC/action/notification */
1422 lybctx->op_node = node;
1423 }
1424
1425 /* register parsed list node */
1426 lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);
1427 }
1428
1429 /* end the sibling */
1430 ret = lyb_read_stop_siblings(lybctx->lybctx);
1431 LY_CHECK_RET(ret);
1432
1433 return LY_SUCCESS;
1434
1435error:
1436 lyd_free_meta_siblings(meta);
1437 lyd_free_tree(node);
1438 return ret;
1439}
1440
1441/**
Michal Vasko9883a3e2022-03-31 12:16:00 +02001442 * @brief Parse a node.
aPiecek17737b52021-09-21 12:29:52 +02001443 *
aPiecek17737b52021-09-21 12:29:52 +02001444 * @param[in] lybctx LYB context.
Michal Vasko9883a3e2022-03-31 12:16:00 +02001445 * @param[in] parent Data parent of the sibling, must be set if @p first_p is not.
1446 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
1447 * @param[in,out] parsed Set of all successfully parsed nodes to add to.
aPiecek17737b52021-09-21 12:29:52 +02001448 * @return LY_ERR value.
1449 */
1450static LY_ERR
1451lyb_parse_node(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node **first_p,
1452 struct ly_set *parsed)
1453{
1454 LY_ERR ret;
1455 const struct lysc_node *snode;
1456 const struct lys_module *mod;
Michal Vasko9883a3e2022-03-31 12:16:00 +02001457 enum lylyb_node_type lyb_type;
1458 char *mod_name = NULL, mod_rev[LY_REV_SIZE];
aPiecek17737b52021-09-21 12:29:52 +02001459
Michal Vasko9883a3e2022-03-31 12:16:00 +02001460 /* read node type */
1461 lyb_read_number(&lyb_type, sizeof lyb_type, 1, lybctx->lybctx);
1462
1463 switch (lyb_type) {
1464 case LYB_NODE_TOP:
1465 /* top-level, read module name */
1466 LY_CHECK_GOTO(ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_opts, &mod), cleanup);
aPiecek17737b52021-09-21 12:29:52 +02001467
1468 /* read hash, find the schema node starting from mod */
Michal Vasko9883a3e2022-03-31 12:16:00 +02001469 LY_CHECK_GOTO(ret = lyb_parse_schema_hash(lybctx, NULL, mod, &snode), cleanup);
1470 break;
1471 case LYB_NODE_CHILD:
1472 case LYB_NODE_OPAQ:
1473 /* read hash, find the schema node starting from parent schema, if any */
1474 LY_CHECK_GOTO(ret = lyb_parse_schema_hash(lybctx, parent ? parent->schema : NULL, NULL, &snode), cleanup);
1475 break;
1476 case LYB_NODE_EXT:
1477 /* ext, read module name */
1478 LY_CHECK_GOTO(ret = lyb_read_model(lybctx->lybctx, &mod_name, mod_rev), cleanup);
1479
1480 /* read schema node name, find the nexted ext schema node */
1481 LY_CHECK_GOTO(ret = lyb_parse_schema_nested_ext(lybctx, parent, mod_name, &snode), cleanup);
1482 break;
aPiecek17737b52021-09-21 12:29:52 +02001483 }
aPiecek17737b52021-09-21 12:29:52 +02001484
1485 if (!snode) {
1486 ret = lyb_parse_node_opaq(lybctx, parent, first_p, parsed);
1487 } else if (snode->nodetype & LYS_LEAFLIST) {
1488 ret = lyb_parse_node_leaflist(lybctx, parent, snode, first_p, parsed);
1489 } else if (snode->nodetype == LYS_LIST) {
1490 ret = lyb_parse_node_list(lybctx, parent, snode, first_p, parsed);
1491 } else if (snode->nodetype & LYD_NODE_ANY) {
1492 ret = lyb_parse_node_any(lybctx, parent, snode, first_p, parsed);
1493 } else if (snode->nodetype & LYD_NODE_INNER) {
1494 ret = lyb_parse_node_inner(lybctx, parent, snode, first_p, parsed);
1495 } else {
1496 ret = lyb_parse_node_leaf(lybctx, parent, snode, first_p, parsed);
1497 }
Michal Vasko9883a3e2022-03-31 12:16:00 +02001498 LY_CHECK_GOTO(ret, cleanup);
aPiecek17737b52021-09-21 12:29:52 +02001499
Michal Vasko9883a3e2022-03-31 12:16:00 +02001500cleanup:
1501 free(mod_name);
aPiecek17737b52021-09-21 12:29:52 +02001502 return ret;
1503}
1504
1505/**
aPiecek570d7ed2021-09-10 07:15:35 +02001506 * @brief Parse siblings (@ref lyb_print_siblings()).
1507 *
1508 * @param[in] lybctx LYB context.
1509 * @param[in] parent Data parent of the sibling, must be set if @p first_p is not.
1510 * @param[in,out] first_p First top-level sibling, must be set if @p parent is not.
1511 * @param[out] parsed Set of all successfully parsed nodes.
1512 * @return LY_ERR value.
1513 */
1514static LY_ERR
1515lyb_parse_siblings(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_node **first_p,
1516 struct ly_set *parsed)
1517{
aPiecek570d7ed2021-09-10 07:15:35 +02001518 ly_bool top_level;
aPiecek570d7ed2021-09-10 07:15:35 +02001519
1520 top_level = !LY_ARRAY_COUNT(lybctx->lybctx->siblings);
1521
1522 /* register a new siblings */
Michal Vasko9883a3e2022-03-31 12:16:00 +02001523 LY_CHECK_RET(lyb_read_start_siblings(lybctx->lybctx));
aPiecek570d7ed2021-09-10 07:15:35 +02001524
1525 while (LYB_LAST_SIBLING(lybctx->lybctx).written) {
Michal Vasko9883a3e2022-03-31 12:16:00 +02001526 LY_CHECK_RET(lyb_parse_node(lybctx, parent, first_p, parsed));
aPiecek570d7ed2021-09-10 07:15:35 +02001527
1528 if (top_level && !(lybctx->int_opts & LYD_INTOPT_WITH_SIBLINGS)) {
1529 break;
1530 }
1531 }
1532
1533 /* end the siblings */
Michal Vasko9883a3e2022-03-31 12:16:00 +02001534 LY_CHECK_RET(lyb_read_stop_siblings(lybctx->lybctx));
aPiecek570d7ed2021-09-10 07:15:35 +02001535
Michal Vasko9883a3e2022-03-31 12:16:00 +02001536 return LY_SUCCESS;
aPiecek570d7ed2021-09-10 07:15:35 +02001537}
1538
1539/**
Michal Vasko60ea6352020-06-29 13:39:39 +02001540 * @brief Parse used YANG data models.
1541 *
1542 * @param[in] lybctx LYB context.
aPiecekfc7cf7e2021-09-09 11:20:27 +02001543 * @param[in] parse_options Flag with options for parsing.
Michal Vasko60ea6352020-06-29 13:39:39 +02001544 * @return LY_ERR value.
1545 */
1546static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001547lyb_parse_data_models(struct lylyb_ctx *lybctx, uint32_t parse_options)
Michal Vasko60ea6352020-06-29 13:39:39 +02001548{
1549 LY_ERR ret;
1550 uint32_t count;
Michal Vaskofd69e1d2020-07-03 11:57:17 +02001551 LY_ARRAY_COUNT_TYPE u;
Michal Vasko60ea6352020-06-29 13:39:39 +02001552
1553 /* read model count */
1554 lyb_read_number(&count, sizeof count, 2, lybctx);
1555
1556 if (count) {
1557 LY_ARRAY_CREATE_RET(lybctx->ctx, lybctx->models, count, LY_EMEM);
1558
1559 /* read modules */
1560 for (u = 0; u < count; ++u) {
Radek Krejci1798aae2020-07-14 13:26:06 +02001561 ret = lyb_parse_model(lybctx, parse_options, &lybctx->models[u]);
Michal Vasko60ea6352020-06-29 13:39:39 +02001562 LY_CHECK_RET(ret);
1563 LY_ARRAY_INCREMENT(lybctx->models);
1564 }
1565 }
1566
1567 return LY_SUCCESS;
1568}
1569
1570/**
1571 * @brief Parse LYB magic number.
1572 *
1573 * @param[in] lybctx LYB context.
1574 * @return LY_ERR value.
1575 */
1576static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001577lyb_parse_magic_number(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001578{
1579 char magic_byte = 0;
1580
1581 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1582 if (magic_byte != 'l') {
1583 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
1584 return LY_EINVAL;
1585 }
1586
1587 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1588 if (magic_byte != 'y') {
1589 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
1590 return LY_EINVAL;
1591 }
1592
1593 lyb_read((uint8_t *)&magic_byte, 1, lybctx);
1594 if (magic_byte != 'b') {
1595 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
1596 return LY_EINVAL;
1597 }
1598
1599 return LY_SUCCESS;
1600}
1601
1602/**
1603 * @brief Parse LYB header.
1604 *
1605 * @param[in] lybctx LYB context.
1606 * @return LY_ERR value.
1607 */
1608static LY_ERR
Radek Krejci1798aae2020-07-14 13:26:06 +02001609lyb_parse_header(struct lylyb_ctx *lybctx)
Michal Vasko60ea6352020-06-29 13:39:39 +02001610{
1611 uint8_t byte = 0;
1612
1613 /* version, future flags */
1614 lyb_read((uint8_t *)&byte, sizeof byte, lybctx);
1615
1616 if ((byte & LYB_VERSION_MASK) != LYB_VERSION_NUM) {
1617 LOGERR(lybctx->ctx, LY_EINVAL, "Invalid LYB format version \"0x%02x\", expected \"0x%02x\".",
Michal Vasko69730152020-10-09 16:30:07 +02001618 byte & LYB_VERSION_MASK, LYB_VERSION_NUM);
Michal Vasko60ea6352020-06-29 13:39:39 +02001619 return LY_EINVAL;
1620 }
1621
1622 return LY_SUCCESS;
1623}
1624
Michal Vasko02ed9d82021-07-15 14:58:04 +02001625static LY_ERR
1626_lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1627 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 +01001628 struct ly_set *parsed, struct lyd_ctx **lydctx_p)
Michal Vasko60ea6352020-06-29 13:39:39 +02001629{
Michal Vaskoe0665742021-02-11 11:08:44 +01001630 LY_ERR rc = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001631 struct lyd_lyb_ctx *lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001632
Michal Vaskoe0665742021-02-11 11:08:44 +01001633 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1634 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
Radek Krejci7931b192020-06-25 17:05:03 +02001635
Radek Krejci1798aae2020-07-14 13:26:06 +02001636 lybctx = calloc(1, sizeof *lybctx);
1637 LY_CHECK_ERR_RET(!lybctx, LOGMEM(ctx), LY_EMEM);
1638 lybctx->lybctx = calloc(1, sizeof *lybctx->lybctx);
Michal Vaskoe0665742021-02-11 11:08:44 +01001639 LY_CHECK_ERR_GOTO(!lybctx->lybctx, LOGMEM(ctx); rc = LY_EMEM, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001640
Radek Krejci1798aae2020-07-14 13:26:06 +02001641 lybctx->lybctx->in = in;
1642 lybctx->lybctx->ctx = ctx;
Michal Vaskoe0665742021-02-11 11:08:44 +01001643 lybctx->parse_opts = parse_opts;
1644 lybctx->val_opts = val_opts;
Michal Vaskoe0665742021-02-11 11:08:44 +01001645 lybctx->int_opts = int_opts;
Michal Vasko02ed9d82021-07-15 14:58:04 +02001646 lybctx->free = lyd_lyb_ctx_free;
Radek Krejcif16e2542021-02-17 15:39:23 +01001647 lybctx->ext = ext;
Michal Vaskoe0665742021-02-11 11:08:44 +01001648
1649 /* find the operation node if it exists already */
1650 LY_CHECK_GOTO(rc = lyd_parser_find_operation(parent, int_opts, &lybctx->op_node), cleanup);
1651
Michal Vasko60ea6352020-06-29 13:39:39 +02001652 /* read magic number */
Michal Vaskoe0665742021-02-11 11:08:44 +01001653 rc = lyb_parse_magic_number(lybctx->lybctx);
1654 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001655
1656 /* read header */
Michal Vaskoe0665742021-02-11 11:08:44 +01001657 rc = lyb_parse_header(lybctx->lybctx);
1658 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001659
1660 /* read used models */
Michal Vaskoe0665742021-02-11 11:08:44 +01001661 rc = lyb_parse_data_models(lybctx->lybctx, lybctx->parse_opts);
1662 LY_CHECK_GOTO(rc, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001663
aPiecek570d7ed2021-09-10 07:15:35 +02001664 /* read sibling(s) */
1665 rc = lyb_parse_siblings(lybctx, parent, first_p, parsed);
1666 LY_CHECK_GOTO(rc, cleanup);
Michal Vaskoe0665742021-02-11 11:08:44 +01001667
1668 if ((int_opts & LYD_INTOPT_NO_SIBLINGS) && lybctx->lybctx->in->current[0]) {
1669 LOGVAL(ctx, LYVE_SYNTAX, "Unexpected sibling node.");
1670 rc = LY_EVALID;
1671 goto cleanup;
1672 }
1673 if ((int_opts & (LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NOTIF | LYD_INTOPT_REPLY)) && !lybctx->op_node) {
1674 LOGVAL(ctx, LYVE_DATA, "Missing the operation node.");
1675 rc = LY_EVALID;
1676 goto cleanup;
Michal Vasko60ea6352020-06-29 13:39:39 +02001677 }
1678
1679 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001680 ly_in_skip(lybctx->lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001681
Michal Vasko60ea6352020-06-29 13:39:39 +02001682cleanup:
Michal Vaskoe0665742021-02-11 11:08:44 +01001683 /* there should be no unres stored if validation should be skipped */
1684 assert(!(parse_opts & LYD_PARSE_ONLY) || (!lybctx->node_types.count && !lybctx->meta_types.count &&
1685 !lybctx->node_when.count));
1686
1687 if (rc) {
Radek Krejci1798aae2020-07-14 13:26:06 +02001688 lyd_lyb_ctx_free((struct lyd_ctx *)lybctx);
Radek Krejci1798aae2020-07-14 13:26:06 +02001689 } else {
Michal Vaskoe0665742021-02-11 11:08:44 +01001690 *lydctx_p = (struct lyd_ctx *)lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001691 }
Michal Vaskoe0665742021-02-11 11:08:44 +01001692 return rc;
Michal Vasko60ea6352020-06-29 13:39:39 +02001693}
1694
Michal Vasko02ed9d82021-07-15 14:58:04 +02001695LY_ERR
1696lyd_parse_lyb(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct lyd_node *parent,
1697 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 +01001698 struct ly_set *parsed, ly_bool *subtree_sibling, struct lyd_ctx **lydctx_p)
Michal Vasko02ed9d82021-07-15 14:58:04 +02001699{
1700 uint32_t int_opts;
1701
1702 assert(!(parse_opts & ~LYD_PARSE_OPTS_MASK));
1703 assert(!(val_opts & ~LYD_VALIDATE_OPTS_MASK));
1704
Michal Vaskoddd76592022-01-17 13:34:48 +01001705 LY_CHECK_ARG_RET(ctx, !(parse_opts & LYD_PARSE_SUBTREE), LY_EINVAL);
1706
Michal Vasko02ed9d82021-07-15 14:58:04 +02001707 switch (data_type) {
1708 case LYD_TYPE_DATA_YANG:
1709 int_opts = LYD_INTOPT_WITH_SIBLINGS;
1710 break;
1711 case LYD_TYPE_RPC_YANG:
1712 int_opts = LYD_INTOPT_RPC | LYD_INTOPT_ACTION | LYD_INTOPT_NO_SIBLINGS;
1713 break;
1714 case LYD_TYPE_NOTIF_YANG:
1715 int_opts = LYD_INTOPT_NOTIF | LYD_INTOPT_NO_SIBLINGS;
1716 break;
1717 case LYD_TYPE_REPLY_YANG:
1718 int_opts = LYD_INTOPT_REPLY | LYD_INTOPT_NO_SIBLINGS;
1719 break;
1720 default:
1721 LOGINT(ctx);
1722 return LY_EINT;
1723 }
1724
Michal Vaskoddd76592022-01-17 13:34:48 +01001725 if (subtree_sibling) {
1726 *subtree_sibling = 0;
1727 }
Michal Vasko02ed9d82021-07-15 14:58:04 +02001728 return _lyd_parse_lyb(ctx, ext, parent, first_p, in, parse_opts, val_opts, int_opts, parsed, lydctx_p);
1729}
1730
Jan Kundrátc53a7ec2021-12-09 16:01:19 +01001731LIBYANG_API_DEF int
Michal Vasko60ea6352020-06-29 13:39:39 +02001732lyd_lyb_data_length(const char *data)
1733{
1734 LY_ERR ret = LY_SUCCESS;
Radek Krejci1798aae2020-07-14 13:26:06 +02001735 struct lylyb_ctx *lybctx;
Michal Vasko60ea6352020-06-29 13:39:39 +02001736 int count, i;
1737 size_t len;
1738 uint8_t buf[LYB_SIZE_MAX];
aPiecek6828a312021-09-17 15:53:18 +02001739 uint8_t zero[LYB_SIZE_BYTES] = {0};
Michal Vasko60ea6352020-06-29 13:39:39 +02001740
1741 if (!data) {
1742 return -1;
1743 }
1744
Radek Krejci1798aae2020-07-14 13:26:06 +02001745 lybctx = calloc(1, sizeof *lybctx);
1746 LY_CHECK_ERR_RET(!lybctx, LOGMEM(NULL), LY_EMEM);
1747 ret = ly_in_new_memory(data, &lybctx->in);
Michal Vasko63f3d842020-07-08 10:10:14 +02001748 LY_CHECK_GOTO(ret, cleanup);
Michal Vasko60ea6352020-06-29 13:39:39 +02001749
1750 /* read magic number */
Radek Krejci1798aae2020-07-14 13:26:06 +02001751 ret = lyb_parse_magic_number(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001752 LY_CHECK_GOTO(ret, cleanup);
1753
1754 /* read header */
Radek Krejci1798aae2020-07-14 13:26:06 +02001755 ret = lyb_parse_header(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001756 LY_CHECK_GOTO(ret, cleanup);
1757
1758 /* read model count */
Radek Krejci1798aae2020-07-14 13:26:06 +02001759 lyb_read_number(&count, sizeof count, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001760
1761 /* read all models */
1762 for (i = 0; i < count; ++i) {
1763 /* module name length */
1764 len = 0;
Radek Krejci1798aae2020-07-14 13:26:06 +02001765 lyb_read_number(&len, sizeof len, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001766
1767 /* model name */
Radek Krejci1798aae2020-07-14 13:26:06 +02001768 lyb_read(buf, len, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001769
1770 /* revision */
Radek Krejci1798aae2020-07-14 13:26:06 +02001771 lyb_read(buf, 2, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001772 }
1773
aPiecek6828a312021-09-17 15:53:18 +02001774 if (memcmp(zero, lybctx->in->current, LYB_SIZE_BYTES)) {
aPiecek570d7ed2021-09-10 07:15:35 +02001775 /* register a new sibling */
1776 ret = lyb_read_start_siblings(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001777 LY_CHECK_GOTO(ret, cleanup);
1778
1779 /* skip it */
aPiecek570d7ed2021-09-10 07:15:35 +02001780 lyb_skip_siblings(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001781
aPiecek570d7ed2021-09-10 07:15:35 +02001782 /* sibling finished */
1783 ret = lyb_read_stop_siblings(lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001784 LY_CHECK_GOTO(ret, cleanup);
aPiecek570d7ed2021-09-10 07:15:35 +02001785 } else {
aPiecek6828a312021-09-17 15:53:18 +02001786 lyb_read(NULL, LYB_SIZE_BYTES, lybctx);
Michal Vasko60ea6352020-06-29 13:39:39 +02001787 }
1788
1789 /* read the last zero, parsing finished */
Radek Krejci1798aae2020-07-14 13:26:06 +02001790 ly_in_skip(lybctx->in, 1);
Michal Vasko60ea6352020-06-29 13:39:39 +02001791
1792cleanup:
Radek Krejci1798aae2020-07-14 13:26:06 +02001793 count = lybctx->in->current - lybctx->in->start;
Michal Vasko63f3d842020-07-08 10:10:14 +02001794
Radek Krejci1798aae2020-07-14 13:26:06 +02001795 ly_in_free(lybctx->in, 0);
1796 lylyb_ctx_free(lybctx);
1797
Michal Vasko63f3d842020-07-08 10:10:14 +02001798 return ret ? -1 : count;
Michal Vasko60ea6352020-06-29 13:39:39 +02001799}