/* $Id: nodetree.c,v 1.11 2011/08/28 12:25:20 sbajic Exp $ */
/*
DSPAM
COPYRIGHT (C) 2002-2012 DSPAM PROJECT
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
#include
#include
#ifndef _WIN32
#include
#endif
#include "nodetree.h"
#include "util.h"
#include "error.h"
#include "libdspam_objects.h"
#include "language.h"
/* nt_node_create (used internally) to allocate space for a new node */
struct nt_node * nt_node_create (void *data) {
struct nt_node *node;
if ((node = (struct nt_node *) malloc (sizeof (struct nt_node))) == 0)
{
LOG (LOG_CRIT, ERR_MEM_ALLOC);
exit (1);
}
node->ptr = data;
node->next = (struct nt_node *) NULL;
return (node);
}
/* nt_create allocates space for and initializes a nodetree */
struct nt *
nt_create (int nodetype)
{
struct nt *nt = (struct nt *) malloc (sizeof (struct nt));
if (nt == NULL)
{
LOG (LOG_CRIT, ERR_MEM_ALLOC);
return NULL;
}
nt->first = (struct nt_node *) NULL;
nt->insert = (struct nt_node *) NULL;
nt->items = 0;
nt->nodetype = nodetype;
return (nt);
}
/* nt_destroy methodically destroys a nodetree, freeing resources */
void
nt_destroy (struct nt *nt)
{
struct nt_node *cur, *next;
int i;
if (!nt)
return;
cur = nt->first;
for (i = 0; i < nt->items; i++)
{
next = cur->next;
if (nt->nodetype != NT_INDEX)
free (cur->ptr);
free (cur);
cur = next;
}
free (nt);
}
/* nt_add adds an item to the nodetree */
struct nt_node *
nt_add (struct nt *nt, void *data)
{
struct nt_node *prev;
struct nt_c c;
struct nt_node *node = c_nt_first (nt, &c);
void *vptr;
if (nt->insert) {
prev = nt->insert;
} else {
prev = 0;
while (node)
{
prev = node;
node = node->next;
}
}
nt->items++;
if (nt->nodetype == NT_CHAR)
{
long size = strlen ((char *) data) + 1;
/* vptr is compared with 'From' and 'X-DSPAM-'even if data is shorter; but a larger buffer is allocated to prevent a comparison against garbage */
vptr = malloc (size < 16 ? 16 : size);
if (vptr == NULL)
{
LOG (LOG_CRIT, ERR_MEM_ALLOC);
return NULL;
}
strlcpy (vptr, data, size);
}
else
{
vptr = data;
}
if (prev)
{
node = nt_node_create (vptr);
prev->next = node;
nt->insert = node;
return (node);
}
else
{
node = nt_node_create (vptr);
nt->first = node;
nt->insert = node;
return (node);
}
}
/* c_nt_next returns the next item in a nodetree */
struct nt_node *
c_nt_next (struct nt *nt, struct nt_c *c)
{
struct nt_node *node = c->iter_index;
if (node)
{
c->iter_index = node->next;
return (node->next);
}
else
{
if (nt->items > 0)
{
c->iter_index = nt->first;
return nt->first;
}
}
return ((struct nt_node *) NULL);
}
/* nt_first returns the first item in a nodetree */
struct nt_node *
c_nt_first (struct nt *nt, struct nt_c *c)
{
c->iter_index = nt->first;
return (nt->first);
}