]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
rename functions and add a few more helper functions
authorAlan T. DeKok <aland@freeradius.org>
Thu, 25 Nov 2021 21:30:49 +0000 (16:30 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 26 Nov 2021 17:05:05 +0000 (12:05 -0500)
src/lib/util/edit.c
src/lib/util/edit.h
src/lib/util/edit_tests.c

index a29e3983b362f1e5d0160c9149847925dc15070d..c59c89092b434b8507ce52fe5a8a7ae7782e71c1 100644 (file)
@@ -28,6 +28,7 @@ RCSID("$Id$")
 #include <freeradius-devel/util/value.h>
 #include <freeradius-devel/util/talloc.h>
 #include "edit.h"
+#include "calc.h"
 
 typedef enum {
        FR_EDIT_INVALID = 0,
@@ -409,7 +410,7 @@ static int edit_record(fr_edit_list_t *el, fr_edit_op_t op, fr_pair_t *vp, fr_pa
  *  After this function returns, the new VP has been inserted into the
  *  list.
  */
-int fr_edit_list_insert_after(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *pos, fr_pair_t *vp)
+int fr_edit_list_insert_pair_after(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *pos, fr_pair_t *vp)
 {
        if (!el) return 0;
 
@@ -423,7 +424,7 @@ int fr_edit_list_insert_after(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_
  *
  *  After this function returns, the VP has been removed from the list.
  */
-int fr_edit_list_delete(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *vp)
+int fr_edit_list_pair_delete(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *vp)
 {
        return edit_record(el, FR_EDIT_DELETE, vp, list, NULL);
 }
@@ -432,7 +433,7 @@ int fr_edit_list_delete(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *vp)
  *
  *  After this function returns, it's safe to edit the pair.
  */
-int fr_edit_list_save_value(fr_edit_list_t *el, fr_pair_t *vp)
+int fr_edit_list_save_pair_value(fr_edit_list_t *el, fr_pair_t *vp)
 {
        if (!el) return 0;
 
@@ -445,7 +446,7 @@ int fr_edit_list_save_value(fr_edit_list_t *el, fr_pair_t *vp)
  *
  *  After this function returns, the value has been updated.
  */
-int fr_edit_list_replace_value(fr_edit_list_t *el, fr_pair_t *vp, fr_value_box_t *box)
+int fr_edit_list_replace_pair_value(fr_edit_list_t *el, fr_pair_t *vp, fr_value_box_t *box)
 {
        if (!el) return 0;
 
@@ -465,7 +466,7 @@ int fr_edit_list_replace_value(fr_edit_list_t *el, fr_pair_t *vp, fr_value_box_t
  *  After this function returns, the new VP has replaced the old one,
  *  and the new one can be edited.
  */
-int fr_edit_list_replace(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *to_replace, fr_pair_t *vp)
+int fr_edit_list_replace_pair(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *to_replace, fr_pair_t *vp)
 {
        if (!el) return 0;
 
@@ -507,7 +508,7 @@ int fr_edit_list_replace(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *to
  *  After this function returns, the new VP has replaced the old one,
  *  and the new one can be edited.
  */
-int fr_edit_list_free_children(fr_edit_list_t *el, fr_pair_t *vp)
+int fr_edit_list_free_pair_children(fr_edit_list_t *el, fr_pair_t *vp)
 {
        if (!el) return 0;
 
@@ -521,42 +522,6 @@ int fr_edit_list_free_children(fr_edit_list_t *el, fr_pair_t *vp)
        return edit_record(el, FR_EDIT_CLEAR, vp, NULL, NULL);
 }
 
-/** Insert a list after a particular point in another list.
- *
- *  This function mirrors fr_pair_list_append(), but with a bit more
- *  control over where the to_insert list ends up.
- *
- *  There's nothing magical about this function, it's just easier to
- *  have it here than in multiple places in the code.
- */
-int fr_edit_list_insert_list_after(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *pos, fr_pair_list_t *to_insert)
-{
-       fr_pair_t *prev, *vp;
-
-       if (!el) return 0;
-
-       prev = pos;
-
-       /*
-        *      We have to record each individual insert as a separate
-        *      item.  Some later edit may insert pairs in the middle
-        *      of the ones we've added.
-        */
-       while ((vp = fr_pair_list_head(to_insert)) != NULL) {
-               (void) fr_pair_remove(to_insert, vp);
-
-               if (edit_record(el, FR_EDIT_INSERT, vp, list, prev) < 0) {
-                       fr_pair_prepend(to_insert, vp); /* don't lose it! */
-                       return -1;
-               }
-
-               prev = vp;
-       }
-
-       return 0;
-}
-
-
 /** Finalize the edits when we destroy the edit list.
  *
  *  Which in large part means freeing the VPs which have been deleted,
@@ -642,3 +607,151 @@ fr_edit_list_t *fr_edit_list_alloc(TALLOC_CTX *ctx, int hint)
  *     free temporary map
  *     commit(edit list)
  */
+
+/**********************************************************************
+ *
+ *  Now we have helper functions which use the edit list to get things
+ *  done.
+ *
+ **********************************************************************/
+
+/** Insert a list after a particular point in another list.
+ *
+ *  This function mirrors fr_pair_list_append(), but with a bit more
+ *  control over where the to_insert list ends up.
+ *
+ *  There's nothing magical about this function, it's just easier to
+ *  have it here than in multiple places in the code.
+ */
+int fr_edit_list_insert_list_after(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *pos, fr_pair_list_t *to_insert)
+{
+       fr_pair_t *prev, *vp;
+
+       if (!el) return 0;
+
+       prev = pos;
+
+       /*
+        *      We have to record each individual insert as a separate
+        *      item.  Some later edit may insert pairs in the middle
+        *      of the ones we've added.
+        */
+       while ((vp = fr_pair_list_head(to_insert)) != NULL) {
+               (void) fr_pair_remove(to_insert, vp);
+
+               if (edit_record(el, FR_EDIT_INSERT, vp, list, prev) < 0) {
+                       fr_pair_prepend(to_insert, vp); /* don't lose it! */
+                       return -1;
+               }
+
+               prev = vp;
+       }
+
+       return 0;
+}
+
+/** Apply operators to pairs.
+ *
+ *  := is "if found vp, call fr_pair_replace().  Otherwise call fr_edit_list_insert_pair_tail()
+ *   = is "if found vp, do nothing.  Otherwise call fr_edit_list_insert_pair_tail()
+ *
+ */
+int fr_edit_list_apply_pair_assignment(fr_edit_list_t *el, fr_pair_t *vp, fr_token_t op, fr_value_box_t const *in)
+{
+       if (fr_edit_list_save_pair_value(el, vp) < 0) return -1;
+
+       if (fr_value_calc_assignment_op(vp, &vp->data, op, in) < 0) return -1;
+
+       return 0;
+}
+
+/** Apply operators to lists.
+ *
+ *   = is "if found vp, do nothing.  Otherwise call fr_edit_list_insert_pair_tail()
+ *
+ *  The src list MUST have been talloc'd from the right place already.
+ */
+int fr_edit_list_apply_list_assignment(fr_edit_list_t *el, fr_pair_t *dst, fr_token_t op, fr_pair_list_t *src)
+{
+       if (!fr_type_is_structural(dst->vp_type)) {
+               return -1;
+       }
+
+       switch (op) {
+               /*
+                *      Over-ride existing value (i.e. children) with
+                *      new list.
+                */
+       case T_OP_SET:
+               if (fr_edit_list_free_pair_children(el, dst) < 0) return -1;
+               FALL_THROUGH;
+
+       case T_OP_ADD_EQ:
+               return fr_edit_list_insert_list_tail(el, &dst->children, src);
+
+       case T_OP_PREPEND:
+               return fr_edit_list_insert_list_head(el, &dst->children, src);
+
+       default:
+               break;
+       }
+
+       fr_strerror_printf("Invalid assignment operator %s for destination type %s",
+                          fr_tokens[op],
+                          fr_table_str_by_value(fr_value_box_type_table, dst->type, "<INVALID>"));
+       return -1;
+}
+
+/** Apply operators to lists.
+ *
+ *   = is "if found vp, do nothing.  Otherwise call fr_edit_list_insert_pair_tail()
+ *
+ *  The src list here is "const".  This is a separate function, which
+ *  means that in many cases we can avoid copying the source list.
+ *
+ *  This isn't much use for simple operations, but it can have
+ *  significant benefits for union, merge, etc. where only some of the
+ *  source list is copied.
+ */
+int fr_edit_list_apply_list_assignment_const(fr_edit_list_t *el, fr_pair_t *dst, fr_token_t op, fr_pair_list_t const *src)
+{
+       fr_pair_list_t copy;
+
+       if (!fr_type_is_structural(dst->vp_type)) {
+               return -1;
+       }
+
+#define COPY do { \
+               fr_pair_list_init(&copy); \
+               if (fr_pair_list_copy(dst, &copy, src) < 0) return -1; \
+       } while (0)
+       
+
+       switch (op) {
+               /*
+                *      Over-ride existing value (i.e. children) with
+                *      new list.
+                */
+       case T_OP_SET:
+               if (fr_edit_list_free_pair_children(el, dst) < 0) return -1;
+               FALL_THROUGH;
+
+       case T_OP_ADD_EQ:
+               COPY;
+
+               return fr_edit_list_insert_list_tail(el, &dst->children, &copy);
+
+       case T_OP_PREPEND:
+               COPY;
+
+               return fr_edit_list_insert_list_head(el, &dst->children, &copy);
+
+       default:
+               break;
+       }
+
+       fr_strerror_printf("Invalid assignment operator %s for destination type %s",
+                          fr_tokens[op],
+                          fr_table_str_by_value(fr_value_box_type_table, dst->type, "<INVALID>"));
+       return -1;
+}
index e83872862c2ca7f83c1243d1796344950476522d..0d847ea6fcc3490cd31639ebf69f87de8da8ec09 100644 (file)
@@ -39,20 +39,39 @@ void fr_edit_list_abort(fr_edit_list_t *el);
 
 #define fr_edit_list_commit(_x) talloc_free(_x)
 
-int fr_edit_list_insert_after(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *pos, fr_pair_t *vp) CC_HINT(nonnull(2,4));
+/*
+ *     Functions to modify #fr_pair_t
+ */
+int fr_edit_list_insert_pair_after(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *pos, fr_pair_t *vp) CC_HINT(nonnull(2,4));
+
+#define fr_edit_list_insert_pair_head(_el, _list, _vp) fr_edit_list_insert_after(_el, _list, NULL, _vp)
+
+#define fr_edit_list_insert_pair_tail(_el, _list, _vp) fr_edit_list_insert_after(_el, _list, fr_pair_list_tail(_list), _vp)
+
+int fr_edit_list_pair_delete(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *vp) CC_HINT(nonnull(2,3));
 
-int fr_edit_list_delete(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *vp) CC_HINT(nonnull(2,3));
+int fr_edit_list_save_pair_value(fr_edit_list_t *el, fr_pair_t *vp) CC_HINT(nonnull(2));
 
-int fr_edit_list_save_value(fr_edit_list_t *el, fr_pair_t *vp) CC_HINT(nonnull(2));
+int fr_edit_list_replace_pair_value(fr_edit_list_t *el, fr_pair_t *vp, fr_value_box_t *box) CC_HINT(nonnull(2,3));
 
-int fr_edit_list_replace_value(fr_edit_list_t *el, fr_pair_t *vp, fr_value_box_t *box) CC_HINT(nonnull(2,3));
+int fr_edit_list_replace_pair(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *to_replace, fr_pair_t *vp) CC_HINT(nonnull(2,3,4));
 
-int fr_edit_list_replace(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *to_replace, fr_pair_t *vp) CC_HINT(nonnull(2,3,4));
+int fr_edit_list_free_pair_children(fr_edit_list_t *el, fr_pair_t *vp) CC_HINT(nonnull(2));
 
+int fr_edit_list_apply_pair_assignment(fr_edit_list_t *el, fr_pair_t *vp, fr_token_t op, fr_value_box_t const *in);
+
+/*
+ *     Functions to modify #fr_pair_list_t
+ */
 int fr_edit_list_insert_list_after(fr_edit_list_t *el, fr_pair_list_t *list, fr_pair_t *pos, fr_pair_list_t *to_insert) CC_HINT(nonnull(2,4));
 
+#define fr_edit_list_insert_list_head(_el, _list, _to_insert) fr_edit_list_insert_list_after(_el, _list, NULL, _to_insert)
+
+#define fr_edit_list_insert_list_tail(_el, _list, _to_insert) fr_edit_list_insert_list_after(_el, _list, fr_pair_list_tail(_list), _to_insert)
+
+int fr_edit_list_apply_list_assignment(fr_edit_list_t *el, fr_pair_t *dst, fr_token_t op, fr_pair_list_t *src) CC_HINT(nonnull(1,2,4));
 
-int fr_edit_list_free_children(fr_edit_list_t *el, fr_pair_t *vp) CC_HINT(nonnull(2));
+int fr_edit_list_apply_list_assignment_const(fr_edit_list_t *el, fr_pair_t *dst, fr_token_t op, fr_pair_list_t const *src)  CC_HINT(nonnull(1,2,4));
 
 #ifdef __cplusplus
 }
index bef97e4b26716ccb3d746c7d72e6e8d55435dc16..218910d1dc6e8c75ed280c10ee402c3e86267f4b 100644 (file)
@@ -132,7 +132,7 @@ static void test_pair_delete_head(void)
        el = fr_edit_list_alloc(NULL, 5);
        fr_assert(el != NULL);
 
-       rcode = fr_edit_list_delete(el, &local_pairs, vp);
+       rcode = fr_edit_list_pair_delete(el, &local_pairs, vp);
        TEST_CHECK(rcode == 0);
 
        fr_edit_list_commit(el);
@@ -165,7 +165,7 @@ static void test_pair_delete_head_abort(void)
        el = fr_edit_list_alloc(NULL, 5);
        fr_assert(el != NULL);
 
-       rcode = fr_edit_list_delete(el, &local_pairs, vp);
+       rcode = fr_edit_list_pair_delete(el, &local_pairs, vp);
        TEST_CHECK(rcode == 0);
 
        count = fr_pair_list_len(&local_pairs);
@@ -199,7 +199,7 @@ static void test_pair_delete_middle(void)
        el = fr_edit_list_alloc(NULL, 5);
        fr_assert(el != NULL);
 
-       rcode = fr_edit_list_delete(el, &local_pairs, vp);
+       rcode = fr_edit_list_pair_delete(el, &local_pairs, vp);
        TEST_CHECK(rcode == 0);
 
        fr_edit_list_commit(el);
@@ -238,7 +238,7 @@ static void test_pair_delete_middle_abort(void)
        el = fr_edit_list_alloc(NULL, 5);
        fr_assert(el != NULL);
 
-       rcode = fr_edit_list_delete(el, &local_pairs, middle);
+       rcode = fr_edit_list_pair_delete(el, &local_pairs, middle);
        TEST_CHECK(rcode == 0);
 
        count = fr_pair_list_len(&local_pairs);
@@ -278,13 +278,13 @@ static void test_pair_delete_multiple(void)
        el = fr_edit_list_alloc(NULL, 5);
        fr_assert(el != NULL);
 
-       rcode = fr_edit_list_delete(el, &local_pairs, vp); /* middle */
+       rcode = fr_edit_list_pair_delete(el, &local_pairs, vp); /* middle */
        TEST_CHECK(rcode == 0);
 
        vp = fr_pair_list_tail(&local_pairs);
        fr_assert(vp != NULL);
 
-       rcode = fr_edit_list_delete(el, &local_pairs, vp); /* tail */
+       rcode = fr_edit_list_pair_delete(el, &local_pairs, vp); /* tail */
        TEST_CHECK(rcode == 0);
 
        fr_edit_list_commit(el);
@@ -321,13 +321,13 @@ static void test_pair_delete_multiple_abort(void)
        el = fr_edit_list_alloc(NULL, 5);
        fr_assert(el != NULL);
 
-       rcode = fr_edit_list_delete(el, &local_pairs, vp); /* middle */
+       rcode = fr_edit_list_pair_delete(el, &local_pairs, vp); /* middle */
        TEST_CHECK(rcode == 0);
 
        vp = fr_pair_list_tail(&local_pairs);
        fr_assert(vp != NULL);
 
-       rcode = fr_edit_list_delete(el, &local_pairs, vp); /* tail */
+       rcode = fr_edit_list_pair_delete(el, &local_pairs, vp); /* tail */
        TEST_CHECK(rcode == 0);
 
        count = fr_pair_list_len(&local_pairs);
@@ -366,7 +366,7 @@ static void test_pair_edit_value(void)
        el = fr_edit_list_alloc(NULL, 5);
        fr_assert(el != NULL);
 
-       rcode = fr_edit_list_save_value(el, vp);
+       rcode = fr_edit_list_save_pair_value(el, vp);
        TEST_CHECK(rcode == 0);
 
        TEST_CHECK(vp->vp_uint32 == 0);
@@ -400,7 +400,7 @@ static void test_pair_edit_value_abort(void)
        el = fr_edit_list_alloc(NULL, 5);
        fr_assert(el != NULL);
 
-       rcode = fr_edit_list_save_value(el, vp);
+       rcode = fr_edit_list_save_pair_value(el, vp);
        TEST_CHECK(rcode == 0);
 
        TEST_CHECK(vp->vp_uint32 == 0);
@@ -437,7 +437,7 @@ static void test_pair_insert_after_head(void)
 
        TEST_CHECK((vp = fr_pair_afrom_da(autofree, fr_dict_attr_test_string)) != NULL);
 
-       rcode = fr_edit_list_insert_after(el, &local_pairs, NULL, vp);
+       rcode = fr_edit_list_insert_pair_after(el, &local_pairs, NULL, vp);
        TEST_CHECK(rcode == 0);
 
        fr_edit_list_commit(el);
@@ -470,7 +470,7 @@ static void test_pair_insert_after_head_abort(void)
 
        TEST_CHECK((vp = fr_pair_afrom_da(autofree, fr_dict_attr_test_string)) != NULL);
 
-       rcode = fr_edit_list_insert_after(el, &local_pairs, NULL, vp);
+       rcode = fr_edit_list_insert_pair_after(el, &local_pairs, NULL, vp);
        TEST_CHECK(rcode == 0);
 
        count = fr_pair_list_len(&local_pairs);
@@ -506,7 +506,7 @@ static void test_pair_insert_after_middle(void)
 
        TEST_CHECK((vp = fr_pair_afrom_da(autofree, fr_dict_attr_test_string)) != NULL);
 
-       rcode = fr_edit_list_insert_after(el, &local_pairs, middle, vp);
+       rcode = fr_edit_list_insert_pair_after(el, &local_pairs, middle, vp);
        TEST_CHECK(rcode == 0);
 
        fr_edit_list_commit(el);
@@ -539,7 +539,7 @@ static void test_pair_insert_after_middle_abort(void)
 
        TEST_CHECK((vp = fr_pair_afrom_da(autofree, fr_dict_attr_test_string)) != NULL);
 
-       rcode = fr_edit_list_insert_after(el, &local_pairs, middle, vp);
+       rcode = fr_edit_list_insert_pair_after(el, &local_pairs, middle, vp);
        TEST_CHECK(rcode == 0);
 
        count = fr_pair_list_len(&local_pairs);
@@ -571,7 +571,7 @@ static void test_pair_edit_value_delete(void)
        el = fr_edit_list_alloc(NULL, 5);
        fr_assert(el != NULL);
 
-       rcode = fr_edit_list_save_value(el, vp);
+       rcode = fr_edit_list_save_pair_value(el, vp);
        TEST_CHECK(rcode == 0);
 
        TEST_CHECK(vp->vp_uint32 == 0);
@@ -579,7 +579,7 @@ static void test_pair_edit_value_delete(void)
        vp->vp_uint32 = 1;
        TEST_CHECK(vp->vp_uint32 == 1);
 
-       rcode = fr_edit_list_delete(el, &local_pairs, vp);
+       rcode = fr_edit_list_pair_delete(el, &local_pairs, vp);
        TEST_CHECK(rcode == 0);
 
        fr_edit_list_commit(el);
@@ -609,7 +609,7 @@ static void test_pair_edit_value_delete_abort(void)
        el = fr_edit_list_alloc(NULL, 5);
        fr_assert(el != NULL);
 
-       rcode = fr_edit_list_save_value(el, vp);
+       rcode = fr_edit_list_save_pair_value(el, vp);
        TEST_CHECK(rcode == 0);
 
        TEST_CHECK(vp->vp_uint32 == 0);
@@ -617,7 +617,7 @@ static void test_pair_edit_value_delete_abort(void)
        vp->vp_uint32 = 1;
        TEST_CHECK(vp->vp_uint32 == 1);
 
-       rcode = fr_edit_list_delete(el, &local_pairs, vp);
+       rcode = fr_edit_list_pair_delete(el, &local_pairs, vp);
        TEST_CHECK(rcode == 0);
 
        /*
@@ -649,14 +649,14 @@ static void test_pair_insert_after_head_delete(void)
 
        TEST_CHECK((vp = fr_pair_afrom_da(autofree, fr_dict_attr_test_string)) != NULL);
 
-       rcode = fr_edit_list_insert_after(el, &local_pairs, NULL, vp);
+       rcode = fr_edit_list_insert_pair_after(el, &local_pairs, NULL, vp);
        TEST_CHECK(rcode == 0);
 
        count = fr_pair_list_len(&local_pairs);
        TEST_CASE("Expected (count == 4) after inserting a new one");
        TEST_CHECK(count == 4);
 
-       rcode = fr_edit_list_delete(el, &local_pairs, vp);
+       rcode = fr_edit_list_pair_delete(el, &local_pairs, vp);
        TEST_CHECK(rcode == 0);
 
        count = fr_pair_list_len(&local_pairs);
@@ -685,7 +685,7 @@ static void test_pair_insert_after_head_delete_abort(void)
 
        TEST_CHECK((vp = fr_pair_afrom_da(autofree, fr_dict_attr_test_string)) != NULL);
 
-       rcode = fr_edit_list_insert_after(el, &local_pairs, NULL, vp);
+       rcode = fr_edit_list_insert_pair_after(el, &local_pairs, NULL, vp);
        TEST_CHECK(rcode == 0);
 
        count = fr_pair_list_len(&local_pairs);