#ifndef LIST_H_
#define LIST_H_

#include <stddef.h>
#include <stdio.h>
#include <linux/kernel.h>

#define container_of(ptr, type , member) ({ \
	const typeof(((type *)0)->member) *__mptr = (ptr) ; \
	(type *)((char *)__mptr - offsetof(type,member)) ;})

// from kernel list
typedef struct list_t list_t;

struct list_t {
    list_t             *next, *prev;
};

#define LIST_HEAD_INIT(name) {&(name), &(name)}
#define list_init(ptr) do {                \
        (ptr)->next = (ptr);                    \
        (ptr)->prev = (ptr);                    \
    } while (0)

static inline void __list_add(list_t *list,
                                   list_t *prev, list_t *next)
{
    next->prev = list;
    list->next = next;
    list->prev = prev;
    prev->next = list;
}
// list head to add it after
static inline void list_add_head(list_t *list, list_t *head)
{
    __list_add(list, head, head->next);
}
// list head to add it before
static inline void list_add_tail(list_t *list, list_t *head)
{
    __list_add(list, head->prev, head);
}
static inline void __list_del(list_t *prev, list_t *next)
{
    next->prev = prev;
    prev->next = next;
}
// deletes entry from list
static inline void list_del(list_t *entry)
{
    __list_del(entry->prev, entry->next);
    list_init(entry);
}
// tests whether a list is empty
static inline int list_empty(const list_t *head)
{
    return (head->next == head);
}
// move list to new_list
static inline void list_movelist(list_t *list, list_t *new_list)
{
    if (!list_empty(list)) {
        new_list->prev = list->prev;
        new_list->next = list->next;
        new_list->prev->next = new_list;
        new_list->next->prev = new_list;
        list_init(list);
    } else {
        list_init(new_list);
    }
}
// join list to head
static inline void list_join(list_t *list, list_t *head)
{
    if (!list_empty(list)) {
        list_t             *first = list->next;
        list_t             *last = list->prev;
        list_t             *at = head->prev;

        first->prev = at;
        at->next = first;
        last->next = head;
        head->prev = last;
    }
}

// get last
#define list_get_last(list, type, member)                              \
    list_empty(list) ? NULL : list_entry((list)->prev, type, member)

// get first
#define list_get_first(list, type, member)                             \
    list_empty(list) ? NULL : list_entry((list)->next, type, member)

#define list_entry(ptr, type, member) ({                               \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);                \
        (type *)( (char *)__mptr - offsetof(type,member) );})


#define list_for_each_entry(pos, head, member)                         \
    for (pos = list_entry((head)->next, typeof(*pos), member);         \
            &pos->member != (head);                                         \
            pos = list_entry(pos->member.next, typeof(*pos), member))

#define list_for_each_entry_reverse(pos, head, member)                 \
    for (pos = list_entry((head)->prev, typeof(*pos), member);     \
            &pos->member != (head);                                        \
            pos = list_entry(pos->member.prev, typeof(*pos), member))

#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))

#define list_for_each_entry_safe_reverse(pos, n, head, member)         \
    for (pos = list_entry((head)->prev, typeof(*pos), member),         \
            n = list_entry(pos->member.prev, typeof(*pos), member);    \
            &pos->member != (head);                                         \
            pos = n, n = list_entry(n->member.prev, typeof(*n), member))


#endif
