/* OpenIDA - Outil d'analyse de fichiers binaires * dllist.h - prototypes de l'implantation simple des listes doublement chaînées * * Copyright (C) 2008 Cyrille Bagard * * This file is part of OpenIDA. * * OpenIDA 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. * * OpenIDA 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 Foobar. If not, see . */ #ifndef _DLLIST_H #define _DLLIST_H #define NULL ((void *)0) /* Structure à inclure en tête de structure */ typedef struct _dl_list_item { struct _dl_list_item *prev; /* Elément précédent */ struct _dl_list_item *next; /* Elément suivant */ } dl_list_item; typedef dl_list_item *dl_list_head; #define DL_LIST_ITEM dl_list_item dummy #define DLL_CAST(item) ((dl_list_item *)item) #define DL_LIST_HEAD_INIT(head) \ *(head) = NULL #define DL_LIST_ITEM_INIT(item) \ do \ { \ DLL_CAST(item)->prev = NULL; \ DLL_CAST(item)->next = NULL; \ \ } while(0) #define DL_LIST_NEXT(item, type) (type)DLL_CAST(item)->next #define DL_LIST_PREV(item, type) (type)DLL_CAST(item)->prev #define DL_LIST_IS_ALONE(head) (DLL_CAST(head)->next == DLL_CAST(head)) /* Ajoute un élément dans une liste doublement chaînée. */ void __dl_list_add(dl_list_item *, dl_list_head *, dl_list_item *, dl_list_item *); /* Supprime un élément d'une liste doublement chaînée. */ void __dl_list_del(dl_list_item *, dl_list_item *); /* Intervertit deux éléments dans une liste doublement chaînée. */ void swap_dl_list_items(dl_list_head *, dl_list_item *, dl_list_item *); /* Compte le nombre d'éléments présents dans une liste. */ unsigned int count_dl_list_items(dl_list_head); #define dl_list_empty(head) \ ((head) == NULL) #define dl_list_last(head, type) \ (dl_list_empty(head) ? NULL : (type)((head)->prev == NULL ? (head) : (head)->prev)) #define dl_list_add(new, head) \ __dl_list_add(DLL_CAST(new), (head), (dl_list_empty(*(head)) ? DLL_CAST(new) : dl_list_last(*head, dl_list_item *)), (dl_list_empty(*(head)) ? DLL_CAST(new) : *(head))) #define dl_list_add_tail(new, head) \ __dl_list_add(DLL_CAST(new), (head), (dl_list_empty(*(head)) ? DLL_CAST(new) : (*(head))->prev), (dl_list_empty(*(head)) ? DLL_CAST(new) : *(head))) #define dl_list_del(item, head) \ do \ { \ __dl_list_del(DLL_CAST(item)->prev, DLL_CAST(item)->next); \ if (*head == DLL_CAST(item)) *head = DLL_CAST(item)->next; \ if (*head == DLL_CAST(item)) *head = NULL; \ DLL_CAST(item)->next = NULL; \ DLL_CAST(item)->prev = NULL; \ \ } while(0) #define dl_list_move_tail(item, head) \ do \ { \ dl_list_del(item, head); \ dl_list_add_tail(item, head); \ \ } while(0) #define dl_list_for_each(pos, head, type) \ for (pos = (type)(head); \ pos != NULL; \ pos = (type)(DLL_CAST(pos)->next == (head) ? NULL : DLL_CAST(pos)->next)) #define dl_list_for_each_safe(pos, head, tmp, type) \ for (pos = (type)*(head), \ tmp = (type)(pos != NULL && DLL_CAST(pos)->next != *(head) ?\ DLL_CAST(pos)->next : NULL); \ pos != NULL; \ pos = tmp, \ tmp = (type)(pos != NULL && DLL_CAST(pos)->next != *(head) ?\ DLL_CAST(pos)->next : NULL)) #define dl_list_for_each_prev(pos, head, type) \ for (pos = dl_list_last(head, type); \ pos != NULL; \ pos = (type)(DLL_CAST(pos) == (head) ? NULL : DLL_CAST(pos)->prev)) #endif /* _DLLIST_H */