avs2bdnxml/abstract_lists.h
2013-07-23 12:04:20 +02:00

201 lines
5.9 KiB
C

/*----------------------------------------------------------------------------
* abstract_lists.h - Simple, typesafe, doubly linked lists for C
* Copyright (C) 2010 Arne Bochem <abstract.lists at ps-auxw de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*----------------------------------------------------------------------------*/
#ifndef ABSTRACT_LISTS_H
#define ABSTRACT_LISTS_H
#include <stdlib.h>
#define DECLARE_LIST_BACKEND(kind, prefix, type) \
typedef struct prefix##_list_s prefix##_list_t;\
typedef struct prefix##_list_node_s prefix##_list_node_t;\
struct prefix##_list_s\
{\
prefix##_list_node_t *current, *first, *last;\
};\
struct prefix##_list_node_s\
{\
type *v;\
prefix##_list_node_t *prev, *next;\
};\
kind prefix##_list_t *prefix##_list_new ();\
kind type *prefix##_list_get (prefix##_list_t *l) __attribute__ ((unused));\
kind type *prefix##_list_next (prefix##_list_t *l) __attribute__ ((unused));\
kind type *prefix##_list_prev (prefix##_list_t *l) __attribute__ ((unused));\
kind type *prefix##_list_first (prefix##_list_t *l) __attribute__ ((unused));\
kind type *prefix##_list_last (prefix##_list_t *l) __attribute__ ((unused));\
kind int prefix##_list_empty (prefix##_list_t *l) __attribute__ ((unused));\
kind void prefix##_list_set (prefix##_list_t *l, type *v) __attribute__ ((unused));\
kind void prefix##_list_insert (prefix##_list_t *l, type *v) __attribute__ ((unused));\
kind void prefix##_list_insert_after (prefix##_list_t *l, type *v) __attribute__ ((unused));\
kind void prefix##_list_delete (prefix##_list_t *l) __attribute__ ((unused));\
kind void prefix##_list_remove (prefix##_list_t *l, type *v) __attribute__ ((unused));\
kind void prefix##_list_destroy (prefix##_list_t *l) __attribute__ ((unused));\
kind void prefix##_list_destroy_deep (prefix##_list_t *l) __attribute__ ((unused));
#define IMPLEMENT_LIST_BACKEND(kind, prefix, type) \
kind prefix##_list_t *prefix##_list_new ()\
{\
prefix##_list_t *l = malloc(sizeof(prefix##_list_t));\
l->first = NULL;\
l->last = NULL;\
l->current = NULL;\
return l;\
}\
kind type *prefix##_list_get (prefix##_list_t *l)\
{\
if (l->current == NULL)\
return NULL;\
return l->current->v;\
}\
kind type *prefix##_list_next (prefix##_list_t *l)\
{\
if (l->current != NULL)\
l->current = l->current->next;\
if (l->current != NULL)\
return l->current->v;\
return NULL;\
}\
kind type *prefix##_list_prev (prefix##_list_t *l)\
{\
if (l->current != NULL)\
l->current = l->current->prev;\
if (l->current != NULL)\
return l->current->v;\
return NULL;\
}\
kind type *prefix##_list_first (prefix##_list_t *l)\
{\
l->current = l->first;\
if (l->current == NULL)\
return NULL;\
return l->current->v;\
}\
kind type *prefix##_list_last (prefix##_list_t *l)\
{\
l->current = l->last;\
if (l->current == NULL)\
return NULL;\
return l->current->v;\
}\
kind int prefix##_list_empty (prefix##_list_t *l)\
{\
return (l->first == NULL && l->last == NULL);\
}\
kind void prefix##_list_set (prefix##_list_t *l, type *v)\
{\
if (l->current != NULL)\
l->current->v = v;\
}\
kind void prefix##_list_insert (prefix##_list_t *l, type *v)\
{\
prefix##_list_node_t *new;\
new = calloc(1, sizeof(prefix##_list_node_t));\
new->v = v;\
new->next = l->current;\
new->prev = NULL;\
if (l->first == l->current)\
l->first = new;\
if (l->current != NULL)\
{\
new->prev = l->current->prev;\
if (l->current->prev != NULL)\
l->current->prev->next = new;\
l->current->prev = new;\
}\
l->current = new;\
if (l->last == NULL)\
l->last = new;\
}\
kind void prefix##_list_insert_after (prefix##_list_t *l, type *v)\
{\
prefix##_list_node_t *new;\
new = calloc(1, sizeof(prefix##_list_node_t));\
new->v = v;\
new->next = NULL;\
new->prev = l->current;\
if (l->last == l->current)\
l->last = new;\
if (l->current != NULL)\
{\
new->next = l->current->next;\
if (l->current->next != NULL)\
l->current->next->prev = new;\
l->current->next = new;\
}\
l->current = new;\
if (l->first == NULL)\
l->first = new;\
}\
kind void prefix##_list_delete (prefix##_list_t *l)\
{\
prefix##_list_node_t *node = l->current;\
if (node == NULL)\
return;\
if (node->prev != NULL)\
node->prev->next = node->next;\
if (node->next != NULL)\
node->next->prev = node->prev;\
l->current = node->next;\
if (l->first == node)\
l->first = node->next;\
if (l->last == node)\
l->last = node->prev;\
free(node);\
}\
kind void prefix##_list_remove (prefix##_list_t *l, type *v)\
{\
type *c = prefix##_list_first(l);\
do\
{\
if (c == v)\
{\
prefix##_list_delete(l);\
l->current = l->first;\
return;\
}\
c = prefix##_list_next(l);\
}\
while (c != NULL);\
}\
kind void prefix##_list_destroy (prefix##_list_t *l)\
{\
prefix##_list_first(l);\
while (!prefix##_list_empty(l))\
prefix##_list_delete(l);\
free(l);\
}\
kind void prefix##_list_destroy_deep (prefix##_list_t *l)\
{\
prefix##_list_first(l);\
while (!prefix##_list_empty(l))\
{\
free(l->current->v);\
prefix##_list_delete(l);\
}\
free(l);\
}
#define DECLARE_LIST(prefix, type) DECLARE_LIST_BACKEND(;, prefix, type)
#define IMPLEMENT_LIST(prefix, type) IMPLEMENT_LIST_BACKEND(;, prefix, type)
#define DECLARE_STATIC_LIST(prefix, type) DECLARE_LIST_BACKEND(static, prefix, type)
#define IMPLEMENT_STATIC_LIST(prefix, type) IMPLEMENT_LIST_BACKEND(static, prefix, type)
#define STATIC_LIST(prefix, type) DECLARE_STATIC_LIST(prefix, type) IMPLEMENT_STATIC_LIST(prefix, type)
#endif