From 002a9d19138327953bf483419add89f2b48fe6a1 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Wed, 13 Aug 2008 07:58:57 +0000 Subject: [PATCH] --- ase/include/ase/cmn/dll.h | 243 ++++++++++++++++++++++++++++++++ ase/include/ase/cmn/makefile.am | 2 +- ase/include/ase/cmn/makefile.in | 2 +- ase/include/ase/cmn/sll.h | 18 +-- ase/lib/cmn/dll.c | 221 +++++++++++++++++++++++++++++ ase/lib/cmn/makefile.am | 2 +- ase/lib/cmn/makefile.in | 5 +- ase/lib/cmn/sll.c | 10 +- 8 files changed, 484 insertions(+), 19 deletions(-) create mode 100644 ase/include/ase/cmn/dll.h create mode 100644 ase/lib/cmn/dll.c diff --git a/ase/include/ase/cmn/dll.h b/ase/include/ase/cmn/dll.h new file mode 100644 index 00000000..c28d37c3 --- /dev/null +++ b/ase/include/ase/cmn/dll.h @@ -0,0 +1,243 @@ +/* + * $Id: map.h 223 2008-06-26 06:44:41Z baconevi $ + * + * {License} + */ + +#ifndef _ASE_CMN_DLL_H_ +#define _ASE_CMN_DLL_H_ + +#include +#include + +/* + * Singly Linked List + */ +typedef struct ase_dll_t ase_dll_t; +typedef struct ase_dll_node_t ase_dll_node_t; +typedef enum ase_dll_walk_t ase_dll_walk_t; + +/* data copier */ +typedef void* (*ase_dll_copier_t) (ase_dll_t* dll, void* dptr, ase_size_t dlen); + +/* data freeer */ +typedef void (*ase_dll_freeer_t) (ase_dll_t* dll, void* dptr, ase_size_t dlen); + +/* node visitor */ +typedef ase_dll_walk_t (*ase_dll_walker_t) ( + ase_dll_t* dll, ase_dll_node_t* node, void* arg); + +struct ase_dll_t +{ + ase_mmgr_t* mmgr; + + ase_dll_copier_t copier; + ase_dll_freeer_t freeer; + + ase_size_t size; + ase_dll_node_t* head; + ase_dll_node_t* tail; +}; + +struct ase_dll_node_t +{ + void* dptr; /* pointer to the beginning of data */ + ase_size_t dlen; /* length of data in bytes */ + ase_dll_node_t* next; /* pointer to the next node */ + ase_dll_node_t* prev; /* pointer to the prev node */ +}; + + +enum ase_dll_walk_t +{ + ASE_DLL_WALK_STOP = 0, + ASE_DLL_WALK_FORWARD = 1 +}; + +#define ASE_DLL_COPIER_INLINE ase_dll_copyinline + +#define ASE_DLL_HEAD(dll) ((dll)->head) +#define ASE_DLL_TAIL(dll) ((dll)->tail) +#define ASE_DLL_SIZE(dll) ((dll)->size) + +#define ASE_DLL_DPTR(n) ((n)->dptr) +#define ASE_DLL_DLEN(n) ((n)->dlen) +#define ASE_DLL_NEXT(n) ((n)->next) +#define ASE_DLL_PREV(n) ((n)->prev) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * NAME creates a new singly linked list + * RETURNS a pointer to a newly created singly linked list + */ +ase_dll_t* ase_dll_open ( + ase_mmgr_t* mmgr /* memory manager */ +); + +/* + * NAME creates a new singly linked list with extension + * RETURNS a pointer to a newly created singly linked list + */ +ase_dll_t* ase_dll_openx ( + ase_mmgr_t* mmgr /* memory manager */ , + ase_size_t extension /* size of extension in bytes */, + ase_fuser_t fuser +); + +/* + * NAME destroys a singly linked list + */ +void ase_dll_close ( + ase_dll_t* dll /* a singly linked list */ +); + +/* + * NAME deletes all elements of a singly linked list + */ +void ase_dll_clear ( + ase_dll_t* dll /* a singly linked list */ +); + +/* + * NAME specifies how to clone an element + * + * DESCRIPTION + * A special copier ASE_DLL_COPIER_INLINE is provided. This copier enables + * you to copy the data inline to the internal node. No freeer is invoked + * when the node is freeed. + * + * You may set the copier to ASE_NULL to perform no special operation + * when the data pointer is rememebered. + */ +void ase_dll_setcopier ( + ase_dll_t* dll /* a singly linked list */, + ase_dll_copier_t copier /* a element copier */ +); + +ase_dll_copier_t ase_dll_getcopier ( + ase_dll_t* dll /* a singly linked list */ +); + +/* + * NAME specifies how to destroy an element + * + * DESCRIPTION + * The freeer is called when a node containing the element is destroyed. + */ +void ase_dll_setfreeer ( + ase_dll_t* dll /* a singly linked list */, + ase_dll_freeer_t freeer /* a element freeer */ +); + +ase_dll_freeer_t ase_dll_getfreeer ( + ase_dll_t* dll /* a singly linked list */ +); + +/* + * NAME Gets the pointer to the extension area + * RETURN the pointer to the extension area + */ +void* ase_dll_getextension ( + ase_dll_t* dll /* a singly linked list */ +); + +/* + * NAME Gets the number of elements held in a singly linked list + * RETURN the number of elements the list holds + */ +ase_size_t ase_dll_getsize ( + ase_dll_t* dll /* a singly linked list */ +); + +/* + * NAME Gets the head(first) node + * RETURN the tail node of a singly linked list + */ +ase_dll_node_t* ase_dll_gethead ( + ase_dll_t* dll /* a singly linked list */ +); + +/* + * NAME Gets the tail(last) node + * RETURN the tail node of a singly linked list + */ +ase_dll_node_t* ase_dll_gettail ( + ase_dll_t* dll /* a singly linked list */ +); + +/* + * NAME Inserts data before a positional node given + * + * DESCRIPTION + * Inserts data. + */ +ase_dll_node_t* ase_dll_insert ( + ase_dll_t* dll /* a singly linked list */, + ase_dll_node_t* pos /* a node before which a new node is inserted */, + void* dptr /* the pointer to the data */ , + ase_size_t dlen /* the length of the data in bytes */ +); + +ase_dll_node_t* ase_dll_pushhead ( + ase_dll_t* dll /* a singly linked list */, + void* dptr, + ase_size_t dlen +); + +ase_dll_node_t* ase_dll_pushtail ( + ase_dll_t* dll /* a singly linked list */, + void* dptr, + ase_size_t dlen +); + +void ase_dll_delete ( + ase_dll_t* dll, + ase_dll_node_t* pos +); + +void ase_dll_pophead ( + ase_dll_t* dll +); + +void ase_dll_poptail ( + ase_dll_t* dll +); + +/* + * NAME Traverses s singly linked list + * + * DESCRIPTION + * A singly linked list allows uni-directional in-order traversal. + * The ase_dll_walk() function traverses a singly linkked list from its + * head node down to its tail node as long as the walker function returns + * ASE_DLL_WALK_FORWARD. A walker can return ASE_DLL_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_dll_walk() function. + */ +void ase_dll_walk ( + ase_dll_t* dll /* a singly linked list */, + ase_dll_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. + * Use ASE_DLL_COPIER_INLINE instead. + */ +void* ase_dll_copyinline ( + ase_dll_t* dll /* a singly linked list */, + void* data /* pointer to data to copy */ , + ase_size_t len /* length of data in bytes */ +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ase/include/ase/cmn/makefile.am b/ase/include/ase/cmn/makefile.am index 05fbc866..31b5b9f0 100644 --- a/ase/include/ase/cmn/makefile.am +++ b/ase/include/ase/cmn/makefile.am @@ -1,5 +1,5 @@ -pkginclude_HEADERS = mem.h str.h map.h rex.h +pkginclude_HEADERS = mem.h str.h map.h rex.h sll.h dll.h pkgincludedir= $(includedir)/ase/cmn diff --git a/ase/include/ase/cmn/makefile.in b/ase/include/ase/cmn/makefile.in index 7dd5f7b5..fa0525aa 100644 --- a/ase/include/ase/cmn/makefile.in +++ b/ase/include/ase/cmn/makefile.in @@ -178,7 +178,7 @@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ -pkginclude_HEADERS = mem.h str.h map.h rex.h +pkginclude_HEADERS = mem.h str.h map.h rex.h sll.h dll.h CLEANFILES = *dist all: all-am diff --git a/ase/include/ase/cmn/sll.h b/ase/include/ase/cmn/sll.h index c1179412..6b858c70 100644 --- a/ase/include/ase/cmn/sll.h +++ b/ase/include/ase/cmn/sll.h @@ -18,10 +18,10 @@ typedef struct ase_sll_node_t ase_sll_node_t; typedef enum ase_sll_walk_t ase_sll_walk_t; /* data copier */ -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* dptr, ase_size_t dlen); /* data freeer */ -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* dptr, ase_size_t dlen); /* node visitor */ typedef ase_sll_walk_t (*ase_sll_walker_t) ( @@ -41,13 +41,9 @@ struct ase_sll_t struct ase_sll_node_t { - struct - { - void* ptr; /* pointer to the beginning of data */ - ase_size_t len; /* length of data in bytes */ - } data; - - ase_sll_node_t* next; /* pointer to the next node */ + void* dptr; /* pointer to the beginning of data */ + ase_size_t dlen; /* length of data in bytes */ + ase_sll_node_t* next; /* pointer to the next node */ }; @@ -63,6 +59,10 @@ enum ase_sll_walk_t #define ASE_SLL_TAIL(sll) ((sll)->tail) #define ASE_SLL_SIZE(sll) ((sll)->size) +#define ASE_SLL_DPTR(n) ((n)->dptr) +#define ASE_SLL_DLEN(n) ((n)->dlen) +#define ASE_SLL_NEXT(n) ((n)->next) + #ifdef __cplusplus extern "C" { #endif diff --git a/ase/lib/cmn/dll.c b/ase/lib/cmn/dll.c new file mode 100644 index 00000000..05c1bd96 --- /dev/null +++ b/ase/lib/cmn/dll.c @@ -0,0 +1,221 @@ +/* + * $Id$ + * + * {License} + */ + +#include +#include "mem.h" + +void* ase_dll_copyinline (ase_dll_t* dll, void* dptr, ase_size_t dlen) +{ + /* this is a dummy copier */ + return ASE_NULL; +} + +ase_dll_t* ase_dll_open (ase_mmgr_t* mmgr) +{ + return ase_dll_openx (mmgr, 0, ASE_NULL); +} + +ase_dll_t* ase_dll_openx (ase_mmgr_t* mmgr, ase_size_t extension, ase_fuser_t fuser) +{ + ase_dll_t* dll; + + dll = ASE_MALLOC (mmgr, ASE_SIZEOF(ase_dll_t) + extension); + if (dll == ASE_NULL) return ASE_NULL; + + ASE_MEMSET (dll, 0, ASE_SIZEOF(ase_dll_t) + extension); + if (fuser != ASE_NULL) mmgr = fuser (mmgr, dll + 1); + dll->mmgr = mmgr; + + return dll; +} + +void ase_dll_close (ase_dll_t* dll) +{ + ase_dll_clear (dll); + ASE_FREE (dll->mmgr, dll); +} + +void ase_dll_clear (ase_dll_t* dll) +{ + while (dll->head != ASE_NULL) ase_dll_delete (dll, dll->head); + ASE_ASSERT (dll->tail == ASE_NULL); +} + +void* ase_dll_getextension (ase_dll_t* dll) +{ + return dll + 1; +} + +ase_size_t ase_dll_getsize (ase_dll_t* dll) +{ + return dll->size; +} + +ase_dll_node_t* ase_dll_gethead (ase_dll_t* dll) +{ + return dll->head; +} + +ase_dll_node_t* ase_dll_gettail (ase_dll_t* dll) +{ + return dll->tail; +} + +ase_dll_copier_t ase_dll_getcopier (ase_dll_t* dll) +{ + return dll->copier; +} + +void ase_dll_setcopier (ase_dll_t* dll, ase_dll_copier_t copier) +{ + dll->copier = copier; +} + +ase_dll_freeer_t ase_dll_getfreeer (ase_dll_t* dll) +{ + return dll->freeer; +} + +void ase_dll_setfreeer (ase_dll_t* dll, ase_dll_freeer_t freeer) +{ + dll->freeer = freeer; +} + +static ase_dll_node_t* alloc_node (ase_dll_t* dll, void* dptr, ase_size_t dlen) +{ + ase_dll_node_t* n; + + if (dll->copier == ASE_NULL) + { + n = ASE_MALLOC (dll->mmgr, ASE_SIZEOF(ase_dll_node_t)); + if (n == ASE_NULL) return ASE_NULL; + n->dptr = dptr; + } + else if (dll->copier == ASE_DLL_COPIER_INLINE) + { + n = ASE_MALLOC (dll->mmgr, ASE_SIZEOF(ase_dll_node_t) + dlen); + if (n == ASE_NULL) return ASE_NULL; + + ASE_MEMCPY (n + 1, dptr, dlen); + n->dptr = n + 1; + } + else + { + n = ASE_MALLOC (dll->mmgr, ASE_SIZEOF(ase_dll_node_t)); + if (n == ASE_NULL) return ASE_NULL; + n->dptr = dll->copier (dll, dptr, dlen); + } + + n->dlen = dlen; + n->next = ASE_NULL; + n->prev = ASE_NULL; + + return n; +} + +ase_dll_node_t* ase_dll_insert ( + ase_dll_t* dll, ase_dll_node_t* pos, void* dptr, ase_size_t dlen) +{ + ase_dll_node_t* n = alloc_node (dll, dptr, dlen); + if (n == ASE_NULL) return ASE_NULL; + + if (pos == ASE_NULL) + { + /* insert at the end */ + if (dll->head == ASE_NULL) + { + ASE_ASSERT (dll->tail == ASE_NULL); + dll->head = n; + } + else dll->tail->next = n; + + dll->tail = n; + } + else + { + /* insert in front of the positional node */ + n->next = pos; + if (pos == dll->head) dll->head = n; + else + { + /* take note of performance penalty */ + ase_dll_node_t* n2 = dll->head; + while (n2->next != pos) n2 = n2->next; + n2->next = n; + } + } + + dll->size++; + return n; +} + +ase_dll_node_t* ase_dll_pushhead (ase_dll_t* dll, void* data, ase_size_t size) +{ + return ase_dll_insert (dll, dll->head, data, size); +} + +ase_dll_node_t* ase_dll_pushtail (ase_dll_t* dll, void* data, ase_size_t size) +{ + return ase_dll_insert (dll, ASE_NULL, data, size); +} + +void ase_dll_delete (ase_dll_t* dll, ase_dll_node_t* pos) +{ + if (pos == ASE_NULL) return; /* not a valid node */ + + if (pos == dll->head) + { + /* it is simple to delete the head node */ + dll->head = pos->next; + if (dll->head == ASE_NULL) dll->tail = ASE_NULL; + } + else + { + /* but deletion of other nodes has significant performance + * penalty as it has look for the predecessor of the + * target node */ + ase_dll_node_t* n2 = dll->head; + while (n2->next != pos) n2 = n2->next; + + n2->next = pos->next; + + /* update the tail node if necessary */ + if (pos == dll->tail) dll->tail = n2; + } + + if (dll->freeer != ASE_NULL) + { + /* free the actual data */ + dll->freeer (dll, pos->dptr, pos->dlen); + } + + /* free the node */ + ASE_FREE (dll->mmgr, pos); + + /* decrement the number of elements */ + dll->size--; +} + +void ase_dll_pophead (ase_dll_t* dll) +{ + ase_dll_delete (dll, dll->head); +} + +void ase_dll_poptail (ase_dll_t* dll) +{ + ase_dll_delete (dll, dll->tail); +} + +void ase_dll_walk (ase_dll_t* dll, ase_dll_walker_t walker, void* arg) +{ + ase_dll_node_t* n = dll->head; + + while (n != ASE_NULL) + { + if (walker(dll,n,arg) == ASE_DLL_WALK_STOP) return; + n = n->next; + } +} diff --git a/ase/lib/cmn/makefile.am b/ase/lib/cmn/makefile.am index 58a316ac..1eb63fc3 100644 --- a/ase/lib/cmn/makefile.am +++ b/ase/lib/cmn/makefile.am @@ -4,6 +4,6 @@ AM_CFLAGS = -I$(top_builddir)/include lib_LTLIBRARIES = libasecmn.la libasecmn_la_SOURCES = mem.h \ - map.c mem.c misc.c rex.c str_bas.c str_cnv.c str_dyn.c sll.c + map.c mem.c misc.c rex.c str_bas.c str_cnv.c str_dyn.c sll.c dll.c libasecmn_la_LDFLAGS = -version-info 1:0:0 diff --git a/ase/lib/cmn/makefile.in b/ase/lib/cmn/makefile.in index a0d7074d..75ab79a5 100644 --- a/ase/lib/cmn/makefile.in +++ b/ase/lib/cmn/makefile.in @@ -56,7 +56,7 @@ libLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) libasecmn_la_LIBADD = am_libasecmn_la_OBJECTS = map.lo mem.lo misc.lo rex.lo str_bas.lo \ - str_cnv.lo str_dyn.lo sll.lo + str_cnv.lo str_dyn.lo sll.lo dll.lo libasecmn_la_OBJECTS = $(am_libasecmn_la_OBJECTS) DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/autoconf/depcomp @@ -196,7 +196,7 @@ AUTOMAKE_OPTIONS = nostdinc AM_CFLAGS = -I$(top_builddir)/include lib_LTLIBRARIES = libasecmn.la libasecmn_la_SOURCES = mem.h \ - map.c mem.c misc.c rex.c str_bas.c str_cnv.c str_dyn.c sll.c + map.c mem.c misc.c rex.c str_bas.c str_cnv.c str_dyn.c sll.c dll.c libasecmn_la_LDFLAGS = -version-info 1:0:0 all: all-am @@ -268,6 +268,7 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dll.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@ diff --git a/ase/lib/cmn/sll.c b/ase/lib/cmn/sll.c index 4edeced1..48db2a84 100644 --- a/ase/lib/cmn/sll.c +++ b/ase/lib/cmn/sll.c @@ -92,7 +92,7 @@ static ase_sll_node_t* alloc_node (ase_sll_t* sll, void* dptr, ase_size_t dlen) { n = ASE_MALLOC (sll->mmgr, ASE_SIZEOF(ase_sll_node_t)); if (n == ASE_NULL) return ASE_NULL; - n->data.ptr = dptr; + n->dptr = dptr; } else if (sll->copier == ASE_SLL_COPIER_INLINE) { @@ -100,16 +100,16 @@ static ase_sll_node_t* alloc_node (ase_sll_t* sll, void* dptr, ase_size_t dlen) if (n == ASE_NULL) return ASE_NULL; ASE_MEMCPY (n + 1, dptr, dlen); - n->data.ptr = n + 1; + n->dptr = n + 1; } else { n = ASE_MALLOC (sll->mmgr, ASE_SIZEOF(ase_sll_node_t)); if (n == ASE_NULL) return ASE_NULL; - n->data.ptr = sll->copier (sll, dptr, dlen); + n->dptr = sll->copier (sll, dptr, dlen); } - n->data.len = dlen; + n->dlen = dlen; n->next = ASE_NULL; return n; @@ -188,7 +188,7 @@ void ase_sll_delete (ase_sll_t* sll, ase_sll_node_t* pos) if (sll->freeer != ASE_NULL) { /* free the actual data */ - sll->freeer (sll, pos->data.ptr, pos->data.len); + sll->freeer (sll, pos->dptr, pos->dlen); } /* free the node */