/*
 * lib/list.h
 *
 * Copyright (C) 2013-2014, Samsung Electronics Co., Ltd.
 *
 * Linked list implementation
 */

#ifndef GP_API_CLIENT_LIST_H_
#define GP_API_CLIENT_LIST_H_

typedef struct list_head list_head;

struct list_head {
  list_head *next, *prev;
};

#ifdef NO_ASSERT
  #undef ASSERT
  #define ASSERT(...)
#endif

#ifndef ASSERT
#include <assert.h>
#define ASSERT(...) assert(__VA_ARGS__)
#endif

#ifndef likely
# define likely(x)   __builtin_expect(!!(x), 1)
#endif
#ifndef unlikely
# define unlikely(x) __builtin_expect(!!(x), 0)
#endif

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) struct list_head name = { &(name), &(name) }

#define INIT_LIST_HEAD(ptr) do { \
  (ptr)->prev = (ptr);           \
  (ptr)->next = (ptr);           \
} while (0)

#define IS_EMPTY(list_head) (list_head)->next == (list_head)

#define POS_OF(member, type) ((unsigned long) offsetof(type, member))

#define __list_add(__prev, __next, __new) \
  do {                                    \
    struct list_head *_new = (__new);     \
    struct list_head *_prev = (__prev);   \
    struct list_head *_next = (__next);   \
    _new->prev = _prev;                   \
    _prev->next = _new;                   \
    _next->prev = _new;                   \
    _new->next = _next;                   \
  } while (0)

#define __list_del( __next, __prev)     \
  do {                                  \
    struct list_head *_prev = (__prev); \
    struct list_head *_next = (__next); \
    _next->prev = _prev;                \
    _prev->next = _next;                \
  } while (0)

static inline void list_add(struct list_head *new, struct list_head *head)
{
  __list_add(head, head->next, new);
}

static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
  __list_add(head->prev, head, new);
}

/**
 * list_del - deletes entry from list.
 * @entry: the element to delete from the list.
 */
static inline void list_del(struct list_head *entry)
{
  ASSERT(entry->next->prev == entry);
  ASSERT(entry->prev->next == entry);
  __list_del(entry->next, entry->prev);
}

/**
 * list_del_init - deletes entry from list and reinitialize it.
 * @entry: the element to delete from the list.
 */
static inline void list_del_init(struct list_head *entry)
{
  __list_del(entry->next, entry->prev);
  INIT_LIST_HEAD(entry);
}

/**
 * list_empty - tests whether a list is empty
 * @head: the list to test.
 */
static inline unsigned int list_empty(struct list_head *head)
{
  return IS_EMPTY(head);
}

/**
 * list_splice - join two lists
 * @head: the place to add it in the first list.
 * @list: the new list to add.
 */
static inline int list_splice(struct list_head *head, struct list_head *list)
{
  struct list_head *first = list->next;
  if (unlikely(first == list))
    return -1;
  struct list_head *last = list->prev;
  struct list_head *at = head->next;
  first->prev = head;
  head->next = first;
  last->next = at;
  at->prev = last;
  return 0;
}

/**
 * list_splice_init - join two lists and reinitialize the added list
 * @head: the place to add it in the first list.
 * @list: the new list to add.
 */
static inline void list_splice_init(struct list_head *head, struct list_head *list)
{
  list_splice(head, list);
  INIT_LIST_HEAD(list);
}

#define list_entry(__ptr, __type, __member)       \
  ({                                              \
    unsigned long p = (unsigned long) __ptr;      \
    unsigned long off = POS_OF(__member, __type); \
    (__type *) (p - off);                         \
  })

#define list_first_entry(head, type, member) \
  list_entry((head)->next, type, member)

#define list_for_each(pos, head) \
  for (pos = ((head)->next);     \
      ((pos) != (head));         \
      pos = (pos)->next)

#define list_for_each_safe(__pos, __pos_n, __head)             \
  for (__pos = (__head)->next, __pos_n = (__head)->next->next; \
    (__pos) != (__head);                                       \
    __pos = __pos_n, __pos_n = __pos->next)

#define list_for_each_entry_upto(pos, head, member, upto)    \
  for (pos = list_entry((head)->next, typeof(*pos), member), \
      PREFETCH(pos->member.next);                            \
    &pos->member - (upto);                                   \
    pos = list_entry(pos->member.next,                       \
        typeof(*pos), member),                               \
      PREFETCH(pos->member.next))

#define list_for_each_entry(pos, head, member)      \
  list_for_each_entry_upto(pos, head, member, head)

/**
 * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
 * @pos:        the type * to use as a loop counter.
 * @n:          another type * to use as temporary storage
 * @head:       the head for your list.
 * @member:     the name of the list_struct within the struct.
 */
#define list_for_each_entry_safe(pos, n, head, member)               \
  for (pos = list_entry((head)->next, typeof(*pos), member),         \
    n = list_entry((&pos->member)->next, typeof(*pos), member);      \
    &pos->member - (head);                                           \
    pos = n, n = list_entry((&n->member)->next, typeof(*n), member))

#endif /* GP_API_CLIENT_LIST_H_ */
