Added support for the XPATH function bit-is-set()

This commit is contained in:
Olof hagsand 2021-11-27 15:38:13 +01:00
parent ee5c0a08d5
commit bc1f80b28e
5 changed files with 97 additions and 2 deletions

View file

@ -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;

View file

@ -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)

View file

@ -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 */
@ -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);

View file

@ -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:
@ -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:

View file

@ -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")';
@ -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