Skip to content

Commit

Permalink
parser UPDATE guess opaque node schema nodes
Browse files Browse the repository at this point in the history
... for their descendant parsing purposes.

Refs #2086
  • Loading branch information
michalvasko committed Aug 18, 2023
1 parent 47da70b commit a878a89
Show file tree
Hide file tree
Showing 11 changed files with 226 additions and 72 deletions.
15 changes: 15 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,21 @@ void ly_log_location(const struct lysc_node *scnode, const struct lyd_node *dnod
*/
void ly_log_location_revert(uint32_t scnode_steps, uint32_t dnode_steps, uint32_t path_steps, uint32_t in_steps);

/**
* @brief Get the stored data node for logging at the index.
*
* @param[in] idx Index of the data node.
* @return Logged data node, NULL if out of range.
*/
const struct lyd_node *ly_log_location_dnode(uint32_t idx);

/**
* @brief Get the count of stored data nodes for logging.
*
* @return Count of the data nodes.
*/
uint32_t ly_log_location_dnode_count(void);

/**
* @brief Update location data for logger, not provided arguments (NULLs) are kept (does not override).
*
Expand Down
16 changes: 16 additions & 0 deletions src/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,22 @@ ly_log_location_revert(uint32_t scnode_steps, uint32_t dnode_steps, uint32_t pat
}
}

const struct lyd_node *
ly_log_location_dnode(uint32_t idx)
{
if (idx < log_location.dnodes.count) {
return log_location.dnodes.dnodes[idx];
}

return NULL;
}

uint32_t
ly_log_location_dnode_count(void)
{
return log_location.dnodes.count;
}

/**
* @brief Store generated error in a context.
*
Expand Down
57 changes: 57 additions & 0 deletions src/parser_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,63 @@ lyd_parser_find_operation(const struct lyd_node *parent, uint32_t int_opts, stru
return LY_SUCCESS;
}

const struct lysc_node *
lyd_parser_node_schema(const struct lyd_node *node)
{
uint32_t i;
const struct lyd_node *iter;
const struct lysc_node *schema = NULL;
const struct lys_module *mod;

if (!node) {
return NULL;
} else if (node->schema) {
/* simplest case */
return node->schema;
}

/* find the first schema node in the parsed nodes */
i = ly_log_location_dnode_count();
if (i) {
do {
--i;
if (ly_log_location_dnode(i)->schema) {
/* this node is processed */
schema = ly_log_location_dnode(i)->schema;
++i;
break;
}
} while (i);
}

/* get schema node of an opaque node */
do {
/* get next data node */
if (i == ly_log_location_dnode_count()) {
iter = node;
} else {
iter = ly_log_location_dnode(i);
}
assert(!iter->schema);

/* get module */
mod = lyd_owner_module(iter);
if (!mod) {
/* unknown module, no schema node */
schema = NULL;
break;
}

/* get schema node */
schema = lys_find_child(schema, mod, LYD_NAME(iter), 0, 0, 0);

/* move to the descendant */
++i;
} while (schema && (iter != node));

return schema;
}

