Added support for the XPATH function bit-is-set()
This commit is contained in:
parent
ee5c0a08d5
commit
bc1f80b28e
5 changed files with 97 additions and 2 deletions
|
|
@ -1045,6 +1045,11 @@ xp_eval(xp_ctx *xc,
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
break;
|
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:
|
case XPATHFN_POSITION:
|
||||||
if (xp_function_position(xc, xs->xs_c0, nsc, localonly, xrp) < 0)
|
if (xp_function_position(xc, xs->xs_c0, nsc, localonly, xrp) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -379,6 +379,80 @@ xp_function_derived_from(xp_ctx *xc,
|
||||||
return retval;
|
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.
|
/*! Return a number equal to the context position from the expression evaluation context.
|
||||||
*
|
*
|
||||||
* Signature: number position(node-set)
|
* Signature: number position(node-set)
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ enum clixon_xpath_function{
|
||||||
XPATHFN_DERIVED_FROM, /* RFC 7950 10.4.1 */
|
XPATHFN_DERIVED_FROM, /* RFC 7950 10.4.1 */
|
||||||
XPATHFN_DERIVED_FROM_OR_SELF, /* RFC 7950 10.4.2 */
|
XPATHFN_DERIVED_FROM_OR_SELF, /* RFC 7950 10.4.2 */
|
||||||
XPATHFN_ENUM_VALUE, /* RFC 7950 10.5.1 NYI */
|
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_LAST, /* XPATH 1.0 4.1 NYI */
|
||||||
XPATHFN_POSITION, /* XPATH 1.0 4.1 */
|
XPATHFN_POSITION, /* XPATH 1.0 4.1 */
|
||||||
XPATHFN_COUNT, /* 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_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_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_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_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_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);
|
int xp_function_name(xp_ctx *xc, struct xpath_tree *xs, cvec *nsc, int localonly, xp_ctx **xrp);
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,6 @@ xp_primary_function(clixon_xpath_yacc *xpy,
|
||||||
switch (fn){
|
switch (fn){
|
||||||
case XPATHFN_RE_MATCH: /* Group of NOT IMPLEMENTED xpath functions */
|
case XPATHFN_RE_MATCH: /* Group of NOT IMPLEMENTED xpath functions */
|
||||||
case XPATHFN_ENUM_VALUE:
|
case XPATHFN_ENUM_VALUE:
|
||||||
case XPATHFN_BIT_IS_SET:
|
|
||||||
case XPATHFN_LAST:
|
case XPATHFN_LAST:
|
||||||
case XPATHFN_ID:
|
case XPATHFN_ID:
|
||||||
case XPATHFN_LOCAL_NAME:
|
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_CURRENT: /* Group of implemented xpath functions */
|
||||||
case XPATHFN_DEREF:
|
case XPATHFN_DEREF:
|
||||||
case XPATHFN_DERIVED_FROM:
|
case XPATHFN_DERIVED_FROM:
|
||||||
|
case XPATHFN_BIT_IS_SET:
|
||||||
case XPATHFN_DERIVED_FROM_OR_SELF:
|
case XPATHFN_DERIVED_FROM_OR_SELF:
|
||||||
case XPATHFN_POSITION:
|
case XPATHFN_POSITION:
|
||||||
case XPATHFN_COUNT:
|
case XPATHFN_COUNT:
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,14 @@ module $APPNAME{
|
||||||
base interface-type;
|
base interface-type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
leaf flags {
|
||||||
|
description "See RFC 7950 Sec 10.6.1";
|
||||||
|
type bits{
|
||||||
|
bit UP;
|
||||||
|
bit PROMISCUOUS;
|
||||||
|
bit DISABLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
augment "/ex:interface" {
|
augment "/ex:interface" {
|
||||||
when 'derived-from(type, "ex:ethernet")';
|
when 'derived-from(type, "ex:ethernet")';
|
||||||
|
|
@ -173,6 +181,13 @@ expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><validate><
|
||||||
new "netconf discard-changes"
|
new "netconf discard-changes"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "$DEFAULTHELLO<rpc $DEFAULTNS><discard-changes/></rpc>]]>]]>" "^<rpc-reply $DEFAULTNS><ok/></rpc-reply>]]>]]>$"
|
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
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if premature kill
|
# Check if premature kill
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue