qse/ase/lib/cmn/sll.c

244 lines
4.5 KiB
C
Raw Normal View History

2008-08-06 07:30:10 +00:00
/*
* $Id$
*
* {License}
*/
#include <ase/cmn/sll.h>
#include "mem.h"
2008-08-19 05:21:48 +00:00
ase_sll_t* ase_sll_open (
ase_mmgr_t* mmgr, ase_size_t extension,
void (*initializer) (ase_sll_t*))
2008-08-18 08:51:40 +00:00
{
2008-08-19 05:21:48 +00:00
ase_sll_t* sll;
2008-08-06 07:30:10 +00:00
2008-08-19 05:21:48 +00:00
if (mmgr == ASE_NULL)
{
mmgr = ASE_MMGR_GETDFL();
2008-08-19 05:21:48 +00:00
ASE_ASSERTX (mmgr != ASE_NULL,
"Set the memory manager with ASE_MMGR_SETDFL()");
2008-08-06 07:30:10 +00:00
2008-08-19 05:21:48 +00:00
if (mmgr == ASE_NULL) return ASE_NULL;
}
2008-08-21 03:58:42 +00:00
sll = ASE_MMGR_ALLOC (mmgr, ASE_SIZEOF(ase_sll_t) + extension);
2008-08-06 07:30:10 +00:00
if (sll == ASE_NULL) return ASE_NULL;
ASE_MEMSET (sll, 0, ASE_SIZEOF(ase_sll_t) + extension);
2008-08-06 07:30:10 +00:00
sll->mmgr = mmgr;
2008-08-19 05:21:48 +00:00
if (initializer) initializer (sll);
2008-08-18 08:51:40 +00:00
return sll;
2008-08-06 07:30:10 +00:00
}
2008-08-07 07:52:14 +00:00
void ase_sll_close (ase_sll_t* sll)
{
ase_sll_clear (sll);
2008-08-23 09:23:09 +00:00
ASE_MMGR_FREE (sll->mmgr, sll);
2008-08-07 07:52:14 +00:00
}
void ase_sll_clear (ase_sll_t* sll)
{
2008-08-12 04:52:25 +00:00
while (sll->head != ASE_NULL) ase_sll_delete (sll, sll->head);
ASE_ASSERT (sll->tail == ASE_NULL);
}
void* ase_sll_getextension (ase_sll_t* sll)
{
return sll + 1;
2008-08-07 07:52:14 +00:00
}
2008-08-19 05:21:48 +00:00
ase_mmgr_t* ase_sll_getmmgr (ase_sll_t* sll)
{
return sll->mmgr;
}
void ase_sll_setmmgr (ase_sll_t* sll, ase_mmgr_t* mmgr)
{
sll->mmgr = mmgr;
}
ase_size_t ase_sll_getsize (ase_sll_t* sll)
2008-08-07 07:52:14 +00:00
{
return sll->size;
2008-08-07 07:52:14 +00:00
}
2008-08-09 04:35:04 +00:00
ase_sll_node_t* ase_sll_gethead (ase_sll_t* sll)
{
return sll->head;
}
ase_sll_node_t* ase_sll_gettail (ase_sll_t* sll)
{
return sll->tail;
}
2008-08-11 08:22:31 +00:00
ase_sll_copier_t ase_sll_getcopier (ase_sll_t* sll)
{
return sll->copier;
}
2008-08-12 04:52:25 +00:00
void ase_sll_setcopier (ase_sll_t* sll, ase_sll_copier_t copier)
2008-08-07 07:52:14 +00:00
{
sll->copier = copier;
2008-08-07 07:52:14 +00:00
}
2008-08-11 08:22:31 +00:00
ase_sll_freeer_t ase_sll_getfreeer (ase_sll_t* sll)
{
return sll->freeer;
}
void ase_sll_setfreeer (ase_sll_t* sll, ase_sll_freeer_t freeer)
2008-08-07 07:52:14 +00:00
{
sll->freeer = freeer;
2008-08-07 07:52:14 +00:00
}
2008-08-11 02:27:21 +00:00
static ase_sll_node_t* alloc_node (ase_sll_t* sll, void* dptr, ase_size_t dlen)
2008-08-07 07:52:14 +00:00
{
ase_sll_node_t* n;
if (sll->copier == ASE_NULL)
{
2008-08-23 09:23:09 +00:00
n = ASE_MMGR_ALLOC (sll->mmgr, ASE_SIZEOF(ase_sll_node_t));
if (n == ASE_NULL) return ASE_NULL;
2008-08-13 07:58:57 +00:00
n->dptr = dptr;
}
else if (sll->copier == ASE_SLL_COPIER_INLINE)
{
2008-08-23 09:23:09 +00:00
n = ASE_MMGR_ALLOC (sll->mmgr, ASE_SIZEOF(ase_sll_node_t) + dlen);
if (n == ASE_NULL) return ASE_NULL;
2008-08-07 07:52:14 +00:00
2008-08-11 02:27:21 +00:00
ASE_MEMCPY (n + 1, dptr, dlen);
2008-08-13 07:58:57 +00:00
n->dptr = n + 1;
}
else
{
2008-08-23 09:23:09 +00:00
n = ASE_MMGR_ALLOC (sll->mmgr, ASE_SIZEOF(ase_sll_node_t));
if (n == ASE_NULL) return ASE_NULL;
2008-08-13 07:58:57 +00:00
n->dptr = sll->copier (sll, dptr, dlen);
2008-08-23 09:23:09 +00:00
if (n->dptr == ASE_NULL)
{
ASE_MMGR_FREE (sll->mmgr, n);
return ASE_NULL;
}
}
2008-08-13 07:58:57 +00:00
n->dlen = dlen;
n->next = ASE_NULL;
return n;
}
2008-08-09 04:35:04 +00:00
ase_sll_node_t* ase_sll_insert (
2008-08-11 02:27:21 +00:00
ase_sll_t* sll, ase_sll_node_t* pos, void* dptr, ase_size_t dlen)
2008-08-09 04:35:04 +00:00
{
2008-08-11 02:27:21 +00:00
ase_sll_node_t* n = alloc_node (sll, dptr, dlen);
2008-08-09 04:35:04 +00:00
if (n == ASE_NULL) return ASE_NULL;
if (pos == ASE_NULL)
{
/* insert at the end */
2008-08-11 02:27:21 +00:00
if (sll->head == ASE_NULL)
{
ASE_ASSERT (sll->tail == ASE_NULL);
sll->head = n;
}
else sll->tail->next = n;
sll->tail = n;
2008-08-09 04:35:04 +00:00
}
else
{
/* insert in front of the positional node */
2008-08-11 02:27:21 +00:00
n->next = pos;
2008-08-09 04:35:04 +00:00
if (pos == sll->head) sll->head = n;
2008-08-11 02:27:21 +00:00
else
{
2008-08-11 08:22:31 +00:00
/* take note of performance penalty */
2008-08-11 02:27:21 +00:00
ase_sll_node_t* n2 = sll->head;
while (n2->next != pos) n2 = n2->next;
n2->next = n;
}
2008-08-09 04:35:04 +00:00
}
2008-08-11 02:27:21 +00:00
sll->size++;
2008-08-09 04:35:04 +00:00
return n;
}
2008-08-11 08:22:31 +00:00
ase_sll_node_t* ase_sll_pushhead (ase_sll_t* sll, void* data, ase_size_t size)
2008-08-11 02:27:21 +00:00
{
return ase_sll_insert (sll, sll->head, data, size);
}
2008-08-11 08:22:31 +00:00
ase_sll_node_t* ase_sll_pushtail (ase_sll_t* sll, void* data, ase_size_t size)
2008-08-11 02:27:21 +00:00
{
return ase_sll_insert (sll, ASE_NULL, data, size);
}
2008-08-11 08:22:31 +00:00
void ase_sll_delete (ase_sll_t* sll, ase_sll_node_t* pos)
{
2008-08-12 04:52:25 +00:00
if (pos == ASE_NULL) return; /* not a valid node */
2008-08-11 08:22:31 +00:00
if (pos == sll->head)
{
2008-08-12 04:52:25 +00:00
/* it is simple to delete the head node */
2008-08-11 08:22:31 +00:00
sll->head = pos->next;
if (sll->head == ASE_NULL) sll->tail = ASE_NULL;
}
else
{
2008-08-12 04:52:25 +00:00
/* but deletion of other nodes has significant performance
* penalty as it has look for the predecessor of the
* target node */
2008-08-11 08:22:31 +00:00
ase_sll_node_t* n2 = sll->head;
while (n2->next != pos) n2 = n2->next;
2008-08-12 04:52:25 +00:00
2008-08-11 08:22:31 +00:00
n2->next = pos->next;
2008-08-12 04:52:25 +00:00
/* update the tail node if necessary */
2008-08-11 08:22:31 +00:00
if (pos == sll->tail) sll->tail = n2;
}
2008-08-12 04:52:25 +00:00
if (sll->freeer != ASE_NULL)
{
/* free the actual data */
2008-08-13 07:58:57 +00:00
sll->freeer (sll, pos->dptr, pos->dlen);
2008-08-12 04:52:25 +00:00
}
/* free the node */
2008-08-23 09:23:09 +00:00
ASE_MMGR_FREE (sll->mmgr, pos);
2008-08-12 04:52:25 +00:00
/* decrement the number of elements */
2008-08-11 08:22:31 +00:00
sll->size--;
}
void ase_sll_pophead (ase_sll_t* sll)
{
ase_sll_delete (sll, sll->head);
}
void ase_sll_poptail (ase_sll_t* sll)
{
ase_sll_delete (sll, sll->tail);
}
2008-08-09 04:35:04 +00:00
void ase_sll_walk (ase_sll_t* sll, ase_sll_walker_t walker, void* arg)
{
ase_sll_node_t* n = sll->head;
while (n != ASE_NULL)
{
2008-08-11 08:22:31 +00:00
if (walker(sll,n,arg) == ASE_SLL_WALK_STOP) return;
n = n->next;
}
}
2008-08-23 09:23:09 +00:00
void* ase_sll_copyinline (ase_sll_t* sll, void* dptr, ase_size_t dlen)
{
/* this is a dummy copier */
return ASE_NULL;
}