Skip to content

Instantly share code, notes, and snippets.

@ForgotMyCode
Created April 4, 2023 01:14
Show Gist options
  • Select an option

  • Save ForgotMyCode/5b2b814cb6970c3901df77793fb0f247 to your computer and use it in GitHub Desktop.

Select an option

Save ForgotMyCode/5b2b814cb6970c3901df77793fb0f247 to your computer and use it in GitHub Desktop.

Revisions

  1. ForgotMyCode created this gist Apr 4, 2023.
    134 changes: 134 additions & 0 deletions ll.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,134 @@
    #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))