From 6629f3d7802f4c70a373525a2304328cf1b45804 Mon Sep 17 00:00:00 2001 From: Olof hagsand Date: Wed, 20 May 2020 15:21:59 +0200 Subject: [PATCH] * Added new function `xml_child_index_each()` to iterate over the children of an XML node according to the order defined by an explicit index variable. --- CHANGELOG.md | 4 +++ lib/clixon/clixon_xml.h | 2 ++ lib/src/clixon_xml.c | 59 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c91d940..6cafe636 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,10 @@ ## 4.6.0 Expected: July 2020 +### Minor changes + +* Added new function `xml_child_index_each()` to iterate over the children of an XML node according to the order defined by an explicit index variable. This is a complement to `xml_child_each()` which iterates using the default order. + ## 4.5.0 12 May 2020 diff --git a/lib/clixon/clixon_xml.h b/lib/clixon/clixon_xml.h index 590da2e1..16e2fa95 100644 --- a/lib/clixon/clixon_xml.h +++ b/lib/clixon/clixon_xml.h @@ -249,6 +249,8 @@ int xml_search_index_p(cxobj *x); int xml_search_vector_get(cxobj *x, char *name, clixon_xvec **xvec); int xml_search_child_insert(cxobj *xp, cxobj *x); int xml_search_child_rm(cxobj *xp, cxobj *x); +cxobj *xml_child_index_each(cxobj *xparent, char *name, cxobj *xprev, enum cxobj_type type); + #endif diff --git a/lib/src/clixon_xml.c b/lib/src/clixon_xml.c index 02baef8c..d7915da0 100644 --- a/lib/src/clixon_xml.c +++ b/lib/src/clixon_xml.c @@ -877,8 +877,8 @@ xml_child_order(cxobj *xp, * ... * } * @endcode - * @note makes uses _x_vector_i:can be changed if list changed between calls - * @note Never manipulate the child-list during operation or using the + * @note uses _x_vector_i as a shared resource: you cannot mix loops over same parent + * Further, never manipulate the child-list during operation or using the * same object recursively, the function uses an internal field to remember the * index used. It works as long as the same object is not iterated concurrently. * If you need to delete a node you can do somethjing like: @@ -894,6 +894,9 @@ xml_child_order(cxobj *xp, * } * } * @endcode +#ifdef XML_EXPLICIT_INDEX + * @see xml_child_index_each +#endif XML_EXPLICIT_INDEX */ cxobj * xml_child_each(cxobj *xparent, @@ -922,6 +925,7 @@ xml_child_each(cxobj *xparent, return xn; } + /*! Extend child vector with one and insert xml node there * @note does not do anything with child, you may need to set its parent, etc * @see xml_child_insert_pos @@ -2581,4 +2585,55 @@ xml_search_child_rm(cxobj *xp, return retval; } +/*! Iterator over xml children objects using (explicit) index variable + * + * @param[in] xparent xml tree node whose children should be iterated + * @param[in] name Name of index variable + * @param[in] xprev previous child, or NULL on init + * @param[in] type matching type or -1 for any + * @code + * cxobj *x = NULL; + * while ((x = xml_child_index_each(x_top, "i", x, -1)) != NULL) { + * ... + * } + * @endcode + * @see xml_child_each for looping over structural children. + * @note uses _x_vector_i as a shared resource: you cannot mix loops over same parent + * Further, never manipulate the child-list during operation or using the + * same object recursively, the function uses an internal field to remember the + * index used. It works as long as the same object is not iterated concurrently. + * If you need to delete a node you can do somethjing like: + */ +cxobj * +xml_child_index_each(cxobj *xparent, + char *name, + cxobj *xprev, + enum cxobj_type type) +{ + cxobj *xn = NULL; + clixon_xvec *xv = NULL; + int i; + + if (xparent == NULL) + return NULL; + if (!is_element(xparent)) + return NULL; + if (xml_search_vector_get(xparent, name, &xv) < 0) + return NULL; + if (xv == NULL) + return NULL; + for (i=xprev?xprev->_x_vector_i+1:0; i_x_vector_i = i; + else + xn = NULL; + return xn; +} + #endif /* XML_EXPLICIT_INDEX */