blob: 265f8efd095f9a93831a2d9347dd30b2df9e71cd [file] [log] [blame]
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001/**
2 * @file parser_lyb.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief LYB data parser for libyang
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#include <assert.h>
16#include <errno.h>
17#include <stdlib.h>
18#include <string.h>
Michal Vaskoe581e982018-08-21 12:26:55 +020019#include <inttypes.h>
Michal Vasko6b69e4b2018-10-17 12:07:27 +020020#ifdef __APPLE__
Michal Vaskob27fb152018-10-17 12:54:47 +020021# include <libkern/OSByteOrder.h>
22
23# define le16toh(x) OSSwapLittleToHostInt16(x)
24# define le32toh(x) OSSwapLittleToHostInt32(x)
25# define le64toh(x) OSSwapLittleToHostInt64(x)
Martin Winter9b14f182019-01-28 12:30:24 -080026#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
27# include <sys/endian.h>
David Lamparterbd4c4ff2019-01-29 18:19:31 +010028#elif defined(__sun__)
29# include <endian.h>
30# include <sys/byteorder.h>
31# if defined(_BIG_ENDIAN)
32# define le16toh(x) BSWAP_16(x)
33# define le32toh(x) BSWAP_32(x)
34# define le64toh(x) BSWAP_64(x)
35# define htole64(x) le64toh(x)
36# define htole32(x) le32toh(x)
37# define htole16(x) le16toh(x)
38# else
39# define le16toh(x) (x)
40# define le32toh(x) (x)
41# define le64toh(x) (x)
42# define htole64(x) (x)
43# define htole32(x) (x)
44# define htole16(x) (x)
45# endif
Michal Vasko6b69e4b2018-10-17 12:07:27 +020046#else
Michal Vaskob27fb152018-10-17 12:54:47 +020047# include <endian.h>
Michal Vasko6b69e4b2018-10-17 12:07:27 +020048#endif
Michal Vasko1e82a3b2018-07-03 12:16:58 +020049
50#include "libyang.h"
51#include "common.h"
52#include "context.h"
53#include "parser.h"
54#include "tree_internal.h"
55
56#define LYB_HAVE_READ_GOTO(r, d, go) if (r < 0) goto go; d += r;
57#define LYB_HAVE_READ_RETURN(r, d, ret) if (r < 0) return ret; d += r;
58
59static int
60lyb_read(const char *data, uint8_t *buf, size_t count, struct lyb_state *lybs)
61{
62 int ret = 0, i, empty_chunk_i;
63 size_t to_read;
Graeme Campbell856a40e2018-10-05 14:35:37 +130064 uint8_t meta_buf[LYB_META_BYTES];
Michal Vasko1e82a3b2018-07-03 12:16:58 +020065
66 assert(data && lybs);
67
68 while (1) {
69 /* check for fully-read (empty) data chunks */
70 to_read = count;
71 empty_chunk_i = -1;
72 for (i = 0; i < lybs->used; ++i) {
73 /* we want the innermost chunks resolved first, so replace previous empty chunks,
74 * also ignore chunks that are completely finished, there is nothing for us to do */
Michal Vaskoae4b7d32018-07-13 12:21:01 +020075 if ((lybs->written[i] <= to_read) && lybs->position[i]) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +020076 /* empty chunk, do not read more */
77 to_read = lybs->written[i];
78 empty_chunk_i = i;
79 }
80 }
81
82 if ((empty_chunk_i == -1) && !count) {
83 break;
84 }
85
86 /* we are actually reading some data, not just finishing another chunk */
87 if (to_read) {
Michal Vasko228431e2018-07-10 15:47:11 +020088 if (buf) {
89 memcpy(buf, data + ret, to_read);
90 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +020091
92 for (i = 0; i < lybs->used; ++i) {
93 /* decrease all written counters */
94 lybs->written[i] -= to_read;
Michal Vaskoae4b7d32018-07-13 12:21:01 +020095 assert(lybs->written[i] <= LYB_SIZE_MAX);
Michal Vasko1e82a3b2018-07-03 12:16:58 +020096 }
97 /* decrease count/buf */
98 count -= to_read;
Michal Vasko228431e2018-07-10 15:47:11 +020099 if (buf) {
100 buf += to_read;
101 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200102
103 ret += to_read;
104 }
105
106 if (empty_chunk_i > -1) {
Michal Vaskoa9852522018-08-08 16:24:45 +0200107 /* read the next chunk meta information */
Graeme Campbell856a40e2018-10-05 14:35:37 +1300108 memcpy(meta_buf, data + ret, LYB_META_BYTES);
109 lybs->written[empty_chunk_i] = meta_buf[0];
110 lybs->inner_chunks[empty_chunk_i] = meta_buf[1];
Michal Vaskoa9852522018-08-08 16:24:45 +0200111
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200112 /* remember whether there is a following chunk or not */
113 lybs->position[empty_chunk_i] = (lybs->written[empty_chunk_i] == LYB_SIZE_MAX ? 1 : 0);
114
Michal Vaskoa9852522018-08-08 16:24:45 +0200115 ret += LYB_META_BYTES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200116 }
117 }
118
119 return ret;
120}
121
122static int
Michal Vasko1440eb52018-08-14 13:42:14 +0200123lyb_read_number(uint64_t *num, size_t bytes, const char *data, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200124{
Michal Vasko1440eb52018-08-14 13:42:14 +0200125 int r, ret = 0;
126 size_t i;
Michal Vasko228431e2018-07-10 15:47:11 +0200127 uint8_t byte;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200128
Michal Vasko1440eb52018-08-14 13:42:14 +0200129 for (i = 0; i < bytes; ++i) {
Michal Vasko228431e2018-07-10 15:47:11 +0200130 ret += (r = lyb_read(data, &byte, 1, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200131 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vasko228431e2018-07-10 15:47:11 +0200132
133 *(((uint8_t *)num) + i) = byte;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200134 }
135
136 return ret;
137}
138
139static int
Michal Vasko1440eb52018-08-14 13:42:14 +0200140lyb_read_enum(uint64_t *enum_idx, uint32_t count, const char *data, struct lyb_state *lybs)
141{
Graeme Campbell856a40e2018-10-05 14:35:37 +1300142 int ret = 0;
Michal Vasko1440eb52018-08-14 13:42:14 +0200143 size_t bytes;
Graeme Campbell856a40e2018-10-05 14:35:37 +1300144 uint64_t tmp_enum = 0;
Michal Vasko1440eb52018-08-14 13:42:14 +0200145
Michal Vasko81426892018-11-21 11:57:49 +0100146 if (count < (1 << 8)) {
Michal Vasko1440eb52018-08-14 13:42:14 +0200147 bytes = 1;
Michal Vasko81426892018-11-21 11:57:49 +0100148 } else if (count < (1 << 16)) {
Michal Vasko1440eb52018-08-14 13:42:14 +0200149 bytes = 2;
Michal Vasko81426892018-11-21 11:57:49 +0100150 } else if (count < (1 << 24)) {
Michal Vasko1440eb52018-08-14 13:42:14 +0200151 bytes = 3;
152 } else {
153 bytes = 4;
154 }
155
Graeme Campbell856a40e2018-10-05 14:35:37 +1300156 /* The enum is always read into a uint64_t buffer */
157 ret = lyb_read_number(&tmp_enum, bytes, data, lybs);
158 *enum_idx = le64toh(tmp_enum);
159
160 return ret;
Michal Vasko1440eb52018-08-14 13:42:14 +0200161}
162
163static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200164lyb_read_string(const char *data, char **str, int with_length, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200165{
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200166 int next_chunk = 0, r, ret = 0;
167 size_t len = 0, cur_len;
Graeme Campbell856a40e2018-10-05 14:35:37 +1300168 uint8_t len_buf[2];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200169
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200170 if (with_length) {
Graeme Campbell856a40e2018-10-05 14:35:37 +1300171 ret += (r = lyb_read(data, len_buf, 2, lybs));
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200172 LYB_HAVE_READ_GOTO(r, data, error);
Graeme Campbell856a40e2018-10-05 14:35:37 +1300173 len = len_buf[0] | (len_buf[1] << 8);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200174 } else {
175 /* read until the end of this subtree */
176 len = lybs->written[lybs->used - 1];
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200177 if (lybs->position[lybs->used - 1]) {
178 next_chunk = 1;
179 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200180 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200181
182 *str = malloc((len + 1) * sizeof **str);
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100183 LY_CHECK_ERR_RETURN(!*str, LOGMEM(lybs->ctx), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200184
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200185 ret += (r = lyb_read(data, (uint8_t *)*str, len, lybs));
Michal Vaskoed5fc582018-08-09 11:34:44 +0200186 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200187
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200188 while (next_chunk) {
189 cur_len = lybs->written[lybs->used - 1];
190 if (lybs->position[lybs->used - 1]) {
191 next_chunk = 1;
192 } else {
193 next_chunk = 0;
194 }
195
196 *str = ly_realloc(*str, (len + cur_len + 1) * sizeof **str);
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100197 LY_CHECK_ERR_RETURN(!*str, LOGMEM(lybs->ctx), -1);
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200198
199 ret += (r = lyb_read(data, ((uint8_t *)*str) + len, cur_len, lybs));
Michal Vaskoed5fc582018-08-09 11:34:44 +0200200 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko0d73b8c2018-08-08 16:25:43 +0200201
202 len += cur_len;
203 }
204
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200205 ((char *)*str)[len] = '\0';
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200206 return ret;
207
208error:
209 free((char *)*str);
210 *str = NULL;
211 return -1;
212}
213
214static void
215lyb_read_stop_subtree(struct lyb_state *lybs)
216{
217 if (lybs->written[lybs->used - 1]) {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100218 LOGINT(lybs->ctx);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200219 }
220
221 --lybs->used;
222}
223
224static int
225lyb_read_start_subtree(const char *data, struct lyb_state *lybs)
226{
Graeme Campbell856a40e2018-10-05 14:35:37 +1300227 uint8_t meta_buf[LYB_META_BYTES];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200228
229 if (lybs->used == lybs->size) {
230 lybs->size += LYB_STATE_STEP;
231 lybs->written = ly_realloc(lybs->written, lybs->size * sizeof *lybs->written);
232 lybs->position = ly_realloc(lybs->position, lybs->size * sizeof *lybs->position);
Michal Vaskoa9852522018-08-08 16:24:45 +0200233 lybs->inner_chunks = ly_realloc(lybs->inner_chunks, lybs->size * sizeof *lybs->inner_chunks);
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100234 LY_CHECK_ERR_RETURN(!lybs->written || !lybs->position || !lybs->inner_chunks, LOGMEM(lybs->ctx), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200235 }
236
Graeme Campbell856a40e2018-10-05 14:35:37 +1300237 memcpy(meta_buf, data, LYB_META_BYTES);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200238
239 ++lybs->used;
Graeme Campbell856a40e2018-10-05 14:35:37 +1300240 lybs->written[lybs->used - 1] = meta_buf[0];
241 lybs->inner_chunks[lybs->used - 1] = meta_buf[LYB_SIZE_BYTES];
Michal Vaskoa9852522018-08-08 16:24:45 +0200242 lybs->position[lybs->used - 1] = (lybs->written[lybs->used - 1] == LYB_SIZE_MAX ? 1 : 0);
243
244 return LYB_META_BYTES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200245}
246
247static int
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100248lyb_parse_model(const char *data, const struct lys_module **mod, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200249{
250 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200251 char *mod_name = NULL, mod_rev[11];
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200252 uint16_t rev = 0;
Graeme Campbell856a40e2018-10-05 14:35:37 +1300253 uint8_t tmp_buf[2];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200254
255 /* model name */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200256 ret += (r = lyb_read_string(data, &mod_name, 1, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200257 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200258
259 /* revision */
Graeme Campbell856a40e2018-10-05 14:35:37 +1300260 ret += (r = lyb_read(data, tmp_buf, sizeof tmp_buf, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200261 LYB_HAVE_READ_GOTO(r, data, error);
Graeme Campbell856a40e2018-10-05 14:35:37 +1300262 rev = tmp_buf[0] | (tmp_buf[1] << 8);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200263
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200264 if (rev) {
265 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & 0xFE00) >> 9) + 2000, (rev & 0x01E0) >> 5, (rev & 0x001F));
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100266 *mod = ly_ctx_get_module(lybs->ctx, mod_name, mod_rev, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200267 } else {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100268 *mod = ly_ctx_get_module(lybs->ctx, mod_name, NULL, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200269 }
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100270 if (lybs->ctx->data_clb) {
Michal Vasko18c3b6d2018-07-24 16:08:57 +0200271 if (!*mod) {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100272 *mod = lybs->ctx->data_clb(lybs->ctx, mod_name, NULL, 0, lybs->ctx->data_clb_data);
Michal Vasko18c3b6d2018-07-24 16:08:57 +0200273 } else if (!(*mod)->implemented) {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100274 *mod = lybs->ctx->data_clb(lybs->ctx, mod_name, (*mod)->ns, LY_MODCLB_NOT_IMPLEMENTED, lybs->ctx->data_clb_data);
Michal Vasko18c3b6d2018-07-24 16:08:57 +0200275 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200276 }
277
Michal Vasko60b02ff2018-09-25 11:01:18 +0200278 if (!*mod) {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100279 LOGERR(lybs->ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
Michal Vasko60b02ff2018-09-25 11:01:18 +0200280 mod_name, rev ? "@" : "", rev ? mod_rev : "");
281 goto error;
282 } else if (!(*mod)->implemented) {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100283 LOGERR(lybs->ctx, LY_EINVAL, "Invalid context for LYB data parsing, module \"%s%s%s\" not implemented.",
Michal Vasko60b02ff2018-09-25 11:01:18 +0200284 mod_name, rev ? "@" : "", rev ? mod_rev : "");
285 goto error;
286 }
287
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200288 free(mod_name);
289 return ret;
290
291error:
292 free(mod_name);
293 return -1;
294}
295
296static struct lyd_node *
297lyb_new_node(const struct lys_node *schema)
298{
299 struct lyd_node *node;
300
301 switch (schema->nodetype) {
302 case LYS_CONTAINER:
303 case LYS_LIST:
304 case LYS_NOTIF:
305 case LYS_RPC:
306 case LYS_ACTION:
307 node = calloc(sizeof(struct lyd_node), 1);
308 break;
309 case LYS_LEAF:
310 case LYS_LEAFLIST:
311 node = calloc(sizeof(struct lyd_node_leaf_list), 1);
Michal Vaskob7400232018-07-11 15:35:57 +0200312
313 if (((struct lys_node_leaf *)schema)->type.base == LY_TYPE_LEAFREF) {
314 node->validity |= LYD_VAL_LEAFREF;
315 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200316 break;
317 case LYS_ANYDATA:
318 case LYS_ANYXML:
319 node = calloc(sizeof(struct lyd_node_anydata), 1);
320 break;
321 default:
322 return NULL;
323 }
324 LY_CHECK_ERR_RETURN(!node, LOGMEM(schema->module->ctx), NULL);
325
326 /* fill basic info */
327 node->schema = (struct lys_node *)schema;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200328 if (resolve_applies_when(schema, 0, NULL)) {
Michal Vasko7b2a5822018-12-18 13:13:03 +0100329 /* this data are considered trusted so if this node exists, it means its when must have been true */
330 node->when_status = LYD_WHEN | LYD_WHEN_TRUE;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200331 }
332 node->prev = node;
333
334 return node;
335}
336
337static int
338lyb_parse_anydata(struct lyd_node *node, const char *data, struct lyb_state *lybs)
339{
340 int r, ret = 0;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200341 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200342 struct lyd_node_anydata *any = (struct lyd_node_anydata *)node;
343
344 /* read value type */
345 ret += (r = lyb_read(data, (uint8_t *)&any->value_type, sizeof any->value_type, lybs));
346 LYB_HAVE_READ_RETURN(r, data, -1);
347
348 /* read anydata content */
349 if (any->value_type == LYD_ANYDATA_DATATREE) {
Michal Vasko33901702018-08-17 10:29:09 +0200350 /* invalid situation */
351 LOGINT(node->schema->module->ctx);
352 return -1;
Michal Vaskodcaf7222018-08-08 16:27:00 +0200353 } else if (any->value_type == LYD_ANYDATA_LYB) {
354 ret += (r = lyb_read_string(data, &any->value.mem, 0, lybs));
355 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200356 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200357 ret += (r = lyb_read_string(data, &str, 0, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200358 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200359
360 /* add to dictionary */
361 any->value.str = lydict_insert_zc(node->schema->module->ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200362 }
363
364 return ret;
365}
366
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200367/* generally, fill lyd_val value union */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200368static int
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100369lyb_parse_val_1(struct lys_type *type, LY_DATA_TYPE value_type, uint8_t value_flags, const char *data,
370 const char **value_str, lyd_val *value, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200371{
Michal Vasko228431e2018-07-10 15:47:11 +0200372 int r, ret;
373 size_t i;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200374 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200375 uint8_t byte;
Michal Vasko228431e2018-07-10 15:47:11 +0200376 uint64_t num;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200377
Michal Vasko42132c52018-07-24 16:09:21 +0200378 if (value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200379 /* just read value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200380 ret = lyb_read_string(data, &str, 0, lybs);
381 if (ret > -1) {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100382 *value_str = lydict_insert_zc(lybs->ctx, str);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200383 }
384 return ret;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200385 }
386
Michal Vasko6fb57892018-08-23 10:21:21 +0200387 /* find the correct structure, go through leafrefs and typedefs */
388 switch (value_type) {
389 case LY_TYPE_ENUM:
390 for (; type->base == LY_TYPE_LEAFREF; type = &type->info.lref.target->type);
391 for (; !type->info.enums.count; type = &type->der->type);
392 break;
393 case LY_TYPE_BITS:
394 for (; type->base == LY_TYPE_LEAFREF; type = &type->info.lref.target->type);
395 for (; !type->info.bits.count; type = &type->der->type);
396 break;
397 default:
398 break;
399 }
400
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200401 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200402 case LY_TYPE_INST:
403 case LY_TYPE_IDENT:
404 case LY_TYPE_UNION:
405 /* we do not actually fill value now, but value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200406 ret = lyb_read_string(data, &str, 0, lybs);
407 if (ret > -1) {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100408 *value_str = lydict_insert_zc(lybs->ctx, str);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200409 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200410 break;
411 case LY_TYPE_BINARY:
412 case LY_TYPE_STRING:
413 case LY_TYPE_UNKNOWN:
414 /* read string */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200415 ret = lyb_read_string(data, &str, 0, lybs);
416 if (ret > -1) {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100417 value->string = lydict_insert_zc(lybs->ctx, str);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200418 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200419 break;
420 case LY_TYPE_BITS:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200421 value->bit = calloc(type->info.bits.count, sizeof *value->bit);
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100422 LY_CHECK_ERR_RETURN(!value->bit, LOGMEM(lybs->ctx), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200423
424 /* read values */
Michal Vasko228431e2018-07-10 15:47:11 +0200425 ret = 0;
426 for (i = 0; i < type->info.bits.count; ++i) {
427 if (i % 8 == 0) {
428 /* read another byte */
Andrew Langefeld1f3e4f52018-08-24 22:30:37 -0500429 ret += (r = lyb_read(data + ret, &byte, sizeof byte, lybs));
Michal Vasko228431e2018-07-10 15:47:11 +0200430 if (r < 0) {
431 return -1;
432 }
433 }
434
435 if (byte & (0x01 << (i % 8))) {
436 /* bit is set */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200437 value->bit[i] = &type->info.bits.bit[i];
Michal Vasko228431e2018-07-10 15:47:11 +0200438 }
439 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200440 break;
441 case LY_TYPE_BOOL:
442 /* read byte */
443 ret = lyb_read(data, &byte, sizeof byte, lybs);
444 if ((ret > 0) && byte) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200445 value->bln = 1;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200446 }
447 break;
448 case LY_TYPE_EMPTY:
449 /* nothing to read */
450 ret = 0;
451 break;
452 case LY_TYPE_ENUM:
Michal Vasko228431e2018-07-10 15:47:11 +0200453 num = 0;
Michal Vasko1440eb52018-08-14 13:42:14 +0200454 ret = lyb_read_enum(&num, type->info.enums.count, data, lybs);
Michal Vaskob7400232018-07-11 15:35:57 +0200455 if (ret > 0) {
456 assert(num < type->info.enums.count);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200457 value->enm = &type->info.enums.enm[num];
Michal Vasko228431e2018-07-10 15:47:11 +0200458 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200459 break;
460 case LY_TYPE_INT8:
461 case LY_TYPE_UINT8:
Michal Vasko1440eb52018-08-14 13:42:14 +0200462 ret = lyb_read_number((uint64_t *)&value->uint8, 1, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200463 break;
464 case LY_TYPE_INT16:
465 case LY_TYPE_UINT16:
Michal Vasko1440eb52018-08-14 13:42:14 +0200466 ret = lyb_read_number((uint64_t *)&value->uint16, 2, data, lybs);
Graeme Campbell856a40e2018-10-05 14:35:37 +1300467 value->uint16 = le16toh(value->uint16);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200468 break;
469 case LY_TYPE_INT32:
470 case LY_TYPE_UINT32:
Michal Vasko1440eb52018-08-14 13:42:14 +0200471 ret = lyb_read_number((uint64_t *)&value->uint32, 4, data, lybs);
Graeme Campbell856a40e2018-10-05 14:35:37 +1300472 value->uint32 = le32toh(value->uint32);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200473 break;
474 case LY_TYPE_DEC64:
475 case LY_TYPE_INT64:
476 case LY_TYPE_UINT64:
Michal Vasko1440eb52018-08-14 13:42:14 +0200477 ret = lyb_read_number((uint64_t *)&value->uint64, 8, data, lybs);
Graeme Campbell856a40e2018-10-05 14:35:37 +1300478 value->uint64 = le64toh(value->uint64);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200479 break;
480 default:
481 return -1;
482 }
483
484 return ret;
485}
486
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200487/* generally, fill value_str */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200488static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200489lyb_parse_val_2(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, struct unres_data *unres)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200490{
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200491 struct ly_ctx *ctx;
492 struct lys_module *mod;
Michal Vasko6fb57892018-08-23 10:21:21 +0200493 struct lys_type *rtype;
Michal Vasko228431e2018-07-10 15:47:11 +0200494 char num_str[22], *str;
Michal Vasko27e5e682018-07-23 14:22:57 +0200495 int64_t frac;
Michal Vasko228431e2018-07-10 15:47:11 +0200496 uint32_t i, str_len;
Michal Vaskob0c3d9e2018-07-23 14:35:17 +0200497 uint8_t *value_flags, dig;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200498 const char **value_str;
499 LY_DATA_TYPE value_type;
500 lyd_val *value;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200501
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200502 if (leaf) {
503 ctx = leaf->schema->module->ctx;
504 mod = lys_node_module(leaf->schema);
505
506 value = &leaf->value;
507 value_str = &leaf->value_str;
508 value_flags = &leaf->value_flags;
509 value_type = leaf->value_type;
510 } else {
511 ctx = attr->annotation->module->ctx;
512 mod = lys_main_module(attr->annotation->module);
513
514 value = &attr->value;
515 value_str = &attr->value_str;
516 value_flags = &attr->value_flags;
517 value_type = attr->value_type;
518 }
519
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200520 if (*value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200521 /* unfortunately, we need to also fill the value properly, so just parse it again */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200522 *value_flags &= ~LY_VALUE_USER;
523 if (!lyp_parse_value(type, value_str, NULL, leaf, attr, NULL, 1, (leaf ? leaf->dflt : 0), 1)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200524 return -1;
525 }
526
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200527 if (!(*value_flags & LY_VALUE_USER)) {
528 LOGWRN(ctx, "Value \"%s\" was stored as a user type, but it is not in the current context.", value_str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200529 }
530 return 0;
531 }
532
Michal Vaskob7400232018-07-11 15:35:57 +0200533 /* we are parsing leafref/ptr union stored as the target type,
534 * so we first parse it into string and then resolve the leafref/ptr union */
Michal Vaskod0826ca2018-12-19 16:31:10 +0100535 if ((type->base == LY_TYPE_LEAFREF) || (type->base == LY_TYPE_INST)
536 || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type)) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200537 if ((value_type == LY_TYPE_INST) || (value_type == LY_TYPE_IDENT) || (value_type == LY_TYPE_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200538 /* we already have a string */
539 goto parse_reference;
540 }
541 }
542
Michal Vasko6fb57892018-08-23 10:21:21 +0200543 /* find the correct structure, go through leafrefs and typedefs */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200544 switch (value_type) {
Michal Vasko58608522018-08-22 13:04:37 +0200545 case LY_TYPE_BITS:
Michal Vasko6fb57892018-08-23 10:21:21 +0200546 for (rtype = type; rtype->base == LY_TYPE_LEAFREF; rtype = &rtype->info.lref.target->type);
547 for (; !rtype->info.bits.count; rtype = &rtype->der->type);
548 break;
Michal Vasko58608522018-08-22 13:04:37 +0200549 case LY_TYPE_DEC64:
Michal Vasko6fb57892018-08-23 10:21:21 +0200550 for (rtype = type; rtype->base == LY_TYPE_LEAFREF; rtype = &type->info.lref.target->type);
Michal Vasko58608522018-08-22 13:04:37 +0200551 break;
552 default:
553 break;
554 }
555
556 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200557 case LY_TYPE_IDENT:
558 /* fill the identity pointer now */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200559 value->ident = resolve_identref(type, *value_str, (struct lyd_node *)leaf, mod, (leaf ? leaf->dflt : 0));
560 if (!value->ident) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200561 return -1;
562 }
563 break;
Michal Vasko56670362018-08-08 16:27:21 +0200564 case LY_TYPE_INST:
565 /* unresolved instance-identifier, keep value NULL */
566 value->instance = NULL;
567 break;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200568 case LY_TYPE_BINARY:
569 case LY_TYPE_STRING:
570 case LY_TYPE_UNKNOWN:
571 /* just re-assign it */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200572 *value_str = value->string;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200573 break;
574 case LY_TYPE_BITS:
Michal Vasko228431e2018-07-10 15:47:11 +0200575 /* print the set bits */
576 str = malloc(1);
577 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
578 str[0] = '\0';
Michal Vaskob7400232018-07-11 15:35:57 +0200579 str_len = 0;
Michal Vasko6fb57892018-08-23 10:21:21 +0200580 for (i = 0; i < rtype->info.bits.count; ++i) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200581 if (value->bit[i]) {
582 str = ly_realloc(str, str_len + strlen(value->bit[i]->name) + (str_len ? 1 : 0) + 1);
Michal Vasko228431e2018-07-10 15:47:11 +0200583 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
584
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200585 str_len += sprintf(str + str_len, "%s%s", str_len ? " " : "", value->bit[i]->name);
Michal Vasko228431e2018-07-10 15:47:11 +0200586 }
587 }
588
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200589 *value_str = lydict_insert_zc(ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200590 break;
591 case LY_TYPE_BOOL:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200592 *value_str = lydict_insert(ctx, (value->bln ? "true" : "false"), 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200593 break;
594 case LY_TYPE_EMPTY:
Michal Vasko27e5e682018-07-23 14:22:57 +0200595 *value_str = lydict_insert(ctx, "", 0);
596 break;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200597 case LY_TYPE_UNION:
Michal Vasko27e5e682018-07-23 14:22:57 +0200598 if (attr) {
599 /* we do not support union type attribute */
600 LOGINT(ctx);
601 return -1;
602 }
603
604 if (resolve_union(leaf, type, 1, 2, NULL)) {
605 return -1;
606 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200607 break;
608 case LY_TYPE_ENUM:
Michal Vasko228431e2018-07-10 15:47:11 +0200609 /* print the value */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200610 *value_str = lydict_insert(ctx, value->enm->name, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200611 break;
612 case LY_TYPE_INT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200613 sprintf(num_str, "%d", value->int8);
614 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200615 break;
616 case LY_TYPE_UINT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200617 sprintf(num_str, "%u", value->uint8);
618 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200619 break;
620 case LY_TYPE_INT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200621 sprintf(num_str, "%d", value->int16);
622 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200623 break;
624 case LY_TYPE_UINT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200625 sprintf(num_str, "%u", value->uint16);
626 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200627 break;
628 case LY_TYPE_INT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200629 sprintf(num_str, "%d", value->int32);
630 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200631 break;
632 case LY_TYPE_UINT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200633 sprintf(num_str, "%u", value->uint32);
634 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200635 break;
636 case LY_TYPE_INT64:
Michal Vaskoe581e982018-08-21 12:26:55 +0200637 sprintf(num_str, "%"PRId64, value->int64);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200638 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200639 break;
640 case LY_TYPE_UINT64:
Michal Vaskoe581e982018-08-21 12:26:55 +0200641 sprintf(num_str, "%"PRIu64, value->uint64);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200642 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200643 break;
644 case LY_TYPE_DEC64:
Michal Vasko6fb57892018-08-23 10:21:21 +0200645 frac = value->dec64 % rtype->info.dec64.div;
646 dig = rtype->info.dec64.dig;
Michal Vaskob0c3d9e2018-07-23 14:35:17 +0200647 /* remove trailing zeros */
648 while ((dig > 1) && !(frac % 10)) {
649 frac /= 10;
650 --dig;
651 }
652
Michal Vasko6fb57892018-08-23 10:21:21 +0200653 sprintf(num_str, "%"PRId64".%.*"PRId64, value->dec64 / (int64_t)rtype->info.dec64.div, dig, frac);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200654 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200655 break;
656 default:
657 return -1;
658 }
659
Michal Vaskod0826ca2018-12-19 16:31:10 +0100660 if ((type->base == LY_TYPE_LEAFREF) || (type->base == LY_TYPE_INST)
Michal Vaskoc2a25242018-12-19 08:52:28 +0100661 || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200662parse_reference:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200663 assert(*value_str);
Michal Vaskob7400232018-07-11 15:35:57 +0200664
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200665 if (attr) {
666 /* we do not support reference types of attributes */
667 LOGINT(ctx);
668 return -1;
669 }
670
671 if (type->base == LY_TYPE_INST) {
672 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_INSTID)) {
673 return -1;
674 }
675 } else if (type->base == LY_TYPE_LEAFREF) {
676 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_LEAFREF)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200677 return -1;
678 }
679 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200680 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200681 return -1;
682 }
683 }
684 }
685
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200686 return 0;
687}
688
689static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200690lyb_parse_value(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, const char *data,
691 struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200692{
693 int r, ret = 0;
694 uint8_t start_byte;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200695
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200696 const char **value_str;
697 lyd_val *value;
698 LY_DATA_TYPE *value_type;
699 uint8_t *value_flags;
700
701 assert((leaf || attr) && (!leaf || !attr));
702
703 if (leaf) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200704 value_str = &leaf->value_str;
705 value = &leaf->value;
706 value_type = &leaf->value_type;
707 value_flags = &leaf->value_flags;
708 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200709 value_str = &attr->value_str;
710 value = &attr->value;
711 value_type = &attr->value_type;
712 value_flags = &attr->value_flags;
713 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200714
715 /* read value type and flags on the first byte */
716 ret += (r = lyb_read(data, &start_byte, sizeof start_byte, lybs));
717 LYB_HAVE_READ_RETURN(r, data, -1);
718
719 /* fill value type, flags */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200720 *value_type = start_byte & 0x1F;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200721 if (start_byte & 0x80) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200722 assert(leaf);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200723 leaf->dflt = 1;
724 }
725 if (start_byte & 0x40) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200726 *value_flags |= LY_VALUE_USER;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200727 }
728 if (start_byte & 0x20) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200729 *value_flags |= LY_VALUE_UNRES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200730 }
731
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100732 ret += (r = lyb_parse_val_1(type, *value_type, *value_flags, data, value_str, value, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200733 LYB_HAVE_READ_RETURN(r, data, -1);
734
Michal Vasko27e5e682018-07-23 14:22:57 +0200735 /* union is handled specially */
Michal Vaskoe32c0f22019-01-09 14:58:36 +0100736 if ((type->base == LY_TYPE_UNION) && !(*value_flags & LY_VALUE_USER)) {
Michal Vasko27e5e682018-07-23 14:22:57 +0200737 assert(*value_type == LY_TYPE_STRING);
738
739 *value_str = value->string;
740 value->string = NULL;
741 *value_type = LY_TYPE_UNION;
742 }
743
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200744 ret += (r = lyb_parse_val_2(type, leaf, attr, unres));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200745 LYB_HAVE_READ_RETURN(r, data, -1);
746
747 return ret;
748}
749
750static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200751lyb_parse_attr_name(const struct lys_module *mod, const char *data, struct lys_ext_instance_complex **ext, int options,
752 struct lyb_state *lybs)
753{
754 int r, ret = 0, pos, i, j, k;
755 const struct lys_submodule *submod = NULL;
756 char *attr_name = NULL;
757
758 /* attr name */
759 ret += (r = lyb_read_string(data, &attr_name, 1, lybs));
760 LYB_HAVE_READ_RETURN(r, data, -1);
761
762 /* search module */
763 pos = -1;
764 for (i = 0, j = 0; i < mod->ext_size; i = i + j + 1) {
765 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &mod->ext[i], mod->ext_size - i);
766 if (j == -1) {
767 break;
768 }
769 if (ly_strequal(mod->ext[i + j]->arg_value, attr_name, 0)) {
770 pos = i + j;
771 break;
772 }
773 }
774
775 /* try submodules */
776 if (pos == -1) {
777 for (k = 0; k < mod->inc_size; ++k) {
778 submod = mod->inc[k].submodule;
779 for (i = 0, j = 0; i < submod->ext_size; i = i + j + 1) {
780 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &submod->ext[i], submod->ext_size - i);
781 if (j == -1) {
782 break;
783 }
784 if (ly_strequal(submod->ext[i + j]->arg_value, attr_name, 0)) {
785 pos = i + j;
786 break;
787 }
788 }
789 }
790 }
791
792 if (pos == -1) {
793 *ext = NULL;
794 } else {
795 *ext = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] : (struct lys_ext_instance_complex *)mod->ext[pos];
796 }
797
798 if (!*ext && (options & LYD_OPT_STRICT)) {
799 LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find annotation \"%s\" in \"%s\".", attr_name, mod->name);
800 free(attr_name);
801 return -1;
802 }
803
804 free(attr_name);
805 return ret;
806}
807
808static int
809lyb_parse_attributes(struct lyd_node *node, const char *data, int options, struct unres_data *unres, struct lyb_state *lybs)
810{
811 int r, ret = 0;
812 uint8_t i, count = 0;
813 const struct lys_module *mod;
Michal Vasko3cb7d172018-08-17 10:54:40 +0200814 struct lys_type **type;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200815 struct lyd_attr *attr = NULL;
816 struct lys_ext_instance_complex *ext;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200817
818 /* read number of attributes stored */
819 ret += (r = lyb_read(data, &count, 1, lybs));
820 LYB_HAVE_READ_GOTO(r, data, error);
821
822 /* read attributes */
823 for (i = 0; i < count; ++i) {
824 ret += (r = lyb_read_start_subtree(data, lybs));
825 LYB_HAVE_READ_GOTO(r, data, error);
826
827 /* find model */
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100828 ret += (r = lyb_parse_model(data, &mod, lybs));
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200829 LYB_HAVE_READ_GOTO(r, data, error);
830
Michal Vasko53830662018-07-24 16:09:49 +0200831 if (mod) {
832 /* annotation name */
833 ret += (r = lyb_parse_attr_name(mod, data, &ext, options, lybs));
834 LYB_HAVE_READ_GOTO(r, data, error);
835 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200836
Michal Vasko53830662018-07-24 16:09:49 +0200837 if (!mod || !ext) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200838 /* unknown attribute, skip it */
839 do {
840 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200841 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200842 } while (lybs->written[lybs->used - 1]);
843 goto stop_subtree;
844 }
845
846 /* allocate new attribute */
847 if (!attr) {
848 assert(!node->attr);
849
850 attr = calloc(1, sizeof *attr);
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100851 LY_CHECK_ERR_GOTO(!attr, LOGMEM(lybs->ctx), error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200852
853 node->attr = attr;
854 } else {
855 attr->next = calloc(1, sizeof *attr);
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100856 LY_CHECK_ERR_GOTO(!attr->next, LOGMEM(lybs->ctx), error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200857
858 attr = attr->next;
859 }
860
861 /* attribute annotation */
862 attr->annotation = ext;
863
864 /* attribute name */
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100865 attr->name = lydict_insert(lybs->ctx, attr->annotation->arg_value, 0);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200866
867 /* get the type */
Michal Vasko3cb7d172018-08-17 10:54:40 +0200868 type = (struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, attr->annotation, NULL);
869 if (!type || !(*type)) {
870 goto error;
871 }
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200872
873 /* attribute value */
Michal Vasko3cb7d172018-08-17 10:54:40 +0200874 ret += (r = lyb_parse_value(*type, NULL, attr, data, unres, lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200875 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200876
877stop_subtree:
878 lyb_read_stop_subtree(lybs);
879 }
880
881 return ret;
882
883error:
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100884 lyd_free_attr(lybs->ctx, node, node->attr, 1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200885 return -1;
886}
887
888static int
Michal Vaskob7400232018-07-11 15:35:57 +0200889lyb_is_schema_hash_match(struct lys_node *sibling, LYB_HASH *hash, uint8_t hash_count)
Michal Vasko228431e2018-07-10 15:47:11 +0200890{
891 LYB_HASH sibling_hash;
Michal Vaskob7400232018-07-11 15:35:57 +0200892 uint8_t i;
Michal Vasko228431e2018-07-10 15:47:11 +0200893
Michal Vaskob7400232018-07-11 15:35:57 +0200894 /* compare all the hashes starting from collision ID 0 */
895 for (i = 0; i < hash_count; ++i) {
896 sibling_hash = lyb_hash(sibling, i);
897 if (sibling_hash != hash[i]) {
898 return 0;
899 }
900 }
Michal Vasko228431e2018-07-10 15:47:11 +0200901
Michal Vaskob7400232018-07-11 15:35:57 +0200902 return 1;
Michal Vasko228431e2018-07-10 15:47:11 +0200903}
904
905static int
906lyb_parse_schema_hash(const struct lys_node *sparent, const struct lys_module *mod, const char *data, const char *yang_data_name,
907 int options, struct lys_node **snode, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200908{
909 int r, ret = 0;
Michal Vaskob7400232018-07-11 15:35:57 +0200910 uint8_t i, j;
911 struct lys_node *sibling;
912 LYB_HASH hash[LYB_HASH_BITS - 1];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200913
914 assert((sparent || mod) && (!sparent || !mod));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200915
Michal Vaskob7400232018-07-11 15:35:57 +0200916 /* read the first hash */
917 ret += (r = lyb_read(data, &hash[0], sizeof *hash, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200918 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskob7400232018-07-11 15:35:57 +0200919
920 /* based on the first hash read all the other ones, if any */
Michal Vasko01fc23a2018-11-21 11:58:26 +0100921 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
922 if (i > LYB_HASH_BITS) {
923 return -1;
924 }
925 }
Michal Vaskob7400232018-07-11 15:35:57 +0200926
927 /* move the first hash on its accurate position */
928 hash[i] = hash[0];
929
930 /* read the rest of hashes */
931 for (j = i; j; --j) {
932 ret += (r = lyb_read(data, &hash[j - 1], sizeof *hash, lybs));
933 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200934
Michal Vasko365849c2018-08-07 11:31:30 +0200935 /* correct collision ID */
936 assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
937 /* preceded with zeros */
938 assert(!(hash[j - 1] & (LYB_HASH_MASK << (LYB_HASH_BITS - (j - 1)))));
Michal Vasko228431e2018-07-10 15:47:11 +0200939 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200940
Michal Vaskoe3880e62018-07-11 16:18:34 +0200941 /* handle yang data templates */
942 if ((options & LYD_OPT_DATA_TEMPLATE) && yang_data_name && mod) {
943 sparent = lyp_get_yang_data_template(mod, yang_data_name, strlen(yang_data_name));
944 if (!sparent) {
945 sibling = NULL;
946 goto finish;
947 }
948 }
949
950 /* handle RPC/action input/output */
Michal Vaskob7400232018-07-11 15:35:57 +0200951 if (sparent && (sparent->nodetype & (LYS_RPC | LYS_ACTION))) {
952 sibling = NULL;
953 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, NULL, LYS_GETNEXT_WITHINOUT))) {
954 if ((sibling->nodetype == LYS_INPUT) && (options & LYD_OPT_RPC)) {
955 break;
956 }
957 if ((sibling->nodetype == LYS_OUTPUT) && (options & LYD_OPT_RPCREPLY)) {
958 break;
959 }
960 }
961 if (!sibling) {
962 /* fail */
963 goto finish;
964 }
965
966 /* use only input/output children nodes */
967 sparent = sibling;
968 }
969
970 /* find our node with matching hashes */
971 sibling = NULL;
Michal Vasko228431e2018-07-10 15:47:11 +0200972 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, mod, 0))) {
973 /* skip schema nodes from models not present during printing */
Michal Vaskob7400232018-07-11 15:35:57 +0200974 if (lyb_has_schema_model(sibling, lybs->models, lybs->mod_count) && lyb_is_schema_hash_match(sibling, hash, i + 1)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200975 /* match found */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200976 break;
977 }
978 }
979
Michal Vaskob7400232018-07-11 15:35:57 +0200980finish:
Michal Vasko228431e2018-07-10 15:47:11 +0200981 *snode = sibling;
982 if (!sibling && (options & LYD_OPT_STRICT)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200983 if (mod) {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100984 LOGVAL(lybs->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find matching hash for a top-level node from \"%s\".",
985 mod->name);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200986 } else {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100987 LOGVAL(lybs->ctx, LYE_SPEC, LY_VLOG_LYS, sparent, "Failed to find matching hash for a child of \"%s\".",
988 sparent->name);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200989 }
990 return -1;
991 }
992
993 return ret;
994}
995
996static int
Michal Vaskoeda0a6d2019-02-21 09:36:47 +0100997lyb_parse_subtree(const char *data, struct lyd_node *parent, struct lyd_node **first_sibling, const char *yang_data_name,
998 int options, struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200999{
1000 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001001 struct lyd_node *node = NULL, *iter;
1002 const struct lys_module *mod;
Michal Vaskoe3880e62018-07-11 16:18:34 +02001003 struct lys_node *snode;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001004
1005 assert((parent && !first_sibling) || (!parent && first_sibling));
1006
1007 /* register a new subtree */
1008 ret += (r = lyb_read_start_subtree(data, lybs));
1009 LYB_HAVE_READ_GOTO(r, data, error);
1010
1011 if (!parent) {
1012 /* top-level, read module name */
Michal Vaskoeda0a6d2019-02-21 09:36:47 +01001013 ret += (r = lyb_parse_model(data, &mod, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001014 LYB_HAVE_READ_GOTO(r, data, error);
1015
Michal Vasko53830662018-07-24 16:09:49 +02001016 if (mod) {
1017 /* read hash, find the schema node starting from mod, possibly yang_data_name */
1018 r = lyb_parse_schema_hash(NULL, mod, data, yang_data_name, options, &snode, lybs);
1019 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001020 } else {
Michal Vasko53830662018-07-24 16:09:49 +02001021 mod = lyd_node_module(parent);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001022
Michal Vaskoe3880e62018-07-11 16:18:34 +02001023 /* read hash, find the schema node starting from parent schema */
1024 r = lyb_parse_schema_hash(parent->schema, NULL, data, NULL, options, &snode, lybs);
1025 }
1026 ret += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001027 LYB_HAVE_READ_GOTO(r, data, error);
1028
Michal Vasko53830662018-07-24 16:09:49 +02001029 if (!mod || !snode) {
Michal Vasko997071e2018-07-10 15:56:14 +02001030 /* unknown data subtree, skip it whole */
1031 do {
1032 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vaskoa9852522018-08-08 16:24:45 +02001033 /* also skip the meta information inside */
Michal Vaskofb1582f2019-01-22 14:07:26 +01001034 r = lybs->inner_chunks[lybs->used - 1] * LYB_META_BYTES;
1035 data += r;
1036 ret += r;
Michal Vasko997071e2018-07-10 15:56:14 +02001037 } while (lybs->written[lybs->used - 1]);
Michal Vasko228431e2018-07-10 15:47:11 +02001038 goto stop_subtree;
1039 }
1040
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001041 /*
1042 * read the node
1043 */
1044 node = lyb_new_node(snode);
1045 if (!node) {
1046 goto error;
1047 }
1048
Michal Vaskoae4b7d32018-07-13 12:21:01 +02001049 ret += (r = lyb_parse_attributes(node, data, options, unres, lybs));
1050 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001051
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001052 /* read node content */
1053 switch (snode->nodetype) {
1054 case LYS_CONTAINER:
1055 case LYS_LIST:
Michal Vaskob7400232018-07-11 15:35:57 +02001056 case LYS_NOTIF:
1057 case LYS_RPC:
1058 case LYS_ACTION:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001059 /* nothing to read */
1060 break;
1061 case LYS_LEAF:
1062 case LYS_LEAFLIST:
Michal Vaskoae4b7d32018-07-13 12:21:01 +02001063 ret += (r = lyb_parse_value(&((struct lys_node_leaf *)node->schema)->type, (struct lyd_node_leaf_list *)node,
1064 NULL, data, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001065 LYB_HAVE_READ_GOTO(r, data, error);
1066 break;
1067 case LYS_ANYXML:
1068 case LYS_ANYDATA:
1069 ret += (r = lyb_parse_anydata(node, data, lybs));
1070 LYB_HAVE_READ_GOTO(r, data, error);
1071 break;
1072 default:
1073 goto error;
1074 }
1075
1076 /* insert into data tree, manually */
1077 if (parent) {
1078 if (!parent->child) {
1079 /* only child */
1080 parent->child = node;
1081 } else {
1082 /* last child */
1083 parent->child->prev->next = node;
1084 node->prev = parent->child->prev;
1085 parent->child->prev = node;
1086 }
1087 node->parent = parent;
1088 } else if (*first_sibling) {
1089 /* last sibling */
1090 (*first_sibling)->prev->next = node;
1091 node->prev = (*first_sibling)->prev;
1092 (*first_sibling)->prev = node;
1093 } else {
1094 /* only sibling */
1095 *first_sibling = node;
1096 }
1097
1098 /* read all descendants */
1099 while (lybs->written[lybs->used - 1]) {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +01001100 ret += (r = lyb_parse_subtree(data, node, NULL, NULL, options, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001101 LYB_HAVE_READ_GOTO(r, data, error);
1102 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001103
1104 /* make containers default if should be */
Michal Vaskoddd545b2018-08-09 11:34:58 +02001105 if ((node->schema->nodetype == LYS_CONTAINER) && !((struct lys_node_container *)node->schema)->presence) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001106 LY_TREE_FOR(node->child, iter) {
1107 if (!iter->dflt) {
1108 break;
1109 }
1110 }
1111
1112 if (!iter) {
1113 node->dflt = 1;
1114 }
1115 }
1116
Michal Vaskofe43d042018-07-24 09:43:46 +02001117#ifdef LY_ENABLED_CACHE
Michal Vasko4968b9c2018-08-14 13:43:52 +02001118 /* calculate the hash and insert it into parent (list with keys is handled when its keys are inserted) */
1119 if ((node->schema->nodetype != LYS_LIST) || !((struct lys_node_list *)node->schema)->keys_size) {
Michal Vaskofe43d042018-07-24 09:43:46 +02001120 lyd_hash(node);
1121 lyd_insert_hash(node);
1122 }
1123#endif
1124
Michal Vasko228431e2018-07-10 15:47:11 +02001125stop_subtree:
1126 /* end the subtree */
1127 lyb_read_stop_subtree(lybs);
1128
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001129 return ret;
1130
1131error:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001132 lyd_free(node);
Michal Vaskob7400232018-07-11 15:35:57 +02001133 if (first_sibling && (*first_sibling == node)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001134 *first_sibling = NULL;
1135 }
1136 return -1;
1137}
1138
1139static int
Michal Vaskoeda0a6d2019-02-21 09:36:47 +01001140lyb_parse_data_models(const char *data, struct lyb_state *lybs)
Michal Vasko228431e2018-07-10 15:47:11 +02001141{
1142 int i, r, ret = 0;
Graeme Campbell856a40e2018-10-05 14:35:37 +13001143 uint8_t mod_count_buf[2];
Michal Vasko228431e2018-07-10 15:47:11 +02001144
1145 /* read model count */
Graeme Campbell856a40e2018-10-05 14:35:37 +13001146 ret += (r = lyb_read(data, mod_count_buf, 2, lybs));
Michal Vasko228431e2018-07-10 15:47:11 +02001147 LYB_HAVE_READ_RETURN(r, data, -1);
Graeme Campbell856a40e2018-10-05 14:35:37 +13001148 lybs->mod_count = mod_count_buf[0] | (mod_count_buf[1] << 8);
Michal Vasko228431e2018-07-10 15:47:11 +02001149
1150 lybs->models = malloc(lybs->mod_count * sizeof *lybs->models);
Michal Vaskoeda0a6d2019-02-21 09:36:47 +01001151 LY_CHECK_ERR_RETURN(!lybs->models, LOGMEM(lybs->ctx), -1);
Michal Vasko228431e2018-07-10 15:47:11 +02001152
1153 /* read modules */
1154 for (i = 0; i < lybs->mod_count; ++i) {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +01001155 ret += (r = lyb_parse_model(data, &lybs->models[i], lybs));
Michal Vasko228431e2018-07-10 15:47:11 +02001156 LYB_HAVE_READ_RETURN(r, data, -1);
1157 }
1158
1159 return ret;
1160}
1161
1162static int
Michal Vasko5c445042018-08-28 16:27:45 +02001163lyb_parse_magic_number(const char *data, struct lyb_state *lybs)
1164{
Michal Vasko7d15c3a2018-11-22 15:27:46 +01001165 int r, ret = 0;
1166 char magic_byte = 0;
Michal Vasko5c445042018-08-28 16:27:45 +02001167
Michal Vasko7d15c3a2018-11-22 15:27:46 +01001168 ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1169 LYB_HAVE_READ_RETURN(r, data, -1);
1170 if (magic_byte != 'l') {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +01001171 LOGERR(lybs->ctx, LY_EINVAL, "Invalid first magic number byte \"0x%02x\".", magic_byte);
Michal Vasko7d15c3a2018-11-22 15:27:46 +01001172 return -1;
1173 }
Michal Vasko5c445042018-08-28 16:27:45 +02001174
Michal Vasko7d15c3a2018-11-22 15:27:46 +01001175 ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1176 LYB_HAVE_READ_RETURN(r, data, -1);
1177 if (magic_byte != 'y') {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +01001178 LOGERR(lybs->ctx, LY_EINVAL, "Invalid second magic number byte \"0x%02x\".", magic_byte);
Michal Vasko7d15c3a2018-11-22 15:27:46 +01001179 return -1;
1180 }
1181
1182 ret += (r = lyb_read(data, (uint8_t *)&magic_byte, 1, lybs));
1183 LYB_HAVE_READ_RETURN(r, data, -1);
1184 if (magic_byte != 'b') {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +01001185 LOGERR(lybs->ctx, LY_EINVAL, "Invalid third magic number byte \"0x%02x\".", magic_byte);
Michal Vasko5c445042018-08-28 16:27:45 +02001186 return -1;
1187 }
1188
1189 return ret;
1190}
1191
1192static int
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001193lyb_parse_header(const char *data, struct lyb_state *lybs)
1194{
1195 int ret = 0;
1196 uint8_t byte = 0;
1197
Michal Vasko228431e2018-07-10 15:47:11 +02001198 /* TODO version, any flags? */
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001199 ret += lyb_read(data, (uint8_t *)&byte, sizeof byte, lybs);
1200
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001201 return ret;
1202}
1203
1204struct lyd_node *
Michal Vasko228431e2018-07-10 15:47:11 +02001205lyd_parse_lyb(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *data_tree,
1206 const char *yang_data_name, int *parsed)
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001207{
Michal Vaskobeeb1bf2018-08-17 10:29:29 +02001208 int r = 0, ret = 0;
Michal Vasko228431e2018-07-10 15:47:11 +02001209 struct lyd_node *node = NULL, *next, *act_notif = NULL;
1210 struct unres_data *unres = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001211 struct lyb_state lybs;
1212
1213 if (!ctx || !data) {
1214 LOGARG;
1215 return NULL;
1216 }
1217
1218 lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
1219 lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001220 lybs.inner_chunks = malloc(LYB_STATE_STEP * sizeof *lybs.inner_chunks);
1221 LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position || !lybs.inner_chunks, LOGMEM(ctx), finish);
Michal Vasko4968b9c2018-08-14 13:43:52 +02001222 lybs.used = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001223 lybs.size = LYB_STATE_STEP;
Michal Vasko4968b9c2018-08-14 13:43:52 +02001224 lybs.models = NULL;
1225 lybs.mod_count = 0;
Michal Vaskoeda0a6d2019-02-21 09:36:47 +01001226 lybs.ctx = ctx;
Michal Vasko228431e2018-07-10 15:47:11 +02001227
1228 unres = calloc(1, sizeof *unres);
1229 LY_CHECK_ERR_GOTO(!unres, LOGMEM(ctx), finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001230
Michal Vasko5c445042018-08-28 16:27:45 +02001231 /* read magic number */
1232 ret += (r = lyb_parse_magic_number(data, &lybs));
1233 LYB_HAVE_READ_GOTO(r, data, finish);
1234
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001235 /* read header */
1236 ret += (r = lyb_parse_header(data, &lybs));
1237 LYB_HAVE_READ_GOTO(r, data, finish);
1238
Michal Vasko228431e2018-07-10 15:47:11 +02001239 /* read used models */
Michal Vaskoeda0a6d2019-02-21 09:36:47 +01001240 ret += (r = lyb_parse_data_models(data, &lybs));
Michal Vasko228431e2018-07-10 15:47:11 +02001241 LYB_HAVE_READ_GOTO(r, data, finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001242
1243 /* read subtree(s) */
1244 while (data[0]) {
Michal Vaskoeda0a6d2019-02-21 09:36:47 +01001245 ret += (r = lyb_parse_subtree(data, NULL, &node, yang_data_name, options, unres, &lybs));
Michal Vasko228431e2018-07-10 15:47:11 +02001246 if (r < 0) {
1247 lyd_free_withsiblings(node);
1248 node = NULL;
1249 goto finish;
1250 }
1251 data += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001252 }
1253
1254 /* read the last zero, parsing finished */
1255 ++ret;
1256 r = ret;
1257
Michal Vasko228431e2018-07-10 15:47:11 +02001258 if (options & LYD_OPT_DATA_ADD_YANGLIB) {
1259 if (lyd_merge(node, ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
1260 LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
1261 lyd_free_withsiblings(node);
1262 node = NULL;
1263 goto finish;
1264 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001265 }
Michal Vasko228431e2018-07-10 15:47:11 +02001266
1267 /* resolve any unresolved instance-identifiers */
1268 if (unres->count) {
1269 if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
1270 LY_TREE_DFS_BEGIN(node, next, act_notif) {
1271 if (act_notif->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1272 break;
1273 }
1274 LY_TREE_DFS_END(node, next, act_notif);
1275 }
1276 }
Michal Vasko993af1e2018-12-10 12:05:17 +01001277 if (lyd_defaults_add_unres(&node, options, ctx, NULL, 0, data_tree, act_notif, unres, 0)) {
Michal Vasko228431e2018-07-10 15:47:11 +02001278 lyd_free_withsiblings(node);
1279 node = NULL;
1280 goto finish;
1281 }
1282 }
1283
1284finish:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001285 free(lybs.written);
1286 free(lybs.position);
Michal Vaskoa9852522018-08-08 16:24:45 +02001287 free(lybs.inner_chunks);
Michal Vasko228431e2018-07-10 15:47:11 +02001288 free(lybs.models);
1289 if (unres) {
1290 free(unres->node);
1291 free(unres->type);
1292 free(unres);
1293 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001294
1295 if (parsed) {
1296 *parsed = r;
1297 }
1298 return node;
1299}