LY_ERR
lyd_parser_check_schema(struct lyd_ctx *lydctx, const struct lysc_node *snode)
{
Expand Down
8 changes: 8 additions & 0 deletions src/parser_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,14 @@ LY_ERR lyd_parser_notif_eventtime_validate(const struct lyd_node *node);
*/
LY_ERR lyd_parser_find_operation(const struct lyd_node *parent, uint32_t int_opts, struct lyd_node **op);

/**
* @brief Get schema node of a node being parsed, use nodes stored for logging.
*
* @param[in] node Node whose schema node to get.
* @return Schema node even for an opaque node, NULL if none found.
*/
const struct lysc_node *lyd_parser_node_schema(const struct lyd_node *node);

/**
* @brief Check that a data node representing the @p snode is suitable based on options.
*
Expand Down
40 changes: 29 additions & 11 deletions src/parser_json.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ lydjson_get_snode(struct lyd_json_ctx *lydctx, ly_bool is_attr, const char *pref
if (!parent && lydctx->ext) {
*snode = lysc_ext_find_node(lydctx->ext, mod, name, name_len, 0, getnext_opts);
} else {
*snode = lys_find_child(parent ? parent->schema : NULL, mod, name, name_len, 0, getnext_opts);
*snode = lys_find_child(lyd_parser_node_schema(parent), mod, name, name_len, 0, getnext_opts);
}
if (!*snode) {
/* check for extension data */
Expand Down Expand Up @@ -1018,17 +1018,23 @@ lydjson_parse_opaq(struct lyd_json_ctx *lydctx, const char *name, size_t name_le
struct lyd_node *parent, enum LYJSON_PARSER_STATUS *status_p, enum LYJSON_PARSER_STATUS *status_inner_p,
struct lyd_node **first_p, struct lyd_node **node_p)
{
LY_CHECK_RET(lydjson_create_opaq(lydctx, name, name_len, prefix, prefix_len, parent, status_inner_p, node_p));
LY_ERR ret = LY_SUCCESS;

LY_CHECK_GOTO(ret = lydjson_create_opaq(lydctx, name, name_len, prefix, prefix_len, parent, status_inner_p, node_p), cleanup);

assert(*node_p);
LOG_LOCSET(NULL, *node_p, NULL, NULL);

if ((*status_p == LYJSON_ARRAY) && (*status_inner_p == LYJSON_NULL)) {
/* special array null value */
((struct lyd_node_opaq *)*node_p)->hints |= LYD_VALHINT_EMPTY;

/* must be the only item */
LY_CHECK_RET(lyjson_ctx_next(lydctx->jsonctx, status_inner_p));
LY_CHECK_GOTO(ret = lyjson_ctx_next(lydctx->jsonctx, status_inner_p), cleanup);
if (*status_inner_p != LYJSON_ARRAY_CLOSED) {
LOGVAL(lydctx->jsonctx->ctx, LYVE_SYNTAX, "Array \"null\" member with another member.");
return LY_EVALID;
ret = LY_EVALID;
goto cleanup;
}

goto finish;
Expand All @@ -1042,38 +1048,50 @@ lydjson_parse_opaq(struct lyd_json_ctx *lydctx, const char *name, size_t name_le

/* but first process children of the object in the array */
do {
LY_CHECK_RET(lydjson_subtree_r(lydctx, *node_p, lyd_node_child_p(*node_p), NULL));
LY_CHECK_GOTO(ret = lydjson_subtree_r(lydctx, *node_p, lyd_node_child_p(*node_p), NULL), cleanup);
*status_inner_p = lyjson_ctx_status(lydctx->jsonctx);
} while (*status_inner_p == LYJSON_OBJECT_NEXT);
} else {
/* array with values, leaf-list */
((struct lyd_node_opaq *)*node_p)->hints |= LYD_NODEHINT_LEAFLIST;
}

LY_CHECK_RET(lyjson_ctx_next(lydctx->jsonctx, status_inner_p));
LY_CHECK_GOTO(ret = lyjson_ctx_next(lydctx->jsonctx, status_inner_p), cleanup);
if (*status_inner_p == LYJSON_ARRAY_CLOSED) {
goto finish;
}
assert(*status_inner_p == LYJSON_ARRAY_NEXT);

/* continue with the next instance */
LY_CHECK_RET(lyjson_ctx_next(lydctx->jsonctx, status_inner_p));
assert(node_p);
LY_CHECK_GOTO(ret = lyjson_ctx_next(lydctx->jsonctx, status_inner_p), cleanup);
assert(*node_p);
lydjson_maintain_children(parent, first_p, node_p, lydctx->parse_opts & LYD_PARSE_ORDERED ? 1 : 0, NULL);
LY_CHECK_RET(lydjson_create_opaq(lydctx, name, name_len, prefix, prefix_len, parent, status_inner_p, node_p));

LOG_LOCBACK(0, 1, 0, 0);

LY_CHECK_GOTO(ret = lydjson_create_opaq(lydctx, name, name_len, prefix, prefix_len, parent, status_inner_p, node_p), cleanup);

assert(*node_p);
LOG_LOCSET(NULL, *node_p, NULL, NULL);
}

if (*status_p == LYJSON_OBJECT) {
/* process children */
do {
LY_CHECK_RET(lydjson_subtree_r(lydctx, *node_p, lyd_node_child_p(*node_p), NULL));
LY_CHECK_GOTO(ret = lydjson_subtree_r(lydctx, *node_p, lyd_node_child_p(*node_p), NULL), cleanup);
*status_p = lyjson_ctx_status(lydctx->jsonctx);
} while (*status_p == LYJSON_OBJECT_NEXT);
}

finish:
/* finish linking metadata */
return lydjson_metadata_finish(lydctx, lyd_node_child_p(*node_p));
ret = lydjson_metadata_finish(lydctx, lyd_node_child_p(*node_p));

cleanup:
if (*node_p) {
LOG_LOCBACK(0, 1, 0, 0);
}
return ret;
}

/**
Expand Down
35 changes: 34 additions & 1 deletion src/parser_lyb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1171,15 +1171,22 @@ lyb_parse_node_opaq(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct
value, strlen(value), &dynamic, format, val_prefix_data, LYD_HINT_DATA, &node);
LY_CHECK_GOTO(ret, cleanup);

assert(node);
LOG_LOCSET(NULL, node, NULL, NULL);

/* process children */
ret = lyb_parse_siblings(lybctx, node, NULL, NULL);
LY_CHECK_GOTO(ret, cleanup);

/* register parsed opaq node */
lyb_finish_opaq(lybctx, parent, flags, &attr, &node, first_p, parsed);
assert(!attr && !node);
LOG_LOCBACK(0, 1, 0, 0);

cleanup:
if (node) {
LOG_LOCBACK(0, 1, 0, 0);
}
free(prefix);
free(module_key);
free(name);
Expand Down Expand Up @@ -1265,9 +1272,13 @@ lyb_parse_node_any(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const st
goto error;
}

assert(node);
LOG_LOCSET(NULL, node, NULL, NULL);

/* register parsed anydata node */
lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);

