/*
Copyright (C) 1999-2004 IC & S dbmail@ic-s.nl
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: list.c 1550 2005-01-07 12:23:02Z paul $
*
* functions to create lists and add/delete items */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "list.h"
void list_init(struct list *tlist)
{
memset(tlist,'\0', sizeof(struct list));
// tlist->start = NULL;
// tlist->total_nodes = 0;
}
/*
* list_freelist()
*
* frees a list and all the memory associated with it
*/
void list_freelist(struct element **start)
{
/* check if list exists */
if (!(*start))
return;
/* free rest of list */
list_freelist(&(*start)->nextnode);
/* free this item */
dm_free((*start)->data);
dm_free(*start);
*start = NULL;
}
/*
* dbmail_list_reverse()
*
* reverse the order of a linked list
*/
struct element *dbmail_list_reverse(struct element *start)
{
struct element *newstart;
if (!start)
return NULL; /* nothing there */
if (!start->nextnode)
return start; /* nothing to reverse */
newstart = dbmail_list_reverse(start->nextnode); /* reverse rest of list */
start->nextnode->nextnode = start;
start->nextnode = NULL; /* terminate list */
return newstart;
}
/*
* return a empty initialized element;
*/
static struct element *element_new(void)
{
struct element *new = (struct element *)dm_malloc(sizeof(struct element));
if (new != NULL)
memset(new,'\0',sizeof(struct element));
return new;
}
/*
* list_nodeadd()
*
* Adds a node to a linked list (list structure).
* New item will be FIRST element of new linked list.
*
* returns NULL on failure or first element on success
*/
struct element *list_nodeadd(struct list *tlist, const void *data,
size_t dsize)
{
struct element *p;
if (!tlist)
return NULL; /* cannot add to non-existing list */
if (! (p = element_new()))
return NULL;
if (! (p->data = (void *)dm_malloc(dsize))) {
dm_free(p);
return NULL;
}
p->data = memcpy(p->data, data, dsize);
p->dsize=dsize;
p->nextnode=tlist->start;
tlist->start = p;
/* updating node count */
tlist->total_nodes++;
return tlist->start;
}
/*
* list_nodepop()
*
* pops the first element of a linked list
* ! MEMORY SHOULD BE FREED BY CLIENT !
*/
struct element *list_nodepop(struct list *list)
{
struct element *ret;
if (!list || !list->start)
return NULL;
ret = list->start;
list->start = list->start->nextnode;
return ret;
}
/*
* list_nodedel()
*
* removes the item containing 'data' from the list preserving a valid linked-list structure.
*
* returns
*/
struct element *list_nodedel(struct list *tlist, void *data)
{
struct element *temp;
struct element *item;
item = NULL;
if (!tlist)
return NULL;
temp = tlist->start;
/* checking if lists exist else return NULL */
if (temp == NULL)
return NULL;
while (temp != NULL) { /* walk the list */
if (temp->data == data) {
if (item == NULL) {
tlist->start = temp->nextnode;
dm_free(temp->data);
dm_free((struct element *) temp);
break;
} else {
item->nextnode = temp->nextnode;
dm_free(temp->data); /* freeing memory */
dm_free((struct element *) temp);
break;
}
/* updating node count */
tlist->total_nodes--;
}
item = temp;
temp = temp->nextnode;
}
return NULL;
}
struct element *list_getstart(struct list *tlist)
{
return (tlist) ? tlist->start : NULL;
}
long list_totalnodes(struct list *tlist)
{
return (tlist) ? tlist->total_nodes : -1; /* a NULL ptr doesnt even have zero nodes (?) */
}
void list_showlist(struct list *tlist)
{
struct element *temp;
if (!tlist) {
trace(TRACE_MESSAGE,
"list_showlist(): NULL ptr received\n");
return;
}
temp = tlist->start;
while (temp != NULL) {
trace(TRACE_MESSAGE, "list_showlist():item found [%s]\n",
(char *) temp->data);
temp = temp->nextnode;
}
}
/* basic binary tree */
void list_btree_insert(sortitems_t ** tree, sortitems_t * item) {
int val;
if(!(*tree)) {
*tree = item;
return;
}
val = strcmp(item->ustr,(*tree)->ustr);
if(val < 0)
list_btree_insert(&(*tree)->left, item);
else if(val > 0)
list_btree_insert(&(*tree)->right, item);
}
void list_btree_printout(sortitems_t * tree, int * i) {
if(tree->left)
list_btree_printout(tree->left, i);
trace(TRACE_INFO, "list_btree_printout: i '%d' '%d', '%s'\n",
*i, tree->mid, tree->ustr);
(*i)++;
if(tree->right)
list_btree_printout(tree->right, i);
}
void list_btree_traverse(sortitems_t * tree, int * i, unsigned int *rset) {
if(tree->left)
list_btree_traverse(tree->left, i, rset);
trace(TRACE_DEBUG, "list_btree_traverse: i '%d' '%d', '%s'\n",
*i, tree->mid, tree->ustr);
rset[*i] = tree->mid;
(*i)++;
if(tree->right)
list_btree_traverse(tree->right, i, rset);
}
void list_btree_free(sortitems_t * tree) {
if(tree->left)
list_btree_free(tree->left);
dm_free(tree->ustr);
if(tree->right)
list_btree_free(tree->right);
else
dm_free(tree);
}
syntax highlighted by Code2HTML, v. 0.9.1