Skip to content

Instantly share code, notes, and snippets.

@ShawnMcGrath
Created September 21, 2016 00:38
Show Gist options
  • Save ShawnMcGrath/9d210624b9f28822172905ecdb0808fa to your computer and use it in GitHub Desktop.
Save ShawnMcGrath/9d210624b9f28822172905ecdb0808fa to your computer and use it in GitHub Desktop.
#ifndef MG_LINKEDLIST_EXTERN
#define MG_LINKEDLIST_EXTERN extern
#endif
#ifndef MG_LINKEDLIST_INTERN
#define MG_LINKEDLIST_INTERN static
#endif
//mandatory
#ifndef MG_LINKEDLIST_TYPE
#error "Must #define MG_LINKEDLIST_TYPE"
#endif
//optional
#ifndef MG_LINKEDLIST_NEXT_NAME
#define MG_LINKEDLIST_NEXT_NAME next
#endif
#ifndef MG_LINKEDLIST_PREV_NAME
#define MG_LINKEDLIST_PREV_NAME prev
#endif
/*MG_LINKEDLIST_FN_EXT
if you specify this, all linked list functions will be:
mgll_fnNameMG_LINKEDLIST_FN_EXT(..)
if you don't specify it, then it'll rely on C++ overloading and just make the functions:
mggl_fnName(..)
*/
#define __MG_LINKEDLIST_JOIN_HELPER(name0, name1) name0## ##name1
#define __MG_LINKEDLIST_JOIN2(name0, name1) __MG_LINKEDLIST_JOIN_HELPER(name0, name1)
#ifdef MG_LINKEDLIST_FN_EXT
#define __MG_LINKEDLIST_FN(ret, name, ...) ret __MG_LINKEDLIST_JOIN2(mgll_##name, MG_LINKEDLIST_FN_EXT)(__VA_ARGS__)
#else
#define __MG_LINKEDLIST_FN(ret, name, ...) ret mgll_##name(__VA_ARGS__)
#endif
MG_LINKEDLIST_INTERN __MG_LINKEDLIST_FN(MG_LINKEDLIST_TYPE *, getLast, MG_LINKEDLIST_TYPE *list) {
while (list) {
if (!list->MG_LINKEDLIST_NEXT_NAME) {
return list;
}
list = list->MG_LINKEDLIST_NEXT_NAME;
}
return list;
}
MG_LINKEDLIST_INTERN __MG_LINKEDLIST_FN(int, getCount, MG_LINKEDLIST_TYPE *list) {
int c = 0;
while (list) {
list = list->next;
++c;
}
return c;
}
MG_LINKEDLIST_INTERN __MG_LINKEDLIST_FN(void, addToListFront, MG_LINKEDLIST_TYPE *element, MG_LINKEDLIST_TYPE **first_element) {
element->MG_LINKEDLIST_NEXT_NAME = *first_element;
if (*first_element) {
if ((*first_element)->MG_LINKEDLIST_PREV_NAME) {
(*first_element)->MG_LINKEDLIST_PREV_NAME->MG_LINKEDLIST_NEXT_NAME = element;
element->MG_LINKEDLIST_PREV_NAME = (*first_element)->MG_LINKEDLIST_PREV_NAME;
}
(*first_element)->MG_LINKEDLIST_PREV_NAME = element;
} else {
*first_element = element;
}
if (element->MG_LINKEDLIST_PREV_NAME) {
element->MG_LINKEDLIST_PREV_NAME->MG_LINKEDLIST_NEXT_NAME = element->MG_LINKEDLIST_NEXT_NAME;
}
if (element->MG_LINKEDLIST_NEXT_NAME) {
element->MG_LINKEDLIST_NEXT_NAME->MG_LINKEDLIST_PREV_NAME = element->MG_LINKEDLIST_PREV_NAME;
}
}
MG_LINKEDLIST_INTERN __MG_LINKEDLIST_FN(void, addToListBack, MG_LINKEDLIST_TYPE *element, MG_LINKEDLIST_TYPE **first_element) {
if (*first_element) {
MG_LINKEDLIST_TYPE *last = *first_element;
while (last->MG_LINKEDLIST_NEXT_NAME) {
last = last->MG_LINKEDLIST_NEXT_NAME;
}
last->MG_LINKEDLIST_NEXT_NAME = element;
element->MG_LINKEDLIST_PREV_NAME = last;
} else {
element->MG_LINKEDLIST_PREV_NAME = 0;
element->MG_LINKEDLIST_NEXT_NAME = 0;
*first_element = element;
}
}
MG_LINKEDLIST_INTERN __MG_LINKEDLIST_FN(void, removeFromList, MG_LINKEDLIST_TYPE *element, MG_LINKEDLIST_TYPE **opt_root = 0) {
if (opt_root && element == *opt_root) {
*opt_root = element->next;
}
if (element->MG_LINKEDLIST_PREV_NAME) {
element->MG_LINKEDLIST_PREV_NAME->MG_LINKEDLIST_NEXT_NAME = element->MG_LINKEDLIST_NEXT_NAME;
}
if (element->MG_LINKEDLIST_NEXT_NAME) {
element->MG_LINKEDLIST_NEXT_NAME->MG_LINKEDLIST_PREV_NAME = element->MG_LINKEDLIST_PREV_NAME;
}
}
MG_LINKEDLIST_INTERN __MG_LINKEDLIST_FN(void, swap, MG_LINKEDLIST_TYPE *e0, MG_LINKEDLIST_TYPE *e1, MG_LINKEDLIST_TYPE **opt_root = 0) {
MG_LINKEDLIST_TYPE *e0_next = e0->next;
MG_LINKEDLIST_TYPE *e0_prev = e0->prev;
MG_LINKEDLIST_TYPE *e1_next = e1->next;
MG_LINKEDLIST_TYPE *e1_prev = e1->prev;
if (e0_next) {
e0_next->prev = e1;
}
if (e0_prev) {
e0_prev->next = e1;
}
if (e1_next) {
e1_next->prev = e0;
}
if (e1_prev) {
e1_prev->next = e0;
}
mg_swap(e0->next, e1->next);
mg_swap(e0->prev, e1->prev);
if (opt_root) {
if (*opt_root == e0) {
*opt_root = e1;
} else if (*opt_root == e1) {
*opt_root = e0;
}
}
}
#undef __MG_LINKEDLIST_FN
#undef __MG_LINKEDLIST_JOIN_HELPER
#undef __MG_LINKEDLIST_JOIN2
#undef MG_LINKEDLIST_TYPE
#undef MG_LINKEDLIST_NEXT_NAME
#undef MG_LINKEDLIST_PREV_NAME
#ifndef MG_LINKEDLIST_FN_EXT
#undef MG_LINKEDLIST_FN_EXT
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment