]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add fr_pair_dcursor_value_init()
authorAlan T. DeKok <aland@freeradius.org>
Wed, 17 Aug 2022 18:01:15 +0000 (14:01 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Mon, 22 Aug 2022 00:34:06 +0000 (20:34 -0400)
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

src/lib/util/pair.c
src/lib/util/pair.h
src/lib/util/pair_tests.c

index 91c53d8b69284703074f27fb28aa3ebbc85591ff..4125053c7e3896cc3784b39cc1c0c3e7aed50d3b 100644 (file)
@@ -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.
index 694d7ce3df684cee9dce42f294220a525216ae5d..aef5843b4115cc8ffd1ee52d555ebffc454baa8a 100644 (file)
@@ -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
index 7ad0b03242ce55813410d20be4348084d9ba86c1..7bb07f34e6e0fbec8ea3e239bb396c2c9200f7e3 100644 (file)
@@ -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 },