LOG_LOCBACK(0, 1, 0, 0);
return LY_SUCCESS;

error:
Expand Down Expand Up @@ -1304,6 +1315,9 @@ lyb_parse_node_inner(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const
ret = lyd_create_inner(snode, &node);
LY_CHECK_GOTO(ret, error);

assert(node);
LOG_LOCSET(NULL, node, NULL, NULL);

/* process children */
ret = lyb_parse_siblings(lybctx, node, NULL, NULL);
LY_CHECK_GOTO(ret, error);
Expand All @@ -1320,9 +1334,13 @@ lyb_parse_node_inner(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const
/* register parsed node */
lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);

LOG_LOCBACK(0, 1, 0, 0);
return LY_SUCCESS;

error:
if (node) {
LOG_LOCBACK(0, 1, 0, 0);
}
lyd_free_meta_siblings(meta);
lyd_free_tree(node);
return ret;
Expand Down Expand Up @@ -1355,8 +1373,12 @@ lyb_parse_node_leaf(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const s
ret = lyb_create_term(lybctx, snode, &node);
LY_CHECK_GOTO(ret, error);

assert(node);
LOG_LOCSET(NULL, node, NULL, NULL);

lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);

LOG_LOCBACK(0, 1, 0, 0);
return LY_SUCCESS;

error:
Expand Down Expand Up @@ -1416,6 +1438,7 @@ lyb_parse_node_list(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const s
struct lyd_node *node = NULL;
struct lyd_meta *meta = NULL;
uint32_t flags;
ly_bool log_node = 0;

/* register a new sibling */
ret = lyb_read_start_siblings(lybctx->lybctx);
Expand All @@ -1430,6 +1453,10 @@ lyb_parse_node_list(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const s
ret = lyd_create_inner(snode, &node);
LY_CHECK_GOTO(ret, error);

assert(node);
LOG_LOCSET(NULL, node, NULL, NULL);
log_node = 1;

/* process children */
ret = lyb_parse_siblings(lybctx, node, NULL, NULL);
LY_CHECK_GOTO(ret, error);
Expand All @@ -1445,6 +1472,9 @@ lyb_parse_node_list(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const s

/* register parsed list node */
lyb_finish_node(lybctx, parent, flags, &meta, &node, first_p, parsed);

LOG_LOCBACK(0, 1, 0, 0);
log_node = 0;
}

/* end the sibling */
Expand All @@ -1454,6 +1484,9 @@ lyb_parse_node_list(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, const s
return LY_SUCCESS;

error:
if (log_node) {
LOG_LOCBACK(0, 1, 0, 0);
}
lyd_free_meta_siblings(meta);
lyd_free_tree(node);
return ret;
Expand Down Expand Up @@ -1492,7 +1525,7 @@ lyb_parse_node(struct lyd_lyb_ctx *lybctx, struct lyd_node *parent, struct lyd_n
case LYB_NODE_CHILD:
case LYB_NODE_OPAQ:
/* read hash, find the schema node starting from parent schema, if any */
LY_CHECK_GOTO(ret = lyb_parse_schema_hash(lybctx, parent ? parent->schema : NULL, NULL, &snode), cleanup);
LY_CHECK_GOTO(ret = lyb_parse_schema_hash(lybctx, lyd_parser_node_schema(parent), NULL, &snode), cleanup);
break;
case LYB_NODE_EXT:
/* ext, read module name */
Expand Down
Loading

0 comments on commit a878a89

Please sign in to comment.