/******************************************************************************
* $Id: list.c,v 1.1.1.1 2004/04/03 14:01:27 gareuselesinge Exp $
* This file is part of liberopops (http://liberopops.sf.net) *
* This file is distributed under the terms of GNU GPL license. *
******************************************************************************/
/******************************************************************************
* File description:
*
* Notes:
*
* Authors:
* Alessio Caprari <alessio.caprari@tiscali.it>
* Nicola Cocchiaro <ncocchiaro@users.sourceforge.net>
* Enrico Tassi <gareuselesinge@users.sourceforge.net>
******************************************************************************/
#include "list.h"
#include "win32_compatibility.h"
#define HIDDEN static
#define MALLOC_CHECK(a) {if((a)==NULL){fprintf(stderr,"%s %d: malloc failed\n",__FILE__,__LINE__);abort();}}
/***********************************************************************
* adds an element to the end
*/
list_t* list_add(list_t* l,void *data)
{
if( l == NULL )
{
list_t* tmp;
tmp = (list_t*) malloc(sizeof(list_t));
MALLOC_CHECK(tmp);
tmp->next = NULL;
tmp->data = data;
return(tmp);
}
else
{
l->next = list_add(l->next,data);
return(l);
}
}
/***********************************************************************
* adds an element to the end
*/
list_t* list_add_fast (list_t* l,list_t**tl,void *data)
{
list_t* tmp;
tmp = (list_t*) malloc(sizeof(list_t));
MALLOC_CHECK(tmp);
tmp->next = NULL;
tmp->data = data;
if( l == NULL )
{
*tl = tmp;
return(tmp);
}
else
{
(*tl)->next = tmp;
*tl = tmp;
return(l);
}
}
/***********************************************************************
* removes an element(you must free it yourself)
*/
list_t* list_remove(list_t* l,list_t* elem)
{
if ( elem == l )
{
list_t* tmp = l->next;
free(l); // it assumes that you have freed l->data
return(tmp);
}
else if( l != NULL)
{
l->next = list_remove(l->next,elem);
return(l);
}
else
{// elem not found
return(NULL);
}
}
/***********************************************************************
* sort
*/
HIDDEN list_t *list_max(list_t *l,int (*compare)(void *data1,void* data2))
{
if (l==NULL) return(NULL);
else if (l!=NULL && l->next==NULL) return(l);
else
{
l->next=list_max(l->next,compare);
if (compare(l->data ,l->next->data) > 0)
{
list_t *tmp;
tmp=l->next;
l->next=tmp->next;
tmp->next=l;
return(tmp);
}
else return(l);
}
}
list_t *list_sort(list_t *l,int (*compare)(void *data1,void* data2))
{
if (l==NULL) return(l);
else
{
l=list_max(l,compare);
l->next=list_sort(l->next,compare);
return(l);
}
}
/***********************************************************************
* returns the list* that contains x
*/
list_t* list_find(list_t *l,void* x,int (*equal)(void *x,void* data2))
{
if ( l == NULL )
return NULL;
else
{
if ( equal(x,l->data) )
{
return(l);
}
else return(list_find(l->next,x,equal));
}
}
/***********************************************************************
*
*/
list_t* list_duplicate(list_t *l,void* (*copier)(void *data1))
{
if ( l == NULL )
return NULL;
else
{
list_t *tmp;
tmp = malloc(sizeof(list_t ));
MALLOC_CHECK(tmp);
tmp ->data = copier(l->data);
tmp->next = list_duplicate(l->next,copier);
return(tmp);
}
}
/***********************************************************************
* delete each element
*/
/*
list_t* list_free(list_t *l,void (*fr)(void *data1))
{
if ( l != NULL)
{
// assignment is useless
l->next = list_free(l->next,fr);
if(fr != NULL)
fr(l->data);
free(l);
}
return NULL;
}
*/
list_t* list_free(list_t *l,void (*fr)(void *data1))
{
while (l != NULL)
{
list_t* next = l->next;
if(fr != NULL)
fr(l->data);
free(l);
l = next;
}
return NULL;
}
/***********************************************************************
* action on each element
*/
void list_visit(list_t* l,void (*pr)(void *))
{
while( l != NULL )
{
pr(l->data);
l=l->next;
}
}
/***********************************************************************
* gets the position of x
*/
int list_getpos(list_t *l,void* x,int (*equal)(void *data1,void* data2))
{
if( l == NULL)
{
return -1;
}
if ( equal(x,l->data) )
return(0);
else
return (1 + list_getpos(l->next,x,equal));
}
/***********************************************************************
* counts elements
*/
int list_len(list_t *l)
{
if( l == NULL)
{
return 0;
}
else
{
return (1 + list_len(l->next) );
}
}
/***********************************************************************
* concatenates the 2 lists returning the merged list.
*/
list_t* list_concat (list_t *l1,list_t *l2)
{
list_t* tmp=l1;
if(l1 == NULL)
return l2;
if(l2 == NULL)
return l1;
while( tmp->next != NULL)
tmp = tmp->next;
tmp -> next = l2;
return l1;
}
//! uses the list as a stack, removing the head
list_t* list_pop (list_t *l)
{
list_t* tmp;
if(l != NULL)
tmp = l->next;
else
tmp = NULL;
free(l);
return tmp;
}
//! uses the list as a stack, adding a head
extern list_t* list_push (list_t *l,void* data)
{
list_t* tmp;
tmp = (list_t*) malloc(sizeof(list_t));
MALLOC_CHECK(tmp);
tmp->next = l;
tmp->data = data;
return tmp;
}
//! uses the list as a stack, getting the head [may call a pop after that]
extern void* list_head (list_t *l)
{
if(l != NULL)
return l->data;
else
return NULL;
}
syntax highlighted by Code2HTML, v. 0.9.1