/*-
* Copyright (c) 2000-2005 MAEKAWA Masahide <maekawa@cvsync.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the author nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/types.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include "compat_stdbool.h"
#include "list.h"
#include "logmsg.h"
#define LIST_DYNAMIC 1
#define LIST_STATIC 0
#define LIST_MAXCHAINS 16
struct list *
list_init(void)
{
struct list *lp;
size_t i;
if ((lp = malloc(sizeof(*lp))) == NULL) {
logmsg_err("%s", strerror(errno));
return (NULL);
}
lp->l_entries = malloc(LIST_MAXCHAINS * sizeof(*lp->l_entries));
if (lp->l_entries == NULL) {
logmsg_err("%s", strerror(errno));
free(lp);
return (NULL);
}
lp->l_head = NULL;
lp->l_tail = NULL;
lp->l_freelist = NULL;
lp->l_destructor = NULL;
for (i = 0 ; i < LIST_MAXCHAINS ; i++) {
lp->l_entries[i].le_next = lp->l_freelist;
lp->l_freelist = &lp->l_entries[i];
lp->l_freelist->le_state = LIST_STATIC;
}
return (lp);
}
void
list_destroy(struct list *lp)
{
struct listent *lep, *next;
lep = lp->l_head;
while (lep != NULL) {
next = lep->le_next;
if (lp->l_destructor != NULL)
(*lp->l_destructor)(lep->le_elm);
if (lep->le_state == LIST_DYNAMIC)
free(lep);
lep = next;
}
lep = lp->l_freelist;
while (lep != NULL) {
next = lep->le_next;
if (lep->le_state == LIST_DYNAMIC)
free(lep);
lep = next;
}
free(lp->l_entries);
free(lp);
}
void
__list_set_destructor(struct list *lp, list_destructor destructor)
{
lp->l_destructor = destructor;
}
bool
list_insert_head(struct list *lp, void *elm)
{
struct listent *lep;
if (lp->l_freelist != NULL) {
lep = lp->l_freelist;
lp->l_freelist = lep->le_next;
} else {
if ((lep = malloc(sizeof(*lep))) == NULL) {
logmsg_err("%s", strerror(errno));
return (false);
}
lep->le_state = LIST_DYNAMIC;
}
lep->le_next = lp->l_head;
lep->le_priv = NULL;
lep->le_elm = elm;
if (lp->l_head != NULL)
lp->l_head->le_priv = lep;
else
lp->l_tail = lep;
lp->l_head = lep;
return (true);
}
bool
list_insert_tail(struct list *lp, void *elm)
{
struct listent *lep;
if (lp->l_freelist != NULL) {
lep = lp->l_freelist;
lp->l_freelist = lep->le_next;
} else {
if ((lep = malloc(sizeof(*lep))) == NULL) {
logmsg_err("%s", strerror(errno));
return (false);
}
lep->le_state = LIST_DYNAMIC;
}
lep->le_next = NULL;
lep->le_priv = lp->l_tail;
lep->le_elm = elm;
if (lp->l_tail != NULL)
lp->l_tail->le_next = lep;
else
lp->l_head = lep;
lp->l_tail= lep;
return (true);
}
bool
list_remove(struct list *lp, struct listent *target)
{
struct listent *lep, *next, *priv;
if (lp->l_head == NULL)
return (false);
for (lep = lp->l_head ; lep != NULL ; lep = lep->le_next) {
if (lep == target)
break;
}
if (lep == NULL)
return (false);
next = lep->le_next;
priv = lep->le_priv;
if (next != NULL)
next->le_priv = priv;
if (priv != NULL)
priv->le_next = next;
if (next == NULL)
lp->l_tail = priv;
if (priv == NULL)
lp->l_head = next;
lep->le_next = lp->l_freelist;
lep->le_priv = NULL;
lp->l_freelist = lep;
return (true);
}
void *
list_remove_head(struct list *lp)
{
struct listent *lep;
void *elm;
if (lp->l_head == NULL)
return (NULL);
lep = lp->l_head;
lp->l_head = lep->le_next;
if (lp->l_head != NULL)
lp->l_head->le_priv = NULL;
else
lp->l_tail = NULL;
elm = lep->le_elm;
lep->le_next = lp->l_freelist;
lep->le_priv = NULL;
lp->l_freelist = lep;
return (elm);
}
void *
list_remove_tail(struct list *lp)
{
struct listent *lep;
void *elm;
if (lp->l_tail == NULL)
return (NULL);
lep = lp->l_tail;
lp->l_tail = lep->le_priv;
if (lp->l_tail != NULL)
lp->l_tail->le_next = NULL;
else
lp->l_head = NULL;
elm = lep->le_elm;
lep->le_next = lp->l_freelist;
lep->le_priv = NULL;
lp->l_freelist = lep;
return (elm);
}
bool
list_isempty(struct list *lp)
{
if (lp->l_head != NULL)
return (false);
return (true);
}
syntax highlighted by Code2HTML, v. 0.9.1