#include #include #define alloc(type) malloc(sizeof(type)) #define CREATE_LIST(name, type) \ CREATE_TYPE(name, type, name##_node) \ CREATE_PUSH(name, type) \ CREATE_PULL(name) \ CREATE_APPEND(name, type) \ CREATE_POP(name) \ CREATE_FOREACH(name) \ CREATE_FOREACH_REVERSE(name) \ CREATE_FOREACH_TWOPASS(name) \ CREATE_DELETE(name) \ CREATE_SAVE(name) \ CREATE_PRINT(name) \ CREATE_LOAD(name, type) \ CREATE_REMOVE(name, type) #define CREATE_TYPE(name, type, node_name) \ typedef struct node_name { \ struct node_name* next; \ type val; \ } node_name; \ typedef struct name { \ node_name* head; \ } name; #define CREATE_PUSH(name, type) \ int push_##name(name* _list, type element) { \ name##_node* second = _list->head; \ _list->head = alloc(name##_node); \ if (!_list->head) { \ _list->head = second; \ return -1; \ } \ _list->head->next = second; \ \ _list->head->val = element; \ return 0; \ } #define CREATE_PULL(name) \ int pull_##name(name* _list) { \ if (!_list->head) return -1; \ name##_node* first = _list->head->next; \ free(_list->head); \ _list->head = first; \ return 0; \ } #define CREATE_APPEND(name, type) \ int append_##name(name* _list, type element) { \ name##_node* node = _list->head; \ if (!node) return push_##name(_list, element); \ \ for (; node->next; node = node->next); \ node->next = alloc(name##_node); \ if (!node->next) return -1; \ node->next->val = element; \ node->next->next = NULL; \ return 0; \ } #define CREATE_POP(name) \ int pop_##name(name* _list) { \ if (!_list->head) return -1; \ if (!_list->head->next) { \ free(_list->head); \ _list->head = NULL; \ } else { \ name##_node* node = _list->head; \ for (; node->next; node = node->next); \ free(node->next); \ node->next = NULL; \ } \ return 0; \ } #define CREATE_FOREACH(name) \ int foreach_##name( \ name* _list, int (*fun)(name##_node*, void*), void* args \ ) { \ name##_node* node = _list->head; \ int ret = 0; \ for (; node && !ret; node = node->next) ret = fun(node, args); \ return ret; \ } #define CREATE_FOREACH_REVERSE(name) \ int _foreach_reverse_##name( \ name##_node* node, int (*fun)(name##_node*, void*), void* args \ ) { \ if (node) { \ int ret = 0; \ ret = _foreach_reverse_##name(node->next, fun, args); \ return ret ? ret : fun(node, args); \ } \ return 0; \ } \ int foreach_reverse_##name( \ name* _list, int (*fun)(name##_node*, void*), void* args \ ) { \ return _foreach_reverse_##name(_list->head, fun, args); \ } #define CREATE_FOREACH_TWOPASS(name) \ int _foreach_twopass_##name( \ name##_node* node, int (*fun)(name##_node*, void*), void* args \ ) { \ if (node) { \ int ret = fun(node, args); \ if (ret) return ret; \ ret = _foreach_twopass_##name(node->next, fun, args); \ return ret ? ret : fun(node, args); \ } \ return 0; \ } \ int foreach_twopass_##name( \ name* _list, int (*fun)(name##_node*, void*), void* args \ ) { \ return _foreach_twopass_##name(_list->head, fun, args); \ } #define CREATE_DELETE(name) \ int _delete_##name(name##_node* node, void* args) { \ free(node); \ return 0; \ } \ int delete_##name(name* _list) { \ return foreach_reverse_##name(_list, _delete_##name, NULL); \ } typedef struct save_args { FILE* file; char* format; } save_args; #define CREATE_SAVE(name) \ int __save_##name(name##_node* node, void* args) { \ if (fprintf( \ ((save_args*)args)->file, ((save_args*)args)->format, \ node->val \ ) < 0) \ return -2; \ return 0; \ } \ int _save_##name(name* _list, save_args args) { \ return foreach_##name(_list, __save_##name, (void*)&args); \ } \ int save_##name(name* _list, char* file, char* format) { \ save_args args = {.file = fopen(file, "a"), .format = format}; \ if (!args.file) return -1; \ return _save_##name(_list, args); \ } #define CREATE_PRINT(name) \ int print_##name(name* _list, char* format) { \ save_args args = {.format = format, .file = stdout}; \ return _save_##name(_list, args); \ } #define CREATE_LOAD(name, type) \ int load_##name(name* _list, char* format, char* filename, int amout) { \ FILE* file = fopen(filename, "r"); \ if (!file) return -1; \ type buf; \ for (; amout > 0; amout--) { \ if (fscanf(file, format, &buf) < 0) return -2; \ if (push_##name(_list, buf)) return -3; \ } \ return 0; \ } #define CREATE_REMOVE(name, type) \ struct _remove_args_##name { \ int (*eql)(type, type); \ type to_remove; \ }; \ int _remove_##name(name##_node* node, void* args) { \ name##_node* next = node->next; \ struct _remove_args_##name* args_typed = \ (struct _remove_args_##name*)args; \ if (!next) return -1; \ if (!args_typed->eql(next->val, *((type*)args))) return 0; \ name##_node* new_next = next->next; \ free(next); \ node->next = new_next; \ return 1; \ } \ int remove_##name(name* _list, type element, int (*eql)(type, type)) { \ if (!eql) return -2; \ struct _remove_args_##name args = {.eql = eql, .to_remove = element}; \ return foreach_##name(_list, _remove_##name, (void*)&args) != 1; \ }