michael@0: /* $NetBSD: list.h,v 1.2 2004/05/20 19:51:55 christos Exp $ */ michael@0: michael@0: /* michael@0: * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") michael@0: * Copyright (c) 1997,1999 by Internet Software Consortium. michael@0: * michael@0: * Permission to use, copy, modify, and distribute this software for any michael@0: * purpose with or without fee is hereby granted, provided that the above michael@0: * copyright notice and this permission notice appear in all copies. michael@0: * michael@0: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES michael@0: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF michael@0: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR michael@0: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES michael@0: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN michael@0: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT michael@0: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. michael@0: */ michael@0: michael@0: /* michael@0: * This version of this file is derived from Android 2.3 "Gingerbread", michael@0: * which contains uncredited changes by Android/Google developers. It has michael@0: * been modified in 2011 for use in the Android build of Mozilla Firefox by michael@0: * Mozilla contributors (including Michael Edwards , michael@0: * and Steve Workman ). michael@0: * These changes are offered under the same license as the original NetBSD michael@0: * file, whose copyright and license are unchanged above. michael@0: */ michael@0: michael@0: #ifndef LIST_H michael@0: #define LIST_H 1 michael@0: #include "assertions.h" michael@0: michael@0: #define LIST(type) struct { type *head, *tail; } michael@0: #define INIT_LIST(list) \ michael@0: do { (list).head = NULL; (list).tail = NULL; } while (/*CONSTCOND*/0) michael@0: michael@0: #define LINK(type) struct { type *prev, *next; } michael@0: #define INIT_LINK_TYPE(elt, link, type) \ michael@0: do { \ michael@0: (elt)->link.prev = (type *)(-1); \ michael@0: (elt)->link.next = (type *)(-1); \ michael@0: } while (/*CONSTCOND*/0) michael@0: #define INIT_LINK(elt, link) \ michael@0: INIT_LINK_TYPE(elt, link, void) michael@0: #define LINKED(elt, link) ((void *)((elt)->link.prev) != (void *)(-1)) michael@0: michael@0: #define HEAD(list) ((list).head) michael@0: #define TAIL(list) ((list).tail) michael@0: #define EMPTY(list) ((list).head == NULL) michael@0: michael@0: #define PREPEND(list, elt, link) \ michael@0: do { \ michael@0: INSIST(!LINKED(elt, link));\ michael@0: if ((list).head != NULL) \ michael@0: (list).head->link.prev = (elt); \ michael@0: else \ michael@0: (list).tail = (elt); \ michael@0: (elt)->link.prev = NULL; \ michael@0: (elt)->link.next = (list).head; \ michael@0: (list).head = (elt); \ michael@0: } while (/*CONSTCOND*/0) michael@0: michael@0: #define APPEND(list, elt, link) \ michael@0: do { \ michael@0: INSIST(!LINKED(elt, link));\ michael@0: if ((list).tail != NULL) \ michael@0: (list).tail->link.next = (elt); \ michael@0: else \ michael@0: (list).head = (elt); \ michael@0: (elt)->link.prev = (list).tail; \ michael@0: (elt)->link.next = NULL; \ michael@0: (list).tail = (elt); \ michael@0: } while (/*CONSTCOND*/0) michael@0: michael@0: #define UNLINK_TYPE(list, elt, link, type) \ michael@0: do { \ michael@0: INSIST(LINKED(elt, link));\ michael@0: if ((elt)->link.next != NULL) \ michael@0: (elt)->link.next->link.prev = (elt)->link.prev; \ michael@0: else \ michael@0: (list).tail = (elt)->link.prev; \ michael@0: if ((elt)->link.prev != NULL) \ michael@0: (elt)->link.prev->link.next = (elt)->link.next; \ michael@0: else \ michael@0: (list).head = (elt)->link.next; \ michael@0: INIT_LINK_TYPE(elt, link, type); \ michael@0: } while (/*CONSTCOND*/0) michael@0: #define UNLINK(list, elt, link) \ michael@0: UNLINK_TYPE(list, elt, link, void) michael@0: michael@0: #define PREV(elt, link) ((elt)->link.prev) michael@0: #define NEXT(elt, link) ((elt)->link.next) michael@0: michael@0: #define INSERT_BEFORE(list, before, elt, link) \ michael@0: do { \ michael@0: INSIST(!LINKED(elt, link));\ michael@0: if ((before)->link.prev == NULL) \ michael@0: PREPEND(list, elt, link); \ michael@0: else { \ michael@0: (elt)->link.prev = (before)->link.prev; \ michael@0: (before)->link.prev = (elt); \ michael@0: (elt)->link.prev->link.next = (elt); \ michael@0: (elt)->link.next = (before); \ michael@0: } \ michael@0: } while (/*CONSTCOND*/0) michael@0: michael@0: #define INSERT_AFTER(list, after, elt, link) \ michael@0: do { \ michael@0: INSIST(!LINKED(elt, link));\ michael@0: if ((after)->link.next == NULL) \ michael@0: APPEND(list, elt, link); \ michael@0: else { \ michael@0: (elt)->link.next = (after)->link.next; \ michael@0: (after)->link.next = (elt); \ michael@0: (elt)->link.next->link.prev = (elt); \ michael@0: (elt)->link.prev = (after); \ michael@0: } \ michael@0: } while (/*CONSTCOND*/0) michael@0: michael@0: #define ENQUEUE(list, elt, link) APPEND(list, elt, link) michael@0: #define DEQUEUE(list, elt, link) UNLINK(list, elt, link) michael@0: michael@0: #endif /* LIST_H */