From: Alan T. DeKok Date: Thu, 31 Oct 2019 19:59:41 +0000 (-0400) Subject: add API to iterate over children of an attribute X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b15613d00d08bc720aa471839095ec3c233e8756;p=thirdparty%2Ffreeradius-server.git add API to iterate over children of an attribute --- diff --git a/src/lib/util/dict.h b/src/lib/util/dict.h index 0715e479e82..c67884c0a72 100644 --- a/src/lib/util/dict.h +++ b/src/lib/util/dict.h @@ -426,6 +426,9 @@ ssize_t fr_dict_valid_name(char const *name, ssize_t len); ssize_t fr_dict_valid_oid_str(char const *name, ssize_t len); void fr_dict_verify(char const *file, int line, fr_dict_attr_t const *da); + +fr_dict_attr_t const *fr_dict_attr_iterate_children(fr_dict_attr_t const *parent, fr_dict_attr_t const **prev); + /** @} */ #ifdef __cplusplus diff --git a/src/lib/util/dict_util.c b/src/lib/util/dict_util.c index ae08ef93e9c..a10837b84ec 100644 --- a/src/lib/util/dict_util.c +++ b/src/lib/util/dict_util.c @@ -2566,3 +2566,57 @@ void fr_dict_verify(char const *file, int line, fr_dict_attr_t const *da) if (!fr_cond_assert(0)) fr_exit_now(1); } } + +/** Iterate over children of a DA. + * + * @param[in] parent the parent da to iterate over + * @param[in,out] prev pointer to NULL to start, otherwise pointer to the previously returned child + * @return + * - NULL for end of iteration + * - !NULL for a valid child. This child MUST be passed to the next loop. + */ +fr_dict_attr_t const *fr_dict_attr_iterate_children(fr_dict_attr_t const *parent, fr_dict_attr_t const **prev) +{ + fr_dict_attr_t const * const *bin; + fr_dict_attr_t const *child; + int i, start; + + if (!parent || !parent->children || !prev) return NULL; + + if (!*prev) { + start = 0; + + } else if ((*prev)->next) { + /* + * There are more children in this bin, return + * the next one. + */ + return (*prev)->next; + + } else { + /* + * Figure out which bin we were in. If it was + * the last one, we're done. + */ + start = (*prev)->attr & 0xff; + if (start == 255) return NULL; + + /* + * Start at the next bin. + */ + start++; + } + + /* + * Look for a non-empty bin, and return the first child + * from there. + */ + for (i = start; i < 256; i++) { + bin = &parent->children[i & 0xff]; + + if (*bin) return *bin; + } + + return NULL; +} +