|
Packit |
8fb591 |
/**
|
|
Packit |
8fb591 |
* @file printer_lyb.c
|
|
Packit |
8fb591 |
* @author Michal Vasko <mvasko@cesnet.cz>
|
|
Packit |
8fb591 |
* @brief LYB printer for libyang data structure
|
|
Packit |
8fb591 |
*
|
|
Packit |
8fb591 |
* Copyright (c) 2018 CESNET, z.s.p.o.
|
|
Packit |
8fb591 |
*
|
|
Packit |
8fb591 |
* This source code is licensed under BSD 3-Clause License (the "License").
|
|
Packit |
8fb591 |
* You may not use this file except in compliance with the License.
|
|
Packit |
8fb591 |
* You may obtain a copy of the License at
|
|
Packit |
8fb591 |
*
|
|
Packit |
8fb591 |
* https://opensource.org/licenses/BSD-3-Clause
|
|
Packit |
8fb591 |
*/
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
#include <stdlib.h>
|
|
Packit |
8fb591 |
#include <stdio.h>
|
|
Packit |
8fb591 |
#include <stdint.h>
|
|
Packit |
8fb591 |
#include <string.h>
|
|
Packit |
8fb591 |
#include <assert.h>
|
|
Packit |
8fb591 |
#include <stdint.h>
|
|
Packit |
8fb591 |
#ifdef __APPLE__
|
|
Packit |
8fb591 |
# include <libkern/OSByteOrder.h>
|
|
Packit |
8fb591 |
# define htole64(x) OSSwapHostToLittleInt64(x)
|
|
Packit |
8fb591 |
#else
|
|
Packit |
8fb591 |
# include <endian.h>
|
|
Packit |
8fb591 |
#endif
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
#include "common.h"
|
|
Packit |
8fb591 |
#include "printer.h"
|
|
Packit |
8fb591 |
#include "tree_schema.h"
|
|
Packit |
8fb591 |
#include "tree_data.h"
|
|
Packit |
8fb591 |
#include "resolve.h"
|
|
Packit |
8fb591 |
#include "tree_internal.h"
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_hash_equal_cb(void *UNUSED(val1_p), void *UNUSED(val2_p), int UNUSED(mod), void *UNUSED(cb_data))
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
/* for this purpose, if hash matches, the value does also, we do not want 2 values to have the same hash */
|
|
Packit |
8fb591 |
return 1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_ptr_equal_cb(void *val1_p, void *val2_p, int UNUSED(mod), void *UNUSED(cb_data))
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
struct lys_node *val1 = *(struct lys_node **)val1_p;
|
|
Packit |
8fb591 |
struct lys_node *val2 = *(struct lys_node **)val2_p;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (val1 == val2) {
|
|
Packit |
8fb591 |
return 1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* check that sibling collision hash i is safe to insert into ht
|
|
Packit |
8fb591 |
* return: 0 - no whole hash sequence collision, 1 - whole hash sequence collision, -1 - fatal error
|
|
Packit |
8fb591 |
*/
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_hash_sequence_check(struct hash_table *ht, struct lys_node *sibling, int ht_col_id, int compare_col_id)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int j;
|
|
Packit |
8fb591 |
struct lys_node **col_node;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* get the first node inserted with last hash col ID ht_col_id */
|
|
Packit |
8fb591 |
if (lyht_find(ht, &sibling, lyb_hash(sibling, ht_col_id), (void **)&col_node)) {
|
|
Packit |
8fb591 |
/* there is none. valid situation */
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
lyht_set_cb(ht, lyb_ptr_equal_cb);
|
|
Packit |
8fb591 |
do {
|
|
Packit |
8fb591 |
for (j = compare_col_id; j > -1; --j) {
|
|
Packit |
8fb591 |
if (lyb_hash(sibling, j) != lyb_hash(*col_node, j)) {
|
|
Packit |
8fb591 |
/* one non-colliding hash */
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if (j == -1) {
|
|
Packit |
8fb591 |
/* all whole hash sequences of nodes inserted with last hash col ID compare_col_id collide */
|
|
Packit |
8fb591 |
lyht_set_cb(ht, lyb_hash_equal_cb);
|
|
Packit |
8fb591 |
return 1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* get next node inserted with last hash col ID ht_col_id */
|
|
Packit |
8fb591 |
} while (!lyht_find_next(ht, col_node, lyb_hash(*col_node, ht_col_id), (void **)&col_node));
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
lyht_set_cb(ht, lyb_hash_equal_cb);
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
#ifndef NDEBUG
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_check_augment_collision(struct hash_table *ht, struct lys_node *aug1, struct lys_node *aug2)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
struct lys_node *iter1 = NULL, *iter2 = NULL;
|
|
Packit |
8fb591 |
int i, coliding = 0;
|
|
Packit |
8fb591 |
values_equal_cb cb = NULL;
|
|
Packit |
8fb591 |
LYB_HASH hash1, hash2;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* go throught combination of all nodes and check if coliding hash is used */
|
|
Packit |
8fb591 |
while ((iter1 = (struct lys_node *)lys_getnext(iter1, aug1, aug1->module, 0))) {
|
|
Packit |
8fb591 |
iter2 = NULL;
|
|
Packit |
8fb591 |
while ((iter2 = (struct lys_node *)lys_getnext(iter2, aug2, aug2->module, 0))) {
|
|
Packit |
8fb591 |
coliding = 0;
|
|
Packit |
8fb591 |
for (i = 0; i < LYB_HASH_BITS; i++) {
|
|
Packit |
8fb591 |
hash1 = lyb_hash(iter1, i);
|
|
Packit |
8fb591 |
hash2 = lyb_hash(iter2, i);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!hash1 || !hash2, LOGINT(aug1->module->ctx), 0);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (hash1 == hash2) {
|
|
Packit |
8fb591 |
coliding++;
|
|
Packit |
8fb591 |
/* if one of values with coliding hash is in hash table, we have a problem */
|
|
Packit |
8fb591 |
cb = lyht_set_cb(ht, lyb_ptr_equal_cb);
|
|
Packit |
8fb591 |
if ((lyht_find(ht, &iter1, hash1, NULL) == 0) || (lyht_find(ht, &iter2, hash2, NULL) == 0)) {
|
|
Packit |
8fb591 |
LOGWRN(aug1->module->ctx, "Augmentations from modules \"%s\" and \"%s\" have fatal hash collision.",
|
|
Packit |
8fb591 |
iter1->module->name, iter2->module->name);
|
|
Packit |
8fb591 |
LOGWRN(aug1->module->ctx, "It will cause no errors if module \"%s\" is always loaded before \"%s\".",
|
|
Packit |
8fb591 |
iter1->module->name, iter2->module->name);
|
|
Packit |
8fb591 |
lyht_set_cb(ht, cb);
|
|
Packit |
8fb591 |
return 1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
lyht_set_cb(ht, cb);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(coliding == LYB_HASH_BITS, LOGINT(aug1->module->ctx), 1);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* no used hashes with collision found */
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static void
|
|
Packit |
8fb591 |
lyb_check_augments(struct lys_node *parent, struct hash_table *ht, int options)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
struct lys_node *iter, *sibling = NULL, **augs = NULL;
|
|
Packit |
8fb591 |
void *ret;
|
|
Packit |
8fb591 |
int augs_size = 1, augs_found = 0, i, j, found;
|
|
Packit |
8fb591 |
struct lys_module *mod;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
assert(parent);
|
|
Packit |
8fb591 |
mod = lys_node_module(parent);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
augs = malloc(sizeof sibling * augs_size);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!augs, LOGMEM(mod->ctx), );
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
while ((sibling = (struct lys_node *)lys_getnext(sibling, parent, NULL, 0))) {
|
|
Packit |
8fb591 |
if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) {
|
|
Packit |
8fb591 |
for (iter = lys_parent(sibling);
|
|
Packit |
8fb591 |
iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE));
|
|
Packit |
8fb591 |
iter = lys_parent(iter));
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (iter && (((options & LYD_OPT_RPC) && (iter->nodetype == LYS_OUTPUT))
|
|
Packit |
8fb591 |
|| ((options & LYD_OPT_RPCREPLY) && (iter->nodetype == LYS_INPUT)))) {
|
|
Packit |
8fb591 |
/* skip unused nodes */
|
|
Packit |
8fb591 |
continue;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
/* build array of all augments from different modules */
|
|
Packit |
8fb591 |
if (sibling->parent->nodetype == LYS_AUGMENT && lys_node_module(sibling->parent) != mod) {
|
|
Packit |
8fb591 |
found = 0;
|
|
Packit |
8fb591 |
for (i = 0; i < augs_found; i++) {
|
|
Packit |
8fb591 |
if (lys_node_module(augs[i]) == lys_node_module(sibling)) {
|
|
Packit |
8fb591 |
found = 1;
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if (!found) {
|
|
Packit |
8fb591 |
if (augs_size == augs_found) {
|
|
Packit |
8fb591 |
augs_size *= 2;
|
|
Packit |
8fb591 |
ret = realloc(augs, sizeof sibling * augs_size);
|
|
Packit |
8fb591 |
if (!ret) {
|
|
Packit |
8fb591 |
LOGMEM(mod->ctx);
|
|
Packit |
8fb591 |
free(augs);
|
|
Packit |
8fb591 |
return;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
augs = ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
augs[augs_found] = sibling;
|
|
Packit |
8fb591 |
augs_found++;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
/* check collisions for every pair */
|
|
Packit |
8fb591 |
for (i = 0; i < augs_found; i++) {
|
|
Packit |
8fb591 |
for (j = i + 1; j < augs_found; j++) {
|
|
Packit |
8fb591 |
if (lyb_check_augment_collision(ht, augs[i]->parent, augs[j]->parent)) {
|
|
Packit |
8fb591 |
free(augs);
|
|
Packit |
8fb591 |
return;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
free(augs);
|
|
Packit |
8fb591 |
return;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
#endif
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static struct hash_table *
|
|
Packit |
8fb591 |
lyb_hash_siblings(struct lys_node *sibling, const struct lys_module **models, int mod_count, int options)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
struct hash_table *ht;
|
|
Packit |
8fb591 |
struct lys_node *parent, *iter;
|
|
Packit |
8fb591 |
const struct lys_module *mod;
|
|
Packit |
8fb591 |
int i, j;
|
|
Packit |
8fb591 |
#ifndef NDEBUG
|
|
Packit |
8fb591 |
int aug_col = 0;
|
|
Packit |
8fb591 |
const struct lys_module *aug_mod = NULL;
|
|
Packit |
8fb591 |
#endif
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
ht = lyht_new(1, sizeof(struct lys_node *), lyb_hash_equal_cb, NULL, 1);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!ht, LOGMEM(sibling->module->ctx), NULL);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (parent = lys_parent(sibling);
|
|
Packit |
8fb591 |
parent && (parent->nodetype & (LYS_USES | LYS_CHOICE | LYS_CASE | LYS_INPUT | LYS_OUTPUT));
|
|
Packit |
8fb591 |
parent = lys_parent(parent));
|
|
Packit |
8fb591 |
mod = lys_node_module(sibling);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
sibling = NULL;
|
|
Packit |
8fb591 |
while ((sibling = (struct lys_node *)lys_getnext(sibling, parent, mod, 0))) {
|
|
Packit |
8fb591 |
if (models && !lyb_has_schema_model(sibling, models, mod_count)) {
|
|
Packit |
8fb591 |
/* ignore models not present during printing */
|
|
Packit |
8fb591 |
continue;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) {
|
|
Packit |
8fb591 |
for (iter = lys_parent(sibling);
|
|
Packit |
8fb591 |
iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE));
|
|
Packit |
8fb591 |
iter = lys_parent(iter));
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (iter && (((options & LYD_OPT_RPC) && (iter->nodetype == LYS_OUTPUT))
|
|
Packit |
8fb591 |
|| ((options & LYD_OPT_RPCREPLY) && (iter->nodetype == LYS_INPUT)))) {
|
|
Packit |
8fb591 |
/* skip unused nodes */
|
|
Packit |
8fb591 |
continue;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
#ifndef NDEBUG
|
|
Packit |
8fb591 |
if (sibling->parent && sibling->parent->nodetype == LYS_AUGMENT && lys_node_module(sibling->parent) != mod) {
|
|
Packit |
8fb591 |
if (aug_mod && aug_mod != lys_node_module(sibling->parent)) {
|
|
Packit |
8fb591 |
aug_col = 1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
aug_mod = lys_node_module(sibling);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
#endif
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* find the first non-colliding hash (or specifically non-colliding hash sequence) */
|
|
Packit |
8fb591 |
for (i = 0; i < LYB_HASH_BITS; ++i) {
|
|
Packit |
8fb591 |
/* check that we are not colliding with nodes inserted with a lower collision ID than ours */
|
|
Packit |
8fb591 |
for (j = i - 1; j > -1; --j) {
|
|
Packit |
8fb591 |
if (lyb_hash_sequence_check(ht, sibling, j, i)) {
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if (j > -1) {
|
|
Packit |
8fb591 |
/* some check failed, we must use a higher collision ID */
|
|
Packit |
8fb591 |
continue;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* try to insert node with the current collision ID */
|
|
Packit |
8fb591 |
if (!lyht_insert_with_resize_cb(ht, &sibling, lyb_hash(sibling, i), lyb_ptr_equal_cb, NULL)) {
|
|
Packit |
8fb591 |
/* success, no collision */
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* make sure we really cannot insert it with this hash col ID (meaning the whole hash sequence is colliding) */
|
|
Packit |
8fb591 |
if (i && !lyb_hash_sequence_check(ht, sibling, i, i)) {
|
|
Packit |
8fb591 |
/* it can be inserted after all, even though there is already a node with the same last collision ID */
|
|
Packit |
8fb591 |
lyht_set_cb(ht, lyb_ptr_equal_cb);
|
|
Packit |
8fb591 |
if (lyht_insert(ht, &sibling, lyb_hash(sibling, i), NULL)) {
|
|
Packit |
8fb591 |
lyht_set_cb(ht, lyb_hash_equal_cb);
|
|
Packit |
8fb591 |
LOGINT(sibling->module->ctx);
|
|
Packit |
8fb591 |
lyht_free(ht);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
lyht_set_cb(ht, lyb_hash_equal_cb);
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
/* there is still another colliding schema node with the same hash sequence, try higher collision ID */
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (i == LYB_HASH_BITS) {
|
|
Packit |
8fb591 |
/* wow */
|
|
Packit |
8fb591 |
LOGINT(sibling->module->ctx);
|
|
Packit |
8fb591 |
lyht_free(ht);
|
|
Packit |
8fb591 |
return NULL;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
#ifndef NDEBUG
|
|
Packit |
8fb591 |
if (aug_col) {
|
|
Packit |
8fb591 |
lyb_check_augments(parent, ht, options);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
#endif
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* change val equal callback so that the HT is usable for finding value hashes */
|
|
Packit |
8fb591 |
lyht_set_cb(ht, lyb_ptr_equal_cb);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ht;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static LYB_HASH
|
|
Packit |
8fb591 |
lyb_hash_find(struct hash_table *ht, struct lys_node *node)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
LYB_HASH hash;
|
|
Packit |
8fb591 |
uint32_t i;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (i = 0; i < LYB_HASH_BITS; ++i) {
|
|
Packit |
8fb591 |
hash = lyb_hash(node, i);
|
|
Packit |
8fb591 |
if (!hash) {
|
|
Packit |
8fb591 |
LOGINT(node->module->ctx);
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (!lyht_find(ht, &node, hash, NULL)) {
|
|
Packit |
8fb591 |
/* success, no collision */
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
/* cannot happen, we already calculated the hash */
|
|
Packit |
8fb591 |
if (i == LYB_HASH_BITS) {
|
|
Packit |
8fb591 |
LOGINT(node->module->ctx);
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return hash;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* writing function handles writing size information */
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_write(struct lyout *out, const uint8_t *buf, size_t count, struct lyb_state *lybs)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int ret = 0, i, full_chunk_i;
|
|
Packit |
8fb591 |
size_t r, to_write;
|
|
Packit |
8fb591 |
uint8_t meta_buf[LYB_META_BYTES];
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
assert(out && lybs);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
while (1) {
|
|
Packit |
8fb591 |
/* check for full data chunks */
|
|
Packit |
8fb591 |
to_write = count;
|
|
Packit |
8fb591 |
full_chunk_i = -1;
|
|
Packit |
8fb591 |
for (i = 0; i < lybs->used; ++i) {
|
|
Packit |
8fb591 |
/* we want the innermost chunks resolved first, so replace previous full chunks */
|
|
Packit |
8fb591 |
if (lybs->written[i] + to_write >= LYB_SIZE_MAX) {
|
|
Packit |
8fb591 |
/* full chunk, do not write more than allowed */
|
|
Packit |
8fb591 |
to_write = LYB_SIZE_MAX - lybs->written[i];
|
|
Packit |
8fb591 |
full_chunk_i = i;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if ((full_chunk_i == -1) && !count) {
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* we are actually writing some data, not just finishing another chunk */
|
|
Packit |
8fb591 |
if (to_write) {
|
|
Packit |
8fb591 |
r = ly_write(out, (char *)buf, to_write);
|
|
Packit |
8fb591 |
if (r < to_write) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (i = 0; i < lybs->used; ++i) {
|
|
Packit |
8fb591 |
/* increase all written counters */
|
|
Packit |
8fb591 |
lybs->written[i] += r;
|
|
Packit |
8fb591 |
assert(lybs->written[i] <= LYB_SIZE_MAX);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
/* decrease count/buf */
|
|
Packit |
8fb591 |
count -= r;
|
|
Packit |
8fb591 |
buf += r;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
ret += r;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (full_chunk_i > -1) {
|
|
Packit |
8fb591 |
/* write the meta information (inner chunk count and chunk size) */
|
|
Packit |
8fb591 |
meta_buf[0] = lybs->written[full_chunk_i] & 0xFF;
|
|
Packit |
8fb591 |
meta_buf[1] = lybs->inner_chunks[full_chunk_i] & 0xFF;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
r = ly_write_skipped(out, lybs->position[full_chunk_i], (char *)meta_buf, LYB_META_BYTES);
|
|
Packit |
8fb591 |
if (r < LYB_META_BYTES) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* zero written and inner chunks */
|
|
Packit |
8fb591 |
lybs->written[full_chunk_i] = 0;
|
|
Packit |
8fb591 |
lybs->inner_chunks[full_chunk_i] = 0;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* skip space for another chunk size */
|
|
Packit |
8fb591 |
r = ly_write_skip(out, LYB_META_BYTES, &lybs->position[full_chunk_i]);
|
|
Packit |
8fb591 |
if (r < LYB_META_BYTES) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
ret += r;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* increase inner chunk count */
|
|
Packit |
8fb591 |
for (i = 0; i < full_chunk_i; ++i) {
|
|
Packit |
8fb591 |
if (lybs->inner_chunks[i] == LYB_INCHUNK_MAX) {
|
|
Packit |
8fb591 |
LOGINT(NULL);
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
++lybs->inner_chunks[i];
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_write_stop_subtree(struct lyout *out, struct lyb_state *lybs)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int r;
|
|
Packit |
8fb591 |
uint8_t meta_buf[LYB_META_BYTES];
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* write the meta chunk information */
|
|
Packit |
8fb591 |
meta_buf[0] = lybs->written[lybs->used - 1] & 0xFF;
|
|
Packit |
8fb591 |
meta_buf[1] = lybs->inner_chunks[lybs->used - 1] & 0xFF;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
r = ly_write_skipped(out, lybs->position[lybs->used - 1], (char *)&meta_buf, LYB_META_BYTES);
|
|
Packit |
8fb591 |
if (r < LYB_META_BYTES) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
--lybs->used;
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_write_start_subtree(struct lyout *out, struct lyb_state *lybs)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int i;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (lybs->used == lybs->size) {
|
|
Packit |
8fb591 |
lybs->size += LYB_STATE_STEP;
|
|
Packit |
8fb591 |
lybs->written = ly_realloc(lybs->written, lybs->size * sizeof *lybs->written);
|
|
Packit |
8fb591 |
lybs->position = ly_realloc(lybs->position, lybs->size * sizeof *lybs->position);
|
|
Packit |
8fb591 |
lybs->inner_chunks = ly_realloc(lybs->inner_chunks, lybs->size * sizeof *lybs->inner_chunks);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!lybs->written || !lybs->position || !lybs->inner_chunks, LOGMEM(NULL), -1);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
++lybs->used;
|
|
Packit |
8fb591 |
lybs->written[lybs->used - 1] = 0;
|
|
Packit |
8fb591 |
lybs->inner_chunks[lybs->used - 1] = 0;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* another inner chunk */
|
|
Packit |
8fb591 |
for (i = 0; i < lybs->used - 1; ++i) {
|
|
Packit |
8fb591 |
if (lybs->inner_chunks[i] == LYB_INCHUNK_MAX) {
|
|
Packit |
8fb591 |
LOGINT(NULL);
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
++lybs->inner_chunks[i];
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ly_write_skip(out, LYB_META_BYTES, &lybs->position[lybs->used - 1]);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_write_number(uint64_t num, size_t bytes, struct lyout *out, struct lyb_state *lybs)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int ret = 0;
|
|
Packit |
8fb591 |
size_t i;
|
|
Packit |
8fb591 |
uint8_t byte;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
num = htole64(num);
|
|
Packit |
8fb591 |
for (i = 0; i < bytes; ++i) {
|
|
Packit |
8fb591 |
byte = *(((uint8_t *)&num) + i);
|
|
Packit |
8fb591 |
ret += lyb_write(out, &byte, 1, lybs);
|
|
Packit |
8fb591 |
if (ret < 0) {
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_write_enum(uint32_t enum_idx, uint32_t count, struct lyout *out, struct lyb_state *lybs)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
size_t bytes;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (count < (1 << 8)) {
|
|
Packit |
8fb591 |
bytes = 1;
|
|
Packit |
8fb591 |
} else if (count < (1 << 16)) {
|
|
Packit |
8fb591 |
bytes = 2;
|
|
Packit |
8fb591 |
} else if (count < (1 << 24)) {
|
|
Packit |
8fb591 |
bytes = 3;
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
bytes = 4;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return lyb_write_number(enum_idx, bytes, out, lybs);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_write_string(const char *str, size_t str_len, int with_length, struct lyout *out, struct lyb_state *lybs)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int r, ret = 0;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (!str_len) {
|
|
Packit |
8fb591 |
str_len = strlen(str);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if (str_len > UINT16_MAX) {
|
|
Packit |
8fb591 |
LOGINT(NULL);
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (with_length) {
|
|
Packit |
8fb591 |
/* print length on 2 bytes */
|
|
Packit |
8fb591 |
ret += (r = lyb_write_number(str_len, 2, out, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
ret += (r = lyb_write(out, (const uint8_t *)str, str_len, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_print_model(struct lyout *out, const struct lys_module *mod, struct lyb_state *lybs)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int r, ret = 0;
|
|
Packit |
8fb591 |
uint16_t revision;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* model name length and model name */
|
|
Packit |
8fb591 |
ret += (r = lyb_write_string(mod->name, 0, 1, out, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* model revision as XXXX XXXX XXXX XXXX (2B) (year is offset from 2000)
|
|
Packit |
8fb591 |
* YYYY YYYM MMMD DDDD */
|
|
Packit |
8fb591 |
revision = 0;
|
|
Packit |
8fb591 |
if (mod->rev_size) {
|
|
Packit |
8fb591 |
r = atoi(mod->rev[0].date);
|
|
Packit |
8fb591 |
r -= 2000;
|
|
Packit |
8fb591 |
r <<= 9;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
revision |= r;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
r = atoi(mod->rev[0].date + 5);
|
|
Packit |
8fb591 |
r <<= 5;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
revision |= r;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
r = atoi(mod->rev[0].date + 8);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
revision |= r;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
ret += (r = lyb_write_number(revision, sizeof revision, out, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
is_added_model(const struct lys_module **models, size_t mod_count, const struct lys_module *mod)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
size_t i;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (i = 0; i < mod_count; ++i) {
|
|
Packit |
8fb591 |
if (models[i] == mod) {
|
|
Packit |
8fb591 |
return 1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static void
|
|
Packit |
8fb591 |
add_model(const struct lys_module ***models, size_t *mod_count, const struct lys_module *mod)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
if (is_added_model(*models, *mod_count, mod)) {
|
|
Packit |
8fb591 |
return;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
*models = ly_realloc(*models, ++(*mod_count) * sizeof **models);
|
|
Packit |
8fb591 |
(*models)[*mod_count - 1] = mod;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_print_data_models(struct lyout *out, const struct lyd_node *root, struct lyb_state *lybs)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int ret = 0;
|
|
Packit |
8fb591 |
const struct lys_module **models = NULL, *mod;
|
|
Packit |
8fb591 |
const struct lys_submodule *submod;
|
|
Packit |
8fb591 |
const struct lyd_node *node;
|
|
Packit |
8fb591 |
size_t mod_count = 0;
|
|
Packit |
8fb591 |
uint32_t idx = 0, i, j;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* first, collect all data node modules */
|
|
Packit |
8fb591 |
LY_TREE_FOR(root, node) {
|
|
Packit |
8fb591 |
mod = lyd_node_module(node);
|
|
Packit |
8fb591 |
add_model(&models, &mod_count, mod);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (root) {
|
|
Packit |
8fb591 |
/* then add all models augmenting or deviating the used models */
|
|
Packit |
8fb591 |
idx = ly_ctx_internal_modules_count(root->schema->module->ctx);
|
|
Packit |
8fb591 |
while ((mod = ly_ctx_get_module_iter(root->schema->module->ctx, &idx))) {
|
|
Packit |
8fb591 |
if (!mod->implemented) {
|
|
Packit |
8fb591 |
next_mod:
|
|
Packit |
8fb591 |
continue;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (i = 0; i < mod->deviation_size; ++i) {
|
|
Packit |
8fb591 |
if (mod->deviation[i].orig_node && is_added_model(models, mod_count, lys_node_module(mod->deviation[i].orig_node))) {
|
|
Packit |
8fb591 |
add_model(&models, &mod_count, mod);
|
|
Packit |
8fb591 |
goto next_mod;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
for (i = 0; i < mod->augment_size; ++i) {
|
|
Packit |
8fb591 |
if (is_added_model(models, mod_count, lys_node_module(mod->augment[i].target))) {
|
|
Packit |
8fb591 |
add_model(&models, &mod_count, mod);
|
|
Packit |
8fb591 |
goto next_mod;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* submodules */
|
|
Packit |
8fb591 |
for (j = 0; j < mod->inc_size; ++j) {
|
|
Packit |
8fb591 |
submod = mod->inc[j].submodule;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (i = 0; i < submod->deviation_size; ++i) {
|
|
Packit |
8fb591 |
if (submod->deviation[i].orig_node && is_added_model(models, mod_count, lys_node_module(submod->deviation[i].orig_node))) {
|
|
Packit |
8fb591 |
add_model(&models, &mod_count, mod);
|
|
Packit |
8fb591 |
goto next_mod;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
for (i = 0; i < submod->augment_size; ++i) {
|
|
Packit |
8fb591 |
if (is_added_model(models, mod_count, lys_node_module(submod->augment[i].target))) {
|
|
Packit |
8fb591 |
add_model(&models, &mod_count, mod);
|
|
Packit |
8fb591 |
goto next_mod;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* now write module count on 2 bytes */
|
|
Packit |
8fb591 |
ret += lyb_write_number(mod_count, 2, out, lybs);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* and all the used models */
|
|
Packit |
8fb591 |
for (i = 0; i < mod_count; ++i) {
|
|
Packit |
8fb591 |
ret += lyb_print_model(out, models[i], lybs);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
free(models);
|
|
Packit |
8fb591 |
return ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_print_magic_number(struct lyout *out)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
uint32_t magic_number;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* 'l', 'y', 'b' - 0x6c7962 */
|
|
Packit |
8fb591 |
((char *)&magic_number)[0] = 'l';
|
|
Packit |
8fb591 |
((char *)&magic_number)[1] = 'y';
|
|
Packit |
8fb591 |
((char *)&magic_number)[2] = 'b';
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ly_write(out, (char *)&magic_number, 3);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_print_header(struct lyout *out)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int ret = 0;
|
|
Packit |
8fb591 |
uint8_t byte = 0;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* TODO version, some other flags? */
|
|
Packit |
8fb591 |
ret += ly_write(out, (char *)&byte, sizeof byte);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_print_anydata(struct lyd_node_anydata *anydata, struct lyout *out, struct lyb_state *lybs)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int ret = 0, len;
|
|
Packit |
8fb591 |
char *buf;
|
|
Packit |
8fb591 |
LYD_ANYDATA_VALUETYPE type;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (anydata->value_type == LYD_ANYDATA_XML) {
|
|
Packit |
8fb591 |
/* transform XML into CONSTSTRING */
|
|
Packit |
8fb591 |
lyxml_print_mem(&buf, anydata->value.xml, LYXML_PRINT_SIBLINGS);
|
|
Packit |
8fb591 |
lyxml_free(anydata->schema->module->ctx, anydata->value.xml);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
anydata->value_type = LYD_ANYDATA_CONSTSTRING;
|
|
Packit |
8fb591 |
anydata->value.str = lydict_insert_zc(anydata->schema->module->ctx, buf);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (anydata->value_type == LYD_ANYDATA_DATATREE) {
|
|
Packit |
8fb591 |
/* that is the format used */
|
|
Packit |
8fb591 |
type = LYD_ANYDATA_LYB;
|
|
Packit |
8fb591 |
} else if (anydata->value_type & LYD_ANYDATA_STRING) {
|
|
Packit |
8fb591 |
/* dynamic value, only used for input */
|
|
Packit |
8fb591 |
LOGERR(anydata->schema->module->ctx, LY_EINT, "Unsupported anydata value type to print.");
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
type = anydata->value_type;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* first byte is type */
|
|
Packit |
8fb591 |
ret += lyb_write(out, (uint8_t *)&type, sizeof type, lybs);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* followed by the content */
|
|
Packit |
8fb591 |
if (anydata->value_type == LYD_ANYDATA_DATATREE) {
|
|
Packit |
8fb591 |
ret += lyb_print_data(out, anydata->value.tree, 0);
|
|
Packit |
8fb591 |
} else if (anydata->value_type == LYD_ANYDATA_LYB) {
|
|
Packit |
8fb591 |
len = lyd_lyb_data_length(anydata->value.mem);
|
|
Packit |
8fb591 |
if (len > -1) {
|
|
Packit |
8fb591 |
ret += lyb_write_string(anydata->value.str, (size_t)len, 0, out, lybs);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
ret += lyb_write_string(anydata->value.str, 0, 0, out, lybs);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_print_value(const struct lys_type *type, const char *value_str, lyd_val value, LY_DATA_TYPE value_type,
|
|
Packit |
8fb591 |
uint8_t value_flags, uint8_t dflt, struct lyout *out, struct lyb_state *lybs)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int ret = 0;
|
|
Packit |
8fb591 |
uint8_t byte = 0;
|
|
Packit |
8fb591 |
size_t count, i, bits_i;
|
|
Packit |
8fb591 |
LY_DATA_TYPE dtype;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* value type byte - ABCD DDDD
|
|
Packit |
8fb591 |
*
|
|
Packit |
8fb591 |
* A - dflt flag
|
|
Packit |
8fb591 |
* B - user type flag
|
|
Packit |
8fb591 |
* C - unres flag
|
|
Packit |
8fb591 |
* D (5b) - data type value
|
|
Packit |
8fb591 |
*/
|
|
Packit |
8fb591 |
if (dflt) {
|
|
Packit |
8fb591 |
byte |= 0x80;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if (value_flags & LY_VALUE_USER) {
|
|
Packit |
8fb591 |
byte |= 0x40;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if (value_flags & LY_VALUE_UNRES) {
|
|
Packit |
8fb591 |
byte |= 0x20;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* we have only 5b available, must be enough */
|
|
Packit |
8fb591 |
assert((value_type & 0x1f) == value_type);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if ((value_flags & LY_VALUE_USER) || (type->base == LY_TYPE_UNION)) {
|
|
Packit |
8fb591 |
value_type = LY_TYPE_STRING;
|
|
Packit |
8fb591 |
} else if (value_type == LY_TYPE_LEAFREF) {
|
|
Packit |
8fb591 |
assert(!(value_flags & LY_VALUE_UNRES));
|
|
Packit |
8fb591 |
/* find the leafref target type */
|
|
Packit |
8fb591 |
while (type->base == LY_TYPE_LEAFREF) {
|
|
Packit |
8fb591 |
type = &type->info.lref.target->type;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
value_type = type->base;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* and also use its value */
|
|
Packit |
8fb591 |
value = ((struct lyd_node_leaf_list *)value.leafref)->value;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* store the value type */
|
|
Packit |
8fb591 |
byte |= value_type & 0x1f;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* write value type byte */
|
|
Packit |
8fb591 |
ret += lyb_write(out, &byte, sizeof byte, lybs);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* print value itself */
|
|
Packit |
8fb591 |
if (value_flags & LY_VALUE_USER) {
|
|
Packit |
8fb591 |
dtype = LY_TYPE_STRING;
|
|
Packit |
8fb591 |
} else {
|
|
Packit |
8fb591 |
dtype = value_type;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
switch (dtype) {
|
|
Packit |
8fb591 |
case LY_TYPE_BINARY:
|
|
Packit |
8fb591 |
case LY_TYPE_INST:
|
|
Packit |
8fb591 |
case LY_TYPE_STRING:
|
|
Packit |
8fb591 |
case LY_TYPE_UNION:
|
|
Packit |
8fb591 |
case LY_TYPE_IDENT:
|
|
Packit |
8fb591 |
case LY_TYPE_UNKNOWN:
|
|
Packit |
8fb591 |
/* store string */
|
|
Packit |
8fb591 |
ret += lyb_write_string(value_str, 0, 0, out, lybs);
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
case LY_TYPE_BITS:
|
|
Packit |
8fb591 |
/* find the correct structure */
|
|
Packit |
8fb591 |
for (; !type->info.bits.count; type = &type->der->type);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* store a bitfield */
|
|
Packit |
8fb591 |
bits_i = 0;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (count = type->info.bits.count / 8; count; --count) {
|
|
Packit |
8fb591 |
/* will be a full byte */
|
|
Packit |
8fb591 |
for (byte = 0, i = 0; i < 8; ++i) {
|
|
Packit |
8fb591 |
if (value.bit[bits_i + i]) {
|
|
Packit |
8fb591 |
byte |= (1 << i);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
ret += lyb_write(out, &byte, sizeof byte, lybs);
|
|
Packit |
8fb591 |
bits_i += 8;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* store the remainder */
|
|
Packit |
8fb591 |
if (type->info.bits.count % 8) {
|
|
Packit |
8fb591 |
for (byte = 0, i = 0; i < type->info.bits.count % 8; ++i) {
|
|
Packit |
8fb591 |
if (value.bit[bits_i + i]) {
|
|
Packit |
8fb591 |
byte |= (1 << i);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
ret += lyb_write(out, &byte, sizeof byte, lybs);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
case LY_TYPE_BOOL:
|
|
Packit |
8fb591 |
/* store the whole byte */
|
|
Packit |
8fb591 |
byte = 0;
|
|
Packit |
8fb591 |
if (value.bln) {
|
|
Packit |
8fb591 |
byte = 1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
ret += lyb_write(out, &byte, sizeof byte, lybs);
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
case LY_TYPE_EMPTY:
|
|
Packit |
8fb591 |
/* nothing to store */
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
case LY_TYPE_ENUM:
|
|
Packit |
8fb591 |
/* find the correct structure */
|
|
Packit |
8fb591 |
for (; !type->info.enums.count; type = &type->der->type);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* store the enum index (save bytes if possible) */
|
|
Packit |
8fb591 |
i = value.enm - type->info.enums.enm;
|
|
Packit |
8fb591 |
ret += lyb_write_enum(i, type->info.enums.count, out, lybs);
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
case LY_TYPE_INT8:
|
|
Packit |
8fb591 |
case LY_TYPE_UINT8:
|
|
Packit |
8fb591 |
ret += lyb_write_number(value.uint8, 1, out, lybs);
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
case LY_TYPE_INT16:
|
|
Packit |
8fb591 |
case LY_TYPE_UINT16:
|
|
Packit |
8fb591 |
ret += lyb_write_number(value.uint16, 2, out, lybs);
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
case LY_TYPE_INT32:
|
|
Packit |
8fb591 |
case LY_TYPE_UINT32:
|
|
Packit |
8fb591 |
ret += lyb_write_number(value.uint32, 4, out, lybs);
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
case LY_TYPE_DEC64:
|
|
Packit |
8fb591 |
case LY_TYPE_INT64:
|
|
Packit |
8fb591 |
case LY_TYPE_UINT64:
|
|
Packit |
8fb591 |
ret += lyb_write_number(value.uint64, 8, out, lybs);
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
default:
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_print_attributes(struct lyout *out, struct lyd_attr *attr, struct lyb_state *lybs)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int r, ret = 0;
|
|
Packit |
8fb591 |
uint8_t count;
|
|
Packit |
8fb591 |
struct lyd_attr *iter;
|
|
Packit |
8fb591 |
struct lys_type **type;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* count attributes */
|
|
Packit |
8fb591 |
for (count = 0, iter = attr; iter; ++count, iter = iter->next) {
|
|
Packit |
8fb591 |
if (count == UINT8_MAX) {
|
|
Packit |
8fb591 |
LOGERR(NULL, LY_EINT, "Maximum supported number of data node attributes is %u.", UINT8_MAX);
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* write number of attributes on 1 byte */
|
|
Packit |
8fb591 |
ret += (r = lyb_write(out, &count, 1, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* write all the attributes */
|
|
Packit |
8fb591 |
LY_TREE_FOR(attr, iter) {
|
|
Packit |
8fb591 |
/* each attribute is a subtree */
|
|
Packit |
8fb591 |
ret += (r = lyb_write_start_subtree(out, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* model */
|
|
Packit |
8fb591 |
ret += (r = lyb_print_model(out, iter->annotation->module, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* annotation name with length */
|
|
Packit |
8fb591 |
ret += (r = lyb_write_string(iter->annotation->arg_value, 0, 1, out, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* get the type */
|
|
Packit |
8fb591 |
type = (struct lys_type **)lys_ext_complex_get_substmt(LY_STMT_TYPE, iter->annotation, NULL);
|
|
Packit |
8fb591 |
if (!type || !(*type)) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* attribute value */
|
|
Packit |
8fb591 |
ret += (r = lyb_print_value(*type, iter->value_str, iter->value, iter->value_type, iter->value_flags, 0, out, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* finish attribute subtree */
|
|
Packit |
8fb591 |
ret += (r = lyb_write_stop_subtree(out, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_print_schema_hash(struct lyout *out, struct lys_node *schema, struct hash_table **sibling_ht, struct lyb_state *lybs,
|
|
Packit |
8fb591 |
int options)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int r, ret = 0;
|
|
Packit |
8fb591 |
void *mem;
|
|
Packit |
8fb591 |
uint32_t i;
|
|
Packit |
8fb591 |
LYB_HASH hash;
|
|
Packit |
8fb591 |
struct lys_node *first_sibling, *parent, *iter;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* create whole sibling HT if not already created and saved */
|
|
Packit |
8fb591 |
if (!*sibling_ht) {
|
|
Packit |
8fb591 |
/* get first schema data sibling */
|
|
Packit |
8fb591 |
for (parent = lys_parent(schema);
|
|
Packit |
8fb591 |
parent && (parent->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE | LYS_INPUT | LYS_OUTPUT));
|
|
Packit |
8fb591 |
parent = lys_parent(parent)) {
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* we have checked this before */
|
|
Packit |
8fb591 |
assert(!(options & LYD_OPT_RPC) || (parent->nodetype != LYS_OUTPUT));
|
|
Packit |
8fb591 |
assert(!(options & LYD_OPT_RPCREPLY) || (parent->nodetype != LYS_INPUT));
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
first_sibling = (struct lys_node *)lys_getnext(NULL, parent, lys_node_module(schema), 0);
|
|
Packit |
8fb591 |
if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) {
|
|
Packit |
8fb591 |
check_inout:
|
|
Packit |
8fb591 |
for (iter = lys_parent(first_sibling);
|
|
Packit |
8fb591 |
iter && (iter->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE));
|
|
Packit |
8fb591 |
iter = lys_parent(iter));
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (iter && (((options & LYD_OPT_RPC) && (iter->nodetype == LYS_OUTPUT))
|
|
Packit |
8fb591 |
|| ((options & LYD_OPT_RPCREPLY) && (iter->nodetype == LYS_INPUT)))) {
|
|
Packit |
8fb591 |
first_sibling = (struct lys_node *)lys_getnext(first_sibling, NULL, NULL, 0);
|
|
Packit |
8fb591 |
goto check_inout;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (r = 0; r < lybs->sib_ht_count; ++r) {
|
|
Packit |
8fb591 |
if (lybs->sib_ht[r].first_sibling == first_sibling) {
|
|
Packit |
8fb591 |
/* we have already created a hash table for these siblings */
|
|
Packit |
8fb591 |
*sibling_ht = lybs->sib_ht[r].ht;
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (!*sibling_ht) {
|
|
Packit |
8fb591 |
/* we must create sibling hash table */
|
|
Packit |
8fb591 |
*sibling_ht = lyb_hash_siblings(first_sibling, NULL, 0, options);
|
|
Packit |
8fb591 |
if (!*sibling_ht) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* and save it */
|
|
Packit |
8fb591 |
++lybs->sib_ht_count;
|
|
Packit |
8fb591 |
mem = realloc(lybs->sib_ht, lybs->sib_ht_count * sizeof *lybs->sib_ht);
|
|
Packit |
8fb591 |
LY_CHECK_ERR_RETURN(!mem, LOGMEM(schema->module->ctx), -1);
|
|
Packit |
8fb591 |
lybs->sib_ht = mem;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
lybs->sib_ht[lybs->sib_ht_count - 1].first_sibling = first_sibling;
|
|
Packit |
8fb591 |
lybs->sib_ht[lybs->sib_ht_count - 1].ht = *sibling_ht;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* get our hash */
|
|
Packit |
8fb591 |
hash = lyb_hash_find(*sibling_ht, schema);
|
|
Packit |
8fb591 |
if (!hash) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* write the hash */
|
|
Packit |
8fb591 |
ret += (r = lyb_write(out, &hash, sizeof hash, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (hash & LYB_HASH_COLLISION_ID) {
|
|
Packit |
8fb591 |
/* no collision for this hash, we are done */
|
|
Packit |
8fb591 |
return ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* written hash was a collision, write also all the preceding hashes */
|
|
Packit |
8fb591 |
for (i = 0; !(hash & (LYB_HASH_COLLISION_ID >> i)); ++i);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
for (; i; --i) {
|
|
Packit |
8fb591 |
hash = lyb_hash(schema, i - 1);
|
|
Packit |
8fb591 |
if (!hash) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
assert(hash & (LYB_HASH_COLLISION_ID >> (i - 1)));
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
ret += (r = lyb_write(out, &hash, sizeof hash, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
static int
|
|
Packit |
8fb591 |
lyb_print_subtree(struct lyout *out, const struct lyd_node *node, struct hash_table **sibling_ht, struct lyb_state *lybs,
|
|
Packit |
8fb591 |
int options, int top_level)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int r, ret = 0;
|
|
Packit |
8fb591 |
struct lyd_node_leaf_list *leaf;
|
|
Packit |
8fb591 |
struct lys_node *sparent;
|
|
Packit |
8fb591 |
struct hash_table *child_ht = NULL;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* skip nodes that should not be printed */
|
|
Packit |
8fb591 |
if (options & (LYD_OPT_RPC | LYD_OPT_RPCREPLY)) {
|
|
Packit |
8fb591 |
for (sparent = lys_parent(node->schema);
|
|
Packit |
8fb591 |
sparent && (sparent->nodetype & (LYS_USES | LYS_CASE | LYS_CHOICE));
|
|
Packit |
8fb591 |
sparent = lys_parent(sparent));
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (sparent) {
|
|
Packit |
8fb591 |
if ((options & LYD_OPT_RPC) && (sparent->nodetype == LYS_OUTPUT)) {
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if ((options & LYD_OPT_RPCREPLY) && (sparent->nodetype == LYS_INPUT)) {
|
|
Packit |
8fb591 |
return 0;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* register a new subtree */
|
|
Packit |
8fb591 |
ret += (r = lyb_write_start_subtree(out, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/*
|
|
Packit |
8fb591 |
* write the node information
|
|
Packit |
8fb591 |
*/
|
|
Packit |
8fb591 |
if (top_level) {
|
|
Packit |
8fb591 |
/* write model info first */
|
|
Packit |
8fb591 |
ret += (r = lyb_print_model(out, lyd_node_module(node), lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
ret += (r = lyb_print_schema_hash(out, node->schema, sibling_ht, lybs, options));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
ret += (r = lyb_print_attributes(out, node->attr, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* write node content */
|
|
Packit |
8fb591 |
switch (node->schema->nodetype) {
|
|
Packit |
8fb591 |
case LYS_CONTAINER:
|
|
Packit |
8fb591 |
case LYS_LIST:
|
|
Packit |
8fb591 |
case LYS_NOTIF:
|
|
Packit |
8fb591 |
case LYS_RPC:
|
|
Packit |
8fb591 |
case LYS_ACTION:
|
|
Packit |
8fb591 |
/* nothing to write */
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
case LYS_LEAF:
|
|
Packit |
8fb591 |
case LYS_LEAFLIST:
|
|
Packit |
8fb591 |
leaf = (struct lyd_node_leaf_list *)node;
|
|
Packit |
8fb591 |
ret += (r = lyb_print_value(&((struct lys_node_leaf *)leaf->schema)->type, leaf->value_str, leaf->value,
|
|
Packit |
8fb591 |
leaf->value_type, leaf->value_flags, leaf->dflt, out, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
case LYS_ANYXML:
|
|
Packit |
8fb591 |
case LYS_ANYDATA:
|
|
Packit |
8fb591 |
ret += (r = lyb_print_anydata((struct lyd_node_anydata *)node, out, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
default:
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* recursively write all the descendants */
|
|
Packit |
8fb591 |
r = 0;
|
|
Packit |
8fb591 |
if (node->schema->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_NOTIF | LYS_RPC | LYS_ACTION)) {
|
|
Packit |
8fb591 |
LY_TREE_FOR(node->child, node) {
|
|
Packit |
8fb591 |
ret += (r = lyb_print_subtree(out, node, &child_ht, lybs, options, 0));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* finish this subtree */
|
|
Packit |
8fb591 |
ret += (r = lyb_write_stop_subtree(out, lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
return -1;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return ret;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
int
|
|
Packit |
8fb591 |
lyb_print_data(struct lyout *out, const struct lyd_node *root, int options)
|
|
Packit |
8fb591 |
{
|
|
Packit |
8fb591 |
int r, ret = 0, rc = EXIT_SUCCESS;
|
|
Packit |
8fb591 |
uint8_t zero = 0;
|
|
Packit |
8fb591 |
struct hash_table *top_sibling_ht = NULL;
|
|
Packit |
8fb591 |
const struct lys_module *prev_mod = NULL;
|
|
Packit |
8fb591 |
struct lyb_state lybs;
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
memset(&lybs, 0, sizeof lybs);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* LYB magic number */
|
|
Packit |
8fb591 |
ret += (r = lyb_print_magic_number(out));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
rc = EXIT_FAILURE;
|
|
Packit |
8fb591 |
goto finish;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* LYB header */
|
|
Packit |
8fb591 |
ret += (r = lyb_print_header(out));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
rc = EXIT_FAILURE;
|
|
Packit |
8fb591 |
goto finish;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* all used models */
|
|
Packit |
8fb591 |
ret += (r = lyb_print_data_models(out, root, &lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
rc = EXIT_FAILURE;
|
|
Packit |
8fb591 |
goto finish;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
LY_TREE_FOR(root, root) {
|
|
Packit |
8fb591 |
/* do not reuse sibling hash tables from different modules */
|
|
Packit |
8fb591 |
if (lyd_node_module(root) != prev_mod) {
|
|
Packit |
8fb591 |
top_sibling_ht = NULL;
|
|
Packit |
8fb591 |
prev_mod = lyd_node_module(root);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
ret += (r = lyb_print_subtree(out, root, &top_sibling_ht, &lybs, options, 1));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
rc = EXIT_FAILURE;
|
|
Packit |
8fb591 |
goto finish;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
if (!(options & LYP_WITHSIBLINGS)) {
|
|
Packit |
8fb591 |
break;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
/* ending zero byte */
|
|
Packit |
8fb591 |
ret += (r = lyb_write(out, &zero, sizeof zero, &lybs));
|
|
Packit |
8fb591 |
if (r < 0) {
|
|
Packit |
8fb591 |
rc = EXIT_FAILURE;
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
finish:
|
|
Packit |
8fb591 |
free(lybs.written);
|
|
Packit |
8fb591 |
free(lybs.position);
|
|
Packit |
8fb591 |
free(lybs.inner_chunks);
|
|
Packit |
8fb591 |
for (r = 0; r < lybs.sib_ht_count; ++r) {
|
|
Packit |
8fb591 |
lyht_free(lybs.sib_ht[r].ht);
|
|
Packit |
8fb591 |
}
|
|
Packit |
8fb591 |
free(lybs.sib_ht);
|
|
Packit |
8fb591 |
|
|
Packit |
8fb591 |
return rc;
|
|
Packit |
8fb591 |
}
|