data FEATURE parser for YANG data in JSON format
diff --git a/src/parser_lyb.c b/src/parser_lyb.c
index fc74236..3c8fa76 100644
--- a/src/parser_lyb.c
+++ b/src/parser_lyb.c
@@ -33,6 +33,32 @@
#include "tree_schema.h"
#include "validation.h"
+void
+lylyb_ctx_free(struct lylyb_ctx *ctx)
+{
+ LY_ARRAY_COUNT_TYPE u;
+
+ LY_ARRAY_FREE(ctx->subtrees);
+ LY_ARRAY_FREE(ctx->models);
+
+ LY_ARRAY_FOR(ctx->sib_hts, u) {
+ lyht_free(ctx->sib_hts[u].ht);
+ }
+ LY_ARRAY_FREE(ctx->sib_hts);
+
+ free(ctx);
+}
+
+void
+lyd_lyb_ctx_free(struct lyd_ctx *lydctx)
+{
+ struct lyd_lyb_ctx *ctx = (struct lyd_lyb_ctx *)lydctx;
+
+ lyd_ctx_free(lydctx);
+ lylyb_ctx_free(ctx->lybctx);
+ free(ctx);
+}
+
/**
* @brief Read YANG data from LYB input. Metadata are handled transparently and not returned.
*
@@ -41,7 +67,7 @@
* @param[in] lybctx LYB context.
*/
static void
-lyb_read(uint8_t *buf, size_t count, struct lyd_lyb_ctx *lybctx)
+lyb_read(uint8_t *buf, size_t count, struct lylyb_ctx *lybctx)
{
LY_ARRAY_COUNT_TYPE u;
struct lyd_lyb_subtree *empty;
@@ -109,7 +135,7 @@
* @param[in] lybctx LYB context.
*/
static void
-lyb_read_number(void *num, size_t num_size, size_t bytes, struct lyd_lyb_ctx *lybctx)
+lyb_read_number(void *num, size_t num_size, size_t bytes, struct lylyb_ctx *lybctx)
{
uint64_t buf = 0;
@@ -145,7 +171,7 @@
* @return LY_ERR value.
*/
static LY_ERR
-lyb_read_string(char **str, int with_length, struct lyd_lyb_ctx *lybctx)
+lyb_read_string(char **str, int with_length, struct lylyb_ctx *lybctx)
{
int next_chunk = 0;
size_t len = 0, cur_len;
@@ -194,7 +220,7 @@
* @return LY_ERR value.
*/
static LY_ERR
-lyb_read_stop_subtree(struct lyd_lyb_ctx *lybctx)
+lyb_read_stop_subtree(struct lylyb_ctx *lybctx)
{
if (LYB_LAST_SUBTREE(lybctx).written) {
LOGINT_RET(lybctx->ctx);
@@ -211,7 +237,7 @@
* @return LY_ERR value.
*/
static LY_ERR
-lyb_read_start_subtree(struct lyd_lyb_ctx *lybctx)
+lyb_read_start_subtree(struct lylyb_ctx *lybctx)
{
uint8_t meta_buf[LYB_META_BYTES];
LY_ARRAY_COUNT_TYPE u;
@@ -245,7 +271,7 @@
* @return LY_ERR value.
*/
static LY_ERR
-lyb_parse_model(struct lyd_lyb_ctx *lybctx, const struct lys_module **mod)
+lyb_parse_model(struct lylyb_ctx *lybctx, uint32_t parse_options, const struct lys_module **mod)
{
LY_ERR ret = LY_SUCCESS;
char *mod_name = NULL, mod_rev[11];
@@ -267,7 +293,7 @@
if (rev) {
sprintf(mod_rev, "%04u-%02u-%02u", ((rev & 0xFE00) >> 9) + 2000, (rev & 0x01E0) >> 5, rev & 0x001Fu);
*mod = ly_ctx_get_module(lybctx->ctx, mod_name, mod_rev);
- if ((lybctx->parse_options & LYD_PARSE_LYB_MOD_UPDATE) && !(*mod)) {
+ if ((parse_options & LYD_PARSE_LYB_MOD_UPDATE) && !(*mod)) {
/* try to use an updated module */
*mod = ly_ctx_get_module_implemented(lybctx->ctx, mod_name);
if (*mod && (!(*mod)->revision || (strcmp((*mod)->revision, mod_rev) < 0))) {
@@ -288,7 +314,7 @@
}*/
if (!*mod || !(*mod)->implemented) {
- if (lybctx->parse_options & LYD_PARSE_STRICT) {
+ if (parse_options & LYD_PARSE_STRICT) {
if (!*mod) {
LOGERR(lybctx->ctx, LY_EINVAL, "Invalid context for LYB data parsing, missing module \"%s%s%s\".",
mod_name, rev ? "@" : "", rev ? mod_rev : "");
@@ -325,37 +351,37 @@
const struct lys_module *mod;
/* read number of attributes stored */
- lyb_read(&count, 1, lybctx);
+ lyb_read(&count, 1, lybctx->lybctx);
/* read attributes */
for (i = 0; i < count; ++i) {
- ret = lyb_read_start_subtree(lybctx);
+ ret = lyb_read_start_subtree(lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
/* find model */
- ret = lyb_parse_model(lybctx, &mod);
+ ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_options, &mod);
LY_CHECK_GOTO(ret, cleanup);
if (!mod) {
/* skip it */
do {
- lyb_read(NULL, LYB_LAST_SUBTREE(lybctx).written, lybctx);
- } while (LYB_LAST_SUBTREE(lybctx).written);
+ lyb_read(NULL, LYB_LAST_SUBTREE(lybctx->lybctx).written, lybctx->lybctx);
+ } while (LYB_LAST_SUBTREE(lybctx->lybctx).written);
goto stop_subtree;
}
/* meta name */
- ret = lyb_read_string(&meta_name, 1, lybctx);
+ ret = lyb_read_string(&meta_name, 1, lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
/* meta value */
- ret = lyb_read_string(&meta_value, 0, lybctx);
+ ret = lyb_read_string(&meta_value, 0, lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
dynamic = 1;
/* create metadata */
- ret = lyd_create_meta(NULL, meta, mod, meta_name, strlen(meta_name), meta_value, strlen(meta_value), &dynamic,
- lydjson_resolve_prefix, NULL, LYD_JSON, sparent);
+ ret = lyd_parser_create_meta((struct lyd_ctx*)lybctx, NULL, meta, mod, meta_name, strlen(meta_name), meta_value, ly_strlen(meta_value),
+ &dynamic, 0, lydjson_resolve_prefix, NULL, LYD_JSON, sparent);
/* free strings */
free(meta_name);
@@ -365,14 +391,10 @@
dynamic = 0;
}
- if (ret == LY_EINCOMPLETE) {
- ly_set_add(&lybctx->unres_meta_type, *meta, LY_SET_OPT_USEASLIST);
- } else if (ret) {
- goto cleanup;
- }
+ LY_CHECK_GOTO(ret, cleanup);
stop_subtree:
- ret = lyb_read_stop_subtree(lybctx);
+ ret = lyb_read_stop_subtree(lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
}
@@ -393,7 +415,7 @@
* @return LY_ERR value.
*/
static LY_ERR
-lyb_parse_opaq_prefixes(struct lyd_lyb_ctx *lybctx, struct ly_prefix **prefs)
+lyb_parse_opaq_prefixes(struct lylyb_ctx *lybctx, struct ly_prefix **prefs)
{
LY_ERR ret = LY_SUCCESS;
uint8_t count, i;
@@ -412,12 +434,12 @@
/* prefix */
ret = lyb_read_string(&str, 1, lybctx);
LY_CHECK_GOTO(ret, cleanup);
- (*prefs)[i].pref = lydict_insert_zc(lybctx->ctx, str);
+ (*prefs)[i].id = lydict_insert_zc(lybctx->ctx, str);
- /* namespace */
+ /* module reference is the same as JSON name */
ret = lyb_read_string(&str, 1, lybctx);
LY_CHECK_GOTO(ret, cleanup);
- (*prefs)[i].ns = lydict_insert_zc(lybctx->ctx, str);
+ (*prefs)[i].module_name = lydict_insert_zc(lybctx->ctx, str);
}
cleanup:
@@ -436,12 +458,12 @@
* @return LY_ERR value.
*/
static LY_ERR
-lyb_parse_attributes(struct lyd_lyb_ctx *lybctx, struct ly_attr **attr)
+lyb_parse_attributes(struct lylyb_ctx *lybctx, struct lyd_attr **attr)
{
LY_ERR ret = LY_SUCCESS;
uint8_t count, i;
- struct ly_attr *attr2;
- char *prefix = NULL, *ns = NULL, *name = NULL, *value = NULL;
+ struct lyd_attr *attr2;
+ char *prefix = NULL, *module_name = NULL, *name = NULL, *value = NULL;
int dynamic = 0;
LYD_FORMAT format = 0;
struct ly_prefix *val_prefs = NULL;
@@ -463,11 +485,11 @@
}
/* namespace, may be empty */
- ret = lyb_read_string(&ns, 1, lybctx);
+ ret = lyb_read_string(&module_name, 1, lybctx);
LY_CHECK_GOTO(ret, cleanup);
- if (!ns[0]) {
- free(ns);
- ns = NULL;
+ if (!module_name[0]) {
+ free(module_name);
+ module_name = NULL;
}
/* name */
@@ -487,14 +509,14 @@
dynamic = 1;
/* attr2 is always changed to the created attribute */
- ret = ly_create_attr(NULL, &attr2, lybctx->ctx, name, strlen(name), value, strlen(value), &dynamic, format,
- val_prefs, prefix, prefix ? strlen(prefix) : 0, ns);
+ ret = lyd_create_attr(NULL, &attr2, lybctx->ctx, name, strlen(name), value, ly_strlen(value), &dynamic, 0, format,
+ val_prefs, prefix, ly_strlen(prefix), module_name, ly_strlen(module_name));
LY_CHECK_GOTO(ret, cleanup);
free(prefix);
prefix = NULL;
- free(ns);
- ns = NULL;
+ free(module_name);
+ module_name = NULL;
free(name);
name = NULL;
val_prefs = NULL;
@@ -511,7 +533,7 @@
cleanup:
free(prefix);
- free(ns);
+ free(module_name);
free(name);
if (dynamic) {
free(value);
@@ -551,54 +573,6 @@
}
/**
- * @brief Check that a schema node is suitable based on options.
- *
- * @param[in] lybctx LYB context.
- * @param[in] snode Schema node to check.
- * @return LY_ERR value.
- */
-static LY_ERR
-lyb_parse_check_schema(struct lyd_lyb_ctx *lybctx, const struct lysc_node *snode)
-{
- LY_ERR ret = LY_SUCCESS;
-
- if ((lybctx->parse_options & LYD_PARSE_NO_STATE) && (snode->flags & LYS_CONFIG_R)) {
- LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LY_VCODE_INNODE, "state", snode->name);
- return LY_EVALID;
- }
-
- if (snode->nodetype & (LYS_RPC | LYS_ACTION)) {
- if (lybctx->int_opts & LYD_INTOPT_RPC) {
- if (lybctx->op_ntf) {
- LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
- lys_nodetype2str(snode->nodetype), snode->name,
- lys_nodetype2str(lybctx->op_ntf->schema->nodetype), lybctx->op_ntf->schema->name);
- return LY_EVALID;
- }
- } else {
- LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LYVE_DATA, "Unexpected %s element \"%s\".",
- lys_nodetype2str(snode->nodetype), snode->name);
- return LY_EVALID;
- }
- } else if (snode->nodetype == LYS_NOTIF) {
- if (lybctx->int_opts & LYD_INTOPT_NOTIF) {
- if (lybctx->op_ntf) {
- LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LYVE_DATA, "Unexpected %s element \"%s\", %s \"%s\" already parsed.",
- lys_nodetype2str(snode->nodetype), snode->name,
- lys_nodetype2str(lybctx->op_ntf->schema->nodetype), lybctx->op_ntf->schema->name);
- return LY_EVALID;
- }
- } else {
- LOGVAL(lybctx->ctx, LY_VLOG_LYSC, snode, LYVE_DATA, "Unexpected %s element \"%s\".",
- lys_nodetype2str(snode->nodetype), snode->name);
- return LY_EVALID;
- }
- }
-
- return ret;
-}
-
-/**
* @brief Parse schema node hash.
*
* @param[in] lybctx LYB context.
@@ -622,7 +596,7 @@
getnext_opts = LYS_GETNEXT_NOSTATECHECK | (lybctx->int_opts & LYD_INTOPT_REPLY ? LYS_GETNEXT_OUTPUT : 0);
/* read the first hash */
- lyb_read(&hash[0], sizeof *hash, lybctx);
+ lyb_read(&hash[0], sizeof *hash, lybctx->lybctx);
if (!hash[0]) {
/* opaque node */
@@ -632,7 +606,7 @@
/* based on the first hash read all the other ones, if any */
for (i = 0; !(hash[0] & (LYB_HASH_COLLISION_ID >> i)); ++i) {
if (i > LYB_HASH_BITS) {
- LOGINT_RET(lybctx->ctx);
+ LOGINT_RET(lybctx->lybctx->ctx);
}
}
@@ -641,7 +615,7 @@
/* read the rest of hashes */
for (j = i; j; --j) {
- lyb_read(&hash[j - 1], sizeof *hash, lybctx);
+ lyb_read(&hash[j - 1], sizeof *hash, lybctx->lybctx);
/* correct collision ID */
assert(hash[j - 1] & (LYB_HASH_COLLISION_ID >> (j - 1)));
@@ -653,7 +627,7 @@
sibling = NULL;
while ((sibling = lys_getnext(sibling, sparent, mod ? mod->compiled : NULL, getnext_opts))) {
/* skip schema nodes from models not present during printing */
- if (lyb_has_schema_model(sibling, lybctx->models)
+ if (lyb_has_schema_model(sibling, lybctx->lybctx->models)
&& lyb_is_schema_hash_match((struct lysc_node *)sibling, hash, i + 1)) {
/* match found */
break;
@@ -662,14 +636,14 @@
if (!sibling && (lybctx->parse_options & LYD_PARSE_STRICT)) {
if (mod) {
- LOGVAL(lybctx->ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE, "Failed to find matching hash for a top-level node"
+ LOGVAL(lybctx->lybctx->ctx, LY_VLOG_NONE, NULL, LYVE_REFERENCE, "Failed to find matching hash for a top-level node"
" from \"%s\".", mod->name);
} else {
- LOGVAL(lybctx->ctx, LY_VLOG_LYSC, sparent, LYVE_REFERENCE, "Failed to find matching hash for a child node"
+ LOGVAL(lybctx->lybctx->ctx, LY_VLOG_LYSC, sparent, LYVE_REFERENCE, "Failed to find matching hash for a child node"
" of \"%s\".", sparent->name);
}
return LY_EVALID;
- } else if (sibling && (ret = lyb_parse_check_schema(lybctx, sibling))) {
+ } else if (sibling && (ret = lyd_parser_check_schema((struct lyd_ctx *)lybctx, sibling))) {
return ret;
}
@@ -683,7 +657,7 @@
* @param[in] lybctx LYB context.
*/
static void
-lyb_skip_subtree(struct lyd_lyb_ctx *lybctx)
+lyb_skip_subtree(struct lylyb_ctx *lybctx)
{
do {
/* first skip any meta information inside */
@@ -710,20 +684,21 @@
const struct lys_module *mod;
const struct lysc_node *snode = NULL;
struct lyd_meta *meta = NULL, *m;
- struct ly_attr *attr = NULL, *a;
+ struct lyd_attr *attr = NULL, *a;
struct ly_prefix *val_prefs = NULL;
LYD_ANYDATA_VALUETYPE value_type;
- char *value = NULL, *name = NULL, *prefix = NULL, *ns = NULL;
+ char *value = NULL, *name = NULL, *prefix = NULL, *module_key = NULL;
int dynamic = 0;
LYD_FORMAT format = 0;
int prev_lo;
+ const struct ly_ctx *ctx = lybctx->lybctx->ctx;
/* register a new subtree */
- LY_CHECK_GOTO(ret = lyb_read_start_subtree(lybctx), cleanup);
+ LY_CHECK_GOTO(ret = lyb_read_start_subtree(lybctx->lybctx), cleanup);
if (!parent) {
/* top-level, read module name */
- ret = lyb_parse_model(lybctx, &mod);
+ ret = lyb_parse_model(lybctx->lybctx, lybctx->parse_options, &mod);
LY_CHECK_GOTO(ret, cleanup);
/* read hash, find the schema node starting from mod */
@@ -737,7 +712,7 @@
if (!snode && !(lybctx->parse_options & LYD_PARSE_OPAQ)) {
/* unknown data, skip them */
- lyb_skip_subtree(lybctx);
+ lyb_skip_subtree(lybctx->lybctx);
goto stop_subtree;
}
@@ -746,73 +721,67 @@
ret = lyb_parse_metadata(lybctx, snode, &meta);
LY_CHECK_GOTO(ret, cleanup);
} else {
- ret = lyb_parse_attributes(lybctx, &attr);
+ ret = lyb_parse_attributes(lybctx->lybctx, &attr);
LY_CHECK_GOTO(ret, cleanup);
}
if (!snode) {
/* parse prefix */
- ret = lyb_read_string(&prefix, 1, lybctx);
+ ret = lyb_read_string(&prefix, 1, lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
- /* parse namespace */
- ret = lyb_read_string(&ns, 1, lybctx);
+ /* parse module key */
+ ret = lyb_read_string(&module_key, 1, lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
/* parse name */
- ret = lyb_read_string(&name, 1, lybctx);
+ ret = lyb_read_string(&name, 1, lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
/* parse value prefixes */
- ret = lyb_parse_opaq_prefixes(lybctx, &val_prefs);
+ ret = lyb_parse_opaq_prefixes(lybctx->lybctx, &val_prefs);
LY_CHECK_GOTO(ret, cleanup);
/* parse format */
- lyb_read((uint8_t *)&format, 1, lybctx);
+ lyb_read((uint8_t *)&format, 1, lybctx->lybctx);
/* parse value */
- ret = lyb_read_string(&value, 0, lybctx);
+ ret = lyb_read_string(&value, 0, lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
dynamic = 1;
/* create node */
- ret = lyd_create_opaq(lybctx->ctx, name, strlen(name), value, strlen(value), &dynamic, format, val_prefs, prefix,
- strlen(prefix), ns, &node);
+ ret = lyd_create_opaq(ctx, name, strlen(name), value, strlen(value), &dynamic, 0, format, val_prefs, prefix,
+ ly_strlen(prefix), module_key, ly_strlen(module_key), &node);
LY_CHECK_GOTO(ret, cleanup);
/* process children */
- while (LYB_LAST_SUBTREE(lybctx).written) {
+ while (LYB_LAST_SUBTREE(lybctx->lybctx).written) {
ret = lyb_parse_subtree_r(lybctx, (struct lyd_node_inner *)node, NULL);
LY_CHECK_GOTO(ret, cleanup);
}
} else if (snode->nodetype & LYD_NODE_TERM) {
/* parse value */
- ret = lyb_read_string(&value, 0, lybctx);
+ ret = lyb_read_string(&value, 0, lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
dynamic = 1;
/* create node */
- ret = lyd_create_term(snode, value, strlen(value), &dynamic, lydjson_resolve_prefix, NULL, LYD_JSON, &node);
+ ret = lyd_parser_create_term((struct lyd_ctx*)lybctx, snode, value, ly_strlen(value), &dynamic, 0,
+ lydjson_resolve_prefix, NULL, LYD_JSON, &node);
if (dynamic) {
free(value);
dynamic = 0;
}
value = NULL;
- if (ret == LY_EINCOMPLETE) {
- if (!(lybctx->parse_options & LYD_PARSE_ONLY)) {
- ly_set_add(&lybctx->unres_node_type, node, LY_SET_OPT_USEASLIST);
- }
- ret = LY_SUCCESS;
- } else if (ret) {
- goto cleanup;
- }
+ LY_CHECK_GOTO(ret, cleanup);
} else if (snode->nodetype & LYD_NODE_INNER) {
/* create node */
ret = lyd_create_inner(snode, &node);
LY_CHECK_GOTO(ret, cleanup);
/* process children */
- while (LYB_LAST_SUBTREE(lybctx).written) {
+ while (LYB_LAST_SUBTREE(lybctx->lybctx).written) {
ret = lyb_parse_subtree_r(lybctx, (struct lyd_node_inner *)node, NULL);
LY_CHECK_GOTO(ret, cleanup);
}
@@ -831,19 +800,19 @@
if (snode->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) {
/* rememeber the RPC/action/notification */
- lybctx->op_ntf = node;
+ lybctx->op_node = node;
}
} else if (snode->nodetype & LYD_NODE_ANY) {
/* parse value type */
- lyb_read((uint8_t *)&value_type, sizeof value_type, lybctx);
+ lyb_read((uint8_t *)&value_type, sizeof value_type, lybctx->lybctx);
if (value_type == LYD_ANYDATA_DATATREE) {
/* invalid situation */
- LOGINT(lybctx->ctx);
+ LOGINT(ctx);
goto cleanup;
}
/* read anydata content */
- ret = lyb_read_string(&value, 0, lybctx);
+ ret = lyb_read_string(&value, 0, lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
dynamic = 1;
@@ -852,7 +821,7 @@
prev_lo = ly_log_options(0);
/* try to parse LYB into a data tree */
- if (lyd_parse_data_mem((struct ly_ctx *)lybctx->ctx, value, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_OPAQ | LYD_PARSE_STRICT, 0, &tree) == LY_SUCCESS) {
+ if (lyd_parse_data_mem(ctx, value, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_OPAQ | LYD_PARSE_STRICT, 0, &tree) == LY_SUCCESS) {
/* successfully parsed */
free(value);
value = (char *)tree;
@@ -902,20 +871,20 @@
stop_subtree:
/* end the subtree */
- ret = lyb_read_stop_subtree(lybctx);
+ ret = lyb_read_stop_subtree(lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
cleanup:
free(prefix);
- free(ns);
+ free(module_key);
free(name);
if (dynamic) {
free(value);
}
- ly_free_val_prefs(lybctx->ctx, val_prefs);
+ ly_free_val_prefs(ctx, val_prefs);
lyd_free_meta_siblings(meta);
- ly_free_attr_siblings(lybctx->ctx, attr);
+ ly_free_attr_siblings(ctx, attr);
lyd_free_tree(node);
return ret;
}
@@ -927,7 +896,7 @@
* @return LY_ERR value.
*/
static LY_ERR
-lyb_parse_data_models(struct lyd_lyb_ctx *lybctx)
+lyb_parse_data_models(struct lylyb_ctx *lybctx, uint32_t parse_options)
{
LY_ERR ret;
uint32_t count;
@@ -941,7 +910,7 @@
/* read modules */
for (u = 0; u < count; ++u) {
- ret = lyb_parse_model(lybctx, &lybctx->models[u]);
+ ret = lyb_parse_model(lybctx, parse_options, &lybctx->models[u]);
LY_CHECK_RET(ret);
LY_ARRAY_INCREMENT(lybctx->models);
}
@@ -957,7 +926,7 @@
* @return LY_ERR value.
*/
static LY_ERR
-lyb_parse_magic_number(struct lyd_lyb_ctx *lybctx)
+lyb_parse_magic_number(struct lylyb_ctx *lybctx)
{
char magic_byte = 0;
@@ -989,7 +958,7 @@
* @return LY_ERR value.
*/
static LY_ERR
-lyb_parse_header(struct lyd_lyb_ctx *lybctx)
+lyb_parse_header(struct lylyb_ctx *lybctx)
{
uint8_t byte = 0;
@@ -1005,198 +974,139 @@
return LY_SUCCESS;
}
-LY_ERR
-lyd_parse_lyb_data(const struct ly_ctx *ctx, struct ly_in *in, int parse_options, int validate_options,
- struct lyd_node **tree)
+/*
+ * @param[in] ctx libyang context for logging
+ * @param[in] parent Parent node where to connect the parsed data, required for reply where the reply data are connected with the request operation
+ * @param[in] in Input structure.
+ * @param[in] parse_options Options for parser, see @ref dataparseroptions.
+ * @param[in] validate_options Options for the validation phase, see @ref datavalidationoptions.
+ * @param[in] data_type Internal data parser flag to distnguish type of the data to parse (RPC/Reply/Notification/regular data].
+ * @param[out] tree_p Parsed data tree. Note that NULL can be a valid result.
+ * @param[out] op_p Optional pointer to the actual operation. Useful for action and inner notifications.
+ * @param[out] lydctx_p Data parser context to finish validation.
+ */
+static LY_ERR
+lyd_parse_lyb_(const struct ly_ctx *ctx, struct lyd_node_inner **parent, struct ly_in *in, int parse_options, int validate_options,
+ int data_type, struct lyd_node **tree_p, struct lyd_node **op_p, struct lyd_ctx **lydctx_p)
{
LY_ERR ret = LY_SUCCESS;
- struct lyd_lyb_ctx lybctx = {0};
+ struct lyd_lyb_ctx *lybctx;
+ struct lyd_node *tree = NULL;
assert(!(parse_options & ~LYD_PARSE_OPTS_MASK));
assert(!(validate_options & ~LYD_VALIDATE_OPTS_MASK));
- *tree = NULL;
+ lybctx = calloc(1, sizeof *lybctx);
+ LY_CHECK_ERR_RET(!lybctx, LOGMEM(ctx), LY_EMEM);
+ lybctx->lybctx = calloc(1, sizeof *lybctx->lybctx);
+ LY_CHECK_ERR_RET(!lybctx->lybctx, LOGMEM(ctx), LY_EMEM);
- lybctx.in = in;
- lybctx.ctx = ctx;
- lybctx.parse_options = parse_options;
- lybctx.validate_options = validate_options;
+ lybctx->lybctx->in = in;
+ lybctx->lybctx->ctx = ctx;
+ lybctx->parse_options = parse_options;
+ lybctx->validate_options = validate_options;
+ lybctx->int_opts = data_type;
+ lybctx->free = lyd_lyb_ctx_free;
/* read magic number */
- ret = lyb_parse_magic_number(&lybctx);
+ ret = lyb_parse_magic_number(lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
/* read header */
- ret = lyb_parse_header(&lybctx);
+ ret = lyb_parse_header(lybctx->lybctx);
LY_CHECK_GOTO(ret, cleanup);
/* read used models */
- ret = lyb_parse_data_models(&lybctx);
+ ret = lyb_parse_data_models(lybctx->lybctx, lybctx->parse_options);
LY_CHECK_GOTO(ret, cleanup);
/* read subtree(s) */
- while (lybctx.in->current[0]) {
- ret = lyb_parse_subtree_r(&lybctx, NULL, tree);
+ while (lybctx->lybctx->in->current[0]) {
+ ret = lyb_parse_subtree_r(lybctx, parent ? *parent : NULL, &tree);
LY_CHECK_GOTO(ret, cleanup);
}
/* read the last zero, parsing finished */
- ly_in_skip(lybctx.in, 1);
+ ly_in_skip(lybctx->lybctx->in, 1);
- /* TODO validation */
+ if (data_type == LYD_INTOPT_RPC) {
+ /* make sure we have parsed some operation */
+ if (!lybctx->op_node) {
+ LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_DATA, "Missing the \"rpc\"/\"action\" node.");
+ ret = LY_EVALID;
+ goto cleanup;
+ }
+
+ if (op_p) {
+ *op_p = lybctx->op_node;
+ }
+ assert(tree);
+ } else if (data_type == LYD_INTOPT_REPLY) {
+ struct lyd_node_inner *iter;
+
+ assert(parent);
+
+ if (op_p) {
+ *op_p = (struct lyd_node*)(*parent);
+ }
+ for (iter = *parent; iter->parent; iter = iter->parent);
+ tree = (struct lyd_node *)iter;
+ *parent = NULL;
+
+ } else if (data_type == LYD_INTOPT_NOTIF) {
+ /* make sure we have parsed some notification */
+ if (!lybctx->op_node) {
+ LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_DATA, "Missing the \"notification\" node.");
+ ret = LY_EVALID;
+ goto cleanup;
+ }
+
+ if (op_p) {
+ *op_p = lybctx->op_node;
+ }
+ assert(tree);
+ }
cleanup:
- LY_ARRAY_FREE(lybctx.subtrees);
- LY_ARRAY_FREE(lybctx.models);
- ly_set_erase(&lybctx.unres_node_type, NULL);
- ly_set_erase(&lybctx.unres_meta_type, NULL);
- ly_set_erase(&lybctx.when_check, NULL);
-
- if (ret) {
- lyd_free_all(*tree);
- *tree = NULL;
+ if (ret || !lydctx_p) {
+ lyd_lyb_ctx_free((struct lyd_ctx *)lybctx);
+ if (ret) {
+ lyd_free_all(tree);
+ }
+ } else {
+ *lydctx_p = (struct lyd_ctx *)lybctx;
+ if (tree_p) {
+ *tree_p = tree;
+ }
}
return ret;
}
LY_ERR
-lyd_parse_lyb_rpc(const struct ly_ctx *ctx, struct ly_in *in, struct lyd_node **tree, struct lyd_node **op)
+lyd_parse_lyb_data(const struct ly_ctx *ctx, struct ly_in *in, int parse_options, int validate_options,
+ struct lyd_node **tree_p, struct lyd_ctx **lydctx_p)
{
- LY_ERR ret = LY_SUCCESS;
- struct lyd_lyb_ctx lybctx = {0};
-
- lybctx.in = in;
- lybctx.ctx = ctx;
- lybctx.parse_options = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
- lybctx.int_opts = LYD_INTOPT_RPC;
-
- *tree = NULL;
- if (op) {
- *op = NULL;
- }
-
- /* read magic number */
- ret = lyb_parse_magic_number(&lybctx);
- LY_CHECK_GOTO(ret, cleanup);
-
- /* read header */
- ret = lyb_parse_header(&lybctx);
- LY_CHECK_GOTO(ret, cleanup);
-
- /* read used models */
- ret = lyb_parse_data_models(&lybctx);
- LY_CHECK_GOTO(ret, cleanup);
-
- /* read subtree(s) */
- while (lybctx.in->current[0]) {
- ret = lyb_parse_subtree_r(&lybctx, NULL, tree);
- LY_CHECK_GOTO(ret, cleanup);
- }
-
- /* read the last zero, parsing finished */
- ly_in_skip(lybctx.in, 1);
-
- /* make sure we have parsed some operation */
- if (!lybctx.op_ntf) {
- LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_DATA, "Missing the \"rpc\"/\"action\" node.");
- ret = LY_EVALID;
- goto cleanup;
- }
-
- if (op) {
- *op = lybctx.op_ntf;
- }
- assert(*tree);
-
-cleanup:
- LY_ARRAY_FREE(lybctx.subtrees);
- LY_ARRAY_FREE(lybctx.models);
- assert(!lybctx.unres_node_type.count && !lybctx.unres_meta_type.count && !lybctx.when_check.count);
-
- if (ret) {
- lyd_free_all(*tree);
- *tree = NULL;
- }
- return ret;
+ return lyd_parse_lyb_(ctx, NULL, in, parse_options, validate_options, 0, tree_p, NULL, lydctx_p);
}
LY_ERR
-lyd_parse_lyb_notif(const struct ly_ctx *ctx, struct ly_in *in, struct lyd_node **tree, struct lyd_node **ntf)
+lyd_parse_lyb_rpc(const struct ly_ctx *ctx, struct ly_in *in, struct lyd_node **tree_p, struct lyd_node **op_p)
{
- LY_ERR ret = LY_SUCCESS;
- struct lyd_lyb_ctx lybctx = {0};
-
- lybctx.in = in;
- lybctx.ctx = ctx;
- lybctx.parse_options = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
- lybctx.int_opts = LYD_INTOPT_NOTIF;
-
- *tree = NULL;
- if (ntf) {
- *ntf = NULL;
- }
-
- /* read magic number */
- ret = lyb_parse_magic_number(&lybctx);
- LY_CHECK_GOTO(ret, cleanup);
-
- /* read header */
- ret = lyb_parse_header(&lybctx);
- LY_CHECK_GOTO(ret, cleanup);
-
- /* read used models */
- ret = lyb_parse_data_models(&lybctx);
- LY_CHECK_GOTO(ret, cleanup);
-
- /* read subtree(s) */
- while (lybctx.in->current[0]) {
- ret = lyb_parse_subtree_r(&lybctx, NULL, tree);
- LY_CHECK_GOTO(ret, cleanup);
- }
-
- /* read the last zero, parsing finished */
- ly_in_skip(lybctx.in, 1);
-
- /* make sure we have parsed some notification */
- if (!lybctx.op_ntf) {
- LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_DATA, "Missing the \"notification\" node.");
- ret = LY_EVALID;
- goto cleanup;
- }
-
- if (ntf) {
- *ntf = lybctx.op_ntf;
- }
- assert(*tree);
-
-cleanup:
- LY_ARRAY_FREE(lybctx.subtrees);
- LY_ARRAY_FREE(lybctx.models);
- assert(!lybctx.unres_node_type.count && !lybctx.unres_meta_type.count && !lybctx.when_check.count);
-
- if (ret) {
- lyd_free_all(*tree);
- *tree = NULL;
- }
- return ret;
+ return lyd_parse_lyb_(ctx, NULL, in, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LYD_INTOPT_RPC, tree_p, op_p, NULL);
}
LY_ERR
-lyd_parse_lyb_reply(const struct lyd_node *request, struct ly_in *in, struct lyd_node **tree, struct lyd_node **op)
+lyd_parse_lyb_notif(const struct ly_ctx *ctx, struct ly_in *in, struct lyd_node **tree_p, struct lyd_node **ntf_p)
{
- LY_ERR ret = LY_SUCCESS;
- struct lyd_lyb_ctx lybctx = {0};
- struct lyd_node *iter, *req_op, *rep_op = NULL;
+ return lyd_parse_lyb_(ctx, NULL, in, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LYD_INTOPT_NOTIF, tree_p, ntf_p, NULL);
+}
- lybctx.in = in;
- lybctx.ctx = LYD_NODE_CTX(request);
- lybctx.parse_options = LYD_PARSE_ONLY | LYD_PARSE_STRICT;
- lybctx.int_opts = LYD_INTOPT_REPLY;
-
- *tree = NULL;
- if (op) {
- *op = NULL;
- }
+LY_ERR
+lyd_parse_lyb_reply(const struct lyd_node *request, struct ly_in *in, struct lyd_node **tree_p, struct lyd_node **op_p)
+{
+ LY_ERR ret;
+ struct lyd_node *req_op, *rep_op = NULL;
+ const struct ly_ctx *ctx = LYD_NODE_CTX(request);
/* find request OP */
LYD_TREE_DFS_BEGIN((struct lyd_node *)request, req_op) {
@@ -1207,52 +1117,16 @@
}
if (!(req_op->schema->nodetype & (LYS_RPC | LYS_ACTION))) {
LOGERR(LYD_NODE_CTX(request), LY_EINVAL, "No RPC/action in the request found.");
- ret = LY_EINVAL;
- goto cleanup;
+ return LY_EINVAL;
}
/* duplicate request OP with parents */
- ret = lyd_dup_single(req_op, NULL, LYD_DUP_WITH_PARENTS, &rep_op);
- LY_CHECK_GOTO(ret, cleanup);
+ LY_CHECK_RET(lyd_dup_single(req_op, NULL, LYD_DUP_WITH_PARENTS, &rep_op));
- /* read magic number */
- ret = lyb_parse_magic_number(&lybctx);
- LY_CHECK_GOTO(ret, cleanup);
+ ret = lyd_parse_lyb_(ctx, (struct lyd_node_inner **)&rep_op, in, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LYD_INTOPT_REPLY, tree_p, op_p, NULL);
- /* read header */
- ret = lyb_parse_header(&lybctx);
- LY_CHECK_GOTO(ret, cleanup);
-
- /* read used models */
- ret = lyb_parse_data_models(&lybctx);
- LY_CHECK_GOTO(ret, cleanup);
-
- /* read subtree(s) */
- while (lybctx.in->current[0]) {
- ret = lyb_parse_subtree_r(&lybctx, (struct lyd_node_inner *)rep_op, NULL);
- LY_CHECK_GOTO(ret, cleanup);
- }
-
- /* read the last zero, parsing finished */
- ly_in_skip(lybctx.in, 1);
-
- if (op) {
- *op = rep_op;
- }
- for (iter = rep_op; iter->parent; iter = (struct lyd_node *)iter->parent);
- *tree = iter;
- rep_op = NULL;
-
-cleanup:
lyd_free_all(rep_op);
- LY_ARRAY_FREE(lybctx.subtrees);
- LY_ARRAY_FREE(lybctx.models);
- assert(!lybctx.unres_node_type.count && !lybctx.unres_meta_type.count && !lybctx.when_check.count);
- if (ret) {
- lyd_free_all(*tree);
- *tree = NULL;
- }
return ret;
}
@@ -1260,7 +1134,7 @@
lyd_lyb_data_length(const char *data)
{
LY_ERR ret = LY_SUCCESS;
- struct lyd_lyb_ctx lybctx = {0};
+ struct lylyb_ctx *lybctx;
int count, i;
size_t len;
uint8_t buf[LYB_SIZE_MAX];
@@ -1269,53 +1143,56 @@
return -1;
}
- ret = ly_in_new_memory(data, &lybctx.in);
+ lybctx = calloc(1, sizeof *lybctx);
+ LY_CHECK_ERR_RET(!lybctx, LOGMEM(NULL), LY_EMEM);
+ ret = ly_in_new_memory(data, &lybctx->in);
LY_CHECK_GOTO(ret, cleanup);
/* read magic number */
- ret = lyb_parse_magic_number(&lybctx);
+ ret = lyb_parse_magic_number(lybctx);
LY_CHECK_GOTO(ret, cleanup);
/* read header */
- ret = lyb_parse_header(&lybctx);
+ ret = lyb_parse_header(lybctx);
LY_CHECK_GOTO(ret, cleanup);
/* read model count */
- lyb_read_number(&count, sizeof count, 2, &lybctx);
+ lyb_read_number(&count, sizeof count, 2, lybctx);
/* read all models */
for (i = 0; i < count; ++i) {
/* module name length */
len = 0;
- lyb_read_number(&len, sizeof len, 2, &lybctx);
+ lyb_read_number(&len, sizeof len, 2, lybctx);
/* model name */
- lyb_read(buf, len, &lybctx);
+ lyb_read(buf, len, lybctx);
/* revision */
- lyb_read(buf, 2, &lybctx);
+ lyb_read(buf, 2, lybctx);
}
- while (lybctx.in->current[0]) {
+ while (lybctx->in->current[0]) {
/* register a new subtree */
- ret = lyb_read_start_subtree(&lybctx);
+ ret = lyb_read_start_subtree(lybctx);
LY_CHECK_GOTO(ret, cleanup);
/* skip it */
- lyb_skip_subtree(&lybctx);
+ lyb_skip_subtree(lybctx);
/* subtree finished */
- ret = lyb_read_stop_subtree(&lybctx);
+ ret = lyb_read_stop_subtree(lybctx);
LY_CHECK_GOTO(ret, cleanup);
}
/* read the last zero, parsing finished */
- ly_in_skip(lybctx.in, 1);
+ ly_in_skip(lybctx->in, 1);
cleanup:
- count = lybctx.in->current - lybctx.in->start;
+ count = lybctx->in->current - lybctx->in->start;
- ly_in_free(lybctx.in, 0);
- LY_ARRAY_FREE(lybctx.subtrees);
+ ly_in_free(lybctx->in, 0);
+ lylyb_ctx_free(lybctx);
+
return ret ? -1 : count;
}