This commit is contained in:
hyung-hwan 2008-08-11 08:22:31 +00:00
parent f4b28ffb6a
commit 580520d195
2 changed files with 131 additions and 11 deletions

View File

@ -15,6 +15,7 @@
*/ */
typedef struct ase_sll_t ase_sll_t; typedef struct ase_sll_t ase_sll_t;
typedef struct ase_sll_node_t ase_sll_node_t; typedef struct ase_sll_node_t ase_sll_node_t;
typedef enum ase_sll_walk_t ase_sll_walk_t;
struct ase_sll_node_t struct ase_sll_node_t
{ {
@ -29,7 +30,13 @@ struct ase_sll_node_t
typedef void* (*ase_sll_copier_t) (ase_sll_t* sll, void* data, ase_size_t len); typedef void* (*ase_sll_copier_t) (ase_sll_t* sll, void* data, ase_size_t len);
typedef void (*ase_sll_freeer_t) (ase_sll_t* sll, void* data, ase_size_t len); typedef void (*ase_sll_freeer_t) (ase_sll_t* sll, void* data, ase_size_t len);
typedef int (*ase_sll_walker_t) (ase_sll_t* sll, ase_sll_node_t* node, void* arg); typedef ase_sll_walk_t (*ase_sll_walker_t) (ase_sll_t* sll, ase_sll_node_t* node, void* arg);
enum ase_sll_walk_t
{
ASE_SLL_WALK_STOP = 0,
ASE_SLL_WALK_FORWARD = 1
};
#define ASE_SLL_COPIER_INLINE ase_sll_copyinline #define ASE_SLL_COPIER_INLINE ase_sll_copyinline
@ -85,6 +92,10 @@ void ase_sll_setcopier (
ase_sll_copier_t copier /* a element copier */ ase_sll_copier_t copier /* a element copier */
); );
ase_sll_copier_t ase_sll_getcopier (
ase_sll_t* sll /* a singly linked list */
);
/* /*
* NAME specifies how to destroy an element * NAME specifies how to destroy an element
* *
@ -96,30 +107,51 @@ void ase_sll_setfreeer (
ase_sll_freeer_t freeer /* a element freeer */ ase_sll_freeer_t freeer /* a element freeer */
); );
ase_sll_freeer_t ase_sll_getfreeer (
ase_sll_t* sll /* a singly linked list */
);
/* /*
* Returns the pointer to the extension area * NAME Gets the pointer to the extension area
* RETURN the pointer to the extension area
*/ */
void* ase_sll_getextension ( void* ase_sll_getextension (
ase_sll_t* sll /* a singly linked list */ ase_sll_t* sll /* a singly linked list */
); );
/* /*
* Gets the number of elements held in a singly linked list * NAME Gets the number of elements held in a singly linked list
* RETURNS the number of elements the list holds * RETURN the number of elements the list holds
*/ */
ase_size_t ase_sll_getsize ( ase_size_t ase_sll_getsize (
ase_sll_t* sll /* a singly linked list */ ase_sll_t* sll /* a singly linked list */
); );
/*
* NAME Gets the head(first) node
* RETURN the tail node of a singly linked list
*/
ase_sll_node_t* ase_sll_gethead ( ase_sll_node_t* ase_sll_gethead (
ase_sll_t* sll /* a singly linked list */ ase_sll_t* sll /* a singly linked list */
); );
/*
* NAME Gets the tail(last) node
* RETURN the tail node of a singly linked list
*/
ase_sll_node_t* ase_sll_gettail ( ase_sll_node_t* ase_sll_gettail (
ase_sll_t* sll /* a singly linked list */ ase_sll_t* sll /* a singly linked list */
); );
/* Inserts data before a positional node given */ /*
* NAME Inserts data before a positional node given
*
* DESCRIPTION
* There is performance penalty unless the positional node is neither
* the head node nor ASE_NULL. You should consider a different data
* structure such as a doubly linked list if you need to insert data
* into a random position.
*/
ase_sll_node_t* ase_sll_insert ( ase_sll_node_t* ase_sll_insert (
ase_sll_t* sll /* a singly linked list */, ase_sll_t* sll /* a singly linked list */,
ase_sll_node_t* pos /* a node before which a new node is inserted */, ase_sll_node_t* pos /* a node before which a new node is inserted */,
@ -127,14 +159,60 @@ ase_sll_node_t* ase_sll_insert (
ase_size_t dlen /* the length of the data in bytes */ ase_size_t dlen /* the length of the data in bytes */
); );
/* Traverses s singly linked list */ ase_sll_node_t* ase_sll_pushhead (
void ase_sll_walk (ase_sll_t* sll, ase_sll_walker_t walker, void* arg); ase_sll_t* sll /* a singly linked list */,
void* dptr,
ase_size_t dlen
);
ase_sll_node_t* ase_sll_pushtail (
ase_sll_t* sll /* a singly linked list */,
void* dptr,
ase_size_t dlen
);
void ase_sll_delete (
ase_sll_t* sll,
ase_sll_node_t* pos
);
void ase_sll_pophead (
ase_sll_t* sll
);
void ase_sll_poptail (
ase_sll_t* sll
);
/*
* NAME Traverses s singly linked list
*
* DESCRIPTION
* A singly linked list allows uni-directional in-order traversal.
* The ase_sll_walk() function traverses a singly linkked list from its
* head node down to its tail node as long as the walker function returns
* ASE_SLL_WALK_FORWARD. A walker can return ASE_SLL_WALK_STOP to cause
* immediate stop of traversal.
* For each node, the walker function is called and it is passed three
* parameters: the singly linked list, the visiting node, and the
* user-defined data passed as the third parameter in a call to the
* ase_sll_walk() function.
*/
void ase_sll_walk (
ase_sll_t* sll /* a singly linked list */,
ase_sll_walker_t walker /* a user-defined walker function */,
void* arg /* pointer to user-defined data */
);
/* /*
* Causes a singly linked list to copy in data to a node. * Causes a singly linked list to copy in data to a node.
* Use ASE_SLL_COPIER_INLINE instead. * Use ASE_SLL_COPIER_INLINE instead.
*/ */
void* ase_sll_copyinline (ase_sll_t* sll, void* data, ase_size_t len); void* ase_sll_copyinline (
ase_sll_t* sll /* a singly linked list */,
void* data /* pointer to data to copy */ ,
ase_size_t len /* length of data in bytes */
);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -88,11 +88,21 @@ ase_sll_node_t* ase_sll_gettail (ase_sll_t* sll)
return sll->tail; return sll->tail;
} }
ase_sll_copier_t ase_sll_getcopier (ase_sll_t* sll)
{
return sll->copier;
}
void ass_sll_setcopier (ase_sll_t* sll, ase_sll_copier_t copier) void ass_sll_setcopier (ase_sll_t* sll, ase_sll_copier_t copier)
{ {
sll->copier = copier; sll->copier = copier;
} }
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) void ase_sll_setfreeer (ase_sll_t* sll, ase_sll_freeer_t freeer)
{ {
sll->freeer = freeer; sll->freeer = freeer;
@ -154,6 +164,7 @@ ase_sll_node_t* ase_sll_insert (
if (pos == sll->head) sll->head = n; if (pos == sll->head) sll->head = n;
else else
{ {
/* take note of performance penalty */
ase_sll_node_t* n2 = sll->head; ase_sll_node_t* n2 = sll->head;
while (n2->next != pos) n2 = n2->next; while (n2->next != pos) n2 = n2->next;
n2->next = n; n2->next = n;
@ -164,23 +175,54 @@ ase_sll_node_t* ase_sll_insert (
return n; return n;
} }
ase_sll_node_t* ase_sll_prepend (ase_sll_t* sll, void* data, ase_size_t size) ase_sll_node_t* ase_sll_pushhead (ase_sll_t* sll, void* data, ase_size_t size)
{ {
return ase_sll_insert (sll, sll->head, data, size); return ase_sll_insert (sll, sll->head, data, size);
} }
ase_sll_node_t* ase_sll_append (ase_sll_t* sll, void* data, ase_size_t size) ase_sll_node_t* ase_sll_pushtail (ase_sll_t* sll, void* data, ase_size_t size)
{ {
return ase_sll_insert (sll, ASE_NULL, data, size); return ase_sll_insert (sll, ASE_NULL, data, size);
} }
void ase_sll_delete (ase_sll_t* sll, ase_sll_node_t* pos)
{
ASE_ASSERT (pos != ASE_NULL);
if (pos == sll->head)
{
sll->head = pos->next;
if (sll->head == ASE_NULL) sll->tail = ASE_NULL;
}
else
{
/* take note of performance penalty */
ase_sll_node_t* n2 = sll->head;
while (n2->next != pos) n2 = n2->next;
n2->next = pos->next;
if (pos == sll->tail) sll->tail = n2;
}
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);
}
void ase_sll_walk (ase_sll_t* sll, ase_sll_walker_t walker, void* arg) void ase_sll_walk (ase_sll_t* sll, ase_sll_walker_t walker, void* arg)
{ {
ase_sll_node_t* n = sll->head; ase_sll_node_t* n = sll->head;
while (n != ASE_NULL) while (n != ASE_NULL)
{ {
walker (sll, n, arg); if (walker(sll,n,arg) == ASE_SLL_WALK_STOP) return;
n = n->next; n = n->next;
} }
} }