/* llist.c - Linked list functions
 *
 * Linked list structures have a next pointer as their first element.
 */

#include "toys.h"

// Callback function to free data pointer of double_list or arg_list

void llist_free_arg(void *node)
{
  struct arg_list *d = node;

  free(d->arg);
  free(d);
}

void llist_free_double(void *node)
{
  struct double_list *d = node;

  free(d->data);
  free(d);
}

// Call a function (such as free()) on each element of a linked list.
void llist_traverse(void *list, void (*using)(void *node))
{
  void *old = list;

  while (list) {
    void *pop = llist_pop(&list);
    using(pop);

    // End doubly linked list too.
    if (old == list) break;
  }
}

// Return the first item from the list, advancing the list (which must be called
// as &list)
void *llist_pop(void *list)
{
  // I'd use a void ** for the argument, and even accept the typecast in all
  // callers as documentation you need the &, except the stupid compiler
  // would then scream about type-punned pointers.  Screw it.
  void **llist = (void **)list;
  void **next = (void **)*llist;
  *llist = *next;

  return (void *)next;
}

// Remove first item from &list and return it
void *dlist_pop(void *list)
{
  struct double_list **pdlist = (struct double_list **)list, *dlist = *pdlist;

  if (!dlist) return 0;
  if (dlist->next == dlist) *pdlist = 0;
  else {
    if (dlist->next) dlist->next->prev = dlist->prev;
    if (dlist->prev) dlist->prev->next = dlist->next;
    *pdlist = dlist->next;
  }

  return dlist;
}

// remove last item from &list and return it (stack pop)
void *dlist_lpop(void *list)
{
  struct double_list *dl = *(struct double_list **)list;
  void *v = 0;

  if (dl) {
    dl = dl->prev;
    v = dlist_pop(&dl);
    if (!dl) *(void **)list = 0;
  }

  return v;
}

void dlist_add_nomalloc(struct double_list **list, struct double_list *new)
{
  if (*list) {
    new->next = *list;
    new->prev = (*list)->prev;
    (*list)->prev->next = new;
    (*list)->prev = new;
  } else *list = new->next = new->prev = new;
}


// Add an entry to the end of a doubly linked list
struct double_list *dlist_add(struct double_list **list, char *data)
{
  struct double_list *new = xmalloc(sizeof(struct double_list));

  new->data = data;
  dlist_add_nomalloc(list, new);

  return new;
}

// Terminate circular list for traversal in either direction. Returns end *.
void *dlist_terminate(void *list)
{
  struct double_list *end = list;

  if (!end || !end->prev) return 0;

  end = end->prev;
  end->next->prev = 0;
  end->next = 0;

  return end;
}

// Find num in cache
struct num_cache *get_num_cache(struct num_cache *cache, long long num)
{
  while (cache) {
    if (num==cache->num) return cache;
    cache = cache->next;
  }

  return 0;
}

// Uniquely add num+data to cache. Updates *cache, returns pointer to existing
// entry if it was already there.
struct num_cache *add_num_cache(struct num_cache **cache, long long num,
  void *data, int len)
{
  struct num_cache *old = get_num_cache(*cache, num);

  if (old) return old;

  old = xzalloc(sizeof(struct num_cache)+len);
  old->next = *cache;
  old->num = num;
  memcpy(old->data, data, len);
  *cache = old;

  return 0;
}
