This repository has been archived on 2022-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
Luma3DS-3GX/sysmodules/pm/source/intrusive_list.h
2019-03-29 00:32:45 +01:00

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));
}
}