#include <stdlib.h>
#include "list.h"

void *list_front(list *l) { return l->front; }
void *list_back(list *l) { return l->back; }
void *list_prev(void *n) { return ((lnode*)n)->prev; }
void *list_next(void *n) { return ((lnode*)n)->next; }

void list_push_front(list *l, void *n_)
{
	lnode *n = n_;
    n->prev = 0;

    if ((n->next = l->front) == 0)
        l->back = n;
    else
        l->front->prev = n;

    l->front = n;
    l->cnt++;
}

void list_push_back(list *l, void *n_)
{
	lnode *n = n_;
    n->next = 0;

    if ((n->prev = l->back) == 0)
        l->front = n;
    else
        l->back->next = n;

    l->back = n;
    l->cnt++;
}

void list_insert_after(list *l, void *o_, void *n_)
{
	lnode *o = o_;
	lnode *n = n_;
	n->prev = o;
	n->next = o->next;
	o->next = n;

	if (l->back == o)
		l->back = n;

    l->cnt++;
}

void *list_pop_front(list *l)
{
    if (!l->front)
        return 0;

    lnode *n = l->front;
    l->front = l->front->next;

    if (l->front)
        l->front->prev = 0;
    else
        l->back = 0;

    l->cnt--;
    return n;
}

void *list_pop_back(list *l)
{
    if (!l->back)
        return 0;

    lnode *n = l->back;
    l->back = l->back->prev;

    if (l->back)
        l->back->next = 0;
    else
        l->front = 0;

    l->cnt--;
    return n;
}

void *list_remove(list *l, void *n_)
{
	lnode *n = n_;

    if (l->front == n)
        l->front = n->next;
    else
        n->prev->next = n->next;

    if (l->back == n)
        l->back = n->prev;
    else
        n->next->prev = n->prev;

    l->cnt--;
    return n->next;
}
