/* This file is part of GNU cflow Copyright (C) 1997, 2005-2007, 2009-2010, 2014-2016 Sergey Poznyakoff GNU cflow 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. GNU cflow 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 . */ #include static struct linked_list * deref_linked_list(struct linked_list **plist) { if (!*plist) { struct linked_list *list = xmalloc(sizeof(*list)); list->free_data = NULL; list->head = list->tail = NULL; *plist = list; } return *plist; } struct linked_list * linked_list_create(linked_list_free_data_fp fun) { struct linked_list *list = xmalloc(sizeof(*list)); list->free_data = fun; list->head = list->tail = NULL; return list; } void linked_list_append(struct linked_list **plist, void *data) { struct linked_list *list = deref_linked_list (plist); struct linked_list_entry *entry = xmalloc(sizeof(*entry)); entry->list = list; entry->data = data; entry->next = NULL; entry->prev = list->tail; if (list->tail) list->tail->next = entry; else list->head = entry; list->tail = entry; } #if 0 void linked_list_prepend(struct linked_list **plist, void *data) { struct linked_list *list = deref_linked_list (plist); struct linked_list_entry *entry = xmalloc(sizeof(*entry)); entry->list = list; entry->data = data; if (list->head) list->head->prev = entry; entry->next = list->head; entry->prev = NULL; list->head = entry; if (!list->tail) list->tail = entry; } #endif void linked_list_destroy(struct linked_list **plist) { if (plist && *plist) { struct linked_list *list = *plist; struct linked_list_entry *p; for (p = list->head; p; ) { struct linked_list_entry *next = p->next; if (list->free_data) list->free_data(p->data); free(p); p = next; } free(list); *plist = NULL; } } void linked_list_unlink(struct linked_list *list, struct linked_list_entry *ent) { struct linked_list_entry *p; if ((p = ent->prev)) p->next = ent->next; else list->head = ent->next; if ((p = ent->next)) p->prev = ent->prev; else list->tail = ent->prev; if (list->free_data) list->free_data(ent->data); free(ent); } void linked_list_iterate(struct linked_list **plist, int (*itr) (void *, void *), void *data) { struct linked_list *list; struct linked_list_entry *p; if (!*plist) return; list = *plist; for (p = linked_list_head(list); p; ) { struct linked_list_entry *next = p->next; if (itr(p->data, data)) linked_list_unlink(list, p); p = next; } if (!list->head) linked_list_destroy(&list); *plist = list; } int data_in_list(void *data, struct linked_list *list) { struct linked_list_entry *p; for (p = linked_list_head(list); p; p = p->next) if (p->data == data) return 1; return 0; } size_t linked_list_size(struct linked_list *list) { size_t size = 0; if (list) { struct linked_list_entry *p; for (p = linked_list_head(list); p; p = p->next) size++; } return size; }