/* usb/slist.h
 *
 * (c) 2002 Simtec Electronics
 *
 * Ben Dooks
 *
 * simple singly linked list code
 *
 * $Id: slist.h,v 1.5 2003/08/06 15:56:11 ben Exp $
 *
 * This Library file is part of the Simtec Electronics USB stack development
 *   suite.
 * Specific licence is granted to use this file by third parties for the
 *   development of USB device drivers.
 *
*/

#ifndef __USB_SLIST_H
#define __USB_SLIST_H "$Id: slist.h,v 1.5 2003/08/06 15:56:11 ben Exp $"

struct slist_item;

/** slist head structure
 * @memo head structure for slist
*/

struct slist_head {
  struct slist_item   *items;
};


/** slist item structure (to put in each item in the list)
 * @memo slist item structure
*/
struct slist_item {
  struct slist_item   *next;
  void		      *data;
};

typedef struct slist_head slist_head_t;
typedef struct slist_item slist_item_t;

#define SLIST_INIT_HEAD { NULL }

/** initialise the head structure for an slist
 * @memo initialise the head structure for an slist
 * @see slist_head
*/

#define slist_inithead(_sl) do { (_sl)->items = NULL; } while(0)

/** initialise an slist item structure
 * @memo initialise an slist item structure
 * @see slist_item
*/

#define slist_init(_entry,_item) do { (_entry)->data = (_item); } while(0)

/** add an item to the front of an slist
 * @memo add an item to the front of an slist
*/

#define slist_add_front(_sl,_entry) \
  do { (_entry)->next = (_sl)->items; (_sl)->items = (_entry); } while(0)

/** Return the first item's data from the front of a list
*/

#define slist_get_front(_sl) (((_sl)->items == NULL) ? NULL : (_sl)->items->data)

/** Is an slist empty
*/

#define slist_empty(_sl) ((_sl)->items == NULL)

/** slist enumeration function.
 *
 * @param _sl the slist head
 * @param _to the variable to take each item
 * @param _entry the entry field name within the item
 * @param _type type to cast _to to
 * @see slist_head
 * @see slist_item
*/
#define slist_foreach(_sl,_to,_entry,_type) \
  for ((_to) = ((_sl)->items != NULL) ? (_type)((_sl)->items->data) : NULL; \
       (_to) != NULL; \
       (_to) = (_type)((_to)->_entry.next == NULL ? NULL : ((_to)->_entry.next->data)))

/** remove item from an slist
 * @param head head of list
 * @param item item to remove
 * @see slist_item
 * @see slist_head
 */
extern int slist_remove(slist_head_t *head, slist_item_t *item);

extern void slist_add_end(slist_head_t *head, slist_item_t *item);

#endif








