/* grecs - Gray's Extensible Configuration System
Copyright (C) 2007-2011 Sergey Poznyakoff
Grecs 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 3 of the License, or (at your
option) any later version.
Grecs 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 Grecs. If not, see . */
#ifdef HAVE_CONFIG_H
# include
#endif
#include
#include
#include
#include
struct grecs_list *
grecs_list_create()
{
struct grecs_list *lp = grecs_malloc(sizeof(*lp));
memset(lp, 0, sizeof(*lp));
return lp;
}
size_t
grecs_list_size(struct grecs_list *lp)
{
return lp ? lp->count : 0;
}
void
grecs_list_append(struct grecs_list *lp, void *val)
{
struct grecs_list_entry *ep = grecs_malloc(sizeof(*ep));
ep->data = val;
ep->next = NULL;
if (lp->tail)
lp->tail->next = ep;
else
lp->head = ep;
lp->tail = ep;
lp->count++;
}
void
grecs_list_push(struct grecs_list *lp, void *val)
{
struct grecs_list_entry *ep = grecs_malloc(sizeof(*ep));
ep->data = val;
ep->next = lp->head;
lp->head = ep;
lp->count++;
}
void *
grecs_list_pop(struct grecs_list *lp)
{
void *data;
struct grecs_list_entry *ep = lp->head;
if (ep) {
data = ep->data;
lp->head = ep->next;
if (!lp->head)
lp->tail = NULL;
lp->count--;
free (ep);
} else
data = NULL;
return data;
}
void
grecs_list_clear(struct grecs_list *lp)
{
struct grecs_list_entry *ep = lp->head;
while (ep) {
struct grecs_list_entry *next = ep->next;
if (lp->free_entry)
lp->free_entry(ep->data);
free(ep);
ep = next;
}
lp->head = lp->tail = NULL;
lp->count = 0;
}
void
grecs_list_free(struct grecs_list *lp)
{
grecs_list_clear(lp);
free(lp);
}
static int
_ptrcmp(const void *a, const void *b)
{
return a != b;
}
void *
grecs_list_locate(struct grecs_list *lp, void *data)
{
struct grecs_list_entry *ep;
int (*cmp)(const void *, const void *) = lp->cmp ? lp->cmp : _ptrcmp;
for (ep = lp->head; ep; ep = ep->next) {
if (cmp(ep->data, data) == 0)
return ep->data;
}
return NULL;
}
void *
grecs_list_index(struct grecs_list *lp, size_t idx)
{
struct grecs_list_entry *ep;
for (ep = lp->head; ep && idx; ep = ep->next, idx--)
;
return ep ? ep->data : NULL;
}
void *
grecs_list_remove_tail(struct grecs_list *lp)
{
void *data;
if (!lp->head)
return NULL;
data = lp->tail;
if (lp->head == lp->tail) {
free(lp->tail);
lp->head = lp->tail = NULL;
lp->count = 0;
} else {
struct grecs_list_entry *ep;
for (ep = lp->head; ep->next != lp->tail; ep = ep->next)
;
free(lp->tail);
ep->next = NULL;
lp->tail = ep;
}
return data;
}