LinkedList

This commit is contained in:
timerix 2023-03-15 03:28:27 +06:00
parent 2a9214fb79
commit 8e572a9db3
4 changed files with 230 additions and 0 deletions

View File

@ -0,0 +1,3 @@
#include "LinkedList.h"
LinkedList_define(Pointer, true)

View File

@ -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

View File

@ -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

View File

@ -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