
/**
 * Copyright (c) 2016 Tino Reichardt
 * - removed unneeded stuff
 * - added win32 compatibility
 *
 * Copyright (c) 2013 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Taylor R. Campbell.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
 */

#ifndef LIST_H
#define LIST_H

#if defined (__cplusplus)
extern "C" {
#endif

#include "memmt.h"

struct list_head {
	struct list_head *prev;
	struct list_head *next;
};

MEM_STATIC void INIT_LIST_HEAD(struct list_head *head)
{
	head->prev = head;
	head->next = head;
}

MEM_STATIC struct list_head *list_first(const struct list_head *head)
{
	return head->next;
}

MEM_STATIC struct list_head *list_last(const struct list_head *head)
{
	return head->prev;
}

MEM_STATIC struct list_head *list_next(const struct list_head *node)
{
	return node->next;
}

MEM_STATIC struct list_head *list_prev(const struct list_head *node)
{
	return node->prev;
}

MEM_STATIC void __list_add_between(struct list_head *prev,
	struct list_head *node, struct list_head *next)
{
	prev->next = node;
	node->prev = prev;
	node->next = next;
	next->prev = node;
}

MEM_STATIC void list_add(struct list_head *node, struct list_head *head)
{
	__list_add_between(head, node, head->next);
}

MEM_STATIC void list_add_tail(struct list_head *node, struct list_head *head)
{
	__list_add_between(head->prev, node, head);
}

MEM_STATIC void list_del(struct list_head *entry)
{
	entry->prev->next = entry->next;
	entry->next->prev = entry->prev;
}

MEM_STATIC int list_empty(const struct list_head *head)
{
	return (head->next == head);
}

MEM_STATIC void list_move(struct list_head *node, struct list_head *head)
{
	list_del(node);
	list_add(node, head);
}

MEM_STATIC void list_move_tail(struct list_head *node, struct list_head *head)
{
	list_del(node);
	list_add_tail(node, head);
}

#ifndef CONTAINING_RECORD
#define CONTAINING_RECORD(ptr, type, field) \
	((type*)((char*)(ptr) - (char*)(&((type*)0)->field)))
#endif

#define list_entry(ptr, type, member)	CONTAINING_RECORD(ptr, type, member)
#define	list_for_each(var, head) \
	for ((var) = list_first((head)); (var) != (head); (var) = list_next((var)))

#if defined (__cplusplus)
}
#endif

#endif				/* LIST_H */
