qse/ase/lib/cmn/sll.c

332 lines
6.1 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-27 02:50:12 +00:00
#define sll_t ase_sll_t
#define node_t ase_sll_node_t
#define copier_t ase_sll_copier_t
#define freeer_t ase_sll_freeer_t
2008-09-29 00:02:10 +00:00
#define comper_t ase_sll_comper_t
2008-08-27 02:50:12 +00:00
#define walker_t ase_sll_walker_t
#define HEAD(s) ASE_SLL_HEAD(s)
#define TAIL(s) ASE_SLL_TAIL(s)
#define SIZE(s) ASE_SLL_SIZE(s)
#define DPTR(n) ASE_SLL_DPTR(n)
#define DLEN(n) ASE_SLL_DLEN(n)
#define NEXT(n) ASE_SLL_NEXT(n)
#define TOB(sll,len) ((len)*(sll)->scale)
2008-10-08 05:30:16 +00:00
#define SIZEOF(x) ASE_SIZEOF(x)
#define size_t ase_size_t
#define mmgr_t ase_mmgr_t
2008-08-27 02:50:12 +00:00
2008-09-29 00:02:10 +00:00
static int comp_data (sll_t* sll,
const void* dptr1, size_t dlen1,
const void* dptr2, size_t dlen2)
{
if (dlen1 == dlen2) return ASE_MEMCMP (dptr1, dptr2, TOB(sll,dlen1));
/* it just returns 1 to indicate that they are different. */
return 1;
}
2008-10-08 05:30:16 +00:00
static node_t* alloc_node (sll_t* sll, void* dptr, size_t dlen)
{
node_t* n;
2008-10-09 05:43:56 +00:00
if (sll->copier == ASE_SLL_COPIER_SIMPLE)
2008-10-08 05:30:16 +00:00
{
n = ASE_MMGR_ALLOC (sll->mmgr, SIZEOF(node_t));
if (n == ASE_NULL) return ASE_NULL;
DPTR(n) = dptr;
}
else if (sll->copier == ASE_SLL_COPIER_INLINE)
{
n = ASE_MMGR_ALLOC (sll->mmgr,
SIZEOF(node_t) + TOB(sll,dlen));
if (n == ASE_NULL) return ASE_NULL;
ASE_MEMCPY (n + 1, dptr, TOB(sll,dlen));
DPTR(n) = n + 1;
}
else
{
n = ASE_MMGR_ALLOC (sll->mmgr, SIZEOF(node_t));
if (n == ASE_NULL) return ASE_NULL;
DPTR(n) = sll->copier (sll, dptr, dlen);
if (DPTR(n) == ASE_NULL)
{
ASE_MMGR_FREE (sll->mmgr, n);
return ASE_NULL;
}
}
DLEN(n) = dlen;
NEXT(n) = ASE_NULL;
return n;
}
sll_t* ase_sll_open (mmgr_t* mmgr, size_t ext)
2008-08-18 08:51:40 +00:00
{
2008-08-27 02:50:12 +00:00
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-10-08 05:30:16 +00:00
sll = ASE_MMGR_ALLOC (mmgr, SIZEOF(sll_t) + ext);
2008-08-06 07:30:10 +00:00
if (sll == ASE_NULL) return ASE_NULL;
2008-10-14 05:32:58 +00:00
if (ase_sll_init (sll, mmgr) == ASE_NULL)
{
ASE_MMGR_FREE (mmgr, sll);
return ASE_NULL;
}
return sll;
}
void ase_sll_close (sll_t* sll)
{
ase_sll_fini (sll);
ASE_MMGR_FREE (sll->mmgr, sll);
}
sll_t* ase_sll_init (sll_t* sll, mmgr_t* mmgr)
{
/* do not zero out the extension */
2008-10-08 05:30:16 +00:00
ASE_MEMSET (sll, 0, SIZEOF(*sll));
2008-09-30 01:11:08 +00:00
2008-08-06 07:30:10 +00:00
sll->mmgr = mmgr;
sll->size = 0;
sll->scale = 1;
2008-09-29 00:02:10 +00:00
sll->comper = comp_data;
2008-10-09 05:43:56 +00:00
sll->copier = ASE_SLL_COPIER_SIMPLE;
return sll;
2008-08-06 07:30:10 +00:00
}
2008-08-07 07:52:14 +00:00
void ase_sll_fini (sll_t* sll)
2008-08-07 07:52:14 +00:00
{
ase_sll_clear (sll);
}
2008-08-27 02:50:12 +00:00
void* ase_sll_getextension (sll_t* sll)
{
return sll + 1;
2008-08-07 07:52:14 +00:00
}
2008-08-27 02:50:12 +00:00
mmgr_t* ase_sll_getmmgr (sll_t* sll)
2008-08-19 05:21:48 +00:00
{
return sll->mmgr;
}
2008-08-27 02:50:12 +00:00
void ase_sll_setmmgr (sll_t* sll, mmgr_t* mmgr)
2008-08-19 05:21:48 +00:00
{
sll->mmgr = mmgr;
}
int ase_sll_getscale (sll_t* sll)
{
return sll->scale;
}
void ase_sll_setscale (sll_t* sll, int scale)
{
ASE_ASSERTX (scale > 0 && scale <= ASE_TYPE_MAX(ase_byte_t),
"The scale should be larger than 0 and less than or equal to the maximum value that the ase_byte_t type can hold");
if (scale <= 0) scale = 1;
if (scale > ASE_TYPE_MAX(ase_byte_t)) scale = ASE_TYPE_MAX(ase_byte_t);
sll->scale = scale;
}
2008-08-27 02:50:12 +00:00
copier_t ase_sll_getcopier (sll_t* sll)
2008-08-11 08:22:31 +00:00
{
return sll->copier;
}
2008-08-27 02:50:12 +00:00
void ase_sll_setcopier (sll_t* sll, copier_t copier)
2008-08-07 07:52:14 +00:00
{
2008-10-09 05:43:56 +00:00
if (copier == ASE_NULL) copier = ASE_SLL_COPIER_SIMPLE;
sll->copier = copier;
2008-08-07 07:52:14 +00:00
}
2008-08-27 02:50:12 +00:00
freeer_t ase_sll_getfreeer (sll_t* sll)
2008-08-11 08:22:31 +00:00
{
return sll->freeer;
}
2008-08-27 02:50:12 +00:00
void ase_sll_setfreeer (sll_t* sll, freeer_t freeer)
2008-08-07 07:52:14 +00:00
{
sll->freeer = freeer;
2008-08-07 07:52:14 +00:00
}
2008-09-29 00:02:10 +00:00
comper_t ase_sll_getcomper (sll_t* sll)
{
return sll->comper;
}
void ase_sll_setcomper (sll_t* sll, comper_t comper)
{
2008-09-29 08:21:17 +00:00
if (comper == ASE_NULL) comper = comp_data;
2008-09-29 00:02:10 +00:00
sll->comper = comper;
}
2008-10-08 05:30:16 +00:00
size_t ase_sll_getsize (sll_t* sll)
2008-08-07 07:52:14 +00:00
{
2008-10-08 05:30:16 +00:00
return SIZE(sll);
}
2008-10-08 05:30:16 +00:00
node_t* ase_sll_gethead (sll_t* sll)
{
return HEAD(sll);
}
2008-10-08 05:30:16 +00:00
node_t* ase_sll_gettail (sll_t* sll)
{
return TAIL(sll);
}
2008-09-29 08:20:27 +00:00
node_t* ase_sll_search (sll_t* sll, node_t* pos, const void* dptr, size_t dlen)
{
pos = (pos == ASE_NULL)? pos = sll->head: NEXT(pos);
while (pos != ASE_NULL)
{
if (sll->comper (sll, DPTR(pos), DLEN(pos), dptr, dlen) == 0)
{
return pos;
}
pos = NEXT(pos);
}
return ASE_NULL;
}
2008-08-27 02:50:12 +00:00
node_t* ase_sll_insert (
sll_t* sll, node_t* pos, void* dptr, size_t dlen)
2008-08-09 04:35:04 +00:00
{
2008-08-27 02:50:12 +00:00
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-27 02:50:12 +00:00
if (HEAD(sll) == ASE_NULL)
2008-08-11 02:27:21 +00:00
{
2008-08-27 02:50:12 +00:00
ASE_ASSERT (TAIL(sll) == ASE_NULL);
HEAD(sll) = n;
2008-08-11 02:27:21 +00:00
}
2008-08-27 02:50:12 +00:00
else NEXT(TAIL(sll)) = n;
2008-08-11 02:27:21 +00:00
2008-08-27 02:50:12 +00:00
TAIL(sll) = n;
2008-08-09 04:35:04 +00:00
}
else
{
/* insert in front of the positional node */
2008-08-27 02:50:12 +00:00
NEXT(n) = pos;
if (pos == HEAD(sll)) HEAD(sll) = 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-27 02:50:12 +00:00
node_t* n2 = HEAD(sll);
while (NEXT(n2) != pos) n2 = NEXT(n2);
NEXT(n2) = n;
2008-08-11 02:27:21 +00:00
}
2008-08-09 04:35:04 +00:00
}
2008-08-11 02:27:21 +00:00
2008-08-27 02:50:12 +00:00
SIZE(sll)++;
2008-08-09 04:35:04 +00:00
return n;
}
2008-08-27 02:50:12 +00:00
void ase_sll_delete (sll_t* sll, node_t* pos)
2008-08-11 08:22:31 +00:00
{
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
2008-08-27 02:50:12 +00:00
if (pos == HEAD(sll))
2008-08-11 08:22:31 +00:00
{
2008-08-12 04:52:25 +00:00
/* it is simple to delete the head node */
2008-08-27 02:50:12 +00:00
HEAD(sll) = NEXT(pos);
if (HEAD(sll) == ASE_NULL) TAIL(sll) = ASE_NULL;
2008-08-11 08:22:31 +00:00
}
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-27 02:50:12 +00:00
node_t* n2 = HEAD(sll);
while (NEXT(n2) != pos) n2 = NEXT(n2);
2008-08-12 04:52:25 +00:00
2008-08-27 02:50:12 +00:00
NEXT(n2) = NEXT(pos);
2008-08-12 04:52:25 +00:00
/* update the tail node if necessary */
2008-08-27 02:50:12 +00:00
if (pos == TAIL(sll)) TAIL(sll) = n2;
2008-08-11 08:22:31 +00:00
}
2008-08-12 04:52:25 +00:00
if (sll->freeer != ASE_NULL)
{
/* free the actual data */
2008-08-27 02:50:12 +00:00
sll->freeer (sll, DPTR(pos), DLEN(pos));
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-27 02:50:12 +00:00
SIZE(sll)--;
2008-08-11 08:22:31 +00:00
}
void ase_sll_clear (sll_t* sll)
{
while (HEAD(sll) != ASE_NULL) ase_sll_delete (sll, HEAD(sll));
ASE_ASSERT (TAIL(sll) == ASE_NULL);
}
node_t* ase_sll_pushhead (sll_t* sll, void* data, size_t size)
{
return ase_sll_insert (sll, HEAD(sll), data, size);
}
node_t* ase_sll_pushtail (sll_t* sll, void* data, size_t size)
{
return ase_sll_insert (sll, ASE_NULL, data, size);
}
2008-08-27 02:50:12 +00:00
void ase_sll_pophead (sll_t* sll)
2008-08-11 08:22:31 +00:00
{
2008-08-27 02:50:12 +00:00
ase_sll_delete (sll, HEAD(sll));
2008-08-11 08:22:31 +00:00
}
2008-08-27 02:50:12 +00:00
void ase_sll_poptail (sll_t* sll)
2008-08-11 08:22:31 +00:00
{
2008-08-27 02:50:12 +00:00
ase_sll_delete (sll, TAIL(sll));
2008-08-11 08:22:31 +00:00
}
2008-08-27 02:50:12 +00:00
void ase_sll_walk (sll_t* sll, walker_t walker, void* arg)
{
2008-08-27 02:50:12 +00:00
node_t* n = HEAD(sll);
while (n != ASE_NULL)
{
2008-08-11 08:22:31 +00:00
if (walker(sll,n,arg) == ASE_SLL_WALK_STOP) return;
2008-08-27 02:50:12 +00:00
n = NEXT(n);
}
}
2008-08-23 09:23:09 +00:00