tree FEATURE lys_parse_instance_predicate()
TODO: not yet tested!
diff --git a/src/tree_schema_helpers.c b/src/tree_schema_helpers.c
index f38aeec..297bf35 100644
--- a/src/tree_schema_helpers.c
+++ b/src/tree_schema_helpers.c
@@ -92,6 +92,102 @@
}
LY_ERR
+lys_parse_instance_predicate(const char **pred, size_t limit,
+ const char **prefix, size_t *prefix_len, const char **id, size_t *id_len, const char **value, size_t *value_len,
+ const char **errmsg)
+{
+ LY_ERR ret = LY_EVALID;
+ const char *in = *pred;
+ size_t offset = 1;
+ int expr = 0;
+ char quot;
+
+ assert(in[0] == '\[');
+
+ *prefix = *id = *value = NULL;
+ *prefix_len = *id_len = *value_len = 0;
+
+ /* leading *WSP */
+ for (; isspace(in[offset]); offset++);
+
+ if (isdigit(in[offset])) {
+ /* pos: "[" *WSP positive-integer-value *WSP "]" */
+ if (in[offset] == '0') {
+ /* zero */
+ *errmsg = "The position predicate cannot be zero.";
+ goto error;
+ }
+
+ /* positive-integer-value */
+ *id = &in[offset++];
+ for (; isdigit(in[offset]); offset++);
+ *id_len = &in[offset] - *id;
+
+ } else if (in[offset] == '.') {
+ /* leaf-list-predicate: "[" *WSP "." *WSP "=" *WSP quoted-string *WSP "]" */
+ *id = &in[offset];
+ *id_len = 1;
+ offset++;
+ expr = 1;
+
+ } else {
+ /* key-predicate: "[" *WSP node-identifier *WSP "=" *WSP quoted-string *WSP "]" */
+ in = &in[offset];
+ if (lys_parse_nodeid(&in, prefix, prefix_len, id, id_len)) {
+ *errmsg = "Invalid node-identifier.";
+ goto error;
+ }
+ offset = in - *pred;
+ in = *pred;
+ expr = 1;
+ }
+
+ if (expr) {
+ /* *WSP "=" *WSP quoted-string *WSP "]" */
+ for (; isspace(in[offset]); offset++);
+
+ if (in[offset] != '=') {
+ *errmsg = "Unexpected character instead of \'=\'.";
+ goto error;
+ }
+ offset++;
+ for (; isspace(in[offset]); offset++);
+
+ /* quoted-string */
+ quot = in[offset++];
+ if (quot != '\'' && quot != '\"') {
+ *errmsg = "String value is not quoted.";
+ goto error;
+ }
+ *value = &in[offset];
+ for (;offset < limit && in[offset] != quot; offset++);
+ *value_len = &in[offset] - *value;
+ }
+
+ /* *WSP "]" */
+ for(; isspace(in[offset]); offset++);
+ if (in[offset] != ']') {
+ *errmsg = "Predicate is not terminated by \']\' character.";
+ goto error;
+ }
+
+ if (offset < limit) {
+ return LY_SUCCESS;
+ }
+
+ /* we read after the limit */
+ *errmsg = "Predicate is incomplete.";
+ *prefix = *id = *value = NULL;
+ *prefix_len = *id_len = *value_len = 0;
+ offset = limit;
+ ret = LY_EINVAL;
+
+error:
+ *pred = &in[offset];
+ return ret;
+}
+
+LY_ERR
lys_resolve_schema_nodeid(struct lysc_ctx *ctx, const char *nodeid, size_t nodeid_len, const struct lysc_node *context_node,
const struct lys_module *context_module, int nodetype, int implement,
const struct lysc_node **target, uint16_t *result_flag)
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index 2ef0817..b01a496 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -339,6 +339,28 @@
const struct lysc_node **target, uint16_t *result_flag);
/**
+ * @brief parse instance-identifier's predicate, supports key-predicate, leaf-list-predicate and pos rules from YANG ABNF Grammar.
+ *
+ * @param[in, out] pred Predicate string (including the leading '[') to parse. The string is updated according to what was parsed
+ * (even for error case, so it can be used to determine which substring caused failure).
+ * @param[in] limit Limiting length of the @p pred. Function expects NULL terminated string which is not overread.
+ * The limit value is not checked with each character, so it can be overread and the failure is detected later.
+ * @param[out] prefix Start of the node-identifier's prefix if any, NULL in case of pos or leaf-list-predicate rules.
+ * @param[out] prefix_len Length of the parsed @p prefix.
+ * @param[out] id Start of the node-identifier's identifier string, NULL in case of pos rule, "." in case of leaf-list-predicate rule.
+ * @param[out] id_len Length of the parsed @p id.
+ * @param[out] value Start of the quoted-string (without quotation marks), NULL in case of pos rule.
+ * @param[out] value_len Length of the parsed @p value.
+ * @param[out] errmsg Error message string in case of error.
+ * @return LY_SUCCESS in case a complete predicate was parsed.
+ * @return LY_EVALID in case of invalid predicate form.
+ * @return LY_EINVAL in case of reaching @p limit when parsing @p pred.
+ */
+LY_ERR lys_parse_instance_predicate(const char **pred, size_t limit,
+ const char **prefix, size_t *prefix_len, const char **id, size_t *id_len,
+ const char **value, size_t *value_len, const char **errmsg);
+
+/**
* @brief Find the module referenced by prefix in the provided mod.
*
* Reverse function to lys_prefix_find_module().