87 lines
2.3 KiB
C
87 lines
2.3 KiB
C
#pragma once
|
|
|
|
#include <stddef.h>
|
|
#include <stdbool.h>
|
|
|
|
/// Intrusive node structure definition.
|
|
typedef struct IntrusiveNode {
|
|
struct IntrusiveNode *prev; ///< Pointer to the previous node.
|
|
struct IntrusiveNode *next; ///< Pointer to the next node.
|
|
} IntrusiveNode;
|
|
|
|
/// Intrusive list structure definition.
|
|
typedef union IntrusiveList {
|
|
IntrusiveNode node;
|
|
struct {
|
|
IntrusiveNode *last; ///< Pointer to the last element.
|
|
IntrusiveNode *first; ///< Pointer to the first element.
|
|
};
|
|
} IntrusiveList;
|
|
|
|
/**
|
|
* @brief Initializes the intrusive linked list.
|
|
*
|
|
* @param ll The intrusive list to initialize.
|
|
*/
|
|
static inline void IntrusiveList_Init(IntrusiveList *ll)
|
|
{
|
|
ll->node.prev = &ll->node;
|
|
ll->node.next = &ll->node;
|
|
}
|
|
|
|
/**
|
|
* @brief Tests if a node is past the end of the list containing it (if any).
|
|
*
|
|
* @param nd The node to test.
|
|
* @return bool true iff node is past the end of the list.
|
|
*/
|
|
static inline bool IntrusiveList_TestEnd(const IntrusiveList *ll, const IntrusiveNode *nd)
|
|
{
|
|
return nd == &ll->node;
|
|
}
|
|
|
|
/**
|
|
* @brief Inserts a node after another one list.
|
|
*
|
|
* @param pos The node to insert the new node after.
|
|
* @param nd The new node.
|
|
*/
|
|
static inline void IntrusiveList_InsertAfter(IntrusiveNode *pos, IntrusiveNode *nd)
|
|
{
|
|
// if pos is last & list is empty, ->next writes to first, etc.
|
|
pos->next->prev = nd;
|
|
nd->prev = pos;
|
|
nd->next = pos->next;
|
|
pos->next = nd;
|
|
}
|
|
|
|
/**
|
|
* @brief Erases a node.
|
|
*
|
|
* @param nd The node to erase.
|
|
*/
|
|
static inline void IntrusiveList_Erase(const IntrusiveNode *nd)
|
|
{
|
|
nd->prev->next = nd->next;
|
|
nd->next->prev = nd->prev;
|
|
}
|
|
|
|
/**
|
|
* @brief Makes a list storage from a buffer, using each element's intrusive node field at offset 0.
|
|
*
|
|
* @param ll The intrusive list to create.
|
|
* @param buf The buffer to use.
|
|
* @param elem_size The size of each element.
|
|
* @param total_size The total size of the buffer.
|
|
*
|
|
* @pre @ref ll has not been initialized yet.
|
|
* @pre Each element must contain a @ref IntrusiveNode instance at offset 0, which is then used.
|
|
*/
|
|
static inline void IntrusiveList_CreateFromBuffer(IntrusiveList *ll, void *buf, size_t elemSize, size_t totalSize)
|
|
{
|
|
IntrusiveList_Init(ll);
|
|
for (size_t pos = 0; pos < totalSize; pos += elemSize) {
|
|
IntrusiveList_InsertAfter(ll->last, (IntrusiveNode *)((char *)buf + pos));
|
|
}
|
|
}
|