Skip to content

Instantly share code, notes, and snippets.

@fami-com
Last active January 22, 2020 21:37
Show Gist options
  • Save fami-com/975436014d121c19384903f8f1c7aac6 to your computer and use it in GitHub Desktop.
Save fami-com/975436014d121c19384903f8f1c7aac6 to your computer and use it in GitHub Desktop.
Generic linked list in C
#ifndef LIST_H
#define LIST_H
#ifndef ALLOC
#define ALLOC malloc
#endif
#define _CREATE_LIST_TYPE(type, name, prefix)\
typedef struct List_##name List_##name;\
struct List_##name {\
type data;\
List_##name*next;\
};\
\
int prefix##_init(List_##name**list);\
int prefix##_init_arr(List_##name**list,size_t sz, type arr[]);\
type prefix##_get(List_##name*list,size_t i);\
void prefix##_set(List_##name*list,type data,size_t i);\
List_##name* prefix##_tail(List_##name*list);\
size_t prefix##_len(List_##name*list);\
int prefix##_copy(List_##name**dest,List_##name*src);\
int prefix##_append_ip(List_##name*list, type el);\
int prefix##_append(List_##name**dest, List_##name*list, type el);\
int prefix##_insert_ip(List_##name*list,List_##name*other,size_t i);\
int prefix##_insert(List_##name**dest,List_##name*list,List_##name*other,size_t i);\
void prefix##_join_ip(List_##name*first,List_##name*next);\
int prefix##_join(List_##name**dest, List_##name*first,List_##name*next);\
void prefix##_map_ip(List_##name*list, type (*fn)(type));\
int prefix##_map(List_##name**dest, List_##name*list, type (*fn)(type));\
void prefix##_each(List_##name*list, void (*fn)(type));\
int prefix##_filter(List_##name**dest, List_##name*list, int (*fn)(type));\
type prefix##_reduce(List_##name*list, type (*fn)(type,type));\
int prefix##_reverse(List_##name**dest,List_##name*list);\
void prefix##_split(List_##name**first,List_##name**last,List_##name*list);\
void prefix##_merge(List_##name**dest,List_##name*list1,List_##name*list2,int (*cmp)(type,type));\
int prefix##_sort_ip(List_##name**list, int(*cmp)(type,type));\
int prefix##_sort(List_##name**dest,List_##name*list, int (*cmp)(type,type));\
\
int prefix##_init(List_##name**list){\
*list=(List_##name*)ALLOC(sizeof(List_##name));\
if(*list==NULL) return -1;\
else {(*list)->next = NULL;return 0;}\
}\
int prefix##_init_arr(List_##name**list,size_t sz, type arr[]){\
List_##name*tmp1,*tmp2;\
int t;\
t=prefix##_init(list);\
if(t==-1)return -1;\
t=prefix##_init(&tmp1);\
if(t==-1)return -1;\
(*list)->next=tmp1;\
(*list)->data=arr[0];\
for(size_t i = 1; i<sz;i++){\
tmp1->data=arr[i];\
if(i == sz-1){tmp1->next=NULL;break;}\
tmp2=tmp1;\
t=prefix##_init(&tmp1);\
if(t==-1)return -1;\
tmp2->next=tmp1;\
}\
return 0;\
}\
type prefix##_get(List_##name*list,size_t i){\
for(size_t _=0;_<i;_++)list=list->next;\
return list->data;\
}\
void prefix##_set(List_##name*list,type data,size_t i){\
for(size_t _=0;_<i;_++)list=list->next;\
list->data = data;\
}\
List_##name* prefix##_tail(List_##name*list){\
while (list->next) {\
list = list->next;\
}\
return list;\
}\
size_t prefix##_len(List_##name*list){\
size_t len=0;\
while (list) {\
len++;\
list = list->next;\
}\
return len;\
}\
int prefix##_copy(List_##name**dest,List_##name*src){\
List_##name*tmp1,*tmp2;\
int t, sz = prefix##_len(src);\
t = prefix##_init(dest);\
if(t==-1)return -1;\
t=prefix##_init(&tmp1);\
if(t==-1)return -1;\
(*dest)->next=tmp1;\
(*dest)->data = src->data;\
for(size_t i = 1; i<sz;i++){\
tmp1->data=prefix##_get(src, i);\
if(i == sz-1){tmp1->next=NULL;break;}\
tmp2=tmp1;\
t=prefix##_init(&tmp1);\
if(t==-1)return -1;\
tmp2->next=tmp1;\
}\
return 0;\
}\
int prefix##_append_ip(List_##name*list, type el){\
List_##name *tail = prefix##_tail(list), *tmp;\
int t = prefix##_init(&tmp);\
if(t==-1)return-1;\
tmp->data = el;\
tail->next=tmp;\
return 0;\
}\
int prefix##_append(List_##name**dest, List_##name*list, type el){\
int t = prefix##_copy(dest, list);\
if(t==-1)return-1;\
t = prefix##_append_ip(*dest,el);\
return t;\
}\
int prefix##_insert_ip(List_##name*list,List_##name*other,size_t i){\
for(size_t _=0;_<i;_++)list=list->next;\
List_##name*tmp=list->next;\
list->next=other;\
other->next=tmp;\
}\
int prefix##_insert(List_##name**dest,List_##name*list,List_##name*other,size_t i){\
List_##name*tmp1;\
int t=prefix##_copy(dest,list);\
if(t==-1)return-1;\
t=prefix##_copy(&tmp1,other);\
if(t==-1)return-1;\
t = prefix##_insert_ip(*dest,tmp1,i);\
return t;\
}\
void prefix##_join_ip(List_##name*first,List_##name*next){\
prefix##_tail(first)->next=next;\
}\
int prefix##_join(List_##name**dest, List_##name*first,List_##name*next){\
int t =prefix##_copy(dest,first);\
if(t==-1)return -1;\
prefix##_join_ip(*dest,next);\
return 0;\
}\
void prefix##_map_ip(List_##name*list, type (*fn)(type)){\
while (list) {\
list->data = fn(list->data);\
list = list->next;\
}\
}\
int prefix##_map(List_##name**dest, List_##name*list, type (*fn)(type)){\
List_##name*tmp;\
int t=prefix##_copy(dest,list);\
if(t==-1)return -1;\
prefix##_map_ip(*dest, fn);\
return 0;\
}\
void prefix##_each(List_##name*list, void (*fn)(type)){\
while (list) {\
fn(list->data);\
list = list->next;\
}\
}\
int prefix##_filter(List_##name**dest, List_##name*list, int (*fn)(type)){\
int t;\
List_##name*tmp1,*tmp2;\
t = prefix##_init(dest);\
if(t==-1)return -1;\
t = prefix##_init(&tmp1);\
if(t==-1)return -1;\
tmp2 = *dest;\
while(list){\
if(fn(list->data)){\
tmp2->data = list->data;\
if(!list->next)break;\
tmp1=tmp2;\
t = prefix##_init(&tmp2);\
if(t==-1)return -1;\
tmp1->next=tmp2;\
}\
list=list->next;\
}\
return 0;\
}\
type prefix##_reduce(List_##name*list, type (*fn)(type,type)){\
type acc;\
acc = list->data;list=list->next;\
while(list){\
acc = fn(acc,list->data);\
list=list->next;\
}\
return acc;\
}\
int prefix##_reverse(List_##name**dest,List_##name*list){\
List_##name*tmp1,*tmp2;\
int t = prefix##_init(dest);\
if(t==-1)return -1;\
t = prefix##_init(&tmp1);\
if(t==-1)return -1;\
t = prefix##_init(&tmp2);\
if(t==-1)return -1;\
while(list){\
tmp1->data=list->data;\
tmp2=tmp1;\
t = prefix##_init(&tmp1);\
if(t==-1)return -1;\
tmp1->next=tmp2;\
list=list->next;\
}\
*dest=tmp2;\
}\
void prefix##_split(List_##name**first,List_##name**last,List_##name*list){\
List_##name*tmp1=list->next,*tmp2=list;\
while(tmp1){\
tmp1=tmp1->next;\
if(tmp1){tmp2=tmp2->next;tmp1=tmp1->next;}\
}\
*first=list;\
*last=tmp2->next;\
tmp2->next=NULL;\
}\
void prefix##_merge(List_##name**dest,List_##name*list1,List_##name*list2,int (*cmp)(type,type)){\
if(!list1){*dest= list2;return;}\
if(!list2){*dest= list1;return;}\
if(cmp(list1->data,list2->data)<=0){\
*dest=list1;\
prefix##_merge(&(*dest)->next,list1->next,list2,cmp);\
}else{\
*dest=list2;\
prefix##_merge(&(*dest)->next,list1,list2->next,cmp);\
}\
}\
int prefix##_sort_ip(List_##name**list, int(*cmp)(type,type)){\
List_##name*head=*list,*tmp1,*tmp2;\
if(!head||!head->next)return -1;\
prefix##_split(&tmp1,&tmp2,head);\
prefix##_sort_ip(&tmp1,cmp);prefix##_sort_ip(&tmp2,cmp);\
prefix##_merge(list,tmp1,tmp2,cmp);\
}\
int prefix##_sort(List_##name**dest,List_##name*list, int (*cmp)(type,type)){\
prefix##_copy(dest,list);\
prefix##_sort_ip(dest,cmp);\
}
#define CREATE_LIST_TYPE(type, name, prefix) _CREATE_LIST_TYPE(type, name, prefix)
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment