blob: dc479449e098dfbac55d156173ab7d9eb3fa61f9 [file] [log] [blame]
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001/**
2 * @file parser_lyb.c
3 * @author Michal Vasko <mvasko@cesnet.cz>
4 * @brief LYB data parser for libyang
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#include <assert.h>
16#include <errno.h>
17#include <stdlib.h>
18#include <string.h>
19
20#include "libyang.h"
21#include "common.h"
22#include "context.h"
23#include "parser.h"
24#include "tree_internal.h"
25
26#define LYB_HAVE_READ_GOTO(r, d, go) if (r < 0) goto go; d += r;
27#define LYB_HAVE_READ_RETURN(r, d, ret) if (r < 0) return ret; d += r;
28
29static int
30lyb_read(const char *data, uint8_t *buf, size_t count, struct lyb_state *lybs)
31{
32 int ret = 0, i, empty_chunk_i;
33 size_t to_read;
34
35 assert(data && lybs);
36
37 while (1) {
38 /* check for fully-read (empty) data chunks */
39 to_read = count;
40 empty_chunk_i = -1;
41 for (i = 0; i < lybs->used; ++i) {
42 /* we want the innermost chunks resolved first, so replace previous empty chunks,
43 * also ignore chunks that are completely finished, there is nothing for us to do */
Michal Vaskoae4b7d32018-07-13 12:21:01 +020044 if ((lybs->written[i] <= to_read) && lybs->position[i]) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +020045 /* empty chunk, do not read more */
46 to_read = lybs->written[i];
47 empty_chunk_i = i;
48 }
49 }
50
51 if ((empty_chunk_i == -1) && !count) {
52 break;
53 }
54
55 /* we are actually reading some data, not just finishing another chunk */
56 if (to_read) {
Michal Vasko228431e2018-07-10 15:47:11 +020057 if (buf) {
58 memcpy(buf, data + ret, to_read);
59 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +020060
61 for (i = 0; i < lybs->used; ++i) {
62 /* decrease all written counters */
63 lybs->written[i] -= to_read;
Michal Vaskoae4b7d32018-07-13 12:21:01 +020064 assert(lybs->written[i] <= LYB_SIZE_MAX);
Michal Vasko1e82a3b2018-07-03 12:16:58 +020065 }
66 /* decrease count/buf */
67 count -= to_read;
Michal Vasko228431e2018-07-10 15:47:11 +020068 if (buf) {
69 buf += to_read;
70 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +020071
72 ret += to_read;
73 }
74
75 if (empty_chunk_i > -1) {
76 /* read the next chunk size */
77 memcpy(&lybs->written[empty_chunk_i], data + ret, LYB_SIZE_BYTES);
78 /* remember whether there is a following chunk or not */
79 lybs->position[empty_chunk_i] = (lybs->written[empty_chunk_i] == LYB_SIZE_MAX ? 1 : 0);
80
81 ret += LYB_SIZE_BYTES;
82 }
83 }
84
85 return ret;
86}
87
88static int
89lyb_read_number(uint64_t *num, uint64_t max_num, const char *data, struct lyb_state *lybs)
90{
91 int max_bits, max_bytes, i, r, ret = 0;
Michal Vasko228431e2018-07-10 15:47:11 +020092 uint8_t byte;
Michal Vasko1e82a3b2018-07-03 12:16:58 +020093
94 for (max_bits = 0; max_num; max_num >>= 1, ++max_bits);
95 max_bytes = max_bits / 8 + (max_bits % 8 ? 1 : 0);
96
Michal Vasko1e82a3b2018-07-03 12:16:58 +020097 for (i = 0; i < max_bytes; ++i) {
Michal Vasko228431e2018-07-10 15:47:11 +020098 ret += (r = lyb_read(data, &byte, 1, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +020099 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vasko228431e2018-07-10 15:47:11 +0200100
101 *(((uint8_t *)num) + i) = byte;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200102 }
103
104 return ret;
105}
106
107static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200108lyb_read_string(const char *data, char **str, int with_length, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200109{
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200110 int r, ret = 0;
111 size_t len = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200112
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200113 if (with_length) {
114 ret += (r = lyb_read(data, (uint8_t *)&len, 2, lybs));
115 LYB_HAVE_READ_GOTO(r, data, error);
116 } else {
117 /* read until the end of this subtree */
118 len = lybs->written[lybs->used - 1];
119 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200120
121 *str = malloc((len + 1) * sizeof **str);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200122 LY_CHECK_ERR_RETURN(!*str, LOGMEM(NULL), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200123
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200124 ret += (r = lyb_read(data, (uint8_t *)*str, len, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200125 LYB_HAVE_READ_GOTO(ret, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200126
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200127 ((char *)*str)[len] = '\0';
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200128 return ret;
129
130error:
131 free((char *)*str);
132 *str = NULL;
133 return -1;
134}
135
136static void
137lyb_read_stop_subtree(struct lyb_state *lybs)
138{
139 if (lybs->written[lybs->used - 1]) {
140 LOGINT(NULL);
141 }
142
143 --lybs->used;
144}
145
146static int
147lyb_read_start_subtree(const char *data, struct lyb_state *lybs)
148{
149 uint64_t num = 0;
150
151 if (lybs->used == lybs->size) {
152 lybs->size += LYB_STATE_STEP;
153 lybs->written = ly_realloc(lybs->written, lybs->size * sizeof *lybs->written);
154 lybs->position = ly_realloc(lybs->position, lybs->size * sizeof *lybs->position);
155 LY_CHECK_ERR_RETURN(!lybs->written || !lybs->position, LOGMEM(NULL), -1);
156 }
157
158 memcpy(&num, data, LYB_SIZE_BYTES);
159
160 ++lybs->used;
161 lybs->written[lybs->used - 1] = num;
162 lybs->position[lybs->used - 1] = (num == LYB_SIZE_MAX ? 1 : 0);
163
164 return LYB_SIZE_BYTES;
165}
166
167static int
168lyb_parse_model(struct ly_ctx *ctx, const char *data, const struct lys_module **mod, struct lyb_state *lybs)
169{
170 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200171 char *mod_name = NULL, mod_rev[11];
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200172 uint16_t rev = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200173
174 /* model name */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200175 ret += (r = lyb_read_string(data, &mod_name, 1, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200176 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200177
178 /* revision */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200179 ret += (r = lyb_read(data, (uint8_t *)&rev, sizeof rev, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200180 LYB_HAVE_READ_GOTO(r, data, error);
181
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200182 if (rev) {
183 sprintf(mod_rev, "%04u-%02u-%02u", ((rev & 0xFE00) >> 9) + 2000, (rev & 0x01E0) >> 5, (rev & 0x001F));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200184 *mod = ly_ctx_get_module(ctx, mod_name, mod_rev, 0);
185 } else {
186 *mod = ly_ctx_get_module(ctx, mod_name, NULL, 0);
187 }
188 if (!*mod) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200189 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Module \"%s@%s\" not found in the context.", mod_name, (rev ? mod_rev : "<none>"));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200190 goto error;
191 }
192
193 free(mod_name);
194 return ret;
195
196error:
197 free(mod_name);
198 return -1;
199}
200
201static struct lyd_node *
202lyb_new_node(const struct lys_node *schema)
203{
204 struct lyd_node *node;
205
206 switch (schema->nodetype) {
207 case LYS_CONTAINER:
208 case LYS_LIST:
209 case LYS_NOTIF:
210 case LYS_RPC:
211 case LYS_ACTION:
212 node = calloc(sizeof(struct lyd_node), 1);
213 break;
214 case LYS_LEAF:
215 case LYS_LEAFLIST:
216 node = calloc(sizeof(struct lyd_node_leaf_list), 1);
Michal Vaskob7400232018-07-11 15:35:57 +0200217
218 if (((struct lys_node_leaf *)schema)->type.base == LY_TYPE_LEAFREF) {
219 node->validity |= LYD_VAL_LEAFREF;
220 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200221 break;
222 case LYS_ANYDATA:
223 case LYS_ANYXML:
224 node = calloc(sizeof(struct lyd_node_anydata), 1);
225 break;
226 default:
227 return NULL;
228 }
229 LY_CHECK_ERR_RETURN(!node, LOGMEM(schema->module->ctx), NULL);
230
231 /* fill basic info */
232 node->schema = (struct lys_node *)schema;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200233 if (resolve_applies_when(schema, 0, NULL)) {
234 node->when_status = LYD_WHEN;
235 }
236 node->prev = node;
237
238 return node;
239}
240
241static int
242lyb_parse_anydata(struct lyd_node *node, const char *data, struct lyb_state *lybs)
243{
244 int r, ret = 0;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200245 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200246 struct lyd_node_anydata *any = (struct lyd_node_anydata *)node;
247
248 /* read value type */
249 ret += (r = lyb_read(data, (uint8_t *)&any->value_type, sizeof any->value_type, lybs));
250 LYB_HAVE_READ_RETURN(r, data, -1);
251
252 /* read anydata content */
253 if (any->value_type == LYD_ANYDATA_DATATREE) {
Michal Vasko228431e2018-07-10 15:47:11 +0200254 any->value.tree = lyd_parse_lyb(node->schema->module->ctx, data, 0, NULL, NULL, &r);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200255 ret += r;
256 LYB_HAVE_READ_RETURN(r, data, -1);
257 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200258 ret += (r = lyb_read_string(data, &str, 0, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200259 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200260
261 /* add to dictionary */
262 any->value.str = lydict_insert_zc(node->schema->module->ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200263 }
264
265 return ret;
266}
267
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200268/* generally, fill lyd_val value union */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200269static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200270lyb_parse_val_1(struct ly_ctx *ctx, struct lys_type *type, LY_DATA_TYPE value_type, uint8_t value_flags, const char *data,
271 const char **value_str, lyd_val *value, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200272{
Michal Vasko228431e2018-07-10 15:47:11 +0200273 int r, ret;
274 size_t i;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200275 char *str = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200276 uint8_t byte;
Michal Vasko228431e2018-07-10 15:47:11 +0200277 uint64_t num;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200278
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200279 if (value_flags & (LY_VALUE_USER | LY_VALUE_UNRES)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200280 /* just read value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200281 ret = lyb_read_string(data, &str, 0, lybs);
282 if (ret > -1) {
283 *value_str = lydict_insert_zc(ctx, str);
284 }
285 return ret;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200286 }
287
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200288 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200289 case LY_TYPE_INST:
290 case LY_TYPE_IDENT:
291 case LY_TYPE_UNION:
292 /* we do not actually fill value now, but value_str */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200293 ret = lyb_read_string(data, &str, 0, lybs);
294 if (ret > -1) {
295 *value_str = lydict_insert_zc(ctx, str);
296 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200297 break;
298 case LY_TYPE_BINARY:
299 case LY_TYPE_STRING:
300 case LY_TYPE_UNKNOWN:
301 /* read string */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200302 ret = lyb_read_string(data, &str, 0, lybs);
303 if (ret > -1) {
304 value->string = lydict_insert_zc(ctx, str);
305 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200306 break;
307 case LY_TYPE_BITS:
308 /* find the correct structure */
309 for (; !type->info.bits.count; type = &type->der->type);
310
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200311 value->bit = calloc(type->info.bits.count, sizeof *value->bit);
312 LY_CHECK_ERR_RETURN(!value->bit, LOGMEM(ctx), -1);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200313
314 /* read values */
Michal Vasko228431e2018-07-10 15:47:11 +0200315 ret = 0;
316 for (i = 0; i < type->info.bits.count; ++i) {
317 if (i % 8 == 0) {
318 /* read another byte */
319 ret += (r = lyb_read(data, &byte, sizeof byte, lybs));
320 if (r < 0) {
321 return -1;
322 }
323 }
324
325 if (byte & (0x01 << (i % 8))) {
326 /* bit is set */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200327 value->bit[i] = &type->info.bits.bit[i];
Michal Vasko228431e2018-07-10 15:47:11 +0200328 }
329 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200330 break;
331 case LY_TYPE_BOOL:
332 /* read byte */
333 ret = lyb_read(data, &byte, sizeof byte, lybs);
334 if ((ret > 0) && byte) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200335 value->bln = 1;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200336 }
337 break;
338 case LY_TYPE_EMPTY:
339 /* nothing to read */
340 ret = 0;
341 break;
342 case LY_TYPE_ENUM:
343 /* find the correct structure */
Michal Vasko228431e2018-07-10 15:47:11 +0200344 for (; !type->info.enums.count; type = &type->der->type);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200345
Michal Vasko228431e2018-07-10 15:47:11 +0200346 num = 0;
Michal Vaskob7400232018-07-11 15:35:57 +0200347 ret = lyb_read_number(&num, type->info.enums.count, data, lybs);
348 if (ret > 0) {
349 assert(num < type->info.enums.count);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200350 value->enm = &type->info.enums.enm[num];
Michal Vasko228431e2018-07-10 15:47:11 +0200351 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200352 break;
353 case LY_TYPE_INT8:
354 case LY_TYPE_UINT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200355 ret = lyb_read_number((uint64_t *)&value->uint8, UINT8_MAX, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200356 break;
357 case LY_TYPE_INT16:
358 case LY_TYPE_UINT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200359 ret = lyb_read_number((uint64_t *)&value->uint16, UINT16_MAX, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200360 break;
361 case LY_TYPE_INT32:
362 case LY_TYPE_UINT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200363 ret = lyb_read_number((uint64_t *)&value->uint32, UINT32_MAX, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200364 break;
365 case LY_TYPE_DEC64:
366 case LY_TYPE_INT64:
367 case LY_TYPE_UINT64:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200368 ret = lyb_read_number((uint64_t *)&value->uint64, UINT64_MAX, data, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200369 break;
370 default:
371 return -1;
372 }
373
374 return ret;
375}
376
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200377/* generally, fill value_str */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200378static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200379lyb_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 +0200380{
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200381 struct ly_ctx *ctx;
382 struct lys_module *mod;
Michal Vasko228431e2018-07-10 15:47:11 +0200383 char num_str[22], *str;
Michal Vasko27e5e682018-07-23 14:22:57 +0200384 int64_t frac;
Michal Vasko228431e2018-07-10 15:47:11 +0200385 uint32_t i, str_len;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200386 uint8_t *value_flags;
387 const char **value_str;
388 LY_DATA_TYPE value_type;
389 lyd_val *value;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200390
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200391 if (leaf) {
392 ctx = leaf->schema->module->ctx;
393 mod = lys_node_module(leaf->schema);
394
395 value = &leaf->value;
396 value_str = &leaf->value_str;
397 value_flags = &leaf->value_flags;
398 value_type = leaf->value_type;
399 } else {
400 ctx = attr->annotation->module->ctx;
401 mod = lys_main_module(attr->annotation->module);
402
403 value = &attr->value;
404 value_str = &attr->value_str;
405 value_flags = &attr->value_flags;
406 value_type = attr->value_type;
407 }
408
409 if (*value_flags & LY_VALUE_UNRES) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200410 /* nothing to do */
411 return 0;
412 }
413
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200414 if (*value_flags & LY_VALUE_USER) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200415 /* unfortunately, we need to also fill the value properly, so just parse it again */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200416 *value_flags &= ~LY_VALUE_USER;
417 if (!lyp_parse_value(type, value_str, NULL, leaf, attr, NULL, 1, (leaf ? leaf->dflt : 0), 1)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200418 return -1;
419 }
420
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200421 if (!(*value_flags & LY_VALUE_USER)) {
422 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 +0200423 }
424 return 0;
425 }
426
Michal Vaskob7400232018-07-11 15:35:57 +0200427 /* we are parsing leafref/ptr union stored as the target type,
428 * so we first parse it into string and then resolve the leafref/ptr union */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200429 if ((type->base == LY_TYPE_LEAFREF) || (type->base == LY_TYPE_INST) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type)) {
430 if ((value_type == LY_TYPE_INST) || (value_type == LY_TYPE_IDENT) || (value_type == LY_TYPE_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200431 /* we already have a string */
432 goto parse_reference;
433 }
434 }
435
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200436 switch (value_type) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200437 case LY_TYPE_IDENT:
438 /* fill the identity pointer now */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200439 value->ident = resolve_identref(type, *value_str, (struct lyd_node *)leaf, mod, (leaf ? leaf->dflt : 0));
440 if (!value->ident) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200441 return -1;
442 }
443 break;
444 case LY_TYPE_BINARY:
445 case LY_TYPE_STRING:
446 case LY_TYPE_UNKNOWN:
447 /* just re-assign it */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200448 *value_str = value->string;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200449 break;
450 case LY_TYPE_BITS:
Michal Vasko228431e2018-07-10 15:47:11 +0200451 for (; !type->info.bits.count; type = &type->der->type);
452
453 /* print the set bits */
454 str = malloc(1);
455 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
456 str[0] = '\0';
Michal Vaskob7400232018-07-11 15:35:57 +0200457 str_len = 0;
Michal Vasko228431e2018-07-10 15:47:11 +0200458 for (i = 0; i < type->info.bits.count; ++i) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200459 if (value->bit[i]) {
460 str = ly_realloc(str, str_len + strlen(value->bit[i]->name) + (str_len ? 1 : 0) + 1);
Michal Vasko228431e2018-07-10 15:47:11 +0200461 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
462
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200463 str_len += sprintf(str + str_len, "%s%s", str_len ? " " : "", value->bit[i]->name);
Michal Vasko228431e2018-07-10 15:47:11 +0200464 }
465 }
466
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200467 *value_str = lydict_insert_zc(ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200468 break;
469 case LY_TYPE_BOOL:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200470 *value_str = lydict_insert(ctx, (value->bln ? "true" : "false"), 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200471 break;
472 case LY_TYPE_EMPTY:
Michal Vasko27e5e682018-07-23 14:22:57 +0200473 *value_str = lydict_insert(ctx, "", 0);
474 break;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200475 case LY_TYPE_UNION:
Michal Vasko27e5e682018-07-23 14:22:57 +0200476 if (attr) {
477 /* we do not support union type attribute */
478 LOGINT(ctx);
479 return -1;
480 }
481
482 if (resolve_union(leaf, type, 1, 2, NULL)) {
483 return -1;
484 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200485 break;
486 case LY_TYPE_ENUM:
Michal Vasko228431e2018-07-10 15:47:11 +0200487 /* print the value */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200488 *value_str = lydict_insert(ctx, value->enm->name, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200489 break;
490 case LY_TYPE_INT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200491 sprintf(num_str, "%d", value->int8);
492 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200493 break;
494 case LY_TYPE_UINT8:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200495 sprintf(num_str, "%u", value->uint8);
496 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200497 break;
498 case LY_TYPE_INT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200499 sprintf(num_str, "%d", value->int16);
500 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200501 break;
502 case LY_TYPE_UINT16:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200503 sprintf(num_str, "%u", value->uint16);
504 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200505 break;
506 case LY_TYPE_INT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200507 sprintf(num_str, "%d", value->int32);
508 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200509 break;
510 case LY_TYPE_UINT32:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200511 sprintf(num_str, "%u", value->uint32);
512 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200513 break;
514 case LY_TYPE_INT64:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200515 sprintf(num_str, "%ld", value->int64);
516 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200517 break;
518 case LY_TYPE_UINT64:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200519 sprintf(num_str, "%lu", value->uint64);
520 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200521 break;
522 case LY_TYPE_DEC64:
Michal Vasko27e5e682018-07-23 14:22:57 +0200523 frac = value->dec64 % type->info.dec64.div;
524 sprintf(num_str, "%ld.%.*ld", value->dec64 / (int64_t)type->info.dec64.div, frac ? type->info.dec64.dig : 1, frac);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200525 *value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200526 break;
527 default:
528 return -1;
529 }
530
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200531 if ((type->base == LY_TYPE_LEAFREF) || (type->base == LY_TYPE_INST) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200532parse_reference:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200533 assert(*value_str);
Michal Vaskob7400232018-07-11 15:35:57 +0200534
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200535 if (attr) {
536 /* we do not support reference types of attributes */
537 LOGINT(ctx);
538 return -1;
539 }
540
541 if (type->base == LY_TYPE_INST) {
542 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_INSTID)) {
543 return -1;
544 }
545 } else if (type->base == LY_TYPE_LEAFREF) {
546 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_LEAFREF)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200547 return -1;
548 }
549 } else {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200550 if (unres_data_add(unres, (struct lyd_node *)leaf, UNRES_UNION)) {
Michal Vaskob7400232018-07-11 15:35:57 +0200551 return -1;
552 }
553 }
554 }
555
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200556 return 0;
557}
558
559static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200560lyb_parse_value(struct lys_type *type, struct lyd_node_leaf_list *leaf, struct lyd_attr *attr, const char *data,
561 struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200562{
563 int r, ret = 0;
564 uint8_t start_byte;
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200565
566 struct ly_ctx *ctx;
567 const char **value_str;
568 lyd_val *value;
569 LY_DATA_TYPE *value_type;
570 uint8_t *value_flags;
571
572 assert((leaf || attr) && (!leaf || !attr));
573
574 if (leaf) {
575 ctx = leaf->schema->module->ctx;
576 value_str = &leaf->value_str;
577 value = &leaf->value;
578 value_type = &leaf->value_type;
579 value_flags = &leaf->value_flags;
580 } else {
581 ctx = attr->annotation->module->ctx;
582 value_str = &attr->value_str;
583 value = &attr->value;
584 value_type = &attr->value_type;
585 value_flags = &attr->value_flags;
586 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200587
588 /* read value type and flags on the first byte */
589 ret += (r = lyb_read(data, &start_byte, sizeof start_byte, lybs));
590 LYB_HAVE_READ_RETURN(r, data, -1);
591
592 /* fill value type, flags */
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200593 *value_type = start_byte & 0x1F;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200594 if (start_byte & 0x80) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200595 assert(leaf);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200596 leaf->dflt = 1;
597 }
598 if (start_byte & 0x40) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200599 *value_flags |= LY_VALUE_USER;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200600 }
601 if (start_byte & 0x20) {
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200602 *value_flags |= LY_VALUE_UNRES;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200603 }
604
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200605 ret += (r = lyb_parse_val_1(ctx, type, *value_type, *value_flags, data, value_str, value, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200606 LYB_HAVE_READ_RETURN(r, data, -1);
607
Michal Vasko27e5e682018-07-23 14:22:57 +0200608 /* union is handled specially */
609 if (type->base == LY_TYPE_UNION) {
610 assert(*value_type == LY_TYPE_STRING);
611
612 *value_str = value->string;
613 value->string = NULL;
614 *value_type = LY_TYPE_UNION;
615 }
616
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200617 ret += (r = lyb_parse_val_2(type, leaf, attr, unres));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200618 LYB_HAVE_READ_RETURN(r, data, -1);
619
620 return ret;
621}
622
623static int
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200624lyb_parse_attr_name(const struct lys_module *mod, const char *data, struct lys_ext_instance_complex **ext, int options,
625 struct lyb_state *lybs)
626{
627 int r, ret = 0, pos, i, j, k;
628 const struct lys_submodule *submod = NULL;
629 char *attr_name = NULL;
630
631 /* attr name */
632 ret += (r = lyb_read_string(data, &attr_name, 1, lybs));
633 LYB_HAVE_READ_RETURN(r, data, -1);
634
635 /* search module */
636 pos = -1;
637 for (i = 0, j = 0; i < mod->ext_size; i = i + j + 1) {
638 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &mod->ext[i], mod->ext_size - i);
639 if (j == -1) {
640 break;
641 }
642 if (ly_strequal(mod->ext[i + j]->arg_value, attr_name, 0)) {
643 pos = i + j;
644 break;
645 }
646 }
647
648 /* try submodules */
649 if (pos == -1) {
650 for (k = 0; k < mod->inc_size; ++k) {
651 submod = mod->inc[k].submodule;
652 for (i = 0, j = 0; i < submod->ext_size; i = i + j + 1) {
653 j = lys_ext_instance_presence(&mod->ctx->models.list[0]->extensions[0], &submod->ext[i], submod->ext_size - i);
654 if (j == -1) {
655 break;
656 }
657 if (ly_strequal(submod->ext[i + j]->arg_value, attr_name, 0)) {
658 pos = i + j;
659 break;
660 }
661 }
662 }
663 }
664
665 if (pos == -1) {
666 *ext = NULL;
667 } else {
668 *ext = submod ? (struct lys_ext_instance_complex *)submod->ext[pos] : (struct lys_ext_instance_complex *)mod->ext[pos];
669 }
670
671 if (!*ext && (options & LYD_OPT_STRICT)) {
672 LOGVAL(mod->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find annotation \"%s\" in \"%s\".", attr_name, mod->name);
673 free(attr_name);
674 return -1;
675 }
676
677 free(attr_name);
678 return ret;
679}
680
681static int
682lyb_parse_attributes(struct lyd_node *node, const char *data, int options, struct unres_data *unres, struct lyb_state *lybs)
683{
684 int r, ret = 0;
685 uint8_t i, count = 0;
686 const struct lys_module *mod;
687 struct lys_type *type;
688 struct lyd_attr *attr = NULL;
689 struct lys_ext_instance_complex *ext;
690 struct ly_ctx *ctx = node->schema->module->ctx;
691
692 /* read number of attributes stored */
693 ret += (r = lyb_read(data, &count, 1, lybs));
694 LYB_HAVE_READ_GOTO(r, data, error);
695
696 /* read attributes */
697 for (i = 0; i < count; ++i) {
698 ret += (r = lyb_read_start_subtree(data, lybs));
699 LYB_HAVE_READ_GOTO(r, data, error);
700
701 /* find model */
702 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
703 LYB_HAVE_READ_GOTO(r, data, error);
704
705 /* annotation name */
706 ret += (r = lyb_parse_attr_name(mod, data, &ext, options, lybs));
707 LYB_HAVE_READ_GOTO(r, data, error);
708
709 if (!ext) {
710 /* unknown attribute, skip it */
711 do {
712 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200713 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200714 } while (lybs->written[lybs->used - 1]);
715 goto stop_subtree;
716 }
717
718 /* allocate new attribute */
719 if (!attr) {
720 assert(!node->attr);
721
722 attr = calloc(1, sizeof *attr);
723 LY_CHECK_ERR_GOTO(!attr, LOGMEM(ctx), error);
724
725 node->attr = attr;
726 } else {
727 attr->next = calloc(1, sizeof *attr);
728 LY_CHECK_ERR_GOTO(!attr->next, LOGMEM(ctx), error);
729
730 attr = attr->next;
731 }
732
733 /* attribute annotation */
734 attr->annotation = ext;
735
736 /* attribute name */
737 attr->name = lydict_insert(ctx, attr->annotation->arg_value, 0);
738
739 /* get the type */
740 type = *(struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, attr->annotation, NULL);
741
742 /* attribute value */
743 ret += (r = lyb_parse_value(type, NULL, attr, data, unres, lybs));
Michal Vasko27e5e682018-07-23 14:22:57 +0200744 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200745
746stop_subtree:
747 lyb_read_stop_subtree(lybs);
748 }
749
750 return ret;
751
752error:
753 lyd_free_attr(ctx, node, node->attr, 1);
754 return -1;
755}
756
757static int
Michal Vaskob7400232018-07-11 15:35:57 +0200758lyb_is_schema_hash_match(struct lys_node *sibling, LYB_HASH *hash, uint8_t hash_count)
Michal Vasko228431e2018-07-10 15:47:11 +0200759{
760 LYB_HASH sibling_hash;
Michal Vaskob7400232018-07-11 15:35:57 +0200761 uint8_t i;
Michal Vasko228431e2018-07-10 15:47:11 +0200762
Michal Vaskob7400232018-07-11 15:35:57 +0200763 /* compare all the hashes starting from collision ID 0 */
764 for (i = 0; i < hash_count; ++i) {
765 sibling_hash = lyb_hash(sibling, i);
766 if (sibling_hash != hash[i]) {
767 return 0;
768 }
769 }
Michal Vasko228431e2018-07-10 15:47:11 +0200770
Michal Vaskob7400232018-07-11 15:35:57 +0200771 return 1;
Michal Vasko228431e2018-07-10 15:47:11 +0200772}
773
774static int
775lyb_parse_schema_hash(const struct lys_node *sparent, const struct lys_module *mod, const char *data, const char *yang_data_name,
776 int options, struct lys_node **snode, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200777{
778 int r, ret = 0;
Michal Vaskob7400232018-07-11 15:35:57 +0200779 uint8_t i, j;
780 struct lys_node *sibling;
781 LYB_HASH hash[LYB_HASH_BITS - 1];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200782 struct ly_ctx *ctx;
783
784 assert((sparent || mod) && (!sparent || !mod));
785 ctx = (sparent ? sparent->module->ctx : mod->ctx);
786
Michal Vaskob7400232018-07-11 15:35:57 +0200787 /* read the first hash */
788 ret += (r = lyb_read(data, &hash[0], sizeof *hash, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200789 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskob7400232018-07-11 15:35:57 +0200790
791 /* based on the first hash read all the other ones, if any */
792 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i);
793
794 /* move the first hash on its accurate position */
795 hash[i] = hash[0];
796
797 /* read the rest of hashes */
798 for (j = i; j; --j) {
799 ret += (r = lyb_read(data, &hash[j - 1], sizeof *hash, lybs));
800 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200801
802 if (!(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)))) {
803 LOGERR(ctx, LY_EINT, "Invalid hash read with collision ID %d (0x%x).", j - 1, hash[j - 1]);
804 return -1;
805 }
Michal Vasko228431e2018-07-10 15:47:11 +0200806 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200807
Michal Vaskoe3880e62018-07-11 16:18:34 +0200808 /* handle yang data templates */
809 if ((options & LYD_OPT_DATA_TEMPLATE) && yang_data_name && mod) {
810 sparent = lyp_get_yang_data_template(mod, yang_data_name, strlen(yang_data_name));
811 if (!sparent) {
812 sibling = NULL;
813 goto finish;
814 }
815 }
816
817 /* handle RPC/action input/output */
Michal Vaskob7400232018-07-11 15:35:57 +0200818 if (sparent && (sparent->nodetype & (LYS_RPC | LYS_ACTION))) {
819 sibling = NULL;
820 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, NULL, LYS_GETNEXT_WITHINOUT))) {
821 if ((sibling->nodetype == LYS_INPUT) && (options & LYD_OPT_RPC)) {
822 break;
823 }
824 if ((sibling->nodetype == LYS_OUTPUT) && (options & LYD_OPT_RPCREPLY)) {
825 break;
826 }
827 }
828 if (!sibling) {
829 /* fail */
830 goto finish;
831 }
832
833 /* use only input/output children nodes */
834 sparent = sibling;
835 }
836
837 /* find our node with matching hashes */
838 sibling = NULL;
Michal Vasko228431e2018-07-10 15:47:11 +0200839 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, mod, 0))) {
840 /* skip schema nodes from models not present during printing */
Michal Vaskob7400232018-07-11 15:35:57 +0200841 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 +0200842 /* match found */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200843 break;
844 }
845 }
846
Michal Vaskob7400232018-07-11 15:35:57 +0200847finish:
Michal Vasko228431e2018-07-10 15:47:11 +0200848 *snode = sibling;
849 if (!sibling && (options & LYD_OPT_STRICT)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200850 if (mod) {
851 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find matching hash for a top-level node from \"%s\".", mod->name);
852 } else {
853 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, sparent, "Failed to find matching hash for a child of \"%s\".", sparent->name);
854 }
855 return -1;
856 }
857
858 return ret;
859}
860
861static int
862lyb_parse_subtree(struct ly_ctx *ctx, const char *data, struct lyd_node *parent, struct lyd_node **first_sibling,
Michal Vasko228431e2018-07-10 15:47:11 +0200863 const char *yang_data_name, int options, struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200864{
865 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200866 struct lyd_node *node = NULL, *iter;
867 const struct lys_module *mod;
Michal Vaskoe3880e62018-07-11 16:18:34 +0200868 struct lys_node *snode;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200869
870 assert((parent && !first_sibling) || (!parent && first_sibling));
871
872 /* register a new subtree */
873 ret += (r = lyb_read_start_subtree(data, lybs));
874 LYB_HAVE_READ_GOTO(r, data, error);
875
876 if (!parent) {
877 /* top-level, read module name */
878 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
879 LYB_HAVE_READ_GOTO(r, data, error);
880
Michal Vaskoe3880e62018-07-11 16:18:34 +0200881 /* read hash, find the schema node starting from mod, possibly yang_data_name */
882 r = lyb_parse_schema_hash(NULL, mod, data, yang_data_name, options, &snode, lybs);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200883 } else {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200884
Michal Vaskoe3880e62018-07-11 16:18:34 +0200885 /* read hash, find the schema node starting from parent schema */
886 r = lyb_parse_schema_hash(parent->schema, NULL, data, NULL, options, &snode, lybs);
887 }
888 ret += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200889 LYB_HAVE_READ_GOTO(r, data, error);
890
Michal Vasko228431e2018-07-10 15:47:11 +0200891 if (!snode) {
Michal Vasko997071e2018-07-10 15:56:14 +0200892 /* unknown data subtree, skip it whole */
893 do {
894 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
895 } while (lybs->written[lybs->used - 1]);
Michal Vasko228431e2018-07-10 15:47:11 +0200896 goto stop_subtree;
897 }
898
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200899 /*
900 * read the node
901 */
902 node = lyb_new_node(snode);
903 if (!node) {
904 goto error;
905 }
906
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200907 ret += (r = lyb_parse_attributes(node, data, options, unres, lybs));
908 LYB_HAVE_READ_GOTO(r, data, error);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200909
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200910 /* read node content */
911 switch (snode->nodetype) {
912 case LYS_CONTAINER:
913 case LYS_LIST:
Michal Vaskob7400232018-07-11 15:35:57 +0200914 case LYS_NOTIF:
915 case LYS_RPC:
916 case LYS_ACTION:
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200917 /* nothing to read */
918 break;
919 case LYS_LEAF:
920 case LYS_LEAFLIST:
Michal Vaskoae4b7d32018-07-13 12:21:01 +0200921 ret += (r = lyb_parse_value(&((struct lys_node_leaf *)node->schema)->type, (struct lyd_node_leaf_list *)node,
922 NULL, data, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200923 LYB_HAVE_READ_GOTO(r, data, error);
924 break;
925 case LYS_ANYXML:
926 case LYS_ANYDATA:
927 ret += (r = lyb_parse_anydata(node, data, lybs));
928 LYB_HAVE_READ_GOTO(r, data, error);
929 break;
930 default:
931 goto error;
932 }
933
934 /* insert into data tree, manually */
935 if (parent) {
936 if (!parent->child) {
937 /* only child */
938 parent->child = node;
939 } else {
940 /* last child */
941 parent->child->prev->next = node;
942 node->prev = parent->child->prev;
943 parent->child->prev = node;
944 }
945 node->parent = parent;
946 } else if (*first_sibling) {
947 /* last sibling */
948 (*first_sibling)->prev->next = node;
949 node->prev = (*first_sibling)->prev;
950 (*first_sibling)->prev = node;
951 } else {
952 /* only sibling */
953 *first_sibling = node;
954 }
955
956 /* read all descendants */
957 while (lybs->written[lybs->used - 1]) {
Michal Vasko228431e2018-07-10 15:47:11 +0200958 ret += (r = lyb_parse_subtree(ctx, data, node, NULL, NULL, options, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200959 LYB_HAVE_READ_GOTO(r, data, error);
960 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200961
962 /* make containers default if should be */
963 if (node->schema->nodetype == LYS_CONTAINER) {
964 LY_TREE_FOR(node->child, iter) {
965 if (!iter->dflt) {
966 break;
967 }
968 }
969
970 if (!iter) {
971 node->dflt = 1;
972 }
973 }
974
Michal Vasko228431e2018-07-10 15:47:11 +0200975stop_subtree:
976 /* end the subtree */
977 lyb_read_stop_subtree(lybs);
978
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200979 return ret;
980
981error:
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200982 lyd_free(node);
Michal Vaskob7400232018-07-11 15:35:57 +0200983 if (first_sibling && (*first_sibling == node)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200984 *first_sibling = NULL;
985 }
986 return -1;
987}
988
989static int
Michal Vasko228431e2018-07-10 15:47:11 +0200990lyb_parse_data_models(struct ly_ctx *ctx, const char *data, struct lyb_state *lybs)
991{
992 int i, r, ret = 0;
993
994 /* read model count */
995 ret += (r = lyb_read(data, (uint8_t *)&lybs->mod_count, 2, lybs));
996 LYB_HAVE_READ_RETURN(r, data, -1);
997
998 lybs->models = malloc(lybs->mod_count * sizeof *lybs->models);
999 LY_CHECK_ERR_RETURN(!lybs->models, LOGMEM(NULL), -1);
1000
1001 /* read modules */
1002 for (i = 0; i < lybs->mod_count; ++i) {
1003 ret += (r = lyb_parse_model(ctx, data, &lybs->models[i], lybs));
1004 LYB_HAVE_READ_RETURN(r, data, -1);
1005 }
1006
1007 return ret;
1008}
1009
1010static int
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001011lyb_parse_header(const char *data, struct lyb_state *lybs)
1012{
1013 int ret = 0;
1014 uint8_t byte = 0;
1015
Michal Vasko228431e2018-07-10 15:47:11 +02001016 /* TODO version, any flags? */
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001017 ret += lyb_read(data, (uint8_t *)&byte, sizeof byte, lybs);
1018
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001019 return ret;
1020}
1021
1022struct lyd_node *
Michal Vasko228431e2018-07-10 15:47:11 +02001023lyd_parse_lyb(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *data_tree,
1024 const char *yang_data_name, int *parsed)
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001025{
1026 int r, ret = 0;
Michal Vasko228431e2018-07-10 15:47:11 +02001027 struct lyd_node *node = NULL, *next, *act_notif = NULL;
1028 struct unres_data *unres = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001029 struct lyb_state lybs;
1030
1031 if (!ctx || !data) {
1032 LOGARG;
1033 return NULL;
1034 }
1035
1036 lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
1037 lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
1038 LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position, LOGMEM(ctx), finish);
1039 lybs.used = 0;
1040 lybs.size = LYB_STATE_STEP;
Michal Vasko228431e2018-07-10 15:47:11 +02001041 lybs.models = NULL;
1042 lybs.mod_count = 0;
1043
1044 unres = calloc(1, sizeof *unres);
1045 LY_CHECK_ERR_GOTO(!unres, LOGMEM(ctx), finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001046
1047 /* read header */
1048 ret += (r = lyb_parse_header(data, &lybs));
1049 LYB_HAVE_READ_GOTO(r, data, finish);
1050
Michal Vasko228431e2018-07-10 15:47:11 +02001051 /* read used models */
1052 ret += (r = lyb_parse_data_models(ctx, data, &lybs));
1053 LYB_HAVE_READ_GOTO(r, data, finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001054
1055 /* read subtree(s) */
1056 while (data[0]) {
Michal Vasko228431e2018-07-10 15:47:11 +02001057 ret += (r = lyb_parse_subtree(ctx, data, NULL, &node, yang_data_name, options, unres, &lybs));
1058 if (r < 0) {
1059 lyd_free_withsiblings(node);
1060 node = NULL;
1061 goto finish;
1062 }
1063 data += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001064 }
1065
1066 /* read the last zero, parsing finished */
1067 ++ret;
1068 r = ret;
1069
Michal Vasko228431e2018-07-10 15:47:11 +02001070 if (options & LYD_OPT_DATA_ADD_YANGLIB) {
1071 if (lyd_merge(node, ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
1072 LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
1073 lyd_free_withsiblings(node);
1074 node = NULL;
1075 goto finish;
1076 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001077 }
Michal Vasko228431e2018-07-10 15:47:11 +02001078
1079 /* resolve any unresolved instance-identifiers */
1080 if (unres->count) {
1081 if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
1082 LY_TREE_DFS_BEGIN(node, next, act_notif) {
1083 if (act_notif->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
1084 break;
1085 }
1086 LY_TREE_DFS_END(node, next, act_notif);
1087 }
1088 }
1089 if (lyd_defaults_add_unres(&node, options, ctx, data_tree, act_notif, unres, 0)) {
1090 lyd_free_withsiblings(node);
1091 node = NULL;
1092 goto finish;
1093 }
1094 }
1095
1096finish:
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001097 free(lybs.written);
1098 free(lybs.position);
Michal Vasko228431e2018-07-10 15:47:11 +02001099 free(lybs.models);
1100 if (unres) {
1101 free(unres->node);
1102 free(unres->type);
1103 free(unres);
1104 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +02001105
1106 if (parsed) {
1107 *parsed = r;
1108 }
1109 return node;
1110}