Skip to content

Commit

Permalink
Added support for the XPATH function bit-is-set()
Browse files Browse the repository at this point in the history
  • Loading branch information
olofhagsand committed Nov 27, 2021
1 parent ee5c0a0 commit bc1f80b
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 2 deletions.
5 changes: 5 additions & 0 deletions lib/src/clixon_xpath_eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1045,6 +1045,11 @@ xp_eval(xp_ctx *xc,
goto done;
goto ok;
break;
case XPATHFN_BIT_IS_SET:
if (xp_function_bit_is_set(xc, xs->xs_c0, nsc, localonly, xrp) < 0)
goto done;
goto ok;
break;
case XPATHFN_POSITION:
if (xp_function_position(xc, xs->xs_c0, nsc, localonly, xrp) < 0)
goto done;
Expand Down
74 changes: 74 additions & 0 deletions lib/src/clixon_xpath_function.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,80 @@ xp_function_derived_from(xp_ctx *xc,
return retval;
}

/*! Returns true if the first node value has a bit set
*
* The bit-is-set() function returns "true" if the first node in
* document order in the argument "nodes" is a node of type "bits" and
* its value has the bit "bit-name" set; otherwise, it returns "false".
*
* Signature: boolean bit-is-set(node-set nodes, string bit-name)
* @param[in] xc Incoming context
* @param[in] xs XPATH node tree
* @param[in] nsc XML Namespace context
* @param[in] localonly Skip prefix and namespace tests (non-standard)
* @param[out] xrp Resulting context
* @retval 0 OK
* @retval -1 Error
* Example: interface[bit-is-set(flags, 'UP')
* @see RFC 7950 Sec 10.6
* typecheck is not made but assume this is done by validate
* XXX: lacks proper parsing of bits, just use strstr, see eg cv_validate1
*/
int
xp_function_bit_is_set(xp_ctx *xc,
struct xpath_tree *xs,
cvec *nsc,
int localonly,
xp_ctx **xrp)
{
int retval = -1;
xp_ctx *xr = NULL;
xp_ctx *xr0 = NULL;
xp_ctx *xr1 = NULL;
char *s1 = NULL;
cxobj *x;
char *body;

if (xs == NULL || xs->xs_c0 == NULL || xs->xs_c1 == NULL){
clicon_err(OE_XML, EINVAL, "contains expects but did not get two arguments");
goto done;
}
/* First node-set argument */
if (xp_eval(xc, xs->xs_c0, nsc, localonly, &xr0) < 0)
goto done;
/* Second string argument */
if (xp_eval(xc, xs->xs_c1, nsc, localonly, &xr1) < 0)
goto done;
if (ctx2string(xr1, &s1) < 0)
goto done;
if ((xr = malloc(sizeof(*xr))) == NULL){
clicon_err(OE_UNIX, errno, "malloc");
goto done;
}
memset(xr, 0, sizeof(*xr));
xr->xc_type = XT_BOOL;
/* The first node in document order in the argument "nodes"
* is a node of type "bits") and # NOT IMPLEMENTED
* its value has the bit "bit-name" set
*/
if (xr0->xc_size &&
(x = xr0->xc_nodeset[0]) != NULL &&
(body = xml_body(x)) != NULL){
xr->xc_bool = strstr(body, s1) != NULL;
}
*xrp = xr;
retval = 0;
done:
if (xr0)
ctx_free(xr0);
if (xr1)
ctx_free(xr1);
if (s1)
free(s1);
return retval;
}

/*! Return a number equal to the context position from the expression evaluation context.
*
* Signature: number position(node-set)
Expand Down
3 changes: 2 additions & 1 deletion lib/src/clixon_xpath_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ enum clixon_xpath_function{
XPATHFN_DERIVED_FROM, /* RFC 7950 10.4.1 */
XPATHFN_DERIVED_FROM_OR_SELF, /* RFC 7950 10.4.2 */
XPATHFN_ENUM_VALUE, /* RFC 7950 10.5.1 NYI */
XPATHFN_BIT_IS_SET, /* RFC 7950 10.6.1 NYI */
XPATHFN_BIT_IS_SET, /* RFC 7950 10.6.1 */
XPATHFN_LAST, /* XPATH 1.0 4.1 NYI */
XPATHFN_POSITION, /* XPATH 1.0 4.1 */
XPATHFN_COUNT, /* XPATH 1.0 4.1 */
Expand Down Expand Up @@ -96,6 +96,7 @@ const char *xp_fnname_int2str(enum clixon_xpath_function code);
int xp_function_current(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp);
int xp_function_deref(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp);
int xp_function_derived_from(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, int self, xp_ctx **xrp);
int xp_function_bit_is_set(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp);
int xp_function_position(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp);
int xp_function_count(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp);
int xp_function_name(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp);
Expand Down
2 changes: 1 addition & 1 deletion lib/src/clixon_xpath_parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,6 @@ xp_primary_function(clixon_xpath_yacc *xpy,
switch (fn){
case XPATHFN_RE_MATCH: /* Group of NOT IMPLEMENTED xpath functions */
case XPATHFN_ENUM_VALUE:
case XPATHFN_BIT_IS_SET:
case XPATHFN_LAST:
case XPATHFN_ID:
case XPATHFN_LOCAL_NAME:
Expand Down Expand Up @@ -279,6 +278,7 @@ xp_primary_function(clixon_xpath_yacc *xpy,
case XPATHFN_CURRENT: /* Group of implemented xpath functions */
case XPATHFN_DEREF:
case XPATHFN_DERIVED_FROM:
case XPATHFN_BIT_IS_SET:
case XPATHFN_DERIVED_FROM_OR_SELF:
case XPATHFN_POSITION:
case XPATHFN_COUNT:
Expand Down
15 changes: 15 additions & 0 deletions test/test_xpath_functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,14 @@ module $APPNAME{
base interface-type;
}
}
leaf flags {
description "See RFC 7950 Sec 10.6.1";
type bits{
bit UP;
bit PROMISCUOUS;
bit DISABLED;
}
}
}
augment "/ex:interface" {
when 'derived-from(type, "ex:ethernet")';
Expand Down Expand Up @@ -173,6 +181,13 @@ expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><
new "netconf discard-changes"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><discard-changes/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"

# bit-is-set
new "Add interfaces with different flags"
expecteof "$clixon_netconf -qf $cfg -D $DBG" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><edit-config><target><candidate/></target><config><interface xmlns=\"urn:example:clixon\"><name>e0</name><flags>UP</flags></interface><interface xmlns=\"urn:example:clixon\"><name>e1</name><flags>UP PROMISCUOUS</flags></interface><interface xmlns=\"urn:example:clixon\"><name>e2</name><flags>PROMISCUOUS</flags></interface></config></edit-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>"

new "netconf bit-is-set"
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/ex:interface[bit-is-set(ex:flags, 'PROMISCUOUS')]\" xmlns:ex=\"urn:example:clixon\" /></get-config></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><data><interface xmlns=\"urn:example:clixon\"><name>e1</name><flags>UP PROMISCUOUS</flags></interface><interface xmlns=\"urn:example:clixon\"><name>e2</name><flags>PROMISCUOUS</flags></interface></data></rpc-reply>]]>]]>$"

if [ $BE -ne 0 ]; then
new "Kill backend"
# Check if premature kill
Expand Down

0 comments on commit bc1f80b

Please sign in to comment.