#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <yafl_rnt.h>
#include "dbx_rnt.h"
#include "dbx_list.h"

void insert YPARAMS8(dbx_list *,  pl,
                    dbx_elem *,  pe1,
                    dbx_elem *,  pe2,
                    VOID *,  info)
{
  dbx_elem *pe;
  assertp(pl);
  pl->nbr = pl->nbr + 1;
  pe = (dbx_elem*)malloc(sizeof(dbx_elem));
  assertp(pe);
  pe->prev = pe1;
  pe->next = pe2;
  pe->info = info;
  if (pe1 != NULL)
  {
    pe1->next = pe;
  }
  else
  {
    pl->first = pe;
  }
  if (pe2 != NULL)
  {
    pe2->prev = pe;
  }
  else
  {
    pl->last = pe;
  }
  pl->current = pe;
}

VOID *suppress YPARAMS4(dbx_list *,  pl,
                       dbx_elem *,  pe)
{
  dbx_elem *pe1,*pe2;
  VOID *info;
  assertp(pl);
  assertp(pe);
  pe1 = pe->prev;
  pe2 = pe->next;
  info = pe->info;
  if (pe1 != NULL)
  {
    pe1->next = pe2;
  }
  else
  {
    pl->first = pe2;
  }
  if (pe2 != NULL)
  {
    pe2->prev = pe1;
  }
  else
  {
    pl->last = pe1;
  }
  pl->nbr = pl->nbr - 1;
  free(pe);
  if (pl->current == pe)
  {
    if (pe->next)
     pl->current = pe->next;
    else
      pl->current = pe->prev;
  }
  return info;
}


dbx_list *new_list YPARAMS0
{
  dbx_list *pl;
  pl = (dbx_list *)malloc(sizeof(dbx_list));
  assertp(pl);
  pl->first = NULL;
  pl->last = NULL;
  pl->nbr = 0;
  return pl;
}

/* the list must be empty before being destructed */
void dispose_list YPARAMS2(dbx_list *,  pl)
{
  assertp(pl);
  free(pl);
}


 

dbx_elem *nth_elem YPARAMS4(dbx_list *,  pl,
                           unsigned,    n)
{
  dbx_elem *pe;
  unsigned i;
  assertp(pl);
  assert(n >= 1);
  if (n <= pl->nbr)
  {  
    pe = pl->first;
    i = 1;
    while (i < n)
    {
      pe = pe->next;
      i++;
    }
    return pe;
  }
  else
    return NULL;
}

  
unsigned list_size YPARAMS2(dbx_list *,  pl)
{
  assertp(pl);
  return(pl->nbr);
}

/* replace by macros for more speed */

dbx_elem *first_elem YPARAMS2(dbx_list *,  pl)
{
  assertp(pl);
  return (pl->first);
}

dbx_elem *last_elem YPARAMS2(dbx_list *,  pl)
{
  assertp(pl);
  return (pl->last);
}

dbx_elem *current_elem YPARAMS2(dbx_list *,  pl)
{
  assertp(pl);
  return(pl->current);
}

dbx_elem *next_elem YPARAMS2(dbx_elem *,  pe)
{
  assertp(pe);
  return (pe->next);
}

dbx_elem *prev_elem YPARAMS2(dbx_elem *,  pe)
{
  assertp(pe);
  return (pe->prev);
}  

VOID *elem_info YPARAMS2(dbx_elem *,  pe)
{
  assertp(pe);
  return (pe->info);
}

void go_first YPARAMS2(dbx_list *,  pl)
{
  assertp(pl);
  pl->current = pl->first;
}

void go_last YPARAMS2(dbx_list *,  pl)
{
  assertp(pl);
  pl->current = pl->last;
}

void go_next YPARAMS2(dbx_list *,  pl)
{
  assertp(pl);
  pl->current = next_elem(pl->current);
}

void go_prev YPARAMS2(dbx_list *,  pl)
{
  assertp(pl);
  pl->current = prev_elem(pl->current);
}

void go_nth YPARAMS4(dbx_list *,  pl,
                    unsigned,    n)
{
  assertp(pl);
  pl->current = nth_elem(pl,n);                    
}
