]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Define fr_pair_append_by_parent_da() for automatic creation of nested pairs
authorNick Porter <nick@portercomputing.co.uk>
Thu, 4 Aug 2022 10:42:26 +0000 (11:42 +0100)
committerNick Porter <nick@portercomputing.co.uk>
Fri, 19 Aug 2022 08:10:12 +0000 (09:10 +0100)
plus macros for appending and populating pairs

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

index 51d69d764cadb1f3e1a8143792204495df85ab85..91c53d8b69284703074f27fb28aa3ebbc85591ff 100644 (file)
@@ -1268,6 +1268,75 @@ int fr_pair_prepend_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list
        return 0;
 }
 
+/** Alloc a new fr_pair_t, adding the parent attributes if required
+ *
+ * A child pair will be added to the first available matching parent
+ * found.
+ *
+ * @param[in] ctx      to allocate new #fr_pair_t in
+ * @param[out] out     Pair we allocated.  May be NULL if the caller doesn't
+ *                     care about manipulating the fr_pair_t.
+ * @param[in] list     in which to insert the pair.
+ * @param[in] da       of the attribute to create.
+ * @return
+ *     - 0 on success.
+ *     - -1 on failure.
+ */
+int fr_pair_append_by_da_parent(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
+{
+       fr_pair_t               *vp = NULL;
+       fr_da_stack_t           da_stack;
+       fr_dict_attr_t const    **find;
+       TALLOC_CTX              *pair_ctx = ctx;
+
+       /*
+        *      Fast path for non-nested attributes
+        */
+       if (da->depth <= 1) return fr_pair_append_by_da(ctx, out, list, da);
+
+       fr_proto_da_stack_build(&da_stack, da);
+       find = &da_stack.da[0];
+
+       /*
+        *      Walk down the da stack looking for candidate parent
+        *      attributes and then allocating the leaf.
+        */
+       while (true) {
+               fr_assert((*find)->depth <= da->depth);
+
+               /*
+                *      We're not at the leaf, look for a potential parent
+                */
+               if ((*find) != da) vp = fr_pair_find_by_da(list, NULL, *find);
+
+               /*
+                *      Nothing found, create the pair
+                */
+               if (!vp) {
+                       if (fr_pair_append_by_da(pair_ctx, &vp, list, *find) < 0) {
+                               *out = NULL;
+                               return -1;
+                       }
+               }
+
+               /*
+                *      We're at the leaf, return
+                */
+               if ((*find) == da) {
+                       *out = vp;
+                       return 0;
+               }
+
+               /*
+                *      Prepare for next level
+                */
+               list = &vp->vp_group;
+               pair_ctx = vp;
+               vp = NULL;
+               find++;
+       }
+}
+
 /** Return the first fr_pair_t matching the #fr_dict_attr_t or alloc a new fr_pair_t (and append)
  *
  * @param[in] ctx      to allocate any new #fr_pair_t in.
index 7078245ec3b467822925dde639bff03c13558841..694d7ce3df684cee9dce42f294220a525216ae5d 100644 (file)
@@ -291,6 +291,28 @@ do { \
        } \
 } while (0)
 
+#define fr_pair_list_append_by_da_parent(_ctx, _vp, _list, _attr, _val, _tainted) \
+do { \
+       _vp = NULL; \
+       if (fr_pair_append_by_da_parent(_ctx, &_vp, _list, _attr) < 0) break; \
+       fr_value_box(&_vp->data, _val, _tainted); \
+       if (!vp_da_data_type_check(_vp)) { \
+               fr_pair_delete(_list, _vp); \
+               _vp = NULL; \
+       } \
+} while (0)
+
+#define fr_pair_list_append_by_da_parent_len(_ctx, _vp, _list, _attr, _val, _len, _tainted) \
+do { \
+       _vp = NULL; \
+       if (fr_pair_append_by_da_parent(_ctx, &vp, _list, _attr) < 0) break; \
+       fr_value_box_len(_vp, &_vp->data, _val, _len, _tainted); \
+       if (!vp_da_data_type_check(_vp)) { \
+               fr_pair_delete(_list, _vp); \
+               _vp = NULL; \
+       } \
+} while (0)
+
 /** Prepend a pair to a list, assigning its value
  *
  * Version for simple C data types
@@ -465,6 +487,9 @@ int         fr_pair_append_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list
 int            fr_pair_prepend_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list,
                                      fr_dict_attr_t const *da) CC_HINT(nonnull(3,4));
 
+int            fr_pair_append_by_da_parent(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list,
+                                           fr_dict_attr_t const *da) CC_HINT(nonnull(3,4));
+
 int            fr_pair_update_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list,
                                     fr_dict_attr_t const *da, unsigned int n) CC_HINT(nonnull(3,4));