path FEATURE new path prefix format
Fixes #1163
diff --git a/src/path.c b/src/path.c
index 7558f95..3a299ae 100644
--- a/src/path.c
+++ b/src/path.c
@@ -70,6 +70,10 @@
LOGVAL_P(ctx, cur_node, LYVE_XPATH, "Prefix missing for \"%.*s\" in path.", exp->tok_len[*tok_idx],
exp->expr + exp->tok_pos[*tok_idx]);
goto error;
+ } else if ((prefix == LY_PATH_PREFIX_STRICT_INHERIT) && name) {
+ LOGVAL_P(ctx, cur_node, LYVE_XPATH, "Redundant prefix for \"%.*s\" in path.", exp->tok_len[*tok_idx],
+ exp->expr + exp->tok_pos[*tok_idx]);
+ goto error;
}
if (!name) {
name = exp->expr + exp->tok_pos[*tok_idx];
@@ -219,11 +223,13 @@
uint8_t begin, uint8_t lref, uint8_t prefix, uint8_t pred, struct lyxp_expr **expr)
{
struct lyxp_expr *exp;
- uint16_t tok_idx;
+ uint16_t tok_idx, cur_len;
+ const char *cur_node, *prev_prefix = NULL, *ptr;
assert((begin == LY_PATH_BEGIN_ABSOLUTE) || (begin == LY_PATH_BEGIN_EITHER));
assert((lref == LY_PATH_LREF_TRUE) || (lref == LY_PATH_LREF_FALSE));
- assert((prefix == LY_PATH_PREFIX_OPTIONAL) || (prefix == LY_PATH_PREFIX_MANDATORY));
+ assert((prefix == LY_PATH_PREFIX_OPTIONAL) || (prefix == LY_PATH_PREFIX_MANDATORY)
+ || (prefix == LY_PATH_PREFIX_STRICT_INHERIT));
assert((pred == LY_PATH_PRED_KEYS) || (pred == LY_PATH_PRED_SIMPLE) || (pred == LY_PATH_PRED_LEAFREF));
/* parse as a generic XPath expression */
@@ -250,10 +256,36 @@
LY_CHECK_GOTO(lyxp_check_token(ctx, exp, tok_idx, LYXP_TOKEN_NAMETEST), error);
/* check prefix based on the options */
- if ((prefix == LY_PATH_PREFIX_MANDATORY) && !strnstr(exp->expr + exp->tok_pos[tok_idx], ":", exp->tok_len[tok_idx])) {
- LOGVAL_P(ctx, ctx_node, LYVE_XPATH, "Prefix missing for \"%.*s\" in path.", exp->tok_len[tok_idx],
- exp->expr + exp->tok_pos[tok_idx]);
- goto error;
+ cur_node = exp->expr + exp->tok_pos[tok_idx];
+ cur_len = exp->tok_len[tok_idx];
+ if (prefix == LY_PATH_PREFIX_MANDATORY) {
+ if (!strnstr(cur_node, ":", cur_len)) {
+ LOGVAL_P(ctx, ctx_node, LYVE_XPATH, "Prefix missing for \"%.*s\" in path.", cur_len, cur_node);
+ goto error;
+ }
+ } else if (prefix == LY_PATH_PREFIX_STRICT_INHERIT) {
+ if (!prev_prefix) {
+ /* the first node must have a prefix */
+ if (!strnstr(cur_node, ":", cur_len)) {
+ LOGVAL_P(ctx, ctx_node, LYVE_XPATH, "Prefix missing for \"%.*s\" in path.", cur_len, cur_node);
+ goto error;
+ }
+
+ /* remember the first prefix */
+ prev_prefix = cur_node;
+ } else {
+ /* the prefix must be different, if any */
+ ptr = strnstr(cur_node, ":", cur_len);
+ if (ptr) {
+ if (!strncmp(prev_prefix, cur_node, ptr - cur_node) && (prev_prefix[ptr - cur_node] == ':')) {
+ LOGVAL_P(ctx, ctx_node, LYVE_XPATH, "Duplicate prefix for \"%.*s\" in path.", cur_len, cur_node);
+ goto error;
+ }
+
+ /* remember this next prefix */
+ prev_prefix = cur_node;
+ }
+ }
}
++tok_idx;
diff --git a/src/path.h b/src/path.h
index d57cd31..80085a6 100644
--- a/src/path.h
+++ b/src/path.h
@@ -77,7 +77,9 @@
* @{
*/
#define LY_PATH_PREFIX_OPTIONAL 0x10 /**< prefixes in the path are optional */
-#define LY_PATH_PREFIX_MANDATORY 0x20 /**< prefixes in the path are mandatory (XML insatnce-identifier) */
+#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
+ previous prefixes, otherwise they are prohibited (JSON instance-identifier) */
/** @} */
/**