/* DLIFE Copyright (C) 2000 Richard W.M. Jones * and other authors listed in the ``AUTHORS'' file. * * 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 2 * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * $Id: dlink.h,v 1.1 2002/04/05 14:40:26 rich Exp $ */ #ifndef dlink_h #define dlink_h /* This was snarfed from the source for Python 1.5. */ #ifdef HAVE_STDDEF_H #include #endif #ifndef offsetof #define offsetof(type, member) ( (int) & ((type*)0) -> member ) #endif typedef struct dlink_list_element { void *next; void *prev; } dlink_list_element_t; typedef struct dlink_list { void *first; void *last; int offset; } dlink_list_t; #define DLINK_LIST_INIT(offset) { 0, 0, (offset) } #define _DLINK_ELEMENT_PTRS(element,list) ((dlink_list_element_t *) ((element) + (list)->offset)) #define _DLINK_FIRST_PTRS(list) _DLINK_ELEMENT_PTRS((list)->first,(list)) #define _DLINK_LAST_PTRS(list) _DLINK_ELEMENT_PTRS((list)->last,(list)) extern inline void dlink_list_init (dlink_list_t *list, int offset) { list->first = list->last = 0; list->offset = offset; } extern inline void insert_before_first (void *element, dlink_list_t *list) { dlink_list_element_t *eptrs = _DLINK_ELEMENT_PTRS (element, list); eptrs->prev = 0; eptrs->next = list->first; if (list->first) _DLINK_FIRST_PTRS(list)->prev = element; else list->last = element; list->first = element; } extern inline void insert_before_last (void *element, dlink_list_t *list) { dlink_list_element_t *eptrs = _DLINK_ELEMENT_PTRS (element, list); eptrs->next = 0; eptrs->prev = list->last; if (list->last) _DLINK_LAST_PTRS(list)->next = element; else list->first = element; list->last = element; } extern inline void move_towards_last (void *e, dlink_list_t *list) { dlink_list_element_t *eptrs = _DLINK_ELEMENT_PTRS (e, list); void *e0 = eptrs->prev; dlink_list_element_t *e0ptrs = _DLINK_ELEMENT_PTRS (e0, list); void *e1 = eptrs->next; dlink_list_element_t *e1ptrs = _DLINK_ELEMENT_PTRS (e1, list); void *e2 = e1ptrs->next; dlink_list_element_t *e2ptrs = _DLINK_ELEMENT_PTRS (e2, list); /* The elements are: e0 <---> e <---> e1 <---> e2. * * We know that e and e1 exist, but e0 and e2 may or may not exist. * * We want the arrangement to be: * e0 <---> e1 <---> e <---> e2. */ e1ptrs->prev = e0; if (e0) e0ptrs->next = e1; else list->first = e1; e1ptrs->next = e; eptrs->prev = e1; eptrs->next = e2; if (e2) e2ptrs->prev = e; else list->last = e; } extern inline void remove_element (void *element, dlink_list_t *list) { dlink_list_element_t *eptrs = _DLINK_ELEMENT_PTRS (element, list); void *eprev = eptrs->prev; dlink_list_element_t *eprevptrs = _DLINK_ELEMENT_PTRS (eprev, list); void *enext = eptrs->next; dlink_list_element_t *enextptrs = _DLINK_ELEMENT_PTRS (enext, list); if (eptrs->next) enextptrs->prev = eprev; else list->last = eprev; if (eptrs->prev) eprevptrs->next = enext; else list->first = enext; } #endif /* dlink_h */