#ifndef __NICKEL_LINKEDLIST_H_ #define __NICKEL_LINKEDLIST_H_ #include #include #include #include #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_ */