/** Find the dlist pointers within a list item
*
*/
-#define fr_dlist_item_entry(_head, _item) (fr_dlist_t *) (((uint8_t *) _item) + _head->offset);
+#define fr_dlist_item_to_entry(_offset, _item) (fr_dlist_t *) (((uintptr_t) _item) + _offset);
+
+/** Get the item from a fr_dlist_t
+ *
+ */
+#define fr_dlist_entry_to_item(_offset, _entry) (void *) (((uintptr_t) _entry) - _offset);
/** Initialise a linked list without metadata
*
entry->prev = to_link;
}
+/** Replace one entry with another
+ *
+ * @param[in] entry to replace.
+ * @param[in] replacement to link in.
+ */
+static inline CC_HINT(nonnull) void fr_dlist_entry_replace(fr_dlist_t *entry, fr_dlist_t *replacement)
+{
+ /* Link replacement item into list */
+ entry->prev->next = replacement;
+ replacement->prev = entry->prev;
+ entry->next->prev = replacement;
+ replacement->next = entry->next;
+
+ /* Reset links on replaced item */
+ fr_dlist_entry_init(entry);
+}
+
/** Initialise the head structure of a doubly linked list
*
* @note This variant does not perform talloc validation.
if (list_head->type) ptr = _talloc_get_type_abort(ptr, list_head->type, __location__);
#endif
- entry = (fr_dlist_t *) (((uint8_t *) ptr) + list_head->offset);
+ entry = fr_dlist_item_to_entry(list_head->offset, ptr);
head = &(list_head->entry);
if (!fr_cond_assert(head->next != NULL)) return;
if (list_head->type) ptr = _talloc_get_type_abort(ptr, list_head->type, __location__);
#endif
- entry = (fr_dlist_t *) (((uint8_t *) ptr) + list_head->offset);
+ entry = fr_dlist_item_to_entry(list_head->offset, ptr);
head = &(list_head->entry);
if (!fr_cond_assert(head->next != NULL)) return;
if (list_head->type) ptr = _talloc_get_type_abort(ptr, list_head->type, __location__);
#endif
- entry = (fr_dlist_t *) (((uint8_t *) ptr) + list_head->offset);
+ entry = fr_dlist_item_to_entry(list_head->offset, ptr);
if (!pos) {
pos_entry = &(list_head->entry);
} else {
- pos_entry = (fr_dlist_t *) (((uint8_t *) pos) + list_head->offset);
+ pos_entry = fr_dlist_item_to_entry(list_head->offset, pos);
}
if (!fr_cond_assert(pos_entry->next != NULL)) return;
if (list_head->type) ptr = _talloc_get_type_abort(ptr, list_head->type, __location__);
#endif
- entry = (fr_dlist_t *) (((uint8_t *) ptr) + list_head->offset);
+ entry = fr_dlist_item_to_entry(list_head->offset, ptr);
if (!pos) {
pos_entry = &(list_head->entry);
} else {
- pos_entry = (fr_dlist_t *) (((uint8_t *) pos) + list_head->offset);
+ pos_entry = fr_dlist_item_to_entry(list_head->offset, pos);
}
if (!fr_cond_assert(pos_entry->next != NULL)) return;
if (head->next == head) return NULL;
- return (void *) (((uint8_t *) head->next) - list_head->offset);
+ return fr_dlist_entry_to_item(list_head->offset, head->next);
}
/** Check whether a list has any items.
if (head->prev == head) return NULL;
- return (void *) (((uint8_t *) head->prev) - list_head->offset);
+ return fr_dlist_entry_to_item(list_head->offset, head->prev);
}
{
fr_dlist_t const *entry;
fr_dlist_t const *head;
- fr_dlist_t *m_entry;
if (!ptr) return fr_dlist_head(list_head);
#ifndef TALLOC_GET_TYPE_ABORT_NOOP
if (list_head->type) ptr = _talloc_get_type_abort(ptr, list_head->type, __location__);
#endif
- entry = (fr_dlist_t const *)(((uint8_t const *) ptr) + list_head->offset);
+ entry = fr_dlist_item_to_entry(list_head->offset, ptr);
head = &(list_head->entry);
if (entry->next == head) return NULL;
if (!entry->next) return NULL;
entry = entry->next;
- memcpy(&m_entry, &entry, sizeof(m_entry));
-
- return (void *) (((uint8_t *) m_entry) - list_head->offset);
+ return fr_dlist_entry_to_item(list_head->offset, entry);
}
/** Get the previous item in a list
{
fr_dlist_t const *entry;
fr_dlist_t const *head;
- fr_dlist_t *m_entry;
if (!ptr) return fr_dlist_tail(list_head);
if (list_head->type) ptr = _talloc_get_type_abort(ptr, list_head->type, __location__);
#endif
- entry = (fr_dlist_t const *)(((uint8_t const *) ptr) + list_head->offset);
+ entry = fr_dlist_item_to_entry(list_head->offset, ptr);
head = &(list_head->entry);
if (entry->prev == head) return NULL;
entry = entry->prev;
- memcpy(&m_entry, &entry, sizeof(m_entry));
-
- return (void *) (((uint8_t *)m_entry) - list_head->offset);
+ return fr_dlist_entry_to_item(list_head->offset, entry);
}
/** Remove an item from the list
if (list_head->type) (void)_talloc_get_type_abort(ptr, list_head->type, __location__);
#endif
- entry = (fr_dlist_t *)(((uint8_t *)ptr) + list_head->offset);
+ entry = fr_dlist_item_to_entry(list_head->offset, ptr);
if (!fr_dlist_entry_in_list(entry)) return NULL;
head = &(list_head->entry);
if (prev == head) return NULL; /* Works with fr_dlist_next so that the next item is the list HEAD */
- return (void *) (((uint8_t *) prev) - list_head->offset);
+ return fr_dlist_entry_to_item(list_head->offset, entry);
}
/** Remove the head item in a list
if (list_head->type) (void)_talloc_get_type_abort(ptr, list_head->type, __location__);
#endif
- item_entry = (fr_dlist_t *)(((uint8_t *)item) + list_head->offset);
+ item_entry = fr_dlist_item_to_entry(list_head->offset, item);
if (!fr_dlist_entry_in_list(item_entry)) return NULL;
- ptr_entry = (fr_dlist_t *)(((uint8_t *)ptr) + list_head->offset);
+ ptr_entry = fr_dlist_item_to_entry(list_head->offset, ptr);
- /* Link replacement item into list */
- item_entry->prev->next = ptr_entry;
- ptr_entry->prev = item_entry->prev;
- item_entry->next->prev = ptr_entry;
- ptr_entry->next = item_entry->next;
+ fr_dlist_entry_replace(item_entry, ptr_entry);
- /* Reset links on replaced item */
- item_entry->prev = item_entry->next = item_entry;
return item;
}
*front = *source;
- if (*source) entry = fr_dlist_item_entry(head, *source);
+ if (*source) entry = fr_dlist_item_to_entry(head, *source);
/*
* Stopping condition - no more elements left to split
*/
*back = fr_dlist_next(head, slow);
if (slow) {
- entry = fr_dlist_item_entry(head, slow);
+ entry = fr_dlist_item_to_entry(head, slow);
entry->next = NULL;
}
}
next = fr_dlist_sort_merge(head, a, &next, cmp);
}
- result_entry = fr_dlist_item_entry(head, result);
- next_entry = fr_dlist_item_entry(head, next);
+ result_entry = fr_dlist_item_to_entry(head, result);
+ next_entry = fr_dlist_item_to_entry(head, next);
result_entry->next = next_entry;
return result;
void *b;
fr_dlist_t *entry = NULL;
- if (*ptr) entry = fr_dlist_item_entry(head, *ptr);
+ if (*ptr) entry = fr_dlist_item_to_entry(head, *ptr);
if (!*ptr || (!entry->next)) return;
fr_dlist_sort_split(head, ptr, &a, &b); /* Split into sublists */
/*
* Reset "prev" pointers broken during sort
*/
- entry = fr_dlist_item_entry(list, head);
+ entry = fr_dlist_item_to_entry(list, head);
list->entry.next = entry;
entry->prev = &list->entry;
while (head) {
- entry = fr_dlist_item_entry(list, head);
+ entry = fr_dlist_item_to_entry(list, head);
if (entry->next) {
/*
* There is a "next" entry, point it back to the current one