76 lines
2.3 KiB
C
76 lines
2.3 KiB
C
#ifndef __NICKEL_LINKEDLIST_H_
|
|
#define __NICKEL_LINKEDLIST_H_
|
|
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
typedef struct ni_list_node {
|
|
struct ni_list_node* next;
|
|
struct ni_list_node* prev;
|
|
} ni_list_node;
|
|
|
|
// sentinel type structure for head + count
|
|
typedef struct ni_list {
|
|
ni_list_node head;
|
|
size_t count;
|
|
} ni_list;
|
|
|
|
// convenience ptr wrapper struct for a 'generic' list of pointers to things
|
|
typedef struct ni_list_ptr {
|
|
ni_list_node link;
|
|
void* ptr;
|
|
} ni_list_ptr;
|
|
|
|
// List functions
|
|
void ni_list__init(ni_list* l);
|
|
bool ni_list__is_empty(ni_list* l);
|
|
|
|
void ni_list__insert_after(ni_list* l, ni_list_node* entry, ni_list_node* n);
|
|
void ni_list__insert_before(ni_list* l, ni_list_node* entry, ni_list_node* n);
|
|
|
|
void ni_list__push_front(ni_list* l, ni_list_node* n);
|
|
void ni_list__push_back(ni_list* l, ni_list_node* n);
|
|
|
|
void ni_list__remove(ni_list* l, ni_list_node* n);
|
|
|
|
static inline ni_list_node* ni_list__get_front(ni_list* l) {
|
|
// if l is_empty() front == NULL else return the first actual data baring node
|
|
return ni_list__is_empty(l) ? NULL : l->head.next;
|
|
}
|
|
|
|
static inline ni_list_node* ni_list__get_back(ni_list* l) {
|
|
// if l is_empty() front == NULL else return the last node in the list
|
|
return ni_list__is_empty(l) ? NULL : l->head.prev;
|
|
}
|
|
|
|
/* Iter Helpers */
|
|
|
|
// helper macro for element traversal, ordering of operations may cause seg faults
|
|
// generally just don't remove 'it', this causes it->next on the next loop to segfault
|
|
#define NI_LIST__FOREACH(lptr) \
|
|
for (ni_list_node* it = (lptr)->head.next; it != &(lptr)->head; it = it->next)
|
|
|
|
// helper macro for element traversal, that also makes a copy of it in tmp
|
|
// useful for removing/moving the current node (it)
|
|
#define NI_LIST_FOREACH_SAFE(tmp, lptr) \
|
|
for (ni_list_node* it = (lptr)->head.next, *tmp = it->next; \
|
|
it != &(lptr)->head; \
|
|
it = tmp, tmp = it-> next)
|
|
|
|
// create a pointer to struct that contains a ni_list_node member
|
|
// since we know the structure size at compile time we can do some math
|
|
// to retreive the base address of the structure that contains our list node.
|
|
#define NI_LIST_CONTAINER_OF(ptr, type, member) \
|
|
((type*)((uint8_t*)(ptr) - offsetof(type, member)))
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* __NICKEL_LINKEDLIST_H_ */ |