#ifndef LIBREV__LIST_H
#define LIBREV__LIST_H

/*
 * Copyright (c) 2003  Petr Baudis.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials
 *     provided with the distribution.
 *   * Neither the name of the author nor the names of the product's
 *     contributors may be used to endorse or promote products
 *     derived from this software without specific prior written
 *     permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifdef __cplusplus
extern "C" {
#endif


#include <librev/librev.h>



/* Structures */

/* This is {struct rev_list_item}. It is an ordinary list item, pointing at
 * its neighbors and listee structure start. The listee must not equal the
 * {struct rev_list_item} instance address. */
struct rev_list_item {
	struct id_ *prev;
	struct id_ *next;
	void *listee;
};

/* This is {struct rev_list_head}. It is a meta-item starting and ending the
 * list.  If the list as a whole is to be referenced, the head has to be
 * referenced.  You can't do any operation on the list as a whole without
 * knowing the head. */
/* So far it just mirrors list_item, but you must not rely on that. */
struct rev_list_head {
	struct rev_list_item item;
};


/* Tools */

/* This {rev_list_init} initializes {struct rev_list_head}. */
#define rev_list_init(head_) \
	do { \
		head_.item.prev = &(head_.item); \
		head_.item.next = &(head_.item); \
		head_.item.listee = &head_; \
	} while (0);

/* This is a generic add backend, linking the neighbours to the given item
 * and initializing the listee. You do not want to use this. */
#define rev_list_link(listee_,litem_) \
	do { \
		listee_.litem_.next->prev = (&listee_.litem_); \
		listee_.litem_.prev->next = (&listee_.litem_); \
		listee_.litem_.listee = &listee_; \
	} while (0);

/* This {rev_list_add} adds {struct rev_list_item} at the end of the given
 * list. It is equivalent to {rev_list_add_before(head.item)}. */
#define rev_list_add(head_,listee_,litem_) \
	do { \
		listee_.litem_.next = &(head_.item); \
		listee_.litem_.prev = head_.item.prev; \
		rev_list_link (listee_, litem_); \
	} while (0);

/* This {rev_list_add_after} adds {struct rev_list_item} after the given
 * item. */
#define rev_list_add_after(item_,listee_,litem_) \
	do { \
		listee_.litem_.next = item_.next; \
		listee_.litem_.prev = &item_; \
		rev_list_link (listee_, litem_); \
	} while (0);

/* This {rev_list_add_before} adds {struct rev_list_item} in front of the
 * given item. */
#define rev_list_add_before(item_,listee_,litem_) \
	do { \
		listee_.litem_.next = &item_; \
		listee_.litem_.prev = item_.prev; \
		rev_list_link (listee_, litem_); \
	} while (0);

/* This {rev_list_delete} removes an item from the list. Note that result of
 * an attempt to remove a head item is undefined. */
#define rev_list_delete(listee_,litem_) \
	do { \
		listee_.litem_.next->prev = listee_.litem_.prev; \
		listee_.litem_.prev->next = listee_.litem_.next; \
		/* Prevent misusal. Better segfault than do *too* weird
		 * things. */ \
		listee_.litem_.next = NULL; \
		listee_.litem_.prev = NULL; \
	} while (0);

/* This is a generic foreach backend, containing the direction-independent
 * code. You do not want to use this directly. And you do not want to look
 * at it, it is a ##hell##. */
#define rev_list_foreach_do(cur_,dir_,head_,current_) \
	{ \
	struct rev_list_item *current_##__##cur_ = head_.item.dir_; \
	struct rev_list_item *current_##__##dir_ = \
		current_##__##cur_->dir_; \
	for (current_ = current_##__##cur_->listee; \
		(void *) current_##__##cur_ != (void *) &((head_).item); \
		current_##__##cur_ = current_##__##dir_, \
		current_##__##dir_ = current_##__##cur_->dir_, \
		current_ = current_##__##cur_->listee)

/* This {rev_list_foreach} allows iteration through the whole list in the
 * first->last direction. You use it in the style (ptr has to be pre-declared):
 *
 * rev_list_foreach (list, ptr) { ... } rev_list_foreach_end;
 *
 * Note that you must not have inherited foreaches of same ptr. */
#define rev_list_foreach(head_,current_) \
	rev_list_foreach_do (cur, next, head_, current_)

#define rev_list_foreach_end \
	}

/* This {rev_list_foreachback} allows iteration through the whole list in the
 * last->first direction. The usage and rules are same as of
 * {rev_list_foreach}. */
#define rev_list_foreachback(head_,current_) \
	rev_list_foreach_do (pcur, prev, head_, current_)

#define rev_list_foreachback_end \
	}

/* This {rev_list_first} expands in the first item of the list. */
#define rev_list_first(head_) \
	(head_.item.next->listee)

/* This {rev_list_last} expands in the last item of the list. */
#define rev_list_last(head_) \
	(head_.item.prev->listee)

/* This {rev_list_empty} expands in the condition of the list emptiness. */
#define rev_list_empty(head_) \
	((void *) head_.item.prev == (void *) head_.item.next)


	
#ifdef __cplusplus
}
#endif

#endif
