From: Alan T. DeKok Date: Wed, 17 Aug 2022 18:01:15 +0000 (-0400) Subject: add fr_pair_dcursor_value_init() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=22a01d9ecce57c096d3645c714df83bcc1016a71;p=thirdparty%2Ffreeradius-server.git add fr_pair_dcursor_value_init() which takes a pair_list_t, and then returns the relevant value-boxes This is so that we can return the value-boxes to functions which take a dcursor, and expect to see value-boxes out of it --- diff --git a/src/lib/util/pair.c b/src/lib/util/pair.c index 91c53d8b692..4125053c7e3 100644 --- a/src/lib/util/pair.c +++ b/src/lib/util/pair.c @@ -1053,7 +1053,6 @@ fr_pair_t *_fr_pair_dcursor_init(fr_dcursor_t *cursor, fr_pair_list_t const *lis _pair_list_dcursor_insert, _pair_list_dcursor_remove, list, is_const); } - /** Initialise a cursor that will return only attributes matching the specified #fr_dict_attr_t * * @param[in] cursor to initialise. @@ -1092,6 +1091,57 @@ fr_pair_t *_fr_pair_dcursor_by_ancestor_init(fr_dcursor_t *cursor, _pair_list_dcursor_insert, _pair_list_dcursor_remove, list, is_const); } +/** Iterate over pairs + * + * @param[in] list to iterate over. + * @param[in] current The fr_value_box_t cursor->current. Will be advanced and checked to + * see if it matches the specified fr_dict_attr_t. + * @param[in] uctx The fr_dict_attr_t to search for. + * @return + * - Next matching fr_pair_t. + * - NULL if not more matching fr_pair_ts could be found. + */ +static void *_fr_pair_iter_next_value(fr_dlist_head_t *list, void *current, UNUSED void *uctx) +{ + fr_pair_t *vp; + + if (!current) { + vp = NULL; + } else { + vp = (fr_pair_t *) ((uint8_t *) current - offsetof(fr_pair_t, data)); + PAIR_VERIFY(vp); + } + + while ((vp = fr_dlist_next(list, vp))) { + PAIR_VERIFY(vp); + if (!fr_type_is_leaf(vp->da->type)) break; + + continue; + } + + return vp; +} + +/** Initialises a special dcursor over a #fr_pair_list_t, but which returns #fr_value_box_t + * + * Filters can be applied later with fr_dcursor_filter_set. + * + * @note This is the only way to use a dcursor in non-const mode with fr_pair_list_t. + * + * @param[out] cursor to initialise. + * @param[in] list to iterate over. + * @param[in] is_const whether the fr_pair_list_t is const. + * @return + * - NULL if src does not point to any items. + * - The first pair in the list. + */ +fr_value_box_t *_fr_pair_dcursor_value_init(fr_dcursor_t *cursor, fr_pair_list_t const *list, + bool is_const) +{ + return _fr_dcursor_init(cursor, fr_pair_order_list_dlist_head(&list->order), + _fr_pair_iter_next_value, NULL, NULL, NULL, NULL, NULL, is_const); +} + /** Add a VP to the start of the list. * * Links an additional VP 'add' at the beginning a list. diff --git a/src/lib/util/pair.h b/src/lib/util/pair.h index 694d7ce3df6..aef5843b411 100644 --- a/src/lib/util/pair.h +++ b/src/lib/util/pair.h @@ -589,6 +589,24 @@ fr_pair_t *_fr_pair_dcursor_by_ancestor_init(fr_dcursor_t *cursor, fr_pair_list_t const *list, fr_dict_attr_t const *da, bool is_const) CC_HINT(nonnull); +/** Initialises a special dcursor which returns only the values of a pair. + * + * @note - the list cannot be modified, and structural attributes are not returned. + * + * @param[out] cursor to initialise. + * @param[in] list to iterate over. + * @return + * - NULL if src does not point to any items. + * - The first pair in the list. + */ +#define fr_pair_dcursor_value_init(_cursor, _list) \ + _fr_pair_dcursor_value_init(_cursor, \ + _list, \ + IS_CONST(fr_pair_list_t *, _list)) +fr_value_box_t *_fr_pair_dcursor_value_init(fr_dcursor_t *cursor, fr_pair_list_t const *list, + bool is_const) CC_HINT(nonnull); + + /** Compare two attributes using and operator. * * @return diff --git a/src/lib/util/pair_tests.c b/src/lib/util/pair_tests.c index 7ad0b03242c..7bb07f34e6e 100644 --- a/src/lib/util/pair_tests.c +++ b/src/lib/util/pair_tests.c @@ -230,6 +230,61 @@ static void test_fr_pair_dcursor_by_ancestor_init(void) TEST_CHECK(needle && needle->da == fr_dict_attr_test_tlv_string); } +static void test_fr_pair_dcursor_value_init(void) +{ + int i = 0; + fr_value_box_t *box; + fr_dcursor_t cursor; + fr_pair_t *vp; + fr_pair_list_t local_pairs; + + fr_pair_list_init(&local_pairs); + + MEM(vp = fr_pair_afrom_da(autofree, fr_dict_attr_test_string)); + fr_pair_value_strdup(vp, "hello", false); + fr_pair_append(&local_pairs, vp); + + MEM(vp = fr_pair_afrom_da(autofree, fr_dict_attr_test_uint32)); + vp->vp_uint32 = 6809; + fr_pair_append(&local_pairs, vp); + + MEM(vp = fr_pair_afrom_da(autofree, fr_dict_attr_test_uint8)); + vp->vp_uint8 = 12; + fr_pair_append(&local_pairs, vp); + + TEST_CASE("Searching for fr_dict_attr_test_tlv_string as ascend of fr_dict_attr_test_tlv using fr_pair_dcursor_by_ancestor_init()"); + for (box = fr_pair_dcursor_value_init(&cursor, &local_pairs); + box; + box = fr_dcursor_next(&cursor), i++) { + switch (i) { + case 0: + TEST_CASE("First box is a string with value 'hello'"); + TEST_CHECK(box->type == FR_TYPE_STRING); + TEST_CHECK(strcmp(box->vb_strvalue, "hello") == 0); + break; + + case 1: + TEST_CASE("First box is a uint32 with value 6809"); + TEST_CHECK(box->type == FR_TYPE_UINT32); + TEST_CHECK(box->vb_uint32 == 6809); + break; + + case 2: + TEST_CASE("First box is a uint8 r with value 12"); + TEST_CHECK(box->type == FR_TYPE_UINT8); + TEST_CHECK(box->vb_uint8 == 12); + break; + + default: + TEST_CASE("Too many pairs"); + TEST_CHECK(i < 3); + break; + } + } + + fr_pair_list_free(&local_pairs); +} + static void test_fr_pair_find_by_da_idx(void) { fr_pair_t *vp; @@ -1292,6 +1347,7 @@ TEST_LIST = { /* Searching and list modification */ { "fr_dcursor_iter_by_da_init", test_fr_pair_dcursor_by_da_init }, { "fr_pair_dcursor_by_ancestor_init", test_fr_pair_dcursor_by_ancestor_init }, + { "fr_pair_dcursor_value_init", test_fr_pair_dcursor_value_init }, { "fr_pair_to_unknown", test_fr_pair_to_unknown }, { "fr_pair_find_by_da_idx", test_fr_pair_find_by_da_idx }, { "fr_pair_find_by_child_num_idx", test_fr_pair_find_by_child_num_idx },