diff --git a/lladd/doubleLinkedList.h b/lladd/doubleLinkedList.h new file mode 100644 index 0000000..24e7f1d --- /dev/null +++ b/lladd/doubleLinkedList.h @@ -0,0 +1,58 @@ +#ifndef DOUBLE_LINKED_LIST_H +#define DOUBLE_LINKED_LIST_H +#define LL_ENTRY(foo) ll##foo + +typedef void LL_ENTRY(value_t); + +struct LL_ENTRY(node_t) { + LL_ENTRY(value_t) * v; + struct LL_ENTRY(node_t) * prev; + struct LL_ENTRY(node_t) * next; +}; + +struct LL_ENTRY(list) { + struct LL_ENTRY(node_t)* const head; + struct LL_ENTRY(node_t)* const tail; +}; + +struct LL_ENTRY(list)* LL_ENTRY(create)(); +void LL_ENTRY(destroy)(struct LL_ENTRY(list) * l); + +struct LL_ENTRY(node_t)* LL_ENTRY(push) (struct LL_ENTRY(list)* l, + LL_ENTRY(value_t) * v); +LL_ENTRY(value_t)* LL_ENTRY(pop) (struct LL_ENTRY(list)* l); + +struct LL_ENTRY(node_t)* LL_ENTRY(unshift)(struct LL_ENTRY(list)* l, + LL_ENTRY(value_t) * v); +LL_ENTRY(value_t)* LL_ENTRY(shift) (struct LL_ENTRY(list)* l); + +void LL_ENTRY(remove)(struct LL_ENTRY(list)* l, + struct LL_ENTRY(node_t)* n); + +void LL_ENTRY(pushNode) (struct LL_ENTRY(list)* l, + struct LL_ENTRY(node_t) * v); +struct LL_ENTRY(node_t)* LL_ENTRY(popNode) (struct LL_ENTRY(list)* l); + +void LL_ENTRY(unshiftNode)(struct LL_ENTRY(list)* l, + struct LL_ENTRY(node_t) * v); +struct LL_ENTRY(node_t)* LL_ENTRY(shiftNode) (struct LL_ENTRY(list)* l); +void LL_ENTRY(removeNoFree)(struct LL_ENTRY(list)* l, + struct LL_ENTRY(node_t)* n); + +static inline LL_ENTRY(value_t*)LL_ENTRY(head) + (struct LL_ENTRY(list)* l) { + if(l->head->next != l->tail) { + return l->head->next->v; + } else { + return 0; + } +} +static inline LL_ENTRY(value_t*) LL_ENTRY(tail) + (struct LL_ENTRY(list)* l) { + if(l->tail->prev != l->head) { + return l->tail->prev->v; + } else { + return 0; + } +} +#endif diff --git a/src/lladd/doubleLinkedList.c b/src/lladd/doubleLinkedList.c new file mode 100644 index 0000000..893a025 --- /dev/null +++ b/src/lladd/doubleLinkedList.c @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include + +typedef LL_ENTRY(value_t) value_t; +typedef struct LL_ENTRY(node_t) node_t; +typedef struct LL_ENTRY(list) list; + +list * LL_ENTRY(create)() { + list* ret = malloc(sizeof(list)); + + // bypass const annotation on head, tail... + list tmp = { + malloc(sizeof(node_t)), + malloc(sizeof(node_t)) + }; + memcpy(ret, &tmp, sizeof(list)); + + ret->head->prev = 0; + ret->head->next = ret->tail; + ret->tail->prev = ret->head; + ret->tail->next = 0; + return ret; +} + +void LL_ENTRY(destroy)(list* l) { + value_t * n; + while((n = LL_ENTRY(pop)(l))) { + // nop + } + free(l->head); + free(l->tail); + free(l); +} +node_t * LL_ENTRY(push)(list* l, value_t * v) { + node_t * n = malloc(sizeof(node_t)); + n->v = v; + LL_ENTRY(pushNode)(l, n); + return n; +} +value_t* LL_ENTRY(pop) (list* l) { + node_t * n = LL_ENTRY(popNode)(l); + if(n) { + value_t * v = n->v; + free(n); + return v; + } else { + return 0; + } +} +node_t * LL_ENTRY(unshift)(list* l, value_t * v) { + node_t * n = malloc(sizeof(node_t)); + n->v = v; + LL_ENTRY(unshiftNode)(l, n); + return n; +} +value_t * LL_ENTRY(shift) (list* l) { + node_t * n = LL_ENTRY(shiftNode)(l); + if(n) { + value_t * v = n->v; + free(n); + return v; + } else { + return 0; + } +} + + +void LL_ENTRY(pushNode)(list* l, node_t * n) { + + // Need to update 3 nodes: n , tail, tail->prev + + // n + n->prev = l->tail->prev; + n->next = l->tail; + + // tail + l->tail->prev = n; + + // tail->prev is now n->prev + n->prev->next = n; +} +node_t* LL_ENTRY(popNode) (list* l) { + node_t * n = l->tail->prev; + assert(n != l->tail); + if(n != l->head) { + assert(n->prev != 0); + assert(n->next == l->tail); + + // n->prev + n->prev->next = n->next; + + // tail + l->tail->prev = n->prev; + + return n; + } else { + assert(n->prev == 0); + return 0; + } +} +void LL_ENTRY(unshiftNode)(list* l, node_t * n) { + + // n + n->prev = l->head; + n->next = l->head->next; + + // head + l->head->next = n; + + // head->next is now n->next + n->next->prev = n; +} +node_t * LL_ENTRY(shiftNode) (list* l) { + node_t * n = l->head->next; + assert(n != l->head); + if(n != l->tail) { + assert(n->next != 0); + assert(n->prev == l->head); + + // n->next + n->next->prev = n->prev; + + // head + l->head->next = n->next; + + return n; + } else { + assert(n->next == 0); + return 0; + } +} +void LL_ENTRY(remove)(list * l, node_t * n) { + LL_ENTRY(removeNoFree)(l,n); + free(n); +} +void LL_ENTRY(removeNoFree)(list * l, node_t * n) { + assert(n != l->head); + assert(n != l->tail); + assert(n->next != n); + assert(n->prev != n); + assert(n->next != n->prev); + + n->prev->next = n->next; + n->next->prev = n->prev; +}