blob: 98d307dbe25f43fc48a6ef05a7e37d933ab89c8e [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 */
44 if ((lybs->written[i] <= count) && lybs->position[i]) {
45 /* 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;
64 }
65 /* decrease count/buf */
66 count -= to_read;
Michal Vasko228431e2018-07-10 15:47:11 +020067 if (buf) {
68 buf += to_read;
69 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +020070
71 ret += to_read;
72 }
73
74 if (empty_chunk_i > -1) {
75 /* read the next chunk size */
76 memcpy(&lybs->written[empty_chunk_i], data + ret, LYB_SIZE_BYTES);
77 /* remember whether there is a following chunk or not */
78 lybs->position[empty_chunk_i] = (lybs->written[empty_chunk_i] == LYB_SIZE_MAX ? 1 : 0);
79
80 ret += LYB_SIZE_BYTES;
81 }
82 }
83
84 return ret;
85}
86
87static int
88lyb_read_number(uint64_t *num, uint64_t max_num, const char *data, struct lyb_state *lybs)
89{
90 int max_bits, max_bytes, i, r, ret = 0;
Michal Vasko228431e2018-07-10 15:47:11 +020091 uint8_t byte;
Michal Vasko1e82a3b2018-07-03 12:16:58 +020092
93 for (max_bits = 0; max_num; max_num >>= 1, ++max_bits);
94 max_bytes = max_bits / 8 + (max_bits % 8 ? 1 : 0);
95
Michal Vasko1e82a3b2018-07-03 12:16:58 +020096 for (i = 0; i < max_bytes; ++i) {
Michal Vasko228431e2018-07-10 15:47:11 +020097 ret += (r = lyb_read(data, &byte, 1, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +020098 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vasko228431e2018-07-10 15:47:11 +020099
100 *(((uint8_t *)num) + i) = byte;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200101 }
102
103 return ret;
104}
105
106static int
107lyb_read_string(struct ly_ctx *ctx, const char **str, const char *data, struct lyb_state *lybs)
108{
109 int ret;
110 size_t len;
111
112 /* read until the end of this subtree */
113 len = lybs->written[lybs->used - 1];
114
115 *str = malloc((len + 1) * sizeof **str);
116 LY_CHECK_ERR_RETURN(!*str, LOGMEM(ctx), -1);
117
118 ret = lyb_read(data, (uint8_t *)*str, len, lybs);
119 LYB_HAVE_READ_GOTO(ret, data, error);
120 ((char *)*str)[len] = '\0';
121
122 /* store in the dictionary */
123 *str = lydict_insert_zc(ctx, (char *)*str);
124
125 return ret;
126
127error:
128 free((char *)*str);
129 *str = NULL;
130 return -1;
131}
132
133static void
134lyb_read_stop_subtree(struct lyb_state *lybs)
135{
136 if (lybs->written[lybs->used - 1]) {
137 LOGINT(NULL);
138 }
139
140 --lybs->used;
141}
142
143static int
144lyb_read_start_subtree(const char *data, struct lyb_state *lybs)
145{
146 uint64_t num = 0;
147
148 if (lybs->used == lybs->size) {
149 lybs->size += LYB_STATE_STEP;
150 lybs->written = ly_realloc(lybs->written, lybs->size * sizeof *lybs->written);
151 lybs->position = ly_realloc(lybs->position, lybs->size * sizeof *lybs->position);
152 LY_CHECK_ERR_RETURN(!lybs->written || !lybs->position, LOGMEM(NULL), -1);
153 }
154
155 memcpy(&num, data, LYB_SIZE_BYTES);
156
157 ++lybs->used;
158 lybs->written[lybs->used - 1] = num;
159 lybs->position[lybs->used - 1] = (num == LYB_SIZE_MAX ? 1 : 0);
160
161 return LYB_SIZE_BYTES;
162}
163
164static int
165lyb_parse_model(struct ly_ctx *ctx, const char *data, const struct lys_module **mod, struct lyb_state *lybs)
166{
167 int r, ret = 0;
168 uint16_t num = 0;
169 char *mod_name = NULL, mod_rev[11];
170
171 /* model name length */
172 ret += (r = lyb_read(data, (uint8_t *)&num, sizeof(uint16_t), lybs));
173 LYB_HAVE_READ_GOTO(r, data, error);
174
175 mod_name = malloc(num + 1);
176 LY_CHECK_ERR_GOTO(!mod_name, LOGMEM(ctx), error);
177
178 /* model name */
179 ret += (r = lyb_read(data, (uint8_t *)mod_name, num, lybs));
180 LYB_HAVE_READ_GOTO(r, data, error);
181 mod_name[num] = '\0';
182
183 /* revision */
184 ret += (r = lyb_read(data, (uint8_t *)&num, sizeof(uint16_t), lybs));
185 LYB_HAVE_READ_GOTO(r, data, error);
186
187 if (num) {
188 sprintf(mod_rev, "%04u-%02u-%02u", ((num & 0xFE00) >> 9) + 2000, (num & 0x01E0) >> 5, (num & 0x001F));
189 *mod = ly_ctx_get_module(ctx, mod_name, mod_rev, 0);
190 } else {
191 *mod = ly_ctx_get_module(ctx, mod_name, NULL, 0);
192 }
193 if (!*mod) {
194 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Module \"%s@%s\" not found in the context.", mod_name, (num ? mod_rev : "<none>"));
195 goto error;
196 }
197
198 free(mod_name);
199 return ret;
200
201error:
202 free(mod_name);
203 return -1;
204}
205
206static struct lyd_node *
207lyb_new_node(const struct lys_node *schema)
208{
209 struct lyd_node *node;
210
211 switch (schema->nodetype) {
212 case LYS_CONTAINER:
213 case LYS_LIST:
214 case LYS_NOTIF:
215 case LYS_RPC:
216 case LYS_ACTION:
217 node = calloc(sizeof(struct lyd_node), 1);
218 break;
219 case LYS_LEAF:
220 case LYS_LEAFLIST:
221 node = calloc(sizeof(struct lyd_node_leaf_list), 1);
Michal Vaskob7400232018-07-11 15:35:57 +0200222
223 if (((struct lys_node_leaf *)schema)->type.base == LY_TYPE_LEAFREF) {
224 node->validity |= LYD_VAL_LEAFREF;
225 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200226 break;
227 case LYS_ANYDATA:
228 case LYS_ANYXML:
229 node = calloc(sizeof(struct lyd_node_anydata), 1);
230 break;
231 default:
232 return NULL;
233 }
234 LY_CHECK_ERR_RETURN(!node, LOGMEM(schema->module->ctx), NULL);
235
236 /* fill basic info */
237 node->schema = (struct lys_node *)schema;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200238 if (resolve_applies_when(schema, 0, NULL)) {
239 node->when_status = LYD_WHEN;
240 }
241 node->prev = node;
242
243 return node;
244}
245
246static int
247lyb_parse_anydata(struct lyd_node *node, const char *data, struct lyb_state *lybs)
248{
249 int r, ret = 0;
250 struct lyd_node_anydata *any = (struct lyd_node_anydata *)node;
251
252 /* read value type */
253 ret += (r = lyb_read(data, (uint8_t *)&any->value_type, sizeof any->value_type, lybs));
254 LYB_HAVE_READ_RETURN(r, data, -1);
255
256 /* read anydata content */
257 if (any->value_type == LYD_ANYDATA_DATATREE) {
Michal Vasko228431e2018-07-10 15:47:11 +0200258 any->value.tree = lyd_parse_lyb(node->schema->module->ctx, data, 0, NULL, NULL, &r);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200259 ret += r;
260 LYB_HAVE_READ_RETURN(r, data, -1);
261 } else {
262 ret += (r = lyb_read_string(node->schema->module->ctx, &any->value.str, data, lybs));
263 LYB_HAVE_READ_RETURN(r, data, -1);
264 }
265
266 return ret;
267}
268
269static int
270lyb_parse_val(struct lyd_node_leaf_list *node, const char *data, struct lyb_state *lybs)
271{
Michal Vasko228431e2018-07-10 15:47:11 +0200272 int r, ret;
273 size_t i;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200274 uint8_t byte;
Michal Vasko228431e2018-07-10 15:47:11 +0200275 uint64_t num;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200276 struct ly_ctx *ctx = node->schema->module->ctx;
277 struct lys_type *type = &((struct lys_node_leaf *)node->schema)->type;
278
Michal Vaskob7400232018-07-11 15:35:57 +0200279 if (node->value_flags & (LY_VALUE_USER | LY_VALUE_UNRES)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200280 /* just read value_str */
281 return lyb_read_string(ctx, &node->value_str, data, lybs);
282 }
283
284 switch (node->value_type) {
285 case LY_TYPE_INST:
286 case LY_TYPE_IDENT:
287 case LY_TYPE_UNION:
288 /* we do not actually fill value now, but value_str */
289 ret = lyb_read_string(ctx, &node->value_str, data, lybs);
290 break;
291 case LY_TYPE_BINARY:
292 case LY_TYPE_STRING:
293 case LY_TYPE_UNKNOWN:
294 /* read string */
295 ret = lyb_read_string(ctx, &node->value.string, data, lybs);
296 break;
297 case LY_TYPE_BITS:
298 /* find the correct structure */
299 for (; !type->info.bits.count; type = &type->der->type);
300
301 node->value.bit = calloc(type->info.bits.count, sizeof *node->value.bit);
302 LY_CHECK_ERR_RETURN(!node->value.bit, LOGMEM(ctx), -1);
303
304 /* read values */
Michal Vasko228431e2018-07-10 15:47:11 +0200305 ret = 0;
306 for (i = 0; i < type->info.bits.count; ++i) {
307 if (i % 8 == 0) {
308 /* read another byte */
309 ret += (r = lyb_read(data, &byte, sizeof byte, lybs));
310 if (r < 0) {
311 return -1;
312 }
313 }
314
315 if (byte & (0x01 << (i % 8))) {
316 /* bit is set */
317 node->value.bit[i] = &type->info.bits.bit[i];
318 }
319 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200320 break;
321 case LY_TYPE_BOOL:
322 /* read byte */
323 ret = lyb_read(data, &byte, sizeof byte, lybs);
324 if ((ret > 0) && byte) {
325 node->value.bln = 1;
326 }
327 break;
328 case LY_TYPE_EMPTY:
329 /* nothing to read */
330 ret = 0;
331 break;
332 case LY_TYPE_ENUM:
333 /* find the correct structure */
Michal Vasko228431e2018-07-10 15:47:11 +0200334 for (; !type->info.enums.count; type = &type->der->type);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200335
Michal Vasko228431e2018-07-10 15:47:11 +0200336 num = 0;
Michal Vaskob7400232018-07-11 15:35:57 +0200337 ret = lyb_read_number(&num, type->info.enums.count, data, lybs);
338 if (ret > 0) {
339 assert(num < type->info.enums.count);
Michal Vasko228431e2018-07-10 15:47:11 +0200340 node->value.enm = &type->info.enums.enm[num];
341 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200342 break;
343 case LY_TYPE_INT8:
344 case LY_TYPE_UINT8:
345 ret = lyb_read_number((uint64_t *)&node->value.uint8, UINT8_MAX, data, lybs);
346 break;
347 case LY_TYPE_INT16:
348 case LY_TYPE_UINT16:
349 ret = lyb_read_number((uint64_t *)&node->value.uint16, UINT16_MAX, data, lybs);
350 break;
351 case LY_TYPE_INT32:
352 case LY_TYPE_UINT32:
353 ret = lyb_read_number((uint64_t *)&node->value.uint32, UINT32_MAX, data, lybs);
354 break;
355 case LY_TYPE_DEC64:
356 case LY_TYPE_INT64:
357 case LY_TYPE_UINT64:
358 ret = lyb_read_number((uint64_t *)&node->value.uint64, UINT64_MAX, data, lybs);
359 break;
360 default:
361 return -1;
362 }
363
364 return ret;
365}
366
367static int
Michal Vasko228431e2018-07-10 15:47:11 +0200368lyb_parse_val_str(struct lyd_node_leaf_list *node, struct unres_data *unres)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200369{
370 struct ly_ctx *ctx = node->schema->module->ctx;
371 struct lys_type *type = &((struct lys_node_leaf *)node->schema)->type;
Michal Vasko228431e2018-07-10 15:47:11 +0200372 char num_str[22], *str;
373 uint32_t i, str_len;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200374
375 if (node->value_flags & LY_VALUE_UNRES) {
376 /* nothing to do */
377 return 0;
378 }
379
380 if (node->value_flags & LY_VALUE_USER) {
381 /* unfortunately, we need to also fill the value properly, so just parse it again */
382 node->value_flags &= ~LY_VALUE_USER;
383 if (!lyp_parse_value(type, &node->value_str, NULL, node, NULL,
384 lyd_node_module((struct lyd_node *)node), 1, node->dflt, 1)) {
385 return -1;
386 }
387
388 if (!(node->value_flags & LY_VALUE_USER)) {
389 LOGWRN(ctx, "Node \"%s\" value was stored as a user type, but it is not in the current context.", node->schema->name);
390 }
391 return 0;
392 }
393
Michal Vaskob7400232018-07-11 15:35:57 +0200394 /* we are parsing leafref/ptr union stored as the target type,
395 * so we first parse it into string and then resolve the leafref/ptr union */
396 if ((type->base == LY_TYPE_LEAFREF) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type)) {
397 if ((node->value_type == LY_TYPE_INST) || (node->value_type == LY_TYPE_IDENT) || (node->value_type == LY_TYPE_UNION)) {
398 /* we already have a string */
399 goto parse_reference;
400 }
401 }
402
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200403 switch (node->value_type) {
404 case LY_TYPE_INST:
Michal Vasko228431e2018-07-10 15:47:11 +0200405 /* try to fill the instance-identifier target now */
406 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_INSTID)) {
407 return -1;
408 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200409 break;
410 case LY_TYPE_IDENT:
411 /* fill the identity pointer now */
412 node->value.ident = resolve_identref(type, node->value_str, (struct lyd_node *)node, node->schema->module, node->dflt);
413 if (!node->value.ident) {
414 return -1;
415 }
416 break;
417 case LY_TYPE_BINARY:
418 case LY_TYPE_STRING:
419 case LY_TYPE_UNKNOWN:
420 /* just re-assign it */
421 node->value_str = node->value.string;
422 break;
423 case LY_TYPE_BITS:
Michal Vasko228431e2018-07-10 15:47:11 +0200424 for (; !type->info.bits.count; type = &type->der->type);
425
426 /* print the set bits */
427 str = malloc(1);
428 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
429 str[0] = '\0';
Michal Vaskob7400232018-07-11 15:35:57 +0200430 str_len = 0;
Michal Vasko228431e2018-07-10 15:47:11 +0200431 for (i = 0; i < type->info.bits.count; ++i) {
432 if (node->value.bit[i]) {
Michal Vaskob7400232018-07-11 15:35:57 +0200433 str = ly_realloc(str, str_len + strlen(node->value.bit[i]->name) + (str_len ? 1 : 0) + 1);
Michal Vasko228431e2018-07-10 15:47:11 +0200434 LY_CHECK_ERR_RETURN(!str, LOGMEM(ctx), -1);
435
Michal Vaskob7400232018-07-11 15:35:57 +0200436 str_len += sprintf(str + str_len, "%s%s", str_len ? " " : "", node->value.bit[i]->name);
Michal Vasko228431e2018-07-10 15:47:11 +0200437 }
438 }
439
440 node->value_str = lydict_insert_zc(ctx, str);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200441 break;
442 case LY_TYPE_BOOL:
443 node->value_str = lydict_insert(ctx, (node->value.bln ? "true" : "false"), 0);
444 break;
445 case LY_TYPE_EMPTY:
446 case LY_TYPE_UNION:
447 /* leave value empty */
448 break;
449 case LY_TYPE_ENUM:
Michal Vasko228431e2018-07-10 15:47:11 +0200450 /* print the value */
451 node->value_str = lydict_insert(ctx, node->value.enm->name, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200452 break;
453 case LY_TYPE_INT8:
454 sprintf(num_str, "%d", node->value.int8);
455 node->value_str = lydict_insert(ctx, num_str, 0);
456 break;
457 case LY_TYPE_UINT8:
458 sprintf(num_str, "%u", node->value.uint8);
459 node->value_str = lydict_insert(ctx, num_str, 0);
460 break;
461 case LY_TYPE_INT16:
462 sprintf(num_str, "%d", node->value.int16);
463 node->value_str = lydict_insert(ctx, num_str, 0);
464 break;
465 case LY_TYPE_UINT16:
466 sprintf(num_str, "%u", node->value.uint16);
467 node->value_str = lydict_insert(ctx, num_str, 0);
468 break;
469 case LY_TYPE_INT32:
470 sprintf(num_str, "%d", node->value.int32);
471 node->value_str = lydict_insert(ctx, num_str, 0);
472 break;
473 case LY_TYPE_UINT32:
474 sprintf(num_str, "%u", node->value.uint32);
475 node->value_str = lydict_insert(ctx, num_str, 0);
476 break;
477 case LY_TYPE_INT64:
478 sprintf(num_str, "%ld", node->value.int64);
479 node->value_str = lydict_insert(ctx, num_str, 0);
480 break;
481 case LY_TYPE_UINT64:
482 sprintf(num_str, "%lu", node->value.uint64);
483 node->value_str = lydict_insert(ctx, num_str, 0);
484 break;
485 case LY_TYPE_DEC64:
Michal Vaskob7400232018-07-11 15:35:57 +0200486 sprintf(num_str, "%ld.%.*ld", node->value.dec64 / type->info.dec64.div, type->info.dec64.dig,
487 node->value.dec64 % type->info.dec64.div);
Michal Vasko228431e2018-07-10 15:47:11 +0200488 node->value_str = lydict_insert(ctx, num_str, 0);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200489 break;
490 default:
491 return -1;
492 }
493
Michal Vaskob7400232018-07-11 15:35:57 +0200494 if ((type->base == LY_TYPE_LEAFREF) || ((type->base == LY_TYPE_UNION) && type->info.uni.has_ptr_type)) {
495
496parse_reference:
497 assert(node->value_str);
498
499 if (type->base == LY_TYPE_LEAFREF) {
500 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_LEAFREF)) {
501 return -1;
502 }
503 } else {
504 if (unres_data_add(unres, (struct lyd_node *)node, UNRES_UNION)) {
505 return -1;
506 }
507 }
508 }
509
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200510 return 0;
511}
512
513static int
Michal Vasko228431e2018-07-10 15:47:11 +0200514lyb_parse_leaf(struct lyd_node *node, const char *data, struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200515{
516 int r, ret = 0;
517 uint8_t start_byte;
518 struct lyd_node_leaf_list *leaf = (struct lyd_node_leaf_list *)node;
519
520 /* read value type and flags on the first byte */
521 ret += (r = lyb_read(data, &start_byte, sizeof start_byte, lybs));
522 LYB_HAVE_READ_RETURN(r, data, -1);
523
524 /* fill value type, flags */
525 leaf->value_type = start_byte & 0x1F;
526 if (start_byte & 0x80) {
527 leaf->dflt = 1;
528 }
529 if (start_byte & 0x40) {
530 leaf->value_flags |= LY_VALUE_USER;
531 }
532 if (start_byte & 0x20) {
533 leaf->value_flags |= LY_VALUE_UNRES;
534 }
535
536 ret += (r = lyb_parse_val(leaf, data, lybs));
537 LYB_HAVE_READ_RETURN(r, data, -1);
538
Michal Vasko228431e2018-07-10 15:47:11 +0200539 ret += (r = lyb_parse_val_str(leaf, unres));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200540 LYB_HAVE_READ_RETURN(r, data, -1);
541
542 return ret;
543}
544
545static int
Michal Vaskob7400232018-07-11 15:35:57 +0200546lyb_is_schema_hash_match(struct lys_node *sibling, LYB_HASH *hash, uint8_t hash_count)
Michal Vasko228431e2018-07-10 15:47:11 +0200547{
548 LYB_HASH sibling_hash;
Michal Vaskob7400232018-07-11 15:35:57 +0200549 uint8_t i;
Michal Vasko228431e2018-07-10 15:47:11 +0200550
Michal Vaskob7400232018-07-11 15:35:57 +0200551 /* compare all the hashes starting from collision ID 0 */
552 for (i = 0; i < hash_count; ++i) {
553 sibling_hash = lyb_hash(sibling, i);
554 if (sibling_hash != hash[i]) {
555 return 0;
556 }
557 }
Michal Vasko228431e2018-07-10 15:47:11 +0200558
Michal Vaskob7400232018-07-11 15:35:57 +0200559 return 1;
Michal Vasko228431e2018-07-10 15:47:11 +0200560}
561
562static int
563lyb_parse_schema_hash(const struct lys_node *sparent, const struct lys_module *mod, const char *data, const char *yang_data_name,
564 int options, struct lys_node **snode, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200565{
566 int r, ret = 0;
Michal Vaskob7400232018-07-11 15:35:57 +0200567 uint8_t i, j;
568 struct lys_node *sibling;
569 LYB_HASH hash[LYB_HASH_BITS - 1];
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200570 struct ly_ctx *ctx;
571
572 assert((sparent || mod) && (!sparent || !mod));
573 ctx = (sparent ? sparent->module->ctx : mod->ctx);
574
Michal Vaskob7400232018-07-11 15:35:57 +0200575 /* read the first hash */
576 ret += (r = lyb_read(data, &hash[0], sizeof *hash, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200577 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vaskob7400232018-07-11 15:35:57 +0200578
579 /* based on the first hash read all the other ones, if any */
580 for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i);
581
582 /* move the first hash on its accurate position */
583 hash[i] = hash[0];
584
585 /* read the rest of hashes */
586 for (j = i; j; --j) {
587 ret += (r = lyb_read(data, &hash[j - 1], sizeof *hash, lybs));
588 LYB_HAVE_READ_RETURN(r, data, -1);
Michal Vasko228431e2018-07-10 15:47:11 +0200589 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200590
Michal Vaskob7400232018-07-11 15:35:57 +0200591 if (sparent && (sparent->nodetype & (LYS_RPC | LYS_ACTION))) {
592 sibling = NULL;
593 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, NULL, LYS_GETNEXT_WITHINOUT))) {
594 if ((sibling->nodetype == LYS_INPUT) && (options & LYD_OPT_RPC)) {
595 break;
596 }
597 if ((sibling->nodetype == LYS_OUTPUT) && (options & LYD_OPT_RPCREPLY)) {
598 break;
599 }
600 }
601 if (!sibling) {
602 /* fail */
603 goto finish;
604 }
605
606 /* use only input/output children nodes */
607 sparent = sibling;
608 }
609
610 /* find our node with matching hashes */
611 sibling = NULL;
Michal Vasko228431e2018-07-10 15:47:11 +0200612 while ((sibling = (struct lys_node *)lys_getnext(sibling, sparent, mod, 0))) {
613 /* skip schema nodes from models not present during printing */
Michal Vaskob7400232018-07-11 15:35:57 +0200614 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 +0200615 /* match found */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200616 break;
617 }
618 }
619
Michal Vaskob7400232018-07-11 15:35:57 +0200620finish:
Michal Vasko228431e2018-07-10 15:47:11 +0200621 *snode = sibling;
622 if (!sibling && (options & LYD_OPT_STRICT)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200623 if (mod) {
624 LOGVAL(ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Failed to find matching hash for a top-level node from \"%s\".", mod->name);
625 } else {
626 LOGVAL(ctx, LYE_SPEC, LY_VLOG_LYS, sparent, "Failed to find matching hash for a child of \"%s\".", sparent->name);
627 }
628 return -1;
629 }
630
631 return ret;
632}
633
634static int
635lyb_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 +0200636 const char *yang_data_name, int options, struct unres_data *unres, struct lyb_state *lybs)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200637{
638 int r, ret = 0;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200639 struct lyd_node *node = NULL, *iter;
640 const struct lys_module *mod;
641 struct lys_node *sparent, *snode;
642
643 assert((parent && !first_sibling) || (!parent && first_sibling));
644
645 /* register a new subtree */
646 ret += (r = lyb_read_start_subtree(data, lybs));
647 LYB_HAVE_READ_GOTO(r, data, error);
648
649 if (!parent) {
650 /* top-level, read module name */
651 ret += (r = lyb_parse_model(ctx, data, &mod, lybs));
652 LYB_HAVE_READ_GOTO(r, data, error);
653
654 sparent = NULL;
655 } else {
656 mod = NULL;
657 sparent = parent->schema;
658 }
659
660 /* read hash, find the schema node */
Michal Vasko228431e2018-07-10 15:47:11 +0200661 ret += (r = lyb_parse_schema_hash(sparent, mod, data, yang_data_name, options, &snode, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200662 LYB_HAVE_READ_GOTO(r, data, error);
663
Michal Vasko228431e2018-07-10 15:47:11 +0200664 if (!snode) {
Michal Vasko997071e2018-07-10 15:56:14 +0200665 /* unknown data subtree, skip it whole */
666 do {
667 ret += (r = lyb_read(data, NULL, lybs->written[lybs->used - 1], lybs));
668 } while (lybs->written[lybs->used - 1]);
Michal Vasko228431e2018-07-10 15:47:11 +0200669 goto stop_subtree;
670 }
671
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200672 /*
673 * read the node
674 */
675 node = lyb_new_node(snode);
676 if (!node) {
677 goto error;
678 }
679
680 /* TODO read attributes */
681
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200682 /* read node content */
683 switch (snode->nodetype) {
684 case LYS_CONTAINER:
685 case LYS_LIST:
Michal Vaskob7400232018-07-11 15:35:57 +0200686 case LYS_NOTIF:
687 case LYS_RPC:
688 case LYS_ACTION:
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200689 /* nothing to read */
690 break;
691 case LYS_LEAF:
692 case LYS_LEAFLIST:
Michal Vasko228431e2018-07-10 15:47:11 +0200693 ret += (r = lyb_parse_leaf(node, data, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200694 LYB_HAVE_READ_GOTO(r, data, error);
695 break;
696 case LYS_ANYXML:
697 case LYS_ANYDATA:
698 ret += (r = lyb_parse_anydata(node, data, lybs));
699 LYB_HAVE_READ_GOTO(r, data, error);
700 break;
701 default:
702 goto error;
703 }
704
705 /* insert into data tree, manually */
706 if (parent) {
707 if (!parent->child) {
708 /* only child */
709 parent->child = node;
710 } else {
711 /* last child */
712 parent->child->prev->next = node;
713 node->prev = parent->child->prev;
714 parent->child->prev = node;
715 }
716 node->parent = parent;
717 } else if (*first_sibling) {
718 /* last sibling */
719 (*first_sibling)->prev->next = node;
720 node->prev = (*first_sibling)->prev;
721 (*first_sibling)->prev = node;
722 } else {
723 /* only sibling */
724 *first_sibling = node;
725 }
726
727 /* read all descendants */
728 while (lybs->written[lybs->used - 1]) {
Michal Vasko228431e2018-07-10 15:47:11 +0200729 ret += (r = lyb_parse_subtree(ctx, data, node, NULL, NULL, options, unres, lybs));
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200730 LYB_HAVE_READ_GOTO(r, data, error);
731 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200732
733 /* make containers default if should be */
734 if (node->schema->nodetype == LYS_CONTAINER) {
735 LY_TREE_FOR(node->child, iter) {
736 if (!iter->dflt) {
737 break;
738 }
739 }
740
741 if (!iter) {
742 node->dflt = 1;
743 }
744 }
745
Michal Vasko228431e2018-07-10 15:47:11 +0200746stop_subtree:
747 /* end the subtree */
748 lyb_read_stop_subtree(lybs);
749
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200750 return ret;
751
752error:
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200753 lyd_free(node);
Michal Vaskob7400232018-07-11 15:35:57 +0200754 if (first_sibling && (*first_sibling == node)) {
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200755 *first_sibling = NULL;
756 }
757 return -1;
758}
759
760static int
Michal Vasko228431e2018-07-10 15:47:11 +0200761lyb_parse_data_models(struct ly_ctx *ctx, const char *data, struct lyb_state *lybs)
762{
763 int i, r, ret = 0;
764
765 /* read model count */
766 ret += (r = lyb_read(data, (uint8_t *)&lybs->mod_count, 2, lybs));
767 LYB_HAVE_READ_RETURN(r, data, -1);
768
769 lybs->models = malloc(lybs->mod_count * sizeof *lybs->models);
770 LY_CHECK_ERR_RETURN(!lybs->models, LOGMEM(NULL), -1);
771
772 /* read modules */
773 for (i = 0; i < lybs->mod_count; ++i) {
774 ret += (r = lyb_parse_model(ctx, data, &lybs->models[i], lybs));
775 LYB_HAVE_READ_RETURN(r, data, -1);
776 }
777
778 return ret;
779}
780
781static int
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200782lyb_parse_header(const char *data, struct lyb_state *lybs)
783{
784 int ret = 0;
785 uint8_t byte = 0;
786
Michal Vasko228431e2018-07-10 15:47:11 +0200787 /* TODO version, any flags? */
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200788 ret += lyb_read(data, (uint8_t *)&byte, sizeof byte, lybs);
789
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200790 return ret;
791}
792
793struct lyd_node *
Michal Vasko228431e2018-07-10 15:47:11 +0200794lyd_parse_lyb(struct ly_ctx *ctx, const char *data, int options, const struct lyd_node *data_tree,
795 const char *yang_data_name, int *parsed)
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200796{
797 int r, ret = 0;
Michal Vasko228431e2018-07-10 15:47:11 +0200798 struct lyd_node *node = NULL, *next, *act_notif = NULL;
799 struct unres_data *unres = NULL;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200800 struct lyb_state lybs;
801
802 if (!ctx || !data) {
803 LOGARG;
804 return NULL;
805 }
806
807 lybs.written = malloc(LYB_STATE_STEP * sizeof *lybs.written);
808 lybs.position = malloc(LYB_STATE_STEP * sizeof *lybs.position);
809 LY_CHECK_ERR_GOTO(!lybs.written || !lybs.position, LOGMEM(ctx), finish);
810 lybs.used = 0;
811 lybs.size = LYB_STATE_STEP;
Michal Vasko228431e2018-07-10 15:47:11 +0200812 lybs.models = NULL;
813 lybs.mod_count = 0;
814
815 unres = calloc(1, sizeof *unres);
816 LY_CHECK_ERR_GOTO(!unres, LOGMEM(ctx), finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200817
818 /* read header */
819 ret += (r = lyb_parse_header(data, &lybs));
820 LYB_HAVE_READ_GOTO(r, data, finish);
821
Michal Vasko228431e2018-07-10 15:47:11 +0200822 /* read used models */
823 ret += (r = lyb_parse_data_models(ctx, data, &lybs));
824 LYB_HAVE_READ_GOTO(r, data, finish);
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200825
826 /* read subtree(s) */
827 while (data[0]) {
Michal Vasko228431e2018-07-10 15:47:11 +0200828 ret += (r = lyb_parse_subtree(ctx, data, NULL, &node, yang_data_name, options, unres, &lybs));
829 if (r < 0) {
830 lyd_free_withsiblings(node);
831 node = NULL;
832 goto finish;
833 }
834 data += r;
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200835 }
836
837 /* read the last zero, parsing finished */
838 ++ret;
839 r = ret;
840
Michal Vasko228431e2018-07-10 15:47:11 +0200841 if (options & LYD_OPT_DATA_ADD_YANGLIB) {
842 if (lyd_merge(node, ly_ctx_info(ctx), LYD_OPT_DESTRUCT | LYD_OPT_EXPLICIT)) {
843 LOGERR(ctx, LY_EINT, "Adding ietf-yang-library data failed.");
844 lyd_free_withsiblings(node);
845 node = NULL;
846 goto finish;
847 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200848 }
Michal Vasko228431e2018-07-10 15:47:11 +0200849
850 /* resolve any unresolved instance-identifiers */
851 if (unres->count) {
852 if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY | LYD_OPT_NOTIF)) {
853 LY_TREE_DFS_BEGIN(node, next, act_notif) {
854 if (act_notif->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
855 break;
856 }
857 LY_TREE_DFS_END(node, next, act_notif);
858 }
859 }
860 if (lyd_defaults_add_unres(&node, options, ctx, data_tree, act_notif, unres, 0)) {
861 lyd_free_withsiblings(node);
862 node = NULL;
863 goto finish;
864 }
865 }
866
867finish:
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200868 free(lybs.written);
869 free(lybs.position);
Michal Vasko228431e2018-07-10 15:47:11 +0200870 free(lybs.models);
871 if (unres) {
872 free(unres->node);
873 free(unres->type);
874 free(unres);
875 }
Michal Vasko1e82a3b2018-07-03 12:16:58 +0200876
877 if (parsed) {
878 *parsed = r;
879 }
880 return node;
881}