#ifndef COLLECTION_GENERIC_LIST_H
#define COLLECTION_GENERIC_LIST_H
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#ifdef __cplusplus
extern "C"{
#endif
#define GENERATE_LIST(NAME, TYPE)\
struct NAME##_list{\
struct NAME##_list* next, *prev;\
TYPE value;\
};\
static void(*NAME##_list_deleter)(TYPE) = 0;\
inline void NAME##_list_push_back(struct NAME##_list** l, TYPE value){\
struct NAME##_list* prev = 0;\
while(*l){\
prev = *l;\
l = &(*l)->next;\
}\
if(!(*l = malloc(sizeof(struct NAME##_list))))\
fprintf(stderr, "%s", "Could not allocate list");\
(*l)->value = value;\
(*l)->next = 0;\
(*l)->prev = prev;\
}\
inline int NAME##_list_size(struct NAME##_list* l){\
int size = 0;\
for(; l; l = l->next)\
++size;\
return size;\
}\
inline void NAME##_list_insert(struct NAME##_list** l, int n, TYPE value){\
assert((!*l && !n) || n < NAME##_list_size(*l));\
while(n)\
l = &(*l)->next, --n;\
struct NAME##_list* nl = malloc(sizeof(struct NAME##_list*));\
if(!nl)\
fprintf(stderr, "%s", "Could not allocate list");\
nl->next = *l;\
nl->value = value;\
*l = nl;\
}\
inline void NAME##_list_remove(struct NAME##_list** l, int n){\
assert(n < NAME##_list_size(*l));\
while(n)\
l = &(*l)->next, --n;\
struct NAME##_list* old = *l;\
if((*l = (*l)->next))\
(*l)->prev = old->prev;\
if(NAME##_list_deleter)\
NAME##_list_deleter(old->value);\
free(old);\
}\
inline void NAME##_list_clear(struct NAME##_list* l){\
struct NAME##_list* next = l;\
while(next){\
next = l->next;\
if(NAME##_list_deleter)\
NAME##_list_deleter(l->value);\
free(l);\
l = next;\
}\
}\
inline struct NAME##_list* NAME##_list_get(struct NAME##_list* l, int n){\
assert(n < NAME##_list_size(l));\
while(n)\
l = l->next, --n;\
return l;\
}\
inline struct NAME##_list* NAME##_list_find(struct NAME##_list* l, TYPE value){\
while(l){\
if(l->value == value)\
return l;\
l = l->next;\
}\
return l;\
}\
inline struct NAME##_list* NAME##_list_rfind(struct NAME##_list* l, TYPE value){\
struct NAME##_list* p = NAME##_list_get(l, NAME##_list_size(l) - 1);\
while(p){\
if(p->value == value)\
return p;\
p = p->prev;\
}\
return p;\
}
GENERATE_LIST(char, char)
GENERATE_LIST(short, short)
GENERATE_LIST(int, int)
GENERATE_LIST(long, long)
GENERATE_LIST(float, float)
GENERATE_LIST(double, double)
#ifdef __cplusplus
}
#endif
#endif