Files
nickel/include/nickel/linkedlist.h

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_ */