path BUGFIX require first node prefix in JSON paths
diff --git a/src/path.c b/src/path.c
index 72e5fb5..e455b75 100644
--- a/src/path.c
+++ b/src/path.c
@@ -45,7 +45,7 @@
*/
static LY_ERR
ly_path_check_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_node, const struct lyxp_expr *exp,
- uint32_t *tok_idx, uint8_t prefix, uint8_t pred)
+ uint32_t *tok_idx, uint16_t prefix, uint16_t pred)
{
LY_ERR ret = LY_SUCCESS;
struct ly_set *set = NULL;
@@ -242,16 +242,17 @@
LY_ERR
ly_path_parse(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const char *str_path, size_t path_len,
- ly_bool lref, uint8_t begin, uint8_t prefix, uint8_t pred, struct lyxp_expr **expr)
+ ly_bool lref, uint16_t begin, uint16_t prefix, uint16_t pred, struct lyxp_expr **expr)
{
LY_ERR ret = LY_SUCCESS;
struct lyxp_expr *exp = NULL;
uint32_t tok_idx, cur_len;
const char *cur_node, *prev_prefix = NULL, *ptr;
+ ly_bool is_abs;
assert((begin == LY_PATH_BEGIN_ABSOLUTE) || (begin == LY_PATH_BEGIN_EITHER));
assert((prefix == LY_PATH_PREFIX_OPTIONAL) || (prefix == LY_PATH_PREFIX_MANDATORY) ||
- (prefix == LY_PATH_PREFIX_STRICT_INHERIT));
+ (prefix == LY_PATH_PREFIX_FIRST) || (prefix == LY_PATH_PREFIX_STRICT_INHERIT));
assert((pred == LY_PATH_PRED_KEYS) || (pred == LY_PATH_PRED_SIMPLE) || (pred == LY_PATH_PRED_LEAFREF));
LOG_LOCSET(ctx_node, NULL, NULL, NULL);
@@ -275,10 +276,16 @@
/* optional '..' */
} while (!lyxp_next_token(NULL, exp, &tok_idx, LYXP_TOKEN_DDOT));
}
+
+ is_abs = 0;
+ } else {
+ is_abs = 1;
}
} else {
/* '/' */
LY_CHECK_ERR_GOTO(lyxp_next_token(ctx, exp, &tok_idx, LYXP_TOKEN_OPER_PATH), ret = LY_EVALID, error);
+
+ is_abs = 1;
}
do {
@@ -294,8 +301,8 @@
ret = LY_EVALID;
goto error;
}
- } else if (prefix == LY_PATH_PREFIX_STRICT_INHERIT) {
- if (!prev_prefix) {
+ } else if ((prefix == LY_PATH_PREFIX_FIRST) || (prefix == LY_PATH_PREFIX_STRICT_INHERIT)) {
+ if (!prev_prefix && is_abs) {
/* the first node must have a prefix */
if (!strnstr(cur_node, ":", cur_len)) {
LOGVAL(ctx, LYVE_XPATH, "Prefix missing for \"%.*s\" in path.", cur_len, cur_node);
@@ -305,7 +312,7 @@
/* remember the first prefix */
prev_prefix = cur_node;
- } else {
+ } else if (prev_prefix && (prefix == LY_PATH_PREFIX_STRICT_INHERIT)) {
/* the prefix must be different, if any */
ptr = strnstr(cur_node, ":", cur_len);
if (ptr) {
@@ -349,7 +356,7 @@
LY_ERR
ly_path_parse_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_node, const char *str_path,
- size_t path_len, uint8_t prefix, uint8_t pred, struct lyxp_expr **expr)
+ size_t path_len, uint16_t prefix, uint16_t pred, struct lyxp_expr **expr)
{
LY_ERR ret = LY_SUCCESS;
struct lyxp_expr *exp = NULL;
@@ -843,7 +850,7 @@
*/
static LY_ERR
_ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, const struct lysc_node *ctx_node,
- const struct lysc_ext_instance *top_ext, const struct lyxp_expr *expr, ly_bool lref, uint8_t oper, uint8_t target,
+ const struct lysc_ext_instance *top_ext, const struct lyxp_expr *expr, ly_bool lref, uint16_t oper, uint16_t target,
ly_bool limit_access_tree, LY_VALUE_FORMAT format, void *prefix_data, struct ly_path **path)
{
LY_ERR ret = LY_SUCCESS;
@@ -971,7 +978,7 @@
LY_ERR
ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, const struct lysc_node *ctx_node,
- const struct lysc_ext_instance *top_ext, const struct lyxp_expr *expr, uint8_t oper, uint8_t target,
+ const struct lysc_ext_instance *top_ext, const struct lyxp_expr *expr, uint16_t oper, uint16_t target,
ly_bool limit_access_tree, LY_VALUE_FORMAT format, void *prefix_data, struct ly_path **path)
{
return _ly_path_compile(ctx, cur_mod, ctx_node, top_ext, expr, 0, oper, target, limit_access_tree, format,
@@ -980,7 +987,7 @@
LY_ERR
ly_path_compile_leafref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const struct lysc_ext_instance *top_ext,
- const struct lyxp_expr *expr, uint8_t oper, uint8_t target, LY_VALUE_FORMAT format, void *prefix_data,
+ const struct lyxp_expr *expr, uint16_t oper, uint16_t target, LY_VALUE_FORMAT format, void *prefix_data,
struct ly_path **path)
{
return _ly_path_compile(ctx, ctx_node->module, ctx_node, top_ext, expr, 1, oper, target, 1, format, prefix_data, path);
diff --git a/src/path.h b/src/path.h
index ca1c84a..674dd54 100644
--- a/src/path.h
+++ b/src/path.h
@@ -76,9 +76,10 @@
* @defgroup path_prefix_options Path prefix options.
* @{
*/
-#define LY_PATH_PREFIX_OPTIONAL 0x10 /**< prefixes in the path are optional */
+#define LY_PATH_PREFIX_OPTIONAL 0x10 /**< prefixes in the path are optional (XML path) */
#define LY_PATH_PREFIX_MANDATORY 0x20 /**< prefixes in the path are mandatory (XML instance-identifier) */
-#define LY_PATH_PREFIX_STRICT_INHERIT 0x30 /**< prefixes in the path are mandatory in case they differ from the
+#define LY_PATH_PREFIX_FIRST 0x40 /**< prefixes in the path are mandatory only in the first node of absolute path (JSON path) */
+#define LY_PATH_PREFIX_STRICT_INHERIT 0x80 /**< prefixes in the path are mandatory in case they differ from the
previous prefixes, otherwise they are prohibited (JSON instance-identifier) */
/** @} */
@@ -86,10 +87,10 @@
* @defgroup path_pred_options Path predicate options.
* @{
*/
-#define LY_PATH_PRED_KEYS 0x40 /* expected predicate only - [node='value']* */
-#define LY_PATH_PRED_SIMPLE 0x80 /* expected predicates - [node='value']*; [.='value']; [1] */
-#define LY_PATH_PRED_LEAFREF 0xC0 /* expected predicates only leafref - [node=current()/../../../node/node];
- at least 1 ".." and 1 "node" after */
+#define LY_PATH_PRED_KEYS 0x0100 /* expected predicate only - [node='value']* */
+#define LY_PATH_PRED_SIMPLE 0x0200 /* expected predicates - [node='value']*; [.='value']; [1] */
+#define LY_PATH_PRED_LEAFREF 0x0400 /* expected predicates only leafref - [node=current()/../../../node/node];
+ at least 1 ".." and 1 "node" after */
/** @} */
/**
@@ -107,7 +108,7 @@
* @return LY_ERR value.
*/
LY_ERR ly_path_parse(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const char *str_path, size_t path_len,
- ly_bool lref, uint8_t begin, uint8_t prefix, uint8_t pred, struct lyxp_expr **expr);
+ ly_bool lref, uint16_t begin, uint16_t prefix, uint16_t pred, struct lyxp_expr **expr);
/**
* @brief Parse predicate into XPath token structure and perform all additional checks.
@@ -122,7 +123,7 @@
* @return LY_ERR value.
*/
LY_ERR ly_path_parse_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_node, const char *str_path,
- size_t path_len, uint8_t prefix, uint8_t pred, struct lyxp_expr **expr);
+ size_t path_len, uint16_t prefix, uint16_t pred, struct lyxp_expr **expr);
/**
* @defgroup path_oper_options Path operation options.
@@ -162,7 +163,7 @@
* @return LY_ERR value.
*/
LY_ERR ly_path_compile(const struct ly_ctx *ctx, const struct lys_module *cur_mod, const struct lysc_node *ctx_node,
- const struct lysc_ext_instance *top_ext, const struct lyxp_expr *expr, uint8_t oper, uint8_t target,
+ const struct lysc_ext_instance *top_ext, const struct lyxp_expr *expr, uint16_t oper, uint16_t target,
ly_bool limit_access_tree, LY_VALUE_FORMAT format, void *prefix_data, struct ly_path **path);
/**
@@ -182,7 +183,7 @@
* @return LY_ERR value.
*/
LY_ERR ly_path_compile_leafref(const struct ly_ctx *ctx, const struct lysc_node *ctx_node,
- const struct lysc_ext_instance *top_ext, const struct lyxp_expr *expr, uint8_t oper, uint8_t target,
+ const struct lysc_ext_instance *top_ext, const struct lyxp_expr *expr, uint16_t oper, uint16_t target,
LY_VALUE_FORMAT format, void *prefix_data, struct ly_path **path);
/**
diff --git a/src/tree_data.c b/src/tree_data.c
index 50bfa58..69ce8e1 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -2899,7 +2899,7 @@
/* parse the path */
ret = ly_path_parse(LYD_CTX(ctx_node), ctx_node->schema, path, strlen(path), 0, LY_PATH_BEGIN_EITHER,
- LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_SIMPLE, &expr);
+ LY_PATH_PREFIX_FIRST, LY_PATH_PRED_SIMPLE, &expr);
LY_CHECK_GOTO(ret, cleanup);
/* compile the path */
diff --git a/tests/utests/data/test_tree_data.c b/tests/utests/data/test_tree_data.c
index 6b848bc..904c5d8 100644
--- a/tests/utests/data/test_tree_data.c
+++ b/tests/utests/data/test_tree_data.c
@@ -490,6 +490,11 @@
assert_int_equal(LY_SUCCESS, lyd_find_path(root, "/c:cont/nexthop[gateway='10.0.0.1']", 0, NULL));
assert_int_equal(LY_SUCCESS, lyd_find_path(root, "/c:cont/nexthop[gateway='2100::1']", 0, NULL));
assert_int_equal(LY_SUCCESS, lyd_find_path(root, "/c:cont/pref[.='fc00::/64']", 0, NULL));
+
+ assert_int_equal(LY_EVALID, lyd_find_path(root, "/cont", 0, NULL));
+ CHECK_LOG_CTX("Prefix missing for \"cont\" in path.", "Schema location \"/c:cont\".");
+ assert_int_equal(LY_SUCCESS, lyd_find_path(root, "nexthop[gateway='2100::1']", 0, NULL));
+
lyd_free_all(root);
}