#ifndef _TT_LISTS_H_ /****************************************************************************************/
#define _TT_LISTS_H_

/****************************************************************************************************************/

#ifdef ASSEMBLER

/* Minimal list header */
#define LH_NEXT		0			/* 4	Next item in list					*/
#define LH_PREV		4			/* 4	Previous item in list					*/
#define LH_SIZEOF	8

/* List header with priority field */
#define LH_PRI		8			/* 2	Priority field						*/
#define LH_SIZEOF_PRI	10

#endif

/****************************************************************************************************************/

#ifndef ASSEMBLER

#include <sys/cdefs.h>
#include <stddef.h>

#define LIST_CAST(type, ptr, field) ((type *)(void *)((unsigned char *)(ptr) - offsetof(type, field)))

typedef struct list_head {
  struct list_head *lh_next;
  struct list_head *lh_prev;
} list_head;

typedef struct list_head_pri {
  struct list_head *lh_next;
  struct list_head *lh_prev;
  int lh_pri;
} list_head_pri;

/****************************************************************************************************************/

// Init list head
static inline struct list_head *list_init(struct list_head *head) __attribute__((always_inline));

static inline struct list_head *list_init(struct list_head *head) {
  head->lh_next = head;
  head->lh_prev = head;
  return head;
}

/****************************************************************************************************************/

// Insert item after another
static inline struct list_head *list_insert_after(struct list_head *prev,
						  struct list_head *item) __attribute__((always_inline));

static inline struct list_head *list_insert_after(struct list_head *prev, struct list_head *item) {
  item->lh_prev = prev;
  struct list_head *tmp = prev->lh_next;
  item->lh_next = tmp;
  tmp->lh_prev = item;
  prev->lh_next = item;
  return prev;
}

// Put item at top of list
static inline struct list_head *list_prepend(struct list_head *head,
					     struct list_head *item) __attribute__((always_inline));

static inline struct list_head *list_prepend(struct list_head *head, struct list_head *item) {
  return list_insert_after(head, item);
}

/****************************************************************************************************************/

// Insert item before another
static inline struct list_head *list_insert_before(struct list_head *next,
						   struct list_head *item) __attribute__((always_inline));

static inline struct list_head *list_insert_before(struct list_head *next, struct list_head *item) {
  item->lh_next = next;
  struct list_head *tmp = next->lh_prev;
  item->lh_prev = tmp;
  tmp->lh_next = item;
  next->lh_prev = item;
  return next;
}

// Put item at end of list
static inline struct list_head *list_append(struct list_head *next,
					    struct list_head *item) __attribute__((always_inline));

static inline struct list_head *list_append(struct list_head *head, struct list_head *item) {
  return list_insert_before(head, item);
}

/****************************************************************************************************************/

// Remove item from list
static inline struct list_head *list_remove(struct list_head *item) __attribute__((always_inline));

static inline struct list_head *list_remove(struct list_head *item) {

  struct list_head *next = item->lh_next;
  if (!next) return item;

  struct list_head *prev = item->lh_prev;

  next->lh_prev = prev;
  prev->lh_next = next;

  item->lh_next = 0;
  item->lh_prev = 0;

  return item;
}

/****************************************************************************************************************/

// Returns true if list is empty
static inline int list_is_empty(struct list_head *head) {
  return head->lh_next == head->lh_prev;
}

/****************************************************************************************************************/

__BEGIN_DECLS

// Returns number of items in list (slow!)
unsigned int list_count(struct list_head *head);

// Enqueue item according to it's priority
void list_enqueue(struct list_head *next, struct list_head_pri *item);

__END_DECLS

#endif

/****************************************************************************************************************/
#endif
