-
-
Save ForgotMyCode/5b2b814cb6970c3901df77793fb0f247 to your computer and use it in GitHub Desktop.
Generic Linked List in C (Experimental)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdlib.h> | |
#define INTERNAL__CONCAT_2ARGS(LHS, RHS) LHS##RHS | |
#define INTERNAL__CONCAT_3ARGS(A, B, C) A##B##C | |
#define INTERNAL__MAKE_INNER_TYPENAME(LL_DECLNAME, TYPE) INTERNAL__CONCAT_3ARGS(INTERNAL__, LL_DECLNAME, INNER_TYPE) | |
#define INTERNAL__MAKE_INTERNAL_FUNCTION_NAME(LL_DECLNAME, FUNCTION_NAME) INTERNAL__CONCAT_3ARGS(INTERNAL__, LL_DECLNAME, FUNCTION_NAME) | |
#define INTERNAL__MAKE_INTERNAL_NODE_NAME(LL_DECLNAME) INTERNAL__CONCAT_3ARGS(INTERNAL__, LL_DECLNAME, _LL_Node) | |
#define INTERNAL__MAKE_INTERNAL_STRUCTED_NAME(LL_DECLNAME) INTERNAL__CONCAT_3ARGS(INTERNAL__STRUCTED_, LL_DECLNAME, _LL_Type) | |
#define INTERNAL__MAKE_INTERNAL_STRUCTED_NODE_NAME(LL_DECLNAME) INTERNAL__CONCAT_3ARGS(INTERNAL__STRUCTED_, LL_DECLNAME, _LL_Node) | |
#define LL_DECLARE(TYPE, DECLNAME) \ | |
typedef TYPE INTERNAL__MAKE_INNER_TYPENAME(DECLNAME, TYPE); \ | |
\ | |
typedef struct INTERNAL__MAKE_INTERNAL_STRUCTED_NODE_NAME(DECLNAME) { \ | |
struct INTERNAL__MAKE_INTERNAL_STRUCTED_NODE_NAME(DECLNAME)* next; \ | |
struct INTERNAL__MAKE_INTERNAL_STRUCTED_NODE_NAME(DECLNAME)* prev; \ | |
INTERNAL__MAKE_INNER_TYPENAME(DECLNAME, TYPE) value; \ | |
} INTERNAL__MAKE_INTERNAL_NODE_NAME(DECLNAME); \ | |
\ | |
typedef struct INTERNAL__MAKE_INTERNAL_STRUCTED_NAME(DECLNAME) { \ | |
INTERNAL__MAKE_INTERNAL_NODE_NAME(DECLNAME)* head; \ | |
INTERNAL__MAKE_INTERNAL_NODE_NAME(DECLNAME)* tail; \ | |
unsigned long long size; \ | |
\ | |
void (*internal__push_back)(struct INTERNAL__MAKE_INTERNAL_STRUCTED_NAME(DECLNAME)*, INTERNAL__MAKE_INNER_TYPENAME(DECLNAME, TYPE)); \ | |
INTERNAL__MAKE_INNER_TYPENAME(DECLNAME, TYPE)(*internal__pop_back)(struct INTERNAL__MAKE_INTERNAL_STRUCTED_NAME(DECLNAME)*); \ | |
void (*internal__push_front)(struct INTERNAL__MAKE_INTERNAL_STRUCTED_NAME(DECLNAME)*, INTERNAL__MAKE_INNER_TYPENAME(DECLNAME, TYPE)); \ | |
INTERNAL__MAKE_INNER_TYPENAME(DECLNAME, TYPE)(*internal__pop_front)(struct INTERNAL__MAKE_INTERNAL_STRUCTED_NAME(DECLNAME)*); \ | |
} DECLNAME; \ | |
\ | |
INTERNAL__MAKE_INTERNAL_NODE_NAME(DECLNAME)* INTERNAL__MAKE_INTERNAL_FUNCTION_NAME(DECLNAME, NEW_NODE)( \ | |
INTERNAL__MAKE_INTERNAL_NODE_NAME(DECLNAME)* prev, \ | |
INTERNAL__MAKE_INTERNAL_NODE_NAME(DECLNAME)* next, \ | |
INTERNAL__MAKE_INNER_TYPENAME(DECLNAME, TYPE) value \ | |
) { \ | |
INTERNAL__MAKE_INTERNAL_NODE_NAME(DECLNAME)* newNode = (INTERNAL__MAKE_INTERNAL_NODE_NAME(DECLNAME)*) calloc(1, sizeof(INTERNAL__MAKE_INTERNAL_NODE_NAME(DECLNAME))); \ | |
newNode->value = value; \ | |
newNode->prev = prev; \ | |
newNode->next = next; \ | |
return newNode; \ | |
} \ | |
\ | |
void INTERNAL__MAKE_INTERNAL_FUNCTION_NAME(DECLNAME, PUSH_BACK)(DECLNAME* instance, INTERNAL__MAKE_INNER_TYPENAME(DECLNAME, TYPE) value) { \ | |
if(instance->tail) { \ | |
instance->tail->next = INTERNAL__MAKE_INTERNAL_FUNCTION_NAME(DECLNAME, NEW_NODE)(instance->tail, NULL, value); \ | |
instance->tail = instance->tail->next; \ | |
} \ | |
else { \ | |
instance->tail = INTERNAL__MAKE_INTERNAL_FUNCTION_NAME(DECLNAME, NEW_NODE)(NULL, NULL, value); \ | |
instance->head = instance->tail; \ | |
} \ | |
++instance->size; \ | |
} \ | |
\ | |
INTERNAL__MAKE_INNER_TYPENAME(DECLNAME, TYPE) INTERNAL__MAKE_INTERNAL_FUNCTION_NAME(DECLNAME, POP_BACK)(DECLNAME* instance) { \ | |
INTERNAL__MAKE_INTERNAL_NODE_NAME(DECLNAME)* removedNode = instance->tail; \ | |
instance->tail = instance->tail->prev; \ | |
INTERNAL__MAKE_INNER_TYPENAME(DECLNAME, TYPE) ret = removedNode->value; \ | |
free(removedNode); \ | |
\ | |
if(instance->tail) { \ | |
instance->tail->next = NULL; \ | |
} \ | |
else { \ | |
instance->head = NULL; \ | |
} \ | |
--instance->size; \ | |
return ret; \ | |
} \ | |
\ | |
void INTERNAL__MAKE_INTERNAL_FUNCTION_NAME(DECLNAME, PUSH_FRONT)(DECLNAME* instance, INTERNAL__MAKE_INNER_TYPENAME(DECLNAME, TYPE) value) { \ | |
if(instance->head) { \ | |
instance->head->prev = INTERNAL__MAKE_INTERNAL_FUNCTION_NAME(DECLNAME, NEW_NODE)(NULL, instance->head, value); \ | |
instance->head = instance->head->prev; \ | |
} \ | |
else { \ | |
instance->head = INTERNAL__MAKE_INTERNAL_FUNCTION_NAME(DECLNAME, NEW_NODE)(NULL, NULL, value); \ | |
instance->tail = instance->head; \ | |
} \ | |
++instance->size; \ | |
} \ | |
\ | |
INTERNAL__MAKE_INNER_TYPENAME(DECLNAME, TYPE) INTERNAL__MAKE_INTERNAL_FUNCTION_NAME(DECLNAME, POP_FRONT)(DECLNAME* instance) { \ | |
INTERNAL__MAKE_INTERNAL_NODE_NAME(DECLNAME)* removedNode = instance->head; \ | |
instance->head = instance->head->next; \ | |
INTERNAL__MAKE_INNER_TYPENAME(DECLNAME, TYPE) ret = removedNode->value; \ | |
free(removedNode); \ | |
\ | |
if(instance->head) { \ | |
instance->head->prev = NULL; \ | |
} \ | |
else { \ | |
instance->tail = NULL; \ | |
} \ | |
--instance->size; \ | |
return ret; \ | |
} | |
#define LL_MAKE_INSTANCE(LL_DECLNAME, VARIABLE_NAME) \ | |
LL_DECLNAME VARIABLE_NAME; \ | |
{ \ | |
(VARIABLE_NAME).head = NULL; \ | |
(VARIABLE_NAME).tail = NULL; \ | |
(VARIABLE_NAME).size = 0ULL; \ | |
(VARIABLE_NAME).internal__push_back = &INTERNAL__MAKE_INTERNAL_FUNCTION_NAME(LL_DECLNAME, PUSH_BACK); \ | |
(VARIABLE_NAME).internal__pop_back = &INTERNAL__MAKE_INTERNAL_FUNCTION_NAME(LL_DECLNAME, POP_BACK); \ | |
(VARIABLE_NAME).internal__push_front = &INTERNAL__MAKE_INTERNAL_FUNCTION_NAME(LL_DECLNAME, PUSH_FRONT); \ | |
(VARIABLE_NAME).internal__pop_front = &INTERNAL__MAKE_INTERNAL_FUNCTION_NAME(LL_DECLNAME, POP_FRONT); \ | |
} | |
#define LL_DESTRUCT(LL_INSTANCE) {\ | |
while((LL_INSTANCE).head) { \ | |
(LL_INSTANCE).tail = head; \ | |
(LL_INSTANCE).head = (LL_INSTANCE).head->next; \ | |
free((LL_INSTANCE).tail); \ | |
} \ | |
(LL_INSTANCE).tail = NULL; \ | |
(LL_INSTANCE).size = 0ULL; \ | |
} | |
#define LL_GET_SIZE(LL_INSTANCE) \ | |
(LL_INSTANCE).size | |
#define LL_PUSH_BACK(LL_INSTANCE, VALUE) \ | |
(LL_INSTANCE).internal__push_back(&(LL_INSTANCE), VALUE) | |
#define LL_POP_BACK(LL_INSTANCE) \ | |
(LL_INSTANCE).internal__pop_back(&(LL_INSTANCE)) | |
#define LL_PUSH_FRONT(LL_INSTANCE, VALUE) \ | |
(LL_INSTANCE).internal__push_front(&(LL_INSTANCE), VALUE) | |
#define LL_POP_FRONT(LL_INSTANCE) \ | |
(LL_INSTANCE).internal__pop_front(&(LL_INSTANCE)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment