diff --git a/src/LinkedList/LinkedList.c b/src/LinkedList/LinkedList.c new file mode 100644 index 0000000..a6302ed --- /dev/null +++ b/src/LinkedList/LinkedList.c @@ -0,0 +1,3 @@ +#include "LinkedList.h" + +LinkedList_define(Pointer, true) diff --git a/src/LinkedList/LinkedList.h b/src/LinkedList/LinkedList.h new file mode 100644 index 0000000..6283ad7 --- /dev/null +++ b/src/LinkedList/LinkedList.h @@ -0,0 +1,73 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#include "../base/base.h" +#include "LinkedList_declare.h" +#include "LinkedList_define.h" + +// LinkedListNode + +#define LLNode(TYPE) LLNode_##TYPE +#define LinkedList(TYPE) LinkedList_##TYPE + +#define LinkedList_create(TYPE) LinkedList_##TYPE##_create() +#define LinkedList_free(LLIST) ({ LLIST->_functions->freeMembers(LLIST); free(LLIST); }) + +/// inserts NEW_NODE before NEXT_NODE in LLIST +#define LinkedList_insertPrev(LLIST, NEW_NODE, NEXT_NODE) LLIST->_functions->insertPrev(LLIST, NEW_NODE, NEXT_NODE) + +/// inserts NEW_NODE after PREV_NODE in LLIST +#define LinkedList_insertNext(LLIST, NEW_NODE, PREV_NODE) LLIST->_functions->insertNext(LLIST, NEW_NODE, PREV_NODE) + +/// removes node before NEXT_NODE in LLIST +/// if FREE_REMOVED then frees removed node +#define LinkedList_removePrev(LLIST, NEXT_NODE, FREE_REMOVED) LLIST->_functions->removePrev(LLIST, NEXT_NODE, FREE_REMOVED) + +/// removes node after PREV_NODE in LLIST +/// if FREE_REMOVED then frees removed node +#define LinkedList_removeNext(LLIST, PREV_NODE, FREE_REMOVED) LLIST->_functions->removeNext(LLIST, PREV_NODE, FREE_REMOVED) + +///@param FIRST_N first node in enumeration +///@param CURR_N name of iteration variable +///@param CODE code todo in every iteration +#define LLNode_foreach(FIRST_N, CURR_N, CODE...) { \ + typeof(FIRST_N) CURR_N=FIRST_N; \ + while(CURR_N!=NULL) { \ + CODE; \ + CURR_N=CURR_N->next; \ + } \ +} + +///@param FIRST_N first node in enumeration +///@param CURR_N name of iteration variable +///@param CODE code todo in every iteration +#define LLNode_foreachReverse(FIRST_N, CURR_N, CODE...) { \ + typeof(FIRST_N) CURR_N=FIRST_N; \ + while(CURR_N!=NULL) { \ + CODE; \ + CURR_N=CURR_N->prev; \ + } \ +} + +///@param LLIST LinkedList +///@param CURR_N name of iteration variable +///@param CODE code todo in every iteration +#define LinkedList_foreach(LLIST, CURR_N, CODE...) \ + LLNode_foreach(LLIST->first_node, CURR_N, CODE) + +///@param LLIST LinkedList +///@param CURR_N name of iteration variable +///@param CODE code todo in every iteration +#define LinkedList_foreachReverse(LLIST, CURR_N, CODE...) \ + LLNode_foreachReverse(LLIST->last_node, CURR_N, CODE) + + + +LinkedList_declare(Pointer) + +#if __cplusplus +} +#endif diff --git a/src/LinkedList/LinkedList_declare.h b/src/LinkedList/LinkedList_declare.h new file mode 100644 index 0000000..418a722 --- /dev/null +++ b/src/LinkedList/LinkedList_declare.h @@ -0,0 +1,45 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#define LLNode_declare(TYPE)\ +STRUCT(LLNode(TYPE), \ + LLNode(TYPE)* prev; \ + LLNode(TYPE)* next; \ + TYPE value; \ +) \ +\ +LLNode(TYPE)* LLNode_##TYPE##_create(); \ +LLNode(TYPE)* LLNode_##TYPE##_createFromValue(TYPE value); \ +void LLNode_##TYPE##_free(LLNode(TYPE)* node, bool free_value); + + +#define LinkedList_declare(TYPE)\ +LLNode_declare(TYPE) \ +typedef struct LinkedList_##TYPE##_functions_t LinkedList_##TYPE##_functions_t; \ +\ +STRUCT(LinkedList(TYPE), \ + LinkedList_##TYPE##_functions_t* _functions; \ + LLNode(TYPE)* first_node; \ + LLNode(TYPE)* last_node; \ + u32 count; \ +) \ +\ +typedef struct LinkedList_##TYPE##_functions_t { \ + freeMembers_t freeMembers; \ + void (*insertPrev)(LinkedList(TYPE)* llist, LLNode(TYPE)* newNode, LLNode(TYPE)* nextNode); \ + void (*insertNext)(LinkedList(TYPE)* llist, LLNode(TYPE)* newNode, LLNode(TYPE)* prevNode); \ + void (*removePrev)(LinkedList(TYPE)* llist, LLNode(TYPE)* nextNode, bool freeRemoved); \ + void (*removeNext)(LinkedList(TYPE)* llist, LLNode(TYPE)* prevNode, bool freeRemoved); \ +} LinkedList_##TYPE##_functions_t; \ +\ +extern LinkedList_##TYPE##_functions_t _LinkedList_##TYPE##_functions; \ +\ +LinkedList(TYPE)* LinkedList_##TYPE##_create(); \ + + +#if __cplusplus +} +#endif diff --git a/src/LinkedList/LinkedList_define.h b/src/LinkedList/LinkedList_define.h new file mode 100644 index 0000000..2ea4e16 --- /dev/null +++ b/src/LinkedList/LinkedList_define.h @@ -0,0 +1,109 @@ +#pragma once + +#if __cplusplus +extern "C" { +#endif + +#define LLNode_define(TYPE, TYPE_IS_PTR)\ +LLNode(TYPE)* LLNode_##TYPE##_create(){ \ + LLNode(TYPE)* node= (LLNode(TYPE)*)malloc(sizeof(*node)); \ + node->prev=NULL; \ + node->next=NULL; \ + node->value=(TYPE){0}; \ + return node; \ +} \ +\ +LLNode(TYPE)* LLNode_##TYPE##_createFromValue(TYPE value){ \ + LLNode(TYPE)* node= (LLNode(TYPE)*)malloc(sizeof(*node)); \ + node->prev=NULL; \ + node->next=NULL; \ + node->value=value; \ + return node; \ +} \ +\ +void LLNode_##TYPE##_freeMembers(void* _node){ \ + LLNode(TYPE)* node=(LLNode(TYPE)*)_node; \ + void* value_ptr=&node->value; \ + if(TYPE_IS_PTR) value_ptr=*(TYPE**)value_ptr; \ + ktDescriptor_##TYPE.freeMembers(value_ptr); \ + if(node->prev) node->prev->next=NULL; \ + if(node->next) node->next->prev=NULL; \ +} \ +\ +void LLNode_##TYPE##_free(LLNode(TYPE)* node, bool free_value){ \ + if(free_value) LLNode_##TYPE##_freeMembers(node); \ + if(node->prev) node->prev->next=NULL; \ + if(node->next) node->next->prev=NULL; \ + free(node); \ +} \ +\ +kt_define(LLNode_##TYPE, LLNode_##TYPE##_freeMembers, NULL) + + +#define LinkedList_define(TYPE, VALUE_IS_PTR)\ +LLNode_define(TYPE, VALUE_IS_PTR) \ +\ +LinkedList(TYPE)* LinkedList_##TYPE##_create(){ \ + LinkedList(TYPE)* l=malloc(sizeof(*l)); \ + l->_functions=&_LinkedList_##TYPE##_functions; \ + l->first_node=NULL; \ + l->last_node=NULL; \ + l->count=0; \ + return l; \ +} \ +\ +void LinkedList_##TYPE##_freeMembers(void* _l){ \ + LinkedList(TYPE)* l=(LinkedList(TYPE)*)_l; \ + if(l->first_node!=NULL) \ + LinkedList_foreach(l, node, LLNode_##TYPE##_free(node, true)); \ + l->first_node=NULL; l->last_node=NULL; l->count=0; \ +} \ +\ +void LinkedList_##TYPE##_insertPrev(LinkedList(TYPE)* llist, LLNode(TYPE)* newNode, LLNode(TYPE)* nextNode){ \ + llist->count++; \ + newNode->prev=nextNode->prev; \ + newNode->next=nextNode; \ + nextNode->prev=newNode; \ +} \ +\ +void LinkedList_##TYPE##_insertNext(LinkedList(TYPE)* llist, LLNode(TYPE)* newNode, LLNode(TYPE)* prevNode){ \ + llist->count++; \ + newNode->prev=prevNode; \ + newNode->next=prevNode->next; \ + prevNode->next=newNode; \ +} \ +\ +void LinkedList_##TYPE##_removePrev(LinkedList(TYPE)* llist, LLNode(TYPE)* nextNode, bool freeRemoved){ \ + llist->count--; \ + LLNode(TYPE)* removedNode=nextNode->prev; \ + LLNode(TYPE)* prevNode=removedNode->prev; \ + nextNode->prev=prevNode; \ + prevNode->next=nextNode; \ + if(freeRemoved) \ + LLNode_##TYPE##_free(removedNode, true); \ +} \ +\ +void LinkedList_##TYPE##_removeNext(LinkedList(TYPE)* llist, LLNode(TYPE)* prevNode, bool freeRemoved){ \ + llist->count--; \ + LLNode(TYPE)* removedNode=prevNode->next; \ + LLNode(TYPE)* nextNode=removedNode->next; \ + prevNode->next=nextNode; \ + nextNode->prev=prevNode; \ + if(freeRemoved) \ + LLNode_##TYPE##_free(removedNode, true); \ +} \ +\ +LinkedList_##TYPE##_functions_t _LinkedList_##TYPE##_functions={ \ + .freeMembers=LinkedList_##TYPE##_freeMembers, \ + .insertPrev=LinkedList_##TYPE##_insertPrev, \ + .insertNext=LinkedList_##TYPE##_insertNext, \ + .removePrev=LinkedList_##TYPE##_removePrev, \ + .removeNext=LinkedList_##TYPE##_removeNext \ +}; \ +\ +kt_define(LinkedList_##TYPE, LinkedList_##TYPE##_freeMembers, NULL) + + +#if __cplusplus +} +#endif