Reverted some of the nsc xpath API changes. In the revert, xpath_first() and xpath_vec() retain their old syntax with nsc==NULL.

The reason is to be conservative with the API. However, less used functions, such as xpath_vec_bool(), xpath_vec_ctx() and xpath_vec_flag()  are changed with a new `nsc`parameter, which should be set to NULL in most cases.
This commit is contained in:
Olof hagsand 2019-07-09 12:19:03 +02:00
parent 89f751357d
commit 40d5b99d3b
32 changed files with 391 additions and 266 deletions

View file

@ -183,17 +183,17 @@ xpath_tree_free(xpath_tree *xs)
/*! Given XML tree and xpath, parse xpath, eval it and return xpath context,
* This is a raw form of xpath where you can do type conversion, etc,
* not just a nodeset.
* @param[in] nsc XML Namespace context
* @param[in] nsc External XML namespace context, or NULL
* @param[in] xpath String with XPATH 1.0 syntax
* @param[out] xptree Xpath-tree, parsed, structured XPATH, free:xpath_tree_free
* @retval 0 OK
* @retval -1 Error
* @code
* xp_ctx *xc = NULL;
* if (xpath_vec_ctx(x, NULL, xpath, &xc) < 0)
* xpath_tree *xpt = NULL;
* if (xpath_parse(NULL, xpath, &xpt) < 0)
* err;
* if (xc)
* ctx_free(xc);
* if (xpt)
* xptree_free(xpt);
* @endcode
* @see xpath_tree_free
*/
@ -238,7 +238,7 @@ xpath_parse(cvec *nsc,
* This is a raw form of xpath where you can do type conversion of the return
* value, etc, not just a nodeset.
* @param[in] xcur XML-tree where to search
* @param[in] nsc XML Namespace context
* @param[in] nsc External XML namespace context, or NULL
* @param[in] xpath String with XPATH 1.0 syntax
* @param[out] xrp Return XPATH context
* @retval 0 OK
@ -278,35 +278,33 @@ xpath_vec_ctx(cxobj *xcur,
done:
if (xptree)
xpath_tree_free(xptree);
return retval;
}
/*! Xpath nodeset function where only the first matching entry is returned
* args:
*
* @param[in] xcur XML tree where to search
* @param[in] nsc XML Namespace context
* @param[in] format string with XPATH syntax
* @param[in] nsc External XML namespace context, or NULL
* @param[in] xpformat Format string for XPATH syntax
* @retval xml-tree XML tree of first match
* @retval NULL Error or not found
*
* @code
* cxobj *x;
* cvec *nsc; // namespace context
* if ((x = xpath_first(xtop, nsc, "//symbol/foo")) != NULL) {
* if ((x = xpath_first_nsc(xtop, nsc, "//symbol/foo")) != NULL) {
* ...
* }
* @endcode
* @note the returned pointer points into the original tree so should not be freed fter use.
* @note the returned pointer points into the original tree so should not be freed after use.
* @note return value does not see difference between error and not found
* @see also xpath_vec.
* @experimental
*/
cxobj *
xpath_first(cxobj *xcur,
cvec *nsc,
char *format,
...)
xpath_first_nsc(cxobj *xcur,
cvec *nsc,
char *xpformat,
...)
{
cxobj *cx = NULL;
va_list ap;
@ -314,8 +312,8 @@ xpath_first(cxobj *xcur,
char *xpath = NULL;
xp_ctx *xr = NULL;
va_start(ap, format);
len = vsnprintf(NULL, 0, format, ap);
va_start(ap, xpformat);
len = vsnprintf(NULL, 0, xpformat, ap);
va_end(ap);
/* allocate a message string exactly fitting the message length */
if ((xpath = malloc(len+1)) == NULL){
@ -323,8 +321,8 @@ xpath_first(cxobj *xcur,
goto done;
}
/* second round: compute write message from reason and args */
va_start(ap, format);
if (vsnprintf(xpath, len+1, format, ap) < 0){
va_start(ap, xpformat);
if (vsnprintf(xpath, len+1, xpformat, ap) < 0){
clicon_err(OE_UNIX, errno, "vsnprintf");
va_end(ap);
goto done;
@ -342,20 +340,77 @@ xpath_first(cxobj *xcur,
return cx;
}
/*! Xpath nodeset function where only the first matching entry is returned
*
* @param[in] xcur XML tree where to search
* @param[in] xpformat Format string for XPATH syntax
* @retval xml-tree XML tree of first match
* @retval NULL Error or not found
*
* @code
* cxobj *x;
* if ((x = xpath_first(xtop, "//symbol/foo")) != NULL) {
* ...
* }
* @endcode
* @note the returned pointer points into the original tree so should not be freed after use.
* @note return value does not see difference between error and not found
* @see also xpath_vec.
* @see xpath_first_nsc which is more generic with namespace context
*/
cxobj *
xpath_first(cxobj *xcur,
char *xpformat,
...)
{
cxobj *cx = NULL;
va_list ap;
size_t len;
char *xpath = NULL;
xp_ctx *xr = NULL;
va_start(ap, xpformat);
len = vsnprintf(NULL, 0, xpformat, ap);
va_end(ap);
/* allocate a message string exactly fitting the message length */
if ((xpath = malloc(len+1)) == NULL){
clicon_err(OE_UNIX, errno, "malloc");
goto done;
}
/* second round: compute write message from reason and args */
va_start(ap, xpformat);
if (vsnprintf(xpath, len+1, xpformat, ap) < 0){
clicon_err(OE_UNIX, errno, "vsnprintf");
va_end(ap);
goto done;
}
va_end(ap);
if (xpath_vec_ctx(xcur, NULL, xpath, &xr) < 0)
goto done;
if (xr && xr->xc_type == XT_NODESET && xr->xc_size)
cx = xr->xc_nodeset[0];
done:
if (xr)
ctx_free(xr);
if (xpath)
free(xpath);
return cx;
}
/*! Given XML tree and xpath, returns nodeset as xml node vector
* If result is not nodeset, return empty nodeset
* @param[in] xcur xml-tree where to search
* @param[in] format stdarg string with XPATH 1.0 syntax
* @param[in] nsc XML Namespace context for XPATH
* @param[out] vec vector of xml-trees. Vector must be free():d after use
* @param[out] veclen returns length of vector in return value
* @retval 0 OK
* @retval -1 Error
* @param[in] xcur xml-tree where to search
* @param[in] nsc External XML namespace context, or NULL
* @param[in] xpformat Format string for XPATH syntax
* @param[out] vec vector of xml-trees. Vector must be free():d after use
* @param[out] veclen returns length of vector in return value
* @retval 0 OK
* @retval -1 Error
* @code
* cvec *nsc; // namespace context
* cxobj **vec;
* size_t veclen;
* if (xpath_vec(xcur, nsc, "//symbol/foo", &vec, &veclen) < 0)
* if (xpath_vec_nsc(xcur, nsc, "//symbol/foo", &vec, &veclen) < 0)
* goto err;
* for (i=0; i<veclen; i++){
* xn = vec[i];
@ -363,15 +418,14 @@ xpath_first(cxobj *xcur,
* }
* free(vec);
* @endcode
* @note Namespace prefix checking is not properly implemented
*/
int
xpath_vec(cxobj *xcur,
cvec *nsc,
char *format,
cxobj ***vec,
size_t *veclen,
...)
xpath_vec_nsc(cxobj *xcur,
cvec *nsc,
char *xpformat,
cxobj ***vec,
size_t *veclen,
...)
{
int retval = -1;
va_list ap;
@ -380,7 +434,7 @@ xpath_vec(cxobj *xcur,
xp_ctx *xr = NULL;
va_start(ap, veclen);
len = vsnprintf(NULL, 0, format, ap);
len = vsnprintf(NULL, 0, xpformat, ap);
va_end(ap);
/* allocate a message string exactly fitting the message length */
if ((xpath = malloc(len+1)) == NULL){
@ -389,7 +443,7 @@ xpath_vec(cxobj *xcur,
}
/* second round: compute write message from reason and args */
va_start(ap, veclen);
if (vsnprintf(xpath, len+1, format, ap) < 0){
if (vsnprintf(xpath, len+1, xpformat, ap) < 0){
clicon_err(OE_UNIX, errno, "vsnprintf");
va_end(ap);
goto done;
@ -413,15 +467,83 @@ xpath_vec(cxobj *xcur,
return retval;
}
/*! Given XML tree and xpath, returns nodeset as xml node vector
* If result is not nodeset, return empty nodeset
* @param[in] xcur xml-tree where to search
* @param[in] xpformat Format string for XPATH syntax
* @param[out] vec vector of xml-trees. Vector must be free():d after use
* @param[out] veclen returns length of vector in return value
* @retval 0 OK
* @retval -1 Error
* @code
* cxobj **vec;
* size_t veclen;
* if (xpath_vec(xcur, "//symbol/foo", &vec, &veclen) < 0)
* goto err;
* for (i=0; i<veclen; i++){
* xn = vec[i];
* ...
* }
* free(vec);
* @endcode
* @see xpath_vec_nsc which is more generic with namespace context
*/
int
xpath_vec(cxobj *xcur,
char *xpformat,
cxobj ***vec,
size_t *veclen,
...)
{
int retval = -1;
va_list ap;
size_t len;
char *xpath = NULL;
xp_ctx *xr = NULL;
va_start(ap, veclen);
len = vsnprintf(NULL, 0, xpformat, ap);
va_end(ap);
/* allocate a message string exactly fitting the message length */
if ((xpath = malloc(len+1)) == NULL){
clicon_err(OE_UNIX, errno, "malloc");
goto done;
}
/* second round: compute write message from reason and args */
va_start(ap, veclen);
if (vsnprintf(xpath, len+1, xpformat, ap) < 0){
clicon_err(OE_UNIX, errno, "vsnprintf");
va_end(ap);
goto done;
}
va_end(ap);
*vec=NULL;
*veclen = 0;
if (xpath_vec_ctx(xcur, NULL, xpath, &xr) < 0)
goto done;
if (xr && xr->xc_type == XT_NODESET){
*vec = xr->xc_nodeset;
xr->xc_nodeset = NULL;
*veclen = xr->xc_size;
}
retval = 0;
done:
if (xr)
ctx_free(xr);
if (xpath)
free(xpath);
return retval;
}
/* Xpath that returns a vector of matches (only nodes marked with flags)
* @param[in] xcur xml-tree where to search
* @param[in] xpath string with XPATH syntax
* @param[in] nsc External XML namespace context, or NULL
* @param[in] flags Set of flags that return nodes must match (0 if all)
* @param[out] vec vector of xml-trees. Vector must be free():d after use
* @param[out] veclen returns length of vector in return value
* @retval 0 OK
* @retval -1 error.
* @param[in] xcur xml-tree where to search
* @param[in] xpformat Format string for XPATH syntax
* @param[in] nsc External XML namespace context, or NULL
* @param[in] flags Set of flags that return nodes must match (0 if all)
* @param[out] vec vector of xml-trees. Vector must be free():d after use
* @param[out] veclen returns length of vector in return value
* @retval 0 OK
* @retval -1 error.
* @code
* cxobj **vec;
* size_t veclen;
@ -434,14 +556,13 @@ xpath_vec(cxobj *xcur,
* }
* free(vec);
* @endcode
* @Note that although the returned vector must be freed after use, the returned xml
* trees need not be.
* @see also xpath_vec This is a specialized version.
* @Note that although the returned vector must be freed after use, the returned xml trees need not be.
* @see also xpath_vec This is a specialized version.
*/
int
xpath_vec_flag(cxobj *xcur,
cvec *nsc,
char *format,
char *xpformat,
uint16_t flags,
cxobj ***vec,
size_t *veclen,
@ -456,7 +577,7 @@ xpath_vec_flag(cxobj *xcur,
cxobj *x;
va_start(ap, veclen);
len = vsnprintf(NULL, 0, format, ap);
len = vsnprintf(NULL, 0, xpformat, ap);
va_end(ap);
/* allocate a message string exactly fitting the message length */
if ((xpath = malloc(len+1)) == NULL){
@ -465,7 +586,7 @@ xpath_vec_flag(cxobj *xcur,
}
/* second round: compute write message from reason and args */
va_start(ap, veclen);
if (vsnprintf(xpath, len+1, format, ap) < 0){
if (vsnprintf(xpath, len+1, xpformat, ap) < 0){
clicon_err(OE_UNIX, errno, "vsnprintf");
va_end(ap);
goto done;
@ -494,17 +615,17 @@ xpath_vec_flag(cxobj *xcur,
/*! Given XML tree and xpath, returns boolean
* Returns true if the nodeset is non-empty
* @param[in] xcur xml-tree where to search
* @param[in] nsc External XML namespace context, or NULL
* @param[in] xpath stdarg string with XPATH 1.0 syntax
* @retval 1 True
* @retval 0 False
* @retval -1 Error
* @param[in] xcur xml-tree where to search
* @param[in] nsc External XML namespace context, or NULL
* @param[in] xpformat Format string for XPATH syntax
* @retval 1 True
* @retval 0 False
* @retval -1 Error
*/
int
xpath_vec_bool(cxobj *xcur,
cvec *nsc,
char *format,
char *xpformat,
...)
{
int retval = -1;
@ -513,8 +634,8 @@ xpath_vec_bool(cxobj *xcur,
char *xpath = NULL;
xp_ctx *xr = NULL;
va_start(ap, format);
len = vsnprintf(NULL, 0, format, ap);
va_start(ap, xpformat);
len = vsnprintf(NULL, 0, xpformat, ap);
va_end(ap);
/* allocate a message string exactly fitting the message length */
if ((xpath = malloc(len+1)) == NULL){
@ -522,8 +643,8 @@ xpath_vec_bool(cxobj *xcur,
goto done;
}
/* second round: compute write message from reason and args */
va_start(ap, format);
if (vsnprintf(xpath, len+1, format, ap) < 0){
va_start(ap, xpformat);
if (vsnprintf(xpath, len+1, xpformat, ap) < 0){
clicon_err(OE_UNIX, errno, "vsnprintf");
va_end(ap);
goto done;