]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add API to iterate over children of an attribute
authorAlan T. DeKok <aland@freeradius.org>
Thu, 31 Oct 2019 19:59:41 +0000 (15:59 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 31 Oct 2019 19:59:41 +0000 (15:59 -0400)
src/lib/util/dict.h
src/lib/util/dict_util.c

index 0715e479e8283040916cb36c5be87708a5507b6b..c67884c0a72cda76ac46304aa4e4441e0893ce5f 100644 (file)
@@ -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
index ae08ef93e9c0b73b8b3ebc9e8cc7a55620f073b9..a10837b84ec3b10066210c5c1ef684551729f7d2 100644 (file)
@@ -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;
+}
+