]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Implement dcursor insert and remove callbacks
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Mon, 11 Oct 2021 21:24:14 +0000 (16:24 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 12 Oct 2021 02:06:21 +0000 (21:06 -0500)
src/lib/util/dcursor.h
src/lib/util/dlist.h

index 3888a279219d77c6408363a78bd2650ce445c9ec..14a3a3d8814283b4d0c76d707dc51276de9e2d8b 100644 (file)
@@ -65,7 +65,7 @@ typedef int (*fr_dcursor_insert_t)(fr_dlist_head_t *list, void *to_insert, void
  *     - 0 on success.
  *     - -1 on failure.
  */
-typedef int (*fr_dcursor_delete_t)(fr_dlist_head_t *list, void *to_delete, void *uctx);
+typedef int (*fr_dcursor_remove_t)(fr_dlist_head_t *list, void *to_delete, void *uctx);
 /** Type of evaluation functions to pass to the fr_dcursor_filter_*() functions.
  *
  * @param[in] item     the item to be evaluated
@@ -81,7 +81,7 @@ typedef struct {
        void                    *prev;          //!< The previous item in the dlist.
        fr_dcursor_iter_t       iter;           //!< Iterator function.
        fr_dcursor_insert_t     insert;         //!< Callback function on insert.
-       fr_dcursor_delete_t     delete;         //!< Callback function on delete.
+       fr_dcursor_remove_t     remove;         //!< Callback function on delete.
        bool                    is_const;       //!< The list we're iterating over is immutable.
        void                    *uctx;          //!< to pass to iterator function.
 } fr_dcursor_t;
@@ -307,6 +307,11 @@ static inline void * fr_dcursor_set_current(fr_dcursor_t *cursor, void *item)
        if (fr_dlist_empty(cursor->dlist)) return NULL;
        if (!item) return NULL;
 
+       /*
+        *      Item must be in the dlist
+        */
+       if (!fr_dlist_in_list(cursor->dlist, item)) return NULL;
+
        cursor->current = item;
        cursor->prev = fr_dlist_prev(cursor->dlist, item);
 
@@ -325,14 +330,18 @@ static inline void * fr_dcursor_set_current(fr_dcursor_t *cursor, void *item)
  *
  * @hidecallergraph
  */
-static inline void fr_dcursor_prepend(fr_dcursor_t *cursor, void *v)
+static inline int fr_dcursor_prepend(fr_dcursor_t *cursor, void *v)
 {
-       if (!fr_cond_assert_msg(!cursor->is_const, "attempting to modify const list")) return;
+       int ret;
+
+       if (!fr_cond_assert_msg(!cursor->is_const, "attempting to modify const list")) return -1;
 
 #ifndef TALLOC_GET_TYPE_ABORT_NOOP
        if (cursor->dlist->type) _talloc_get_type_abort(v, cursor->dlist->type, __location__);
 #endif
 
+       if (cursor->insert) if ((ret = cursor->insert(cursor->dlist, v, cursor->uctx)) < 0) return ret;
+
        /*
         *      Insert at the head of the list
         */
@@ -346,6 +355,8 @@ static inline void fr_dcursor_prepend(fr_dcursor_t *cursor, void *v)
        if (cursor->current && !cursor->prev) {
                cursor->prev = v;
        }
+
+       return 0;
 }
 
 /** Insert a single item at the end of the list
@@ -354,18 +365,27 @@ static inline void fr_dcursor_prepend(fr_dcursor_t *cursor, void *v)
  *
  * @param[in] cursor to operate on.
  * @param[in] v to insert.
+ * @return
+ *     - 0 on success.
+ *     - -1 if the insert callback failed or a modification was attempted on a const'd list.
  *
  * @hidecallergraph
  */
-static inline void fr_dcursor_append(fr_dcursor_t *cursor, void *v)
+static inline int fr_dcursor_append(fr_dcursor_t *cursor, void *v)
 {
-       if (!fr_cond_assert_msg(!cursor->is_const, "attempting to modify const list")) return;
+       int ret;
+
+       if (!fr_cond_assert_msg(!cursor->is_const, "attempting to modify const list")) return -1;
 
 #ifndef TALLOC_GET_TYPE_ABORT_NOOP
        if (cursor->dlist->type) _talloc_get_type_abort(v, cursor->dlist->type, __location__);
 #endif
 
+       if (cursor->insert) if ((ret = cursor->insert(cursor->dlist, v, cursor->uctx)) < 0) return ret;
+
        fr_dlist_insert_tail(cursor->dlist, v);
+
+       return 0;
 }
 
 /** Insert directly after the current item
@@ -374,22 +394,32 @@ static inline void fr_dcursor_append(fr_dcursor_t *cursor, void *v)
  *
  * @param[in] cursor   to operate on.
  * @param[in] v                Item to insert.
+ * @return
+ *     - 0 on success.
+ *     - -1 if the insert callback failed or a modification was attempted on a const'd list.
  *
  * @hidecallergraph
  */
-static inline void fr_dcursor_insert(fr_dcursor_t *cursor, void *v)
+static inline int fr_dcursor_insert(fr_dcursor_t *cursor, void *v)
 {
-       if (!fr_cond_assert_msg(!cursor->is_const, "attempting to modify const list")) return;
+       int ret;
+
+       if (!fr_cond_assert_msg(!cursor->is_const, "attempting to modify const list")) return -1;
 
 #ifndef TALLOC_GET_TYPE_ABORT_NOOP
        if (cursor->dlist->type) _talloc_get_type_abort(v, cursor->dlist->type, __location__);
 #endif
 
        if (!cursor->current) {
-               fr_dcursor_append(cursor, v);
-               return;
+               if (fr_dcursor_append(cursor, v) < 0) return -1;
+               return 0;
        }
+
+       if (cursor->insert) if ((ret = cursor->insert(cursor->dlist, v, cursor->uctx)) < 0) return ret;
+
        fr_dlist_insert_after(cursor->dlist, cursor->current, v);
+
+       return 0;
 }
 
 /** Remove the current item
@@ -419,6 +449,7 @@ static inline void fr_dcursor_insert(fr_dcursor_t *cursor, void *v)
  */
 static inline void * fr_dcursor_remove(fr_dcursor_t *cursor)
 {
+       int ret;
        void *v, *p;
 
        if (!fr_cond_assert_msg(!cursor->is_const, "attempting to modify const list")) return NULL;
@@ -426,6 +457,9 @@ static inline void * fr_dcursor_remove(fr_dcursor_t *cursor)
        if (!cursor->current) return NULL;                      /* don't do anything fancy, it's just a noop */
 
        v = cursor->current;
+
+       if (cursor->remove) if ((ret = cursor->remove(cursor->dlist, v, cursor->uctx)) < 0) return ret;
+
        p = fr_dcursor_list_prev_peek(cursor);
        fr_dlist_remove(cursor->dlist, v);
 
@@ -553,6 +587,7 @@ void *fr_dcursor_intersect_next(fr_dcursor_t *a, fr_dcursor_t *b) CC_HINT(nonnul
  */
 static inline void * fr_dcursor_replace(fr_dcursor_t *cursor, void *r)
 {
+       int ret;
        void *v, *p;
 
        if (!fr_cond_assert_msg(!cursor->is_const, "attempting to modify const list")) return NULL;
@@ -577,6 +612,8 @@ static inline void * fr_dcursor_replace(fr_dcursor_t *cursor, void *r)
        }
        p = fr_dcursor_list_prev_peek(cursor);
 
+       if (cursor->remove) if ((ret = cursor->remove(cursor->dlist, v, cursor->uctx)) < 0) return ret;
+
        fr_dlist_replace(cursor->dlist, cursor->current, r);
 
        /*
@@ -711,7 +748,7 @@ static inline void fr_dcursor_free_list(fr_dcursor_t *cursor)
  * @param[in] head     of dlist.
  * @param[in] iter     Iterator callback.
  * @param[in] insert   Callback for inserts.
- * @param[in] delete   Callback for removals.
+ * @param[in] remove   Callback for removals.
  * @param[in] is_const Don't allow modification of the underlying list.
  * @param[in] uctx     to pass to iterator function.
  * @return the attribute pointed to by v.
@@ -721,13 +758,13 @@ static inline void fr_dcursor_free_list(fr_dcursor_t *cursor)
 static inline CC_HINT(nonnull(1,2))
 void *_fr_dcursor_init(fr_dcursor_t *cursor, fr_dlist_head_t const *head,
                       fr_dcursor_iter_t iter, fr_dcursor_insert_t insert,
-                      fr_dcursor_delete_t delete, bool is_const, void const *uctx)
+                      fr_dcursor_remove_t remove, bool is_const, void const *uctx)
 {
        *cursor = (fr_dcursor_t){
                .dlist = UNCONST(fr_dlist_head_t *, head),
                .iter = iter,
                .insert = insert,
-               .delete = delete,
+               .remove = remove,
                .uctx = UNCONST(void *, uctx),
                .is_const = is_const
        };
index 2d47885ce6c7f6b8baa735c0cb34d644282784e1..7e9e4d5a72c25bcce06cc9dee62a03721a261295 100644 (file)
@@ -279,6 +279,23 @@ static inline void fr_dlist_clear(fr_dlist_head_t *list_head)
                return -1; \
        }
 
+/** Check if a list entry is part of a list
+ *
+ * This works because the fr_dlist_head_t has an entry in the list.
+ * So if next and prev both point to the entry for the object being
+ * passed in, then it can't be part of a list with a fr_dlist_head_t.
+ *
+ * @return
+ *     - True if in a list.
+ *     - False otherwise.
+ */
+static inline CC_HINT(nonnull) bool fr_dlist_in_list(fr_dlist_head_t *list_head, void *ptr)
+{
+       fr_dlist_t *entry = fr_dlist_item_to_entry(list_head->offset, ptr);
+
+       return fr_dlist_entry_in_list(entry);
+}
+
 /** Insert an item into the head of a list
  *
  * @note If #fr_dlist_talloc_init was used to initialise #fr_dlist_head_t