enhanced dll
This commit is contained in:
		| @ -2,7 +2,7 @@ pkgincludedir = $(includedir)/qse/cmn | ||||
|  | ||||
| pkginclude_HEADERS = \ | ||||
| 	mem.h xma.h fma.h chr.h str.h lda.h htb.h rbt.h \ | ||||
| 	rex.h sll.h dll.h opt.h tio.h \ | ||||
| 	rex.h sll.h gdl.h dll.h opt.h tio.h \ | ||||
| 	fio.h pio.h sio.h time.h misc.h main.h stdio.h   | ||||
|  | ||||
| if ENABLE_CXX | ||||
|  | ||||
| @ -52,8 +52,9 @@ CONFIG_CLEAN_VPATH_FILES = | ||||
| SOURCES = | ||||
| DIST_SOURCES = | ||||
| am__pkginclude_HEADERS_DIST = mem.h xma.h fma.h chr.h str.h lda.h \ | ||||
| 	htb.h rbt.h rex.h sll.h dll.h opt.h tio.h fio.h pio.h sio.h \ | ||||
| 	time.h misc.h main.h stdio.h Mmgr.hpp StdMmgr.hpp Mmged.hpp | ||||
| 	htb.h rbt.h rex.h sll.h gdl.h dll.h opt.h tio.h fio.h pio.h \ | ||||
| 	sio.h time.h misc.h main.h stdio.h Mmgr.hpp StdMmgr.hpp \ | ||||
| 	Mmged.hpp | ||||
| am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; | ||||
| am__vpath_adj = case $$p in \ | ||||
|     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ | ||||
| @ -221,8 +222,8 @@ top_build_prefix = @top_build_prefix@ | ||||
| top_builddir = @top_builddir@ | ||||
| top_srcdir = @top_srcdir@ | ||||
| pkginclude_HEADERS = mem.h xma.h fma.h chr.h str.h lda.h htb.h rbt.h \ | ||||
| 	rex.h sll.h dll.h opt.h tio.h fio.h pio.h sio.h time.h misc.h \ | ||||
| 	main.h stdio.h $(am__append_1) | ||||
| 	rex.h sll.h gdl.h dll.h opt.h tio.h fio.h pio.h sio.h time.h \ | ||||
| 	misc.h main.h stdio.h $(am__append_1) | ||||
| all: all-am | ||||
|  | ||||
| .SUFFIXES: | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: dll.h 352 2010-08-31 13:20:34Z hyunghwan.chung $ | ||||
|  * $Id: dll.h 354 2010-09-03 12:50:08Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -21,162 +21,216 @@ | ||||
| #ifndef _QSE_CMN_DLL_H_ | ||||
| #define _QSE_CMN_DLL_H_ | ||||
|  | ||||
| /** @file | ||||
|  * This file defines a doubly linked list interface. | ||||
|  */ | ||||
|  | ||||
| #include <qse/types.h> | ||||
| #include <qse/macros.h> | ||||
| #include <qse/cmn/gdl.h> | ||||
|  | ||||
| /** | ||||
|  * The qse_dll_nhdr_t type defines a common node header fields used internally. | ||||
|  */ | ||||
| typedef struct qse_dll_nhdr_t qse_dll_nhdr_t; | ||||
| struct qse_dll_nhdr_t | ||||
| { | ||||
| 	qse_dll_nhdr_t* next; | ||||
| 	qse_dll_nhdr_t* prev; | ||||
| }; | ||||
|  | ||||
| #define __QSE_DLL_WRAP(x) do { x } while(0) | ||||
| #define QSE_DLL_DEFINE(list_type,node_type,data_define,manage_define) \ | ||||
| 	typedef struct list_type list_type; \ | ||||
| 	typedef struct node_type node_type; \ | ||||
| 	struct node_type \ | ||||
| 	{ \ | ||||
| 		node_type* prev; \ | ||||
| 		node_type* next; \ | ||||
| 		data_define \ | ||||
| 	}; \ | ||||
| 	struct list_type \ | ||||
| 	{ \ | ||||
| 		node_type   gdl; \ | ||||
| 		qse_size_t  size; \ | ||||
| 		manage_define \ | ||||
| 	} | ||||
|  | ||||
| #define QSE_DLL_TYPE(data_type) qse_dll_ ## data_type ## _t | ||||
| #define QSE_DLL_NODE_TYPE(data_type) qse_dll_ ## data_type ## _node_t | ||||
|  | ||||
| /** | ||||
|  * The QSE_DLL_DEFINE macro defines a new doubly-linked list type for data | ||||
|  * The QSE_DLL_DEFINE_SIMPLE macro defines a doubly-linked list type for data | ||||
|  * of the @a data_type type. | ||||
|  */ | ||||
| #define QSE_DLL_DEFINE(data_type) \ | ||||
| 	typedef struct QSE_DLL_TYPE(data_type) QSE_DLL_TYPE(data_type); \ | ||||
| 	typedef struct QSE_DLL_NODE_TYPE(data_type) QSE_DLL_NODE_TYPE(data_type); \ | ||||
| 	struct QSE_DLL_NODE_TYPE(data_type) \ | ||||
| 	{ \ | ||||
| 		QSE_DLL_NODE_TYPE(data_type)* next; \ | ||||
| 		QSE_DLL_NODE_TYPE(data_type)* prev; \ | ||||
| 		data_type data; \ | ||||
| 	}; \ | ||||
| 	struct QSE_DLL_TYPE(data_type) \ | ||||
| 	{ \ | ||||
| 		QSE_DLL_NODE_TYPE(data_type) link; \ | ||||
| 	} | ||||
| #define QSE_DLL_DEFINE_SIMPLE(data_type) \ | ||||
| 	QSE_DLL_DEFINE ( \ | ||||
| 		QSE_DLL_TYPE(data_type), \ | ||||
| 		QSE_DLL_NODE_TYPE(data_type), \ | ||||
| 		data_type data;, \ | ||||
| 	) | ||||
|  | ||||
| /** | ||||
|  * The QSE_DLL_DEFINE macro defines a new doubly-linked list type for data | ||||
|  * The QSE_DLL_DEFINE_MANAGED macro defines a doubly-linked list type for data | ||||
|  * of the @a data_type type. | ||||
|  */ | ||||
| #define QSE_DLL_DEFINE_MANAGED(data_type,manage_type) \ | ||||
| 	typedef struct QSE_DLL_TYPE(data_type) QSE_DLL_TYPE(data_type); \ | ||||
| 	typedef struct QSE_DLL_NODE_TYPE(data_type) QSE_DLL_NODE_TYPE(data_type); \ | ||||
| 	struct QSE_DLL_NODE_TYPE(data_type) \ | ||||
| 	{ \ | ||||
| 		QSE_DLL_NODE_TYPE(data_type)* next; \ | ||||
| 		QSE_DLL_NODE_TYPE(data_type)* prev; \ | ||||
| 		data_type data; \ | ||||
| 	}; \ | ||||
| 	struct QSE_DLL_TYPE(data_type) \ | ||||
| 	{ \ | ||||
| 		QSE_DLL_NODE_TYPE(data_type) link; \ | ||||
| 	QSE_DLL_DEFINE ( \ | ||||
| 		QSE_DLL_TYPE(data_type), \ | ||||
| 		QSE_DLL_NODE_TYPE(data_type), \ | ||||
| 		data_type data;, \ | ||||
| 		manage_type data; \ | ||||
| 	} | ||||
| 	) | ||||
|  | ||||
| #define QSE_DLL_INIT(dll) __QSE_DLL_WRAP ( \ | ||||
| 	(dll)->link.next = &(dll)->link; \ | ||||
| 	(dll)->link.prev = &(dll)->link; \ | ||||
| ) | ||||
| #define QSE_DLL_INIT(dll) \ | ||||
| 	QSE_BLOCK ( \ | ||||
| 		QSE_GDL_INIT(&(dll)->gdl); \ | ||||
| 		(dll)->size = 0; \ | ||||
| 	) | ||||
|  | ||||
| #define QSE_DLL_FINI(dll) __QSE_DLL_WRAP ( \ | ||||
| 	while (!QSE_DLL_ISEMPTY(dll)) QSE_DLL_DELHEAD(dll); \ | ||||
| ) | ||||
| #define QSE_DLL_FINI(dll) QSE_DLL_CLEAR(dll) | ||||
|  | ||||
| #define QSE_DLL_CHAIN(dll,p,x,n) __QSE_DLL_WRAP ( \ | ||||
| 	register qse_dll_nhdr_t* __qse_dll_chain_prev = (qse_dll_nhdr_t*)(p); \ | ||||
| 	register qse_dll_nhdr_t* __qse_dll_chain_next = (qse_dll_nhdr_t*)(n); \ | ||||
| 	(x)->prev = (void*)__qse_dll_chain_prev; \ | ||||
| 	(x)->next = (void*)__qse_dll_chain_next; \ | ||||
| 	__qse_dll_chain_next->prev = (void*)(x); \ | ||||
| 	__qse_dll_chain_prev->next = (void*)(x); \ | ||||
| ) | ||||
| #define QSE_DLL_CHAIN(dll,p,x,n)  \ | ||||
| 	QSE_BLOCK ( \ | ||||
| 		QSE_GDL_CHAIN ((qse_gdl_t*)p, (qse_gdl_t*)x, (qse_gdl_t*)n); \ | ||||
| 		(dll)->size++; \ | ||||
| 	) | ||||
|  | ||||
| #define QSE_DLL_UNCHAIN(dll,x) __QSE_DLL_WRAP ( \ | ||||
| 	register qse_dll_nhdr_t* __qse_dll_unchain_prev = \ | ||||
| 		(qse_dll_nhdr_t*)((x)->prev); \ | ||||
| 	register qse_dll_nhdr_t* __qse_dll_unchain_next = \ | ||||
| 		(qse_dll_nhdr_t*)((x)->next); \ | ||||
| 	__qse_dll_unchain_next->prev = __qse_dll_unchain_prev; \ | ||||
| 	__qse_dll_unchain_prev->next = __qse_dll_unchain_next; \ | ||||
| ) | ||||
| #define QSE_DLL_UNCHAIN(dll,x) \ | ||||
| 	QSE_BLOCK ( \ | ||||
| 		QSE_GDL_UNCHAIN ((qse_gdl_t*)x); \ | ||||
| 		(dll)->size--; \ | ||||
| 	) | ||||
|  | ||||
| #define QSE_DLL_HEADNODE(dll) ((dll)->link.next) | ||||
| #define QSE_DLL_TAILNODE(dll) ((dll)->link.prev) | ||||
| #define QSE_DLL_NEXTNODE(dll,p) ((p)->next) | ||||
| #define QSE_DLL_PREVNODE(dll,p) ((p)->prev) | ||||
| #define QSE_DLL_ISVALIDNODE(dll,p) ((p) != &(dll)->link) | ||||
| #define QSE_DLL_CLEAR(dll) \ | ||||
| 	QSE_BLOCK ( \ | ||||
| 		while (!QSE_DLL_ISEMPTY(dll)) QSE_DLL_DELHEAD(dll); \ | ||||
| 	) | ||||
|  | ||||
| #define QSE_DLL_ISEMPTY(dll) (QSE_DLL_HEADNODE(dll) == &(dll)->link) | ||||
| #define QSE_DLL_ADDHEAD(dll,x) QSE_DLL_CHAIN(dll,&(dll)->link,x,QSE_DLL_HEADNODE(dll)) | ||||
| #define QSE_DLL_ADDTAIL(dll,x) QSE_DLL_CHAIN(dll,QSE_DLL_TAILNODE(dll),x,&(dll)->link) | ||||
| #define QSE_DLL_DELHEAD(dll) QSE_DLL_UNCHAIN(dll,QSE_DLL_HEADNODE(dll)) | ||||
| #define QSE_DLL_DELTAIL(dll) QSE_DLL_UNCHAIN(dll,QSE_DLL_TAILNODE(dll)) | ||||
| 		 | ||||
| /* | ||||
|  * Doubly Linked List | ||||
| /** | ||||
|  * The QSE_DLL_ISEMPTY macro determines if a list @a dll is empty  | ||||
|  */ | ||||
| #define QSE_DLL_ISEMPTY(dll) QSE_GDL_ISEMPTY(&(dll)->gdl) | ||||
|  | ||||
| /** | ||||
|  * The QSE_DLL_ISMEMBER macro determines if a node @a x is a member | ||||
|  * of a list @a dll. | ||||
|  */ | ||||
| #define QSE_DLL_ISMEMBER(dll,x) ((x) != &(dll)->gdl) | ||||
|  | ||||
| #define QSE_DLL_HEAD(dll) QSE_GDL_HEAD(&(dll)->gdl) | ||||
| #define QSE_DLL_TAIL(dll) QSE_GDL_TAIL(&(dll)->gdl) | ||||
| #define QSE_DLL_SIZE(dll) ((dll)->size) | ||||
|  | ||||
| /** | ||||
|  * The QSE_DLL_ADDHEAD macro add a member node @a x to the head of  | ||||
|  * the list @a dll. | ||||
|  */ | ||||
| #define QSE_DLL_ADDHEAD(dll,x) \ | ||||
| 	QSE_DLL_CHAIN(dll,&(dll)->gdl,x,QSE_DLL_HEAD(dll)) | ||||
|  | ||||
| /** | ||||
|  * The QSE_DLL_ADDHEAD macro add a member node @a x to the tail of  | ||||
|  * the list @a dll. | ||||
|  */ | ||||
| #define QSE_DLL_ADDTAIL(dll,x) \ | ||||
| 	QSE_DLL_CHAIN(dll,QSE_DLL_TAIL(dll),x,&(dll)->gdl) | ||||
|  | ||||
| /** | ||||
|  * The QSE_DLL_DELHEAD macro deletes the head node. | ||||
|  */ | ||||
| #define QSE_DLL_DELHEAD(dll) \ | ||||
| 	QSE_DLL_UNCHAIN(dll,QSE_DLL_HEAD(dll)) | ||||
|  | ||||
| /** | ||||
|  * The QSE_DLL_DELTAIL macro deletes the tail node. | ||||
|  */ | ||||
| #define QSE_DLL_DELTAIL(dll) \ | ||||
| 	QSE_DLL_UNCHAIN(dll,QSE_DLL_TAIL(dll)) | ||||
| 		 | ||||
|  | ||||
| /* ----------- more general implementation below ----------------- */ | ||||
| enum qse_dll_walk_t | ||||
| { | ||||
| 	QSE_DLL_WALK_STOP     = 0, | ||||
| 	QSE_DLL_WALK_FORWARD  = 1, | ||||
| 	QSE_DLL_WALK_BACKWARD = 2 | ||||
| }; | ||||
| typedef enum qse_dll_walk_t qse_dll_walk_t; | ||||
|  | ||||
| typedef struct qse_dll_t qse_dll_t; | ||||
| typedef struct qse_dll_node_t qse_dll_node_t; | ||||
|  | ||||
| /* data copier */ | ||||
| typedef void* (*qse_dll_copier_t) (qse_dll_t* dll, void* dptr, qse_size_t dlen); | ||||
| typedef void* (*qse_dll_copier_t) ( | ||||
| 	qse_dll_t* dll, | ||||
| 	void*      dptr, | ||||
| 	qse_size_t dlen | ||||
| ); | ||||
|  | ||||
| /* data freeer */ | ||||
| typedef void (*qse_dll_freeer_t) (qse_dll_t* dll, void* dptr, qse_size_t dlen); | ||||
| typedef void (*qse_dll_freeer_t) ( | ||||
| 	qse_dll_t* dll, | ||||
| 	void*      dptr, | ||||
| 	qse_size_t dlen | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_dll_comper_t type defines a key comparator that is called when | ||||
|  * the list needs to compare data. A doubly linked list is created with a | ||||
|  * default comparator that performs bitwise comparison. | ||||
|  * | ||||
|  * The comparator must return 0 if the data are the same and a non-zero | ||||
|  * integer otherwise. | ||||
|  */ | ||||
| typedef int (*qse_dll_comper_t) ( | ||||
| 	qse_dll_t*  dll,   /**< doubly linked list */ | ||||
| 	const void* dptr1, /**< data pointer */ | ||||
| 	qse_size_t  dlen1, /**< data length */ | ||||
| 	const void* dptr2, /**< data pointer */ | ||||
| 	qse_size_t  dlen2  /**< data length */ | ||||
| ); | ||||
|  | ||||
| /* node visitor */ | ||||
| typedef int (*qse_dll_walker_t) ( | ||||
| 	qse_dll_t* dll, qse_dll_node_t* node, void* arg); | ||||
|  | ||||
| struct qse_dll_t | ||||
| { | ||||
| 	qse_mmgr_t* mmgr; | ||||
|  | ||||
| 	qse_dll_copier_t copier; | ||||
| 	qse_dll_freeer_t freeer; | ||||
|  | ||||
| 	qse_size_t size; | ||||
| 	qse_dll_node_t* head; | ||||
| 	qse_dll_node_t* tail; | ||||
| }; | ||||
| typedef qse_dll_walk_t (*qse_dll_walker_t) ( | ||||
| 	qse_dll_t*      dll,  | ||||
| 	qse_dll_node_t* node, | ||||
| 	void*           ctx | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_dll_node_t type defines a doubly linked list node. | ||||
|  */ | ||||
| struct qse_dll_node_t | ||||
| { | ||||
| 	void* dptr; /* pointer to the beginning of data */ | ||||
| 	qse_size_t dlen; /* length of data in bytes */ | ||||
| 	qse_dll_node_t* next; /* pointer to the next node */ | ||||
| 	qse_dll_node_t* prev; /* pointer to the prev node */ | ||||
| 	/* the first two fields in sync with qse_gdl_t */ | ||||
| 	qse_dll_node_t* prev; | ||||
| 	qse_dll_node_t* next; | ||||
|  | ||||
| 	void*      dptr; /**< data pointer */ | ||||
| 	qse_size_t dlen; /**< data length */ | ||||
| }; | ||||
|  | ||||
|  | ||||
| enum qse_dll_walk_t | ||||
| /** | ||||
|  * The qse_dll_t type defines a doubly linked list. | ||||
|  */ | ||||
| struct qse_dll_t | ||||
| { | ||||
| 	QSE_DLL_WALK_STOP = 0, | ||||
| 	QSE_DLL_WALK_FORWARD = 1 | ||||
| 	QSE_DEFINE_COMMON_FIELDS (dll) | ||||
|  | ||||
| 	qse_dll_node_t gdl; | ||||
| 	qse_size_t     size; | ||||
|  | ||||
| 	qse_byte_t       scale;   | ||||
| 	qse_dll_copier_t copier;  | ||||
| 	qse_dll_freeer_t freeer; | ||||
| 	qse_dll_comper_t comper; | ||||
| }; | ||||
|  | ||||
| #define QSE_DLL_COPIER_INLINE qse_dll_copyinline | ||||
| #define QSE_DLL_COPIER_SIMPLE ((qse_dll_copier_t)1) | ||||
| #define QSE_DLL_COPIER_INLINE ((qse_dll_copier_t)2) | ||||
|  | ||||
| #define QSE_DLL_HEAD(dll) ((dll)->head) | ||||
| #define QSE_DLL_TAIL(dll) ((dll)->tail) | ||||
| #define QSE_DLL_SIZE(dll) ((dll)->size) | ||||
| #define QSE_DLL_SCALE(dll) ((dll)->scale) | ||||
| #define QSE_DLL_DPTR(node) ((node)->dptr) | ||||
| #define QSE_DLL_DLEN(node) ((node)->dlen) | ||||
|  | ||||
| #define QSE_DLL_DPTR(n) ((n)->dptr) | ||||
| #define QSE_DLL_DLEN(n) ((n)->dlen) | ||||
| #define QSE_DLL_NEXT(n) ((n)->next) | ||||
| #define QSE_DLL_PREV(n) ((n)->prev) | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| /*  | ||||
|  * NAME: creates a doubly linked list with extension area | ||||
|  * | ||||
|  * DESCRIPTION: | ||||
| QSE_DEFINE_COMMON_FUNCTIONS (dll) | ||||
|  | ||||
| /**  | ||||
|  *  The qse_dll_open() function creates an empty doubly linked list. | ||||
|  *  If the memory manager mmgr is QSE_NULL, the function gets the default | ||||
|  *  memory manager with QSE_MMGR_GETMMGR() and uses it if it is not QSE_NULL. | ||||
| @ -185,141 +239,175 @@ extern "C" { | ||||
|  *  after initializing the main area. The extension initializer is passed | ||||
|  *  the pointer to the doubly linked list created. | ||||
|  * | ||||
|  * RETURNS:  | ||||
|  * @return | ||||
|  *  the pointer to a newly created doubly linked list on success. | ||||
|  *  QSE_NULL on failure. | ||||
|  * | ||||
|  * WARNING: | ||||
|  *  In the debug build, it fails the assertion if QSE_MMGR_SETMMGR() returns | ||||
|  *  QSE_NULL when QSE_NULL is passed as the first parameter. In the release | ||||
|  *  build, it returns QSE_NULL if such a thing happens.  | ||||
|  */ | ||||
|  | ||||
| qse_dll_t* qse_dll_open ( | ||||
| 	qse_mmgr_t* mmgr /* memory manager */ ,  | ||||
| 	qse_size_t ext /* size of extension area in bytes */ | ||||
| 	qse_mmgr_t* mmgr,   /**< memory manager */  | ||||
| 	qse_size_t  xtnsize /**< size of extension area in bytes */ | ||||
| ); | ||||
|  | ||||
| /*  | ||||
|  * NAME destroys a singly linked list  | ||||
| /**  | ||||
|  * The qse_dll_close() function destroys a doubly linked list. | ||||
|  */ | ||||
| void qse_dll_close ( | ||||
| 	qse_dll_t* dll /* a singly linked list */ | ||||
| 	qse_dll_t* dll /** doubly linked list */ | ||||
| ); | ||||
|  | ||||
| /*  | ||||
|  * NAME deletes all elements of a singly linked list  | ||||
| /** | ||||
|  * The qse_dll_init() function initializes a statically declared list. | ||||
|  */ | ||||
| void qse_dll_clear ( | ||||
| 	qse_dll_t* dll /* a singly linked list */ | ||||
| qse_dll_t* qse_dll_init ( | ||||
| 	qse_dll_t*  dll, /**< doubly linked list */ | ||||
| 	qse_mmgr_t* mmgr /**< memory manager */ | ||||
| ); | ||||
|  | ||||
| /* | ||||
|  * NAME specifies how to clone an element | ||||
|  * | ||||
|  * DESCRIPTION | ||||
|  *  A special copier QSE_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 QSE_NULL to perform no special operation  | ||||
|  *  when the data pointer is rememebered. | ||||
| /** | ||||
|  * The qse_dll_fini() function finalizes a statically initialized list. | ||||
|  */ | ||||
| void qse_dll_fini ( | ||||
| 	qse_dll_t* dll /**< doubly linked list */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_dll_getscale() function gets the scale factor | ||||
|  */ | ||||
| int qse_dll_getscale ( | ||||
| 	qse_dll_t* dll  /**< doubly linked list */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  *  The qse_dll_setscale() function sets the scale factor of the data length. | ||||
|  *  A scale factor determines the actual length of data in bytes. A doubly  | ||||
|  *  linked list created with a scale factor of 1. The scale factor should be | ||||
|  *  larger than 0 and less than 256. | ||||
|  */ | ||||
| void qse_dll_setscale ( | ||||
| 	qse_dll_t* dll,     /**< doubly linked list */ | ||||
| 	int        scale    /**< scale factor */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_dll_setcopier() function changes the element copier. | ||||
|  * A special copier QSE_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 QSE_NULL to perform | ||||
|  * no special operation when the data pointer is rememebered. | ||||
|  */ | ||||
| void qse_dll_setcopier ( | ||||
| 	qse_dll_t* dll /* a singly linked list */,  | ||||
| 	qse_dll_copier_t copier /* a element copier */ | ||||
| 	qse_dll_t*       dll,   /**< doubly linked list */ | ||||
| 	qse_dll_copier_t copier /**< element copier */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_dll_getcopier() function returns the element copier. | ||||
|  */ | ||||
| qse_dll_copier_t qse_dll_getcopier ( | ||||
| 	qse_dll_t* dll /* a singly linked list */ | ||||
| 	qse_dll_t* dll /**< doubly linked list */ | ||||
| ); | ||||
|  | ||||
| /* | ||||
|  * NAME specifies how to destroy an element | ||||
|  * | ||||
|  * DESCRIPTION | ||||
|  *  The freeer is called when a node containing the element is destroyed. | ||||
| /** | ||||
|  * The qse_dll_setfreeer() function changes the element freeer. | ||||
|  * The freeer is called when a node containing the element is destroyed. | ||||
|  */ | ||||
| void qse_dll_setfreeer ( | ||||
| 	qse_dll_t* dll /* a singly linked list */, | ||||
| 	qse_dll_freeer_t freeer /* a element freeer */ | ||||
| 	qse_dll_t*       dll,   /**< doubly linked list */ | ||||
| 	qse_dll_freeer_t freeer /**< element freeer */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_dll_getfreeer() function returns the element freeer. | ||||
|  */ | ||||
| qse_dll_freeer_t qse_dll_getfreeer ( | ||||
| 	qse_dll_t* dll /* a singly linked list */ | ||||
| 	qse_dll_t* dll /**< doubly linked list */ | ||||
| ); | ||||
|  | ||||
| /* | ||||
|  * NAME Gets the pointer to the extension area | ||||
|  * RETURN the pointer to the extension area | ||||
|  */ | ||||
| void* qse_dll_getxtn ( | ||||
| 	qse_dll_t* dll /* a singly linked list */ | ||||
| ); | ||||
|  | ||||
| /* | ||||
|  * NAME: get the pointer to the memory manager in use  | ||||
|  */ | ||||
| qse_mmgr_t* qse_dll_getmmgr ( | ||||
| 	qse_dll_t* dll /* a singly linked list */ | ||||
| ); | ||||
|  | ||||
| void qse_dll_setmmgr (qse_dll_t* dll, qse_mmgr_t* mmgr); | ||||
|  | ||||
| /* | ||||
|  * NAME Gets the number of elements held in a singly linked list | ||||
|  * RETURN the number of elements the list holds | ||||
| /** | ||||
|  * The qse_dll_getsize() function returns the number of the data nodes held | ||||
|  * in a doubly linked list. | ||||
|  */ | ||||
| qse_size_t qse_dll_getsize ( | ||||
| 	qse_dll_t* dll /* a singly linked list */ | ||||
| 	qse_dll_t* dll  /**< doubly linked list */ | ||||
| ); | ||||
|  | ||||
| /* | ||||
|  * NAME Gets the head(first) node  | ||||
|  * RETURN the tail node of a singly linked list | ||||
| /** | ||||
|  * The qse_dll_gethead() function gets the head node. You may use the  | ||||
|  * #QSE_DLL_HEAD macro instead. | ||||
|  */ | ||||
| qse_dll_node_t* qse_dll_gethead ( | ||||
| 	qse_dll_t* dll /* a singly linked list */ | ||||
| 	qse_dll_t* dll  /**< doubly linked list */ | ||||
| ); | ||||
|  | ||||
| /*  | ||||
|  * NAME Gets the tail(last) node  | ||||
|  * RETURN the tail node of a singly linked list | ||||
| /** | ||||
|  * The qse_dll_gettail() function gets the head node. You may use the  | ||||
|  * #QSE_DLL_TAIL macro instead. | ||||
|  */ | ||||
| qse_dll_node_t* qse_dll_gettail ( | ||||
| 	qse_dll_t* dll /* a singly linked list */ | ||||
| 	qse_dll_t* dll  /**< doubly linked list */ | ||||
| ); | ||||
|  | ||||
| /*  | ||||
|  * NAME Inserts data before a positional node given  | ||||
|  * | ||||
|  * DESCRIPTION | ||||
|  *   Inserts data. | ||||
|  | ||||
| qse_dll_node_t* qse_dll_search ( | ||||
| 	qse_dll_t*      dll,   /**< doubly linked list */ | ||||
| 	qse_dll_node_t* pos,   /**< positional node */ | ||||
| 	const void*     dptr,  /**< data pointer */ | ||||
| 	qse_size_t      dlen   /**< data length */ | ||||
| ); | ||||
|  | ||||
| qse_dll_node_t* qse_dll_rsearch ( | ||||
| 	qse_dll_t*      dll,   /**< doubly linked list */ | ||||
| 	qse_dll_node_t* pos,   /**< positional node */ | ||||
| 	const void*     dptr,  /**< data pointer */ | ||||
| 	qse_size_t      dlen   /**< data length */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_dll_insert() function insert an element into a list  | ||||
|  */ | ||||
| qse_dll_node_t* qse_dll_insert ( | ||||
| 	qse_dll_t* dll /* a singly linked list */, | ||||
| 	qse_dll_node_t* pos /* a node before which a new node is inserted */, | ||||
| 	void* dptr /* the pointer to the data */ , | ||||
| 	qse_size_t dlen /* the length of the data in bytes */ | ||||
| 	qse_dll_t*      dll,  /**< doubly linked list */ | ||||
| 	qse_dll_node_t* pos,  /**< node before which a new node is inserted */ | ||||
| 	void*           dptr, /**< data pointer */ | ||||
| 	qse_size_t      dlen  /**< data length */ | ||||
| ); | ||||
|  | ||||
| void qse_dll_delete ( | ||||
| 	qse_dll_t*      dll,  | ||||
| 	qse_dll_node_t* pos | ||||
| ); | ||||
|  | ||||
| /**  | ||||
|  * The qse_dll_clear() functions deletes all elements of a list | ||||
|  */ | ||||
| void qse_dll_clear ( | ||||
| 	qse_dll_t* dll /**< doubly linked list */ | ||||
| ); | ||||
|  | ||||
| void qse_dll_walk ( | ||||
| 	qse_dll_t*       dll,    /**< doubly linked list */ | ||||
| 	qse_dll_walker_t walker, /**< user-defined walker function */ | ||||
| 	void*            ctx     /**< pointer to user-defined data */ | ||||
| ); | ||||
|  | ||||
| void qse_dll_rwalk ( | ||||
| 	qse_dll_t*       dll,    /**< doubly linked list */ | ||||
| 	qse_dll_walker_t walker, /**< user-defined walker function */ | ||||
| 	void*            ctx     /**< pointer to user-defined data */ | ||||
| ); | ||||
|  | ||||
| qse_dll_node_t* qse_dll_pushhead ( | ||||
| 	qse_dll_t* dll /* a singly linked list */, | ||||
| 	void* dptr,  | ||||
| 	qse_dll_t* dll, /* doubly linked list */ | ||||
| 	void*      dptr,  | ||||
| 	qse_size_t dlen | ||||
| ); | ||||
|  | ||||
| qse_dll_node_t* qse_dll_pushtail ( | ||||
| 	qse_dll_t* dll /* a singly linked list */,  | ||||
| 	void* dptr,  | ||||
| 	qse_dll_t* dll, /* doubly linked list */  | ||||
| 	void*      dptr,  | ||||
| 	qse_size_t dlen | ||||
| ); | ||||
|  | ||||
| void qse_dll_delete ( | ||||
| 	qse_dll_t* dll,  | ||||
| 	qse_dll_node_t* pos | ||||
| ); | ||||
|  | ||||
| void qse_dll_pophead ( | ||||
| 	qse_dll_t* dll | ||||
| ); | ||||
| @ -328,36 +416,6 @@ void qse_dll_poptail ( | ||||
| 	qse_dll_t* dll | ||||
| ); | ||||
|  | ||||
| /*  | ||||
|  * NAME Traverses s singly linked list  | ||||
|  * | ||||
|  * DESCRIPTION | ||||
|  *   A singly linked list allows uni-directional in-order traversal. | ||||
|  *   The qse_dll_walk() function traverses a singly linkked list from its  | ||||
|  *   head node down to its tail node as long as the walker function returns  | ||||
|  *   QSE_DLL_WALK_FORWARD. A walker can return QSE_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  | ||||
|  *   qse_dll_walk() function. | ||||
|  */ | ||||
| void qse_dll_walk ( | ||||
| 	qse_dll_t* dll /* a singly linked list */, | ||||
| 	qse_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 QSE_DLL_COPIER_INLINE instead. | ||||
|  */ | ||||
| void* qse_dll_copyinline ( | ||||
| 	qse_dll_t* dll /* a singly linked list */, | ||||
| 	void* data /* pointer to data to copy */ ,  | ||||
| 	qse_size_t len /* length of data in bytes */ | ||||
| ); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
							
								
								
									
										70
									
								
								qse/include/qse/cmn/gdl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								qse/include/qse/cmn/gdl.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,70 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  */ | ||||
|  | ||||
| #ifndef _QSE_CMN_GDL_H_ | ||||
| #define _QSE_CMN_GDL_H_ | ||||
|  | ||||
| /** @file | ||||
|  * This file defins a generic double link and provides basic macros to  | ||||
|  * manipulate a chain of links. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * The qse_gdl_t type defines a structure to contain forward and  | ||||
|  * backward links.  | ||||
|  */ | ||||
| typedef struct qse_gdl_t qse_gdl_t; | ||||
| struct qse_gdl_t | ||||
| { | ||||
| 	qse_gdl_t* prev; | ||||
| 	qse_gdl_t* next; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * The QSE_GDL_INIT macro initializes a host link to be used for internal | ||||
|  * management. | ||||
|  */ | ||||
| #define QSE_GDL_INIT(host) QSE_BLOCK ( \ | ||||
| 	(host)->next = (host); (host)->prev = (host); \ | ||||
| ) | ||||
|  | ||||
| /** | ||||
|  * The QSE_GDL_CHAIN macro chains a new member node @a x between  | ||||
|  * two nodes @a p and @a n. | ||||
|  */ | ||||
| #define QSE_GDL_CHAIN(p,x,n) qse_gdl_chain(p,x,n) | ||||
|  | ||||
| /** | ||||
|  * The QSE_GDL_UNCHAIN macro unchains a member node @a x. | ||||
|  */ | ||||
| #define QSE_GDL_UNCHAIN(x) qse_gdl_unchain(x) | ||||
|  | ||||
| /** | ||||
|  * The QSE_GDL_ISEMPTY macro checks if the chain is empty. | ||||
|  */ | ||||
| #define QSE_GDL_ISEMPTY(host) ((host)->next == (host)) | ||||
|  | ||||
| /** | ||||
|  * The QSE_GDL_HEAD macro get the first node in the chain. | ||||
|  */ | ||||
| #define QSE_GDL_HEAD(host) ((host)->next) | ||||
|  | ||||
| /** | ||||
|  * The QSE_GDL_TAIL macro gets the last node in the chain. | ||||
|  */ | ||||
| #define QSE_GDL_TAIL(host) ((host)->prev) | ||||
|  | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| void qse_gdl_chain (qse_gdl_t* p, qse_gdl_t* x, qse_gdl_t* n); | ||||
| void qse_gdl_unchain (qse_gdl_t* x); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: htb.h 341 2010-08-04 07:25:48Z hyunghwan.chung $ | ||||
|  * $Id: htb.h 354 2010-09-03 12:50:08Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -38,7 +38,7 @@ typedef struct qse_htb_pair_t qse_htb_pair_t; | ||||
|  */ | ||||
| enum qse_htb_walk_t | ||||
| { | ||||
|         QSE_HTB_WALK_STOP = 0, | ||||
|         QSE_HTB_WALK_STOP    = 0, | ||||
|         QSE_HTB_WALK_FORWARD = 1 | ||||
| }; | ||||
| typedef enum qse_htb_walk_t qse_htb_walk_t; | ||||
|  | ||||
| @ -58,7 +58,7 @@ | ||||
| #	define qse_map_clear(map)                       qse_htb_clear(map) | ||||
| #	define qse_map_walk(map,walker,ctx)             qse_htb_walk(map,walker,ctx) | ||||
| #	define QSE_MAP_WALK_STOP                        QSE_HTB_WALK_STOP | ||||
| #	define QSE_MAP_WALK_FORWARD                     QSE_HTB_WALK_FORWARD | ||||
| #	define QSE_MAP_WALK_FORWARD                    QSE_HTB_WALK_FORWARD | ||||
| #	define qse_map_walk_t                           qse_htb_walk_t | ||||
| #	define QSE_MAP_KEY                              QSE_HTB_KEY | ||||
| #	define QSE_MAP_VAL                              QSE_HTB_VAL | ||||
| @ -111,7 +111,7 @@ | ||||
| #	define qse_map_clear(map)                       qse_rbt_clear(map) | ||||
| #	define qse_map_walk(map,walker,ctx)             qse_rbt_walk(map,walker,ctx) | ||||
| #	define QSE_MAP_WALK_STOP                        QSE_RBT_WALK_STOP | ||||
| #	define QSE_MAP_WALK_FORWARD                     QSE_RBT_WALK_FORWARD | ||||
| #	define QSE_MAP_WALK_FORWARD                    QSE_RBT_WALK_FORWARD | ||||
| #	define qse_map_walk_t                           qse_rbt_walk_t | ||||
| #	define QSE_MAP_KEY                              QSE_RBT_KEY | ||||
| #	define QSE_MAP_VAL                              QSE_RBT_VAL | ||||
|  | ||||
| @ -37,7 +37,7 @@ typedef struct qse_rbt_pair_t qse_rbt_pair_t; | ||||
|  */ | ||||
| enum qse_rbt_walk_t | ||||
| { | ||||
|         QSE_RBT_WALK_STOP = 0, | ||||
|         QSE_RBT_WALK_STOP    = 0, | ||||
|         QSE_RBT_WALK_FORWARD = 1 | ||||
| }; | ||||
| typedef enum qse_rbt_walk_t qse_rbt_walk_t; | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: sll.h 328 2010-07-08 06:58:44Z hyunghwan.chung $ | ||||
|  * $Id: sll.h 354 2010-09-03 12:50:08Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -25,7 +25,7 @@ | ||||
| #include <qse/macros.h> | ||||
|  | ||||
| /** @file | ||||
|  * Singly linked list | ||||
|  * This file provides a singly linked list interface. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
| @ -33,13 +33,14 @@ | ||||
|  */ | ||||
| enum qse_sll_walk_t | ||||
| { | ||||
| 	QSE_SLL_WALK_STOP    = 0,  /**< stop traversal */ | ||||
| 	QSE_SLL_WALK_FORWARD = 1   /**< traverse to the next node */ | ||||
| 	QSE_SLL_WALK_STOP     = 0,  /**< stop traversal */ | ||||
| 	QSE_SLL_WALK_FORWARD  = 1   /**< traverse to the next node */ | ||||
| }; | ||||
| typedef enum qse_sll_walk_t qse_sll_walk_t; | ||||
|  | ||||
|  | ||||
| typedef struct qse_sll_t      qse_sll_t; | ||||
| typedef struct qse_sll_node_t qse_sll_node_t; | ||||
| typedef enum   qse_sll_walk_t qse_sll_walk_t; | ||||
|  | ||||
| /** | ||||
|  * The qse_sll_copier_t type defines a callback function for node construction. | ||||
| @ -89,16 +90,15 @@ typedef int (*qse_sll_comper_t) ( | ||||
|  * The qse_sll_walker_t type defines a list traversal callback for each node. | ||||
|  * The qse_sll_walk() calls a callback function of the type qse_sll_walker_t | ||||
|  * for each node until it returns QSE_SLL_WALK_STOP. The walker should return | ||||
|  * QSE_SLL_WALK_FORWARD to let qse_sll_walk() continue visiting the next node. | ||||
|  * QSE_SLL_WALK_FORWARD  to let qse_sll_walk() continue visiting the next node. | ||||
|  * The third parameter to qse_sll_walk() is passed to the walker as the third | ||||
|  * parameter. | ||||
|  */ | ||||
| typedef qse_sll_walk_t (*qse_sll_walker_t) ( | ||||
| 	qse_sll_t*      sll,   /* singly linked list */ | ||||
| 	qse_sll_node_t* node,  /* visited node */ | ||||
| 	void*           arg    /* user-defined data */ | ||||
| 	qse_sll_t*      sll,   /**< singly linked list */ | ||||
| 	qse_sll_node_t* node,  /**< visited node */ | ||||
| 	void*           ctx    /**< user-defined data */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /** | ||||
|  * The qse_sll_t type defines a singly lnked list. | ||||
| @ -183,203 +183,128 @@ qse_sll_t* qse_sll_open ( | ||||
| 	qse_size_t  ext   /* size of extension area in bytes */ | ||||
| ); | ||||
|  | ||||
| /****f* Common/qse_sll_close | ||||
|  * NAME | ||||
|  *  qse_sll_close - destroy a singly linked list  | ||||
|  * | ||||
|  * DESCRIPTION | ||||
|  *  The qse_sll_close() function destroys a singly linked list freeing up | ||||
|  *  the memory. | ||||
|  * | ||||
|  * SYNOPSIS | ||||
| /** | ||||
|  * The qse_sll_close() function destroys a singly linked list freeing up | ||||
|  * the memory. | ||||
|  */ | ||||
| void qse_sll_close ( | ||||
| 	qse_sll_t* sll /* a singly linked list */ | ||||
| 	qse_sll_t* sll /**< singly linked list */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /****f* Common/qse_sll_init | ||||
|  * NAME | ||||
|  *  qse_sll_init - initialize a singly linked list | ||||
|  * | ||||
|  * DESCRIPTION | ||||
|  *  The qse_sll_init() function initializes a singly linked list. The memory | ||||
|  *  should be allocated by a caller and be passed to it. The caller may declare | ||||
|  *  a static variable of the qse_sll_t type and pass its address. A memory  | ||||
|  *  manager still needs to be passed for node manipulation later. | ||||
| /** | ||||
|  * The qse_sll_init() function initializes a statically declared singly  | ||||
|  * linked list. The memory should be allocated by a caller and be passed  | ||||
|  * to it. The caller may declare a static variable of the qse_sll_t type | ||||
|  * and pass its address. A memory manager still needs to be passed for  | ||||
|  * node manipulation later. | ||||
|  *   | ||||
|  * RETURN | ||||
|  * @return | ||||
|  *  The qse_sll_init() function returns the first parameter on success and | ||||
|  *  QSE_NULL on failure. | ||||
|  *  | ||||
|  * SYNOPSIS | ||||
|  */ | ||||
| qse_sll_t* qse_sll_init ( | ||||
| 	qse_sll_t*  sll   /* an uninitialized singly linked list */, | ||||
| 	qse_mmgr_t* mmgr  /* a memory manager */ | ||||
| 	qse_sll_t*  sll,  /* singly linked list */ | ||||
| 	qse_mmgr_t* mmgr  /* memory manager */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /****f* Common/qse_sll_fini | ||||
|  * NAME | ||||
|  *  qse_sll_init - deinitialize a singly linked list | ||||
|  * | ||||
|  * SYNOPSIS | ||||
| /** | ||||
|  * The qse_sll_fini() function finalizes a statically initialized list. | ||||
|  */ | ||||
| void qse_sll_fini ( | ||||
| 	qse_sll_t* sll  /* a singly linked list */ | ||||
| 	qse_sll_t* sll  /**< singly linked list */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /****f* Common/qse_sll_getsize | ||||
|  * NAME | ||||
|  *  qse_sll_getsize - get the number of nodes | ||||
|  * | ||||
|  * DESCRIPTION | ||||
|  *  The qse_sll_getsize() function returns the number of the data nodes held | ||||
|  *  in a singly linked list. | ||||
|  * | ||||
|  * SYNOPSIS | ||||
|  */ | ||||
| qse_size_t qse_sll_getsize ( | ||||
| 	qse_sll_t* sll  /* a singly linked list */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
|  | ||||
| /****f* Common/qse_sll_getscale | ||||
|  * NAME | ||||
|  *  qse_sll_getscale - get the scale factor | ||||
|  * | ||||
|  * SYNOPSIS | ||||
| /** | ||||
|  * The qse_sll_getscale() function gets the scale factor | ||||
|  */ | ||||
| int qse_sll_getscale ( | ||||
| 	qse_sll_t* sll  /* a singly linked list */ | ||||
| 	qse_sll_t* sll  /**< singly linked list */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /****f* Common/qse_sll_setscale | ||||
|  * NAME | ||||
|  *  qse_sll_setscale - set the scale factor | ||||
|  * | ||||
|  * DESCRIPTION  | ||||
| /** | ||||
|  *  The qse_sll_setscale() function sets the scale factor of the data length. | ||||
|  *  A scale factor determines the actual length of data in bytes. A singly  | ||||
|  *  linked list created with a scale factor of 1. The scale factor should be | ||||
|  *  larger than 0 and less than 256. | ||||
|  * | ||||
|  * NOTES | ||||
|  *  It is a bad idea to change the scale factor when a sll is not empty. | ||||
|  *   | ||||
|  * SYNOPSIS | ||||
|  */ | ||||
| void qse_sll_setscale ( | ||||
| 	qse_sll_t* sll /* a singly linked list */, | ||||
| 	int scale      /* a scale factor */ | ||||
| 	qse_sll_t* sll,     /**< singly linked list */ | ||||
| 	int        scale    /**< scale factor */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /****f* Common/qse_sll_getcopier | ||||
|  * NAME | ||||
|  *  qse_sll_getfreeer - get the data copier | ||||
|  * | ||||
|  * SYNOPSIS | ||||
| /** | ||||
|  * The qse_sll_getfreeer() function gets the data copier. | ||||
|  */ | ||||
| qse_sll_copier_t qse_sll_getcopier ( | ||||
| 	qse_sll_t* sll  /* a singly linked list */ | ||||
| 	qse_sll_t* sll  /* singly linked list */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /****f* Common/qse_sll_setcopier | ||||
|  * NAME  | ||||
|  *  qse_sll_setcopier - set a data copier | ||||
|  * | ||||
|  * DESCRIPTION | ||||
|  *  A special copier QSE_SLL_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 QSE_NULL to perform no special operation  | ||||
|  *  when the data pointer is rememebered. | ||||
|  *  | ||||
|  * SYNOPSIS | ||||
| /** | ||||
|  * The qse_sll_setcopier() function changes the element copier. | ||||
|  * A special copier QSE_SLL_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 QSE_NULL to perform  | ||||
|  * no special operation when the data pointer is rememebered. | ||||
|  */ | ||||
| void qse_sll_setcopier ( | ||||
| 	qse_sll_t* sll          /* a singly linked list */,  | ||||
| 	qse_sll_copier_t copier /* a data copier */ | ||||
| 	qse_sll_t*       sll,   /**< singly linked list */ | ||||
| 	qse_sll_copier_t copier /**< data copier */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /****f* Common/qse_sll_getfreeer | ||||
|  * NAME | ||||
|  *  qse_sll_getfreeer - get the data freeer | ||||
|  * | ||||
|  * SYNOPSIS | ||||
| /** | ||||
|  * The qse_sll_getfreeer() function returns the element freeer. | ||||
|  */ | ||||
| qse_sll_freeer_t qse_sll_getfreeer ( | ||||
| 	qse_sll_t* sll  /* a singly linked list */ | ||||
| 	qse_sll_t* sll  /**< singly linked list */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /****f* Common/qse_sll_setfreeer | ||||
|  * NAME | ||||
|  *  qse_sll_setfreeer - set a data freeer | ||||
|  * | ||||
|  * DESCRIPTION | ||||
|  *  The freeer is called when a node containing the element is destroyed. | ||||
|  *  | ||||
|  * SYNOPSIS | ||||
| /** | ||||
|  * The qse_sll_setfreeer() function changes the element freeer. | ||||
|  * The freeer is called when a node containing the element is destroyed. | ||||
|  */ | ||||
| void qse_sll_setfreeer ( | ||||
| 	qse_sll_t* sll          /* a singly linked list */, | ||||
| 	qse_sll_freeer_t freeer /* a data freeer */ | ||||
| 	qse_sll_t*       sll,   /**< singly linked list */ | ||||
| 	qse_sll_freeer_t freeer /**< data freeer */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /****f* Common/qse_sll_getcomper | ||||
|  * NAME | ||||
|  *  qse_sll_getcomper - get the data comparator | ||||
|  * | ||||
|  * SYNOPSIS | ||||
| /** | ||||
|  * The qse_sll_getcomper() function returns the data comparator. | ||||
|  */ | ||||
| qse_sll_comper_t qse_sll_getcomper ( | ||||
| 	qse_sll_t* sll  /* a singly linked list */ | ||||
| 	qse_sll_t* sll  /**< singly linked list */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /****f* Common/qse_sll_setcomper | ||||
|  * NAME | ||||
|  *  qse_sll_setcomper - set the data comparator | ||||
|  * | ||||
|  * SYNOPSIS | ||||
| /** | ||||
|  * The qse_sll_setcomper() function changes  the data comparator | ||||
|  */ | ||||
| void qse_sll_setcomper ( | ||||
| 	qse_sll_t*       sll     /* a singly linked list */, | ||||
| 	qse_sll_comper_t comper  /* a comparator */ | ||||
| 	qse_sll_t*       sll     /**< singly linked list */, | ||||
| 	qse_sll_comper_t comper  /**< comparator */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /****f* Common/qse_sll_gethead | ||||
|  * NAME | ||||
|  *  qse_sll_gethead - get the head node | ||||
|  * | ||||
|  * SYNOPSIS | ||||
| /** | ||||
|  * The qse_sll_getsize() function returns the number of the data nodes held | ||||
|  * in a singly linked list. | ||||
|  */ | ||||
| qse_size_t qse_sll_getsize ( | ||||
| 	qse_sll_t* sll  /** singly linked list */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_sll_gethead() function gets the head node. You may use the  | ||||
|  * #QSE_SLL_HEAD macro instead. | ||||
|  */ | ||||
| qse_sll_node_t* qse_sll_gethead ( | ||||
| 	qse_sll_t* sll  /* a singly linked list */ | ||||
| 	qse_sll_t* sll  /**< a singly linked list */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /****f* Common/qse_sll_gettail | ||||
|  * NAME | ||||
|  *  qse_sll_gettail - get the tail node | ||||
|  * | ||||
|  * SYNOPSIS | ||||
| /** | ||||
|  * The qse_sll_gettail() function gets the head node. You may use the  | ||||
|  * #QSE_SLL_TAIL macro instead. | ||||
|  */ | ||||
| qse_sll_node_t* qse_sll_gettail ( | ||||
| 	qse_sll_t* sll  /* a singly linked list */ | ||||
| 	qse_sll_t* sll  /**< singly linked list */ | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /** | ||||
|  * The qse_sll_search() function traverses a list to find a node containing | ||||
| @ -387,8 +312,8 @@ qse_sll_node_t* qse_sll_gettail ( | ||||
|  * from the next node of the positional node. If the positional node is  | ||||
|  * QSE_NULL, the traversal begins from the head node.  | ||||
|  * | ||||
|  * Note that no reverse search is provided because a reverse traversal can not be  | ||||
|  * achieved efficiently. | ||||
|  * Note that no reverse search is provided because a reverse traversal can not  | ||||
|  * be achieved efficiently. | ||||
|  * | ||||
|  * @return pointer to the node found. QSE_NULL if no match is found | ||||
|  */ | ||||
| @ -430,31 +355,10 @@ void qse_sll_clear ( | ||||
| 	qse_sll_t* sll  /**< singly linked list */ | ||||
| ); | ||||
|  | ||||
| qse_sll_node_t* qse_sll_pushhead ( | ||||
| 	qse_sll_t* sll /**< singly linked list */, | ||||
| 	void*      dptr,  | ||||
| 	qse_size_t dlen | ||||
| ); | ||||
|  | ||||
| qse_sll_node_t* qse_sll_pushtail ( | ||||
| 	qse_sll_t* sll /**< singly linked list */,  | ||||
| 	void*      dptr,  | ||||
| 	qse_size_t dlen | ||||
| ); | ||||
|  | ||||
|  | ||||
| void qse_sll_pophead ( | ||||
| 	qse_sll_t* sll | ||||
| ); | ||||
|  | ||||
| void qse_sll_poptail ( | ||||
| 	qse_sll_t* sll | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  *  The qse_sll_walk() function traverses a singly linkked list from its  | ||||
|  *  head node down to its tail node as long as the walker function returns  | ||||
|  *  QSE_SLL_WALK_FORWARD. A walker can return QSE_SLL_WALK_STOP to cause  | ||||
|  *  QSE_SLL_WALK_FORWARD . A walker can return QSE_SLL_WALK_STOP to cause  | ||||
|  *  immediate stop of traversal. | ||||
|  *  | ||||
|  *  For each node, the walker function is called and it is passed three | ||||
| @ -468,6 +372,26 @@ void qse_sll_walk ( | ||||
| 	void*            ctx      /**< the pointer to user-defined data */ | ||||
| ); | ||||
|  | ||||
| qse_sll_node_t* qse_sll_pushhead ( | ||||
| 	qse_sll_t* sll /**< singly linked list */, | ||||
| 	void*      dptr,  | ||||
| 	qse_size_t dlen | ||||
| ); | ||||
|  | ||||
| qse_sll_node_t* qse_sll_pushtail ( | ||||
| 	qse_sll_t* sll /**< singly linked list */,  | ||||
| 	void*      dptr,  | ||||
| 	qse_size_t dlen | ||||
| ); | ||||
|  | ||||
| void qse_sll_pophead ( | ||||
| 	qse_sll_t* sll | ||||
| ); | ||||
|  | ||||
| void qse_sll_poptail ( | ||||
| 	qse_sll_t* sll | ||||
| ); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: str.h 353 2010-09-01 13:19:59Z hyunghwan.chung $ | ||||
|  * $Id: str.h 354 2010-09-03 12:50:08Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -25,10 +25,11 @@ | ||||
| #include <qse/macros.h> | ||||
|  | ||||
| /** @file | ||||
|  *  Various functions, types, macros for string manipulation. | ||||
|  * This file provides various functions, types, macros for string manipulation. | ||||
|  * | ||||
|  * The #qse_cstr_t type and the #qse_xstr_t defined in <qse/types.h> help you | ||||
|  * deal with a string pointer and length in a structure. | ||||
|  * | ||||
|  *  The qse_cstr_t type and the qse_xstr_t defined in <qse/types.h> helps you | ||||
|  *  dealing with a string pointer and length. | ||||
|  */ | ||||
|  | ||||
| #define QSE_STR_LEN(s)       ((s)->len)      /**< string length */ | ||||
| @ -170,17 +171,25 @@ qse_size_t qse_strxcpy ( | ||||
| 	const qse_char_t* str | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_strycpy() function copies a length-bounded string into | ||||
|  * a buffer with unknown size.  | ||||
|  */ | ||||
| qse_size_t qse_strncpy ( | ||||
| 	qse_char_t*       buf,  | ||||
| 	const qse_char_t* str, | ||||
| 	qse_size_t        len | ||||
| 	qse_char_t*       buf, /**< buffer with unknown length */ | ||||
| 	const qse_char_t* str, /**< length-bounded string */ | ||||
| 	qse_size_t        len  /**< string length */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_strycpy() function copies a length-bounded string into | ||||
|  * a length-bounded buffer. | ||||
|  */ | ||||
| qse_size_t qse_strxncpy ( | ||||
| 	qse_char_t*       buf, | ||||
| 	qse_size_t        bsz, | ||||
| 	const qse_char_t* str, | ||||
| 	qse_size_t        len | ||||
| 	qse_char_t*       buf, /**< length-bounded buffer */ | ||||
| 	qse_size_t        bsz, /**< buffer length */ | ||||
| 	const qse_char_t* str, /**< length-bounded string */ | ||||
| 	qse_size_t        len  /**< string length */ | ||||
| ); | ||||
|  | ||||
| /** | ||||
| @ -189,13 +198,13 @@ qse_size_t qse_strxncpy ( | ||||
|  * buffer. | ||||
|  */ | ||||
| qse_size_t qse_strxput ( | ||||
|         qse_char_t*       buf,  | ||||
| 	qse_char_t*       buf,  | ||||
| 	qse_size_t        bsz, | ||||
| 	const qse_char_t* str | ||||
| ); | ||||
|  | ||||
| qse_size_t qse_strxnput ( | ||||
|         qse_char_t*       buf, | ||||
| 	qse_char_t*       buf, | ||||
| 	qse_size_t        bsz, | ||||
| 	const qse_char_t* str, | ||||
| 	qse_size_t        len | ||||
| @ -226,8 +235,8 @@ qse_size_t qse_strfcpy ( | ||||
|  * @sa qse_strfcpy, qse_strxfcpy, qse_strxfncpy | ||||
|  */ | ||||
| qse_size_t qse_strfncpy ( | ||||
|         qse_char_t*       buf, | ||||
|         const qse_char_t* fmt,  | ||||
| 	qse_char_t*       buf, | ||||
| 	const qse_char_t* fmt,  | ||||
| 	const qse_cstr_t  str[] | ||||
| ); | ||||
|  | ||||
| @ -256,9 +265,9 @@ qse_size_t qse_strxfcpy ( | ||||
|  * @sa qse_strfcpy, qse_strfncpy, qse_strxfcpy | ||||
|  */ | ||||
| qse_size_t qse_strxfncpy ( | ||||
|         qse_char_t*       buf, | ||||
| 	qse_char_t*       buf, | ||||
| 	qse_size_t        bsz, | ||||
|         const qse_char_t* fmt, | ||||
| 	const qse_char_t* fmt, | ||||
| 	const qse_cstr_t  str[] | ||||
| ); | ||||
|  | ||||
| @ -281,11 +290,11 @@ qse_size_t qse_strxfncpy ( | ||||
|  * @endcode | ||||
|  */ | ||||
| qse_size_t qse_strxsubst ( | ||||
|         qse_char_t*            buf, | ||||
| 	qse_char_t*            buf, | ||||
| 	qse_size_t             bsz, | ||||
| 	const qse_char_t*      fmt, | ||||
| 	qse_strxsubst_subst_t  subst, | ||||
|         void*                  ctx | ||||
| 	void*                  ctx | ||||
| ); | ||||
|  | ||||
| qse_size_t qse_strxcat ( | ||||
| @ -308,15 +317,15 @@ int qse_strcmp ( | ||||
|  | ||||
| int qse_strxcmp ( | ||||
| 	const qse_char_t* s1, | ||||
| 	qse_size_t len1, | ||||
| 	qse_size_t        len1, | ||||
| 	const qse_char_t* s2 | ||||
| ); | ||||
|  | ||||
| int qse_strxncmp ( | ||||
| 	const qse_char_t* s1, | ||||
| 	qse_size_t len1,  | ||||
| 	qse_size_t        len1,  | ||||
| 	const qse_char_t* s2, | ||||
| 	qse_size_t len2 | ||||
| 	qse_size_t        len2 | ||||
| ); | ||||
|  | ||||
| int qse_strcasecmp ( | ||||
| @ -505,17 +514,25 @@ qse_char_t* qse_strxbeg ( | ||||
| 	const qse_char_t* sub) | ||||
| ; | ||||
|  | ||||
| /* | ||||
|  * The qse_strbeg() function checks if the a string begins with a substring. | ||||
|  * @return @a str on match, QSE_NULL on no match | ||||
|  */ | ||||
| qse_char_t* qse_strnbeg ( | ||||
| 	const qse_char_t* str, | ||||
| 	const qse_char_t* sub, | ||||
| 	qse_size_t len | ||||
| 	qse_size_t        len | ||||
| ); | ||||
|  | ||||
| /* | ||||
|  * The qse_strbeg() function checks if the a string begins with a substring. | ||||
|  * @return @a str on match, QSE_NULL on no match | ||||
|  */ | ||||
| qse_char_t* qse_strxnbeg ( | ||||
| 	const qse_char_t* str, | ||||
| 	qse_size_t len1,  | ||||
| 	qse_size_t        len1,  | ||||
| 	const qse_char_t* sub, | ||||
| 	qse_size_t len2 | ||||
| 	qse_size_t        len2 | ||||
| ); | ||||
|  | ||||
| /** | ||||
| @ -565,25 +582,76 @@ qse_char_t* qse_strxnend ( | ||||
| /*  | ||||
|  * string conversion | ||||
|  */ | ||||
| int qse_strtoi (const qse_char_t* str); | ||||
| long qse_strtol (const qse_char_t* str); | ||||
| unsigned int qse_strtoui (const qse_char_t* str); | ||||
| unsigned long qse_strtoul (const qse_char_t* str); | ||||
| int qse_strtoi ( | ||||
| 	const qse_char_t* str | ||||
| ); | ||||
|  | ||||
| int qse_strxtoi (const qse_char_t* str, qse_size_t len); | ||||
| long qse_strxtol (const qse_char_t* str, qse_size_t len); | ||||
| unsigned int qse_strxtoui (const qse_char_t* str, qse_size_t len); | ||||
| unsigned long qse_strxtoul (const qse_char_t* str, qse_size_t len); | ||||
| long qse_strtol ( | ||||
| 	const qse_char_t* str | ||||
| ); | ||||
|  | ||||
| qse_int_t qse_strtoint (const qse_char_t* str); | ||||
| qse_long_t qse_strtolong (const qse_char_t* str); | ||||
| qse_uint_t qse_strtouint (const qse_char_t* str); | ||||
| qse_ulong_t qse_strtoulong (const qse_char_t* str); | ||||
| unsigned int qse_strtoui ( | ||||
| 	const qse_char_t* str | ||||
| ); | ||||
|  | ||||
| qse_int_t qse_strxtoint (const qse_char_t* str, qse_size_t len); | ||||
| qse_long_t qse_strxtolong (const qse_char_t* str, qse_size_t len); | ||||
| qse_uint_t qse_strxtouint (const qse_char_t* str, qse_size_t len); | ||||
| qse_ulong_t qse_strxtoulong (const qse_char_t* str, qse_size_t len); | ||||
| unsigned long qse_strtoul ( | ||||
| 	const qse_char_t* str | ||||
| ); | ||||
|  | ||||
| int qse_strxtoi ( | ||||
| 	const qse_char_t* str, | ||||
| 	qse_size_t        len | ||||
| ); | ||||
|  | ||||
| long qse_strxtol ( | ||||
| 	const qse_char_t* str, | ||||
| 	qse_size_t        len | ||||
| ); | ||||
|  | ||||
| unsigned int qse_strxtoui ( | ||||
| 	const qse_char_t* str, | ||||
| 	qse_size_t        len | ||||
| ); | ||||
|  | ||||
| unsigned long qse_strxtoul ( | ||||
| 	const qse_char_t* str, | ||||
| 	qse_size_t        len | ||||
| ); | ||||
|  | ||||
| qse_int_t qse_strtoint ( | ||||
| 	const qse_char_t* str | ||||
| ); | ||||
|  | ||||
| qse_long_t qse_strtolong ( | ||||
| 	const qse_char_t* str | ||||
| ); | ||||
|  | ||||
| qse_uint_t qse_strtouint ( | ||||
| 	const qse_char_t* str | ||||
| ); | ||||
|  | ||||
| qse_ulong_t qse_strtoulong ( | ||||
| 	const qse_char_t* str | ||||
| ); | ||||
|  | ||||
| qse_int_t qse_strxtoint ( | ||||
| 	const qse_char_t* str, qse_size_t len | ||||
| ); | ||||
|  | ||||
| qse_long_t qse_strxtolong ( | ||||
| 	const qse_char_t* str, | ||||
| 	qse_size_t        len | ||||
| ); | ||||
|  | ||||
| qse_uint_t qse_strxtouint ( | ||||
| 	const qse_char_t* str, | ||||
| 	qse_size_t        len | ||||
| ); | ||||
|  | ||||
| qse_ulong_t qse_strxtoulong ( | ||||
| 	const qse_char_t* str, | ||||
| 	qse_size_t        len | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * The qse_strspl() function splits a string into fields. | ||||
| @ -595,7 +663,6 @@ int qse_strspl ( | ||||
| 	qse_char_t        rquote, | ||||
| 	qse_char_t        escape | ||||
| ); | ||||
| /******/ | ||||
|  | ||||
| /** | ||||
|  * The qse_strspltrn() function splits a string translating special  | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: macros.h 348 2010-08-26 06:26:28Z hyunghwan.chung $ | ||||
|  * $Id: macros.h 354 2010-09-03 12:50:08Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -29,26 +29,35 @@ | ||||
|  | ||||
| #if defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L) | ||||
| #	define QSE_INLINE inline | ||||
| #	define QSE_HAVE_INLINE | ||||
| #elif defined(__GNUC__) && defined(__GNUC_GNU_INLINE__) | ||||
| #	define QSE_INLINE /*extern*/ inline | ||||
| #	define QSE_HAVE_INLINE | ||||
| #else | ||||
| #	define QSE_INLINE  | ||||
| #	undef QSE_HAVE_INLINE | ||||
| #endif | ||||
|  | ||||
| #if defined(__GNUC__) | ||||
| #	define QSE_INLINE_ALWAYS inline __attribute__((__always_inline__)) | ||||
| #	define QSE_HAVE_INLINE_ALWAYS | ||||
| #elif defined(_MSC_VER) || (defined(__CC_ARM) || defined(__ARMCC__)) | ||||
| #	define QSE_INLINE_ALWAYS __forceinline | ||||
| #	define QSE_HAVE_INLINE_ALWAYS | ||||
| #else | ||||
| #	define QSE_INLINE_ALWAYS QSE_INLINE | ||||
| #	undef QSE_HAVE_INLINE_ALWAYS | ||||
| #endif | ||||
|  | ||||
| #if defined(__GNUC__) | ||||
| #	define QSE_INLINE_NEVER inline __attribute__((__noinline__)) | ||||
| #	define QSE_HAVE_INLINE_NEVER | ||||
| #elif (defined(__CC_ARM) || defined(__ARMCC__)) | ||||
| #	define QSE_INLINE_NEVER __declspec(noinline) | ||||
| #	define QSE_HAVE_INLINE_NEVER | ||||
| #else | ||||
| #	define QSE_INLINE_NEVER  | ||||
| #	undef QSE_HAVE_INLINE_NEVER | ||||
| #endif | ||||
|  | ||||
|  | ||||
| @ -142,14 +151,20 @@ | ||||
| #define QSE_TYPE_MIN(type) \ | ||||
| 	((QSE_TYPE_IS_SIGNED(type)? QSE_TYPE_SIGNED_MIN(type): QSE_TYPE_UNSIGNED_MIN(type))) | ||||
|  | ||||
| /** | ||||
|  * The QSE_BLOCK macro encloses one or more statements in a block with  | ||||
|  * no side-effect. | ||||
|  */ | ||||
| #define QSE_BLOCK(code) do { code } while(0) | ||||
|  | ||||
| #define QSE_IS_POWOF2(x) (((x) & ((x) - 1)) == 0) | ||||
|  | ||||
| #define QSE_SWAP(x,y,original_type,casting_type) \ | ||||
| 	do { \ | ||||
| 	QSE_BLOCK ( \ | ||||
| 		x = (original_type)((casting_type)(x) ^ (casting_type)(y)); \ | ||||
| 		y = (original_type)((casting_type)(y) ^ (casting_type)(x)); \ | ||||
| 		x = (original_type)((casting_type)(x) ^ (casting_type)(y)); \ | ||||
| 	} while (0) | ||||
| 	) | ||||
|  | ||||
| #define QSE_ABS(x) ((x) < 0? -(x): (x)) | ||||
|  | ||||
| @ -162,7 +177,7 @@ | ||||
| #define QSE_END_LOOP(id)      QSE_LOOP_CONTINUE(id) } __loop_ ## id ## _end__: | ||||
|  | ||||
| #define QSE_REPEAT(n,blk) \ | ||||
| 	do { \ | ||||
| 	QSE_BLOCK ( \ | ||||
| 		qse_size_t __qse_repeat_x1__ = (qse_size_t)(n); \ | ||||
| 		qse_size_t __qse_repeat_x2__ = __qse_repeat_x1__ >> 4; \ | ||||
| 		__qse_repeat_x1__ &= 15; \ | ||||
| @ -171,7 +186,8 @@ | ||||
| 			blk; blk; blk; blk; blk; blk; blk; blk; \ | ||||
| 			blk; blk; blk; blk; blk; blk; blk; blk; \ | ||||
| 		} \ | ||||
| 	} while (0); | ||||
| 	) | ||||
|  | ||||
|  | ||||
| /* number of characters to number of bytes */ | ||||
| #define QSE_NCTONB(x) ((x)*sizeof(qse_char_t)) | ||||
|  | ||||
| @ -7,7 +7,7 @@ libqsecmn_la_SOURCES = \ | ||||
| 	syscall.h mem.h \ | ||||
| 	mem.c xma.c fma.c chr.c chr_cnv.c rex.c \ | ||||
| 	str_bas.c str_cnv.c str_dyn.c str_utl.c \ | ||||
| 	lda.c htb.c rbt.c sll.c dll.c opt.c \ | ||||
| 	lda.c htb.c rbt.c sll.c gdl.c dll.c opt.c \ | ||||
| 	tio.c tio_get.c tio_put.c \ | ||||
| 	fio.c pio.c sio.c \ | ||||
| 	time.c \ | ||||
|  | ||||
| @ -75,7 +75,7 @@ LTLIBRARIES = $(lib_LTLIBRARIES) | ||||
| libqsecmn_la_DEPENDENCIES = | ||||
| am_libqsecmn_la_OBJECTS = mem.lo xma.lo fma.lo chr.lo chr_cnv.lo \ | ||||
| 	rex.lo str_bas.lo str_cnv.lo str_dyn.lo str_utl.lo lda.lo \ | ||||
| 	htb.lo rbt.lo sll.lo dll.lo opt.lo tio.lo tio_get.lo \ | ||||
| 	htb.lo rbt.lo sll.lo gdl.lo dll.lo opt.lo tio.lo tio_get.lo \ | ||||
| 	tio_put.lo fio.lo pio.lo sio.lo time.lo misc.lo assert.lo \ | ||||
| 	main.lo stdio.lo | ||||
| libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS) | ||||
| @ -264,7 +264,7 @@ libqsecmn_la_SOURCES = \ | ||||
| 	syscall.h mem.h \ | ||||
| 	mem.c xma.c fma.c chr.c chr_cnv.c rex.c \ | ||||
| 	str_bas.c str_cnv.c str_dyn.c str_utl.c \ | ||||
| 	lda.c htb.c rbt.c sll.c dll.c opt.c \ | ||||
| 	lda.c htb.c rbt.c sll.c gdl.c dll.c opt.c \ | ||||
| 	tio.c tio_get.c tio_put.c \ | ||||
| 	fio.c pio.c sio.c \ | ||||
| 	time.c \ | ||||
| @ -363,6 +363,7 @@ distclean-compile: | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dll.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fio.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fma.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gdl.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lda.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Plo@am__quote@ | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: dll.c 287 2009-09-15 10:01:02Z hyunghwan.chung $ | ||||
|  * $Id: dll.c 354 2010-09-03 12:50:08Z hyunghwan.chung $ | ||||
|  *  | ||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -21,7 +21,31 @@ | ||||
| #include <qse/cmn/dll.h> | ||||
| #include "mem.h" | ||||
|  | ||||
| qse_dll_t* qse_dll_open (qse_mmgr_t* mmgr, qse_size_t ext) | ||||
| QSE_IMPLEMENT_COMMON_FUNCTIONS (dll) | ||||
|  | ||||
| #define TOB(dll,len) ((len)*(dll)->scale) | ||||
|  | ||||
| static int default_comper ( | ||||
| 	qse_dll_t* dll,  | ||||
| 	const void* dptr1, size_t dlen1,  | ||||
| 	const void* dptr2, size_t dlen2) | ||||
| { | ||||
| 	if (dlen1 == dlen2) return QSE_MEMCMP (dptr1, dptr2, TOB(dll,dlen1)); | ||||
| 	/* it just returns 1 to indicate that they are different. */ | ||||
| 	return 1; | ||||
|  | ||||
| #if 0 | ||||
| 	qse_size_t min = (dlen1 < dlen2)? dlen1: dlen2; | ||||
| 	int n = QSE_MEMCMP (dptr1, dptr2, TOB(dll,min)); | ||||
| 	if (n == 0 && dlen1 != dlen2) | ||||
| 	{ | ||||
| 		n = (dlen1 > dlen2)? 1: -1; | ||||
| 	} | ||||
| 	return n; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| qse_dll_t* qse_dll_open (qse_mmgr_t* mmgr, qse_size_t xtnsize) | ||||
| { | ||||
| 	qse_dll_t* dll; | ||||
|  | ||||
| @ -35,56 +59,60 @@ qse_dll_t* qse_dll_open (qse_mmgr_t* mmgr, qse_size_t ext) | ||||
| 		if (mmgr == QSE_NULL) return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	dll = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(qse_dll_t) + ext); | ||||
| 	dll = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(qse_dll_t) + xtnsize); | ||||
| 	if (dll == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
| 	/* do not zero the extension */ | ||||
| 	QSE_MEMSET (dll, 0, QSE_SIZEOF(qse_dll_t)); | ||||
| 	dll->mmgr = mmgr; | ||||
| 	if (qse_dll_init (dll, mmgr) == QSE_NULL) | ||||
| 	{ | ||||
| 		QSE_MMGR_FREE (mmgr, dll); | ||||
| 		return QSE_NULL; | ||||
| 	} | ||||
|  | ||||
| 	return dll; | ||||
| } | ||||
|  | ||||
| void qse_dll_close (qse_dll_t* dll) | ||||
| { | ||||
| 	qse_dll_clear (dll); | ||||
| 	qse_dll_fini (dll); | ||||
| 	QSE_MMGR_FREE (dll->mmgr, dll); | ||||
| } | ||||
|  | ||||
| void qse_dll_clear (qse_dll_t* dll) | ||||
| qse_dll_t* qse_dll_init (qse_dll_t* dll, qse_mmgr_t* mmgr) | ||||
| { | ||||
| 	while (dll->head != QSE_NULL) qse_dll_delete (dll, dll->head); | ||||
| 	QSE_ASSERT (dll->tail == QSE_NULL); | ||||
| } | ||||
| 	if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL(); | ||||
|  | ||||
| void* qse_dll_getxtn (qse_dll_t* dll) | ||||
| { | ||||
| 	return dll + 1; | ||||
| } | ||||
| 	/* do not zero out the xtnsizeension */ | ||||
| 	QSE_MEMSET (dll, 0, QSE_SIZEOF(*dll)); | ||||
|  | ||||
| qse_mmgr_t* qse_dll_getmmgr (qse_dll_t* dll) | ||||
| { | ||||
|         return dll->mmgr; | ||||
| } | ||||
|  | ||||
| void qse_dll_setmmgr (qse_dll_t* dll, qse_mmgr_t* mmgr) | ||||
| { | ||||
| 	dll->mmgr = mmgr; | ||||
| 	dll->scale = 1; | ||||
|  | ||||
| 	dll->comper = default_comper; | ||||
| 	dll->copier = QSE_DLL_COPIER_SIMPLE; | ||||
|  | ||||
| 	QSE_DLL_INIT (dll); | ||||
| 	return dll; | ||||
| } | ||||
|  | ||||
| qse_size_t qse_dll_getsize (qse_dll_t* dll) | ||||
| void qse_dll_fini (qse_dll_t* dll) | ||||
| { | ||||
| 	return dll->size; | ||||
| 	qse_dll_clear (dll); | ||||
| } | ||||
|  | ||||
| qse_dll_node_t* qse_dll_gethead (qse_dll_t* dll) | ||||
| int qse_dll_getscale (qse_dll_t* dll) | ||||
| { | ||||
| 	return dll->head; | ||||
| 	return dll->scale; | ||||
| } | ||||
|  | ||||
| qse_dll_node_t* qse_dll_gettail (qse_dll_t* dll) | ||||
| void qse_dll_setscale (qse_dll_t* dll, int scale) | ||||
| { | ||||
| 	return dll->tail; | ||||
| 	QSE_ASSERTX (scale > 0 && scale <= QSE_TYPE_MAX(qse_byte_t),  | ||||
| 		"The scale should be larger than 0 and less than or equal to the maximum value that the qse_byte_t type can hold"); | ||||
|  | ||||
| 	if (scale <= 0) scale = 1; | ||||
| 	if (scale > QSE_TYPE_MAX(qse_byte_t)) scale = QSE_TYPE_MAX(qse_byte_t); | ||||
|  | ||||
| 	dll->scale = scale; | ||||
| } | ||||
|  | ||||
| qse_dll_copier_t qse_dll_getcopier (qse_dll_t* dll) | ||||
| @ -94,6 +122,7 @@ qse_dll_copier_t qse_dll_getcopier (qse_dll_t* dll) | ||||
|  | ||||
| void qse_dll_setcopier (qse_dll_t* dll, qse_dll_copier_t copier) | ||||
| { | ||||
| 	if (copier == QSE_NULL) copier = QSE_DLL_COPIER_SIMPLE; | ||||
| 	dll->copier = copier; | ||||
| } | ||||
|  | ||||
| @ -107,11 +136,37 @@ void qse_dll_setfreeer (qse_dll_t* dll, qse_dll_freeer_t freeer) | ||||
| 	dll->freeer = freeer; | ||||
| } | ||||
|  | ||||
| qse_dll_comper_t qse_dll_getcomper (qse_dll_t* dll) | ||||
| { | ||||
| 	return dll->comper; | ||||
| } | ||||
|  | ||||
| void qse_dll_setcomper (qse_dll_t* dll, qse_dll_comper_t comper) | ||||
| { | ||||
| 	if (comper == QSE_NULL) comper = default_comper; | ||||
| 	dll->comper = comper; | ||||
| } | ||||
|  | ||||
| qse_size_t qse_dll_getsize (qse_dll_t* dll) | ||||
| { | ||||
| 	return QSE_DLL_SIZE(dll); | ||||
| } | ||||
|  | ||||
| qse_dll_node_t* qse_dll_gethead (qse_dll_t* dll) | ||||
| { | ||||
| 	return QSE_DLL_HEAD(dll); | ||||
| } | ||||
|  | ||||
| qse_dll_node_t* qse_dll_gettail (qse_dll_t* dll) | ||||
| { | ||||
| 	return QSE_DLL_TAIL(dll); | ||||
| } | ||||
|  | ||||
| static qse_dll_node_t* alloc_node (qse_dll_t* dll, void* dptr, qse_size_t dlen) | ||||
| { | ||||
| 	qse_dll_node_t* n; | ||||
|  | ||||
| 	if (dll->copier == QSE_NULL) | ||||
| 	if (dll->copier == QSE_DLL_COPIER_SIMPLE) | ||||
| 	{ | ||||
| 		n = QSE_MMGR_ALLOC (dll->mmgr, QSE_SIZEOF(qse_dll_node_t)); | ||||
| 		if (n == QSE_NULL) return QSE_NULL; | ||||
| @ -119,10 +174,11 @@ static qse_dll_node_t* alloc_node (qse_dll_t* dll, void* dptr, qse_size_t dlen) | ||||
| 	} | ||||
| 	else if (dll->copier == QSE_DLL_COPIER_INLINE) | ||||
| 	{ | ||||
| 		n = QSE_MMGR_ALLOC (dll->mmgr, QSE_SIZEOF(qse_dll_node_t) + dlen); | ||||
| 		n = QSE_MMGR_ALLOC (dll->mmgr,  | ||||
| 			QSE_SIZEOF(qse_dll_node_t) + TOB(dll,dlen)); | ||||
| 		if (n == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
| 		QSE_MEMCPY (n + 1, dptr, dlen); | ||||
| 		QSE_MEMCPY (n + 1, dptr, TOB(dll,dlen)); | ||||
| 		n->dptr = n + 1; | ||||
| 	} | ||||
| 	else | ||||
| @ -138,51 +194,132 @@ static qse_dll_node_t* alloc_node (qse_dll_t* dll, void* dptr, qse_size_t dlen) | ||||
| 	} | ||||
|  | ||||
| 	n->dlen = dlen;  | ||||
| 	n->next = QSE_NULL;	 | ||||
| 	n->prev = QSE_NULL; | ||||
|  | ||||
| 	return n; | ||||
| } | ||||
|  | ||||
| static QSE_INLINE void free_node (qse_dll_t* dll, qse_dll_node_t* node) | ||||
| { | ||||
| 	if (dll->freeer != QSE_NULL) | ||||
| 	{ | ||||
| 		/* free the actual data */ | ||||
| 		dll->freeer (dll, node->dptr, node->dlen); | ||||
| 	} | ||||
|  | ||||
| 	/* free the node */ | ||||
| 	QSE_MMGR_FREE (dll->mmgr, node); | ||||
| } | ||||
|  | ||||
| qse_dll_node_t* qse_dll_search ( | ||||
| 	qse_dll_t* dll, qse_dll_node_t* pos, const void* dptr, qse_size_t dlen) | ||||
| { | ||||
| 	if (pos == QSE_NULL) pos = QSE_DLL_HEAD(dll); | ||||
|  | ||||
| 	while (QSE_DLL_ISMEMBER(dll,pos)) | ||||
| 	{ | ||||
| 		if (dll->comper (dll, pos->dptr, pos->dlen, dptr, dlen) == 0) | ||||
| 		{ | ||||
| 			return pos; | ||||
| 		} | ||||
|  | ||||
| 		pos = pos->next; | ||||
| 	}	 | ||||
|  | ||||
| 	return QSE_NULL; | ||||
| } | ||||
|  | ||||
| qse_dll_node_t* qse_dll_rsearch ( | ||||
| 	qse_dll_t* dll, qse_dll_node_t* pos, const void* dptr, qse_size_t dlen) | ||||
| { | ||||
| 	if (pos == QSE_NULL) pos = QSE_DLL_TAIL(dll); | ||||
|  | ||||
| 	while (QSE_DLL_ISMEMBER(dll,pos)) | ||||
| 	{ | ||||
| 		if (dll->comper (dll, pos->dptr, pos->dlen, dptr, dlen) == 0) | ||||
| 		{ | ||||
| 			return pos; | ||||
| 		} | ||||
|  | ||||
| 		pos = pos->prev; | ||||
| 	}	 | ||||
|  | ||||
| 	return QSE_NULL; | ||||
| } | ||||
|  | ||||
| qse_dll_node_t* qse_dll_insert ( | ||||
| 	qse_dll_t* dll, qse_dll_node_t* pos, void* dptr, qse_size_t dlen) | ||||
| { | ||||
| 	qse_dll_node_t* n = alloc_node (dll, dptr, dlen); | ||||
| 	if (n == QSE_NULL) return QSE_NULL; | ||||
|  | ||||
| 	if (pos == QSE_NULL) | ||||
| 	if (n) | ||||
| 	{ | ||||
| 		/* insert at the end */ | ||||
| 		if (dll->head == QSE_NULL) | ||||
| 		if (pos == QSE_NULL) | ||||
| 		{ | ||||
| 			QSE_ASSERT (dll->tail == QSE_NULL); | ||||
| 			dll->head = n; | ||||
| 			/* insert at the end */ | ||||
| 			QSE_DLL_ADDTAIL (dll, 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 */ | ||||
| 			qse_dll_node_t* n2 = dll->head; | ||||
| 			while (n2->next != pos) n2 = n2->next; | ||||
| 			n2->next = n; | ||||
| 			/* insert in front of the positional node */ | ||||
| 			QSE_DLL_CHAIN (dll, pos->prev, n, pos); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	dll->size++; | ||||
| 	return n; | ||||
| } | ||||
|  | ||||
| void qse_dll_delete (qse_dll_t* dll, qse_dll_node_t* pos) | ||||
| { | ||||
| 	if (pos == QSE_NULL || !QSE_DLL_ISMEMBER(dll,pos)) return; | ||||
| 	QSE_DLL_UNCHAIN (dll, pos); | ||||
| 	free_node (dll, pos); | ||||
| } | ||||
|  | ||||
| void qse_dll_clear (qse_dll_t* dll) | ||||
| { | ||||
| 	while (!QSE_DLL_ISEMPTY(dll)) | ||||
| 	{ | ||||
| 		qse_dll_delete (dll, QSE_DLL_HEAD(dll)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void qse_dll_walk (qse_dll_t* dll, qse_dll_walker_t walker, void* ctx) | ||||
| { | ||||
| 	qse_dll_node_t* n = QSE_DLL_HEAD(dll); | ||||
| 	qse_dll_walk_t w = QSE_DLL_WALK_FORWARD; | ||||
|  | ||||
| 	while (QSE_DLL_ISMEMBER(dll,n)) | ||||
| 	{ | ||||
| 		qse_dll_node_t* nxt = n->next; | ||||
| 		qse_dll_node_t* prv = n->prev; | ||||
|  | ||||
| 		w = walker (dll, n, ctx); | ||||
|  | ||||
| 		if (w == QSE_DLL_WALK_FORWARD) n = nxt; | ||||
| 		else if (w == QSE_DLL_WALK_BACKWARD) n = prv; | ||||
| 		else break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void qse_dll_rwalk (qse_dll_t* dll, qse_dll_walker_t walker, void* ctx) | ||||
| { | ||||
| 	qse_dll_node_t* n = QSE_DLL_TAIL(dll); | ||||
| 	qse_dll_walk_t w = QSE_DLL_WALK_BACKWARD; | ||||
|  | ||||
| 	while (QSE_DLL_ISMEMBER(dll,n)) | ||||
| 	{ | ||||
| 		qse_dll_node_t* nxt = n->next; | ||||
| 		qse_dll_node_t* prv = n->prev; | ||||
|  | ||||
| 		w = walker (dll, n, ctx); | ||||
|  | ||||
| 		if (w == QSE_DLL_WALK_FORWARD) n = nxt; | ||||
| 		else if (w == QSE_DLL_WALK_BACKWARD) n = prv; | ||||
| 		else break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| qse_dll_node_t* qse_dll_pushhead (qse_dll_t* dll, void* data, qse_size_t size) | ||||
| { | ||||
| 	return qse_dll_insert (dll, dll->head, data, size); | ||||
| 	return qse_dll_insert (dll, QSE_DLL_HEAD(dll), data, size); | ||||
| } | ||||
|  | ||||
| qse_dll_node_t* qse_dll_pushtail (qse_dll_t* dll, void* data, qse_size_t size) | ||||
| @ -190,67 +327,16 @@ qse_dll_node_t* qse_dll_pushtail (qse_dll_t* dll, void* data, qse_size_t size) | ||||
| 	return qse_dll_insert (dll, QSE_NULL, data, size); | ||||
| } | ||||
|  | ||||
| void qse_dll_delete (qse_dll_t* dll, qse_dll_node_t* pos) | ||||
| { | ||||
| 	if (pos == QSE_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 == QSE_NULL) dll->tail = QSE_NULL; | ||||
| 	} | ||||
| 	else  | ||||
| 	{ | ||||
| 		/* but deletion of other nodes has significant performance | ||||
| 		 * penalty as it has look for the predecessor of the  | ||||
| 		 * target node */ | ||||
| 		qse_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 != QSE_NULL) | ||||
| 	{ | ||||
| 		/* free the actual data */ | ||||
| 		dll->freeer (dll, pos->dptr, pos->dlen); | ||||
| 	} | ||||
|  | ||||
| 	/* free the node */ | ||||
| 	QSE_MMGR_FREE (dll->mmgr, pos); | ||||
|  | ||||
| 	/* decrement the number of elements */ | ||||
| 	dll->size--; | ||||
| } | ||||
|  | ||||
| void qse_dll_pophead (qse_dll_t* dll) | ||||
| { | ||||
| 	qse_dll_delete (dll, dll->head); | ||||
| 	QSE_ASSERT (!QSE_DLL_ISEMPTY(dll)); | ||||
| 	QSE_DLL_DELHEAD (dll); | ||||
| } | ||||
|  | ||||
| void qse_dll_poptail (qse_dll_t* dll) | ||||
| { | ||||
| 	qse_dll_delete (dll, dll->tail); | ||||
| 	QSE_ASSERT (!QSE_DLL_ISEMPTY(dll)); | ||||
| 	QSE_DLL_DELTAIL (dll); | ||||
| } | ||||
|  | ||||
| void qse_dll_walk (qse_dll_t* dll, qse_dll_walker_t walker, void* arg) | ||||
| { | ||||
| 	qse_dll_node_t* n = dll->head; | ||||
|  | ||||
| 	while (n != QSE_NULL) | ||||
| 	{ | ||||
| 		if (walker(dll,n,arg) == QSE_DLL_WALK_STOP) return; | ||||
| 		n = n->next; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void* qse_dll_copyinline (qse_dll_t* dll, void* dptr, qse_size_t dlen) | ||||
| { | ||||
| 	/* this is a dummy copier */ | ||||
| 	return QSE_NULL; | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										33
									
								
								qse/lib/cmn/gdl.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								qse/lib/cmn/gdl.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  * | ||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
|  | ||||
|     QSE is free software: you can redistribute it and/or modify | ||||
|     it under the terms of the GNU Lesser General Public License as  | ||||
|     published by the Free Software Foundation, either version 3 of  | ||||
|     the License, or (at your option) any later version. | ||||
|  | ||||
|     QSE 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 Lesser General Public License for more details. | ||||
|  | ||||
|     You should have received a copy of the GNU Lesser General Public  | ||||
|     License along with QSE. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| #include <qse/cmn/gdl.h> | ||||
|  | ||||
| void qse_gdl_chain (qse_gdl_t* p, qse_gdl_t* x, qse_gdl_t* n) | ||||
| { | ||||
| 	x->prev = p; x->next = n; n->prev = x; p->next = x; | ||||
| } | ||||
|  | ||||
| void qse_gdl_unchain (qse_gdl_t* x) | ||||
| { | ||||
| 	qse_gdl_t* p = x->prev; | ||||
| 	qse_gdl_t* n = x->next; | ||||
| 	n->prev = p; p->next = n; | ||||
| } | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: lda.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ | ||||
|  * $Id: lda.c 354 2010-09-03 12:50:08Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -207,22 +207,22 @@ void qse_lda_setcomper (lda_t* lda, comper_t comper) | ||||
|  | ||||
| keeper_t qse_lda_getkeeper (lda_t* lda) | ||||
| { | ||||
|         return lda->keeper; | ||||
| 	return lda->keeper; | ||||
| } | ||||
|  | ||||
| void qse_lda_setkeeper (lda_t* lda, keeper_t keeper) | ||||
| { | ||||
|         lda->keeper = keeper; | ||||
| 	lda->keeper = keeper; | ||||
| } | ||||
|  | ||||
| sizer_t qse_lda_getsizer (lda_t* lda) | ||||
| { | ||||
|         return lda->sizer; | ||||
| 	return lda->sizer; | ||||
| } | ||||
|  | ||||
| void qse_lda_setsizer (lda_t* lda, sizer_t sizer) | ||||
| { | ||||
|         lda->sizer = sizer; | ||||
| 	lda->sizer = sizer; | ||||
| } | ||||
|  | ||||
| size_t qse_lda_getsize (lda_t* lda) | ||||
| @ -527,7 +527,7 @@ size_t qse_lda_walk (lda_t* lda, walker_t walker, void* ctx) | ||||
| 	{ | ||||
| 		if (lda->node[i] != QSE_NULL)  | ||||
| 		{ | ||||
|                 	w = walker (lda, i, ctx); | ||||
|                w = walker (lda, i, ctx); | ||||
| 			nwalks++; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * $Id: sll.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ | ||||
|  * $Id: sll.c 354 2010-09-03 12:50:08Z hyunghwan.chung $ | ||||
|  * | ||||
|     Copyright 2006-2009 Chung, Hyung-Hwan. | ||||
|     This file is part of QSE. | ||||
| @ -44,13 +44,23 @@ QSE_IMPLEMENT_COMMON_FUNCTIONS (sll) | ||||
| #define size_t    qse_size_t | ||||
| #define mmgr_t    qse_mmgr_t | ||||
|  | ||||
| static int comp_data (sll_t* sll,  | ||||
| static int default_comper (sll_t* sll,  | ||||
| 	const void* dptr1, size_t dlen1,  | ||||
| 	const void* dptr2, size_t dlen2) | ||||
| { | ||||
| 	if (dlen1 == dlen2) return QSE_MEMCMP (dptr1, dptr2, TOB(sll,dlen1)); | ||||
| 	/* it just returns 1 to indicate that they are different. */ | ||||
| 	return 1; | ||||
|  | ||||
| #if 0 | ||||
| 	size_t min = (dlen1 < dlen2)? dlen1: dlen2; | ||||
| 	int n = QSE_MEMCMP (dptr1, dptr2, TOB(sll,min)); | ||||
| 	if (n == 0 && dlen1 != dlen2) | ||||
| 	{ | ||||
| 		n = (dlen1 > dlen2)? 1: -1; | ||||
| 	} | ||||
| 	return n; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| static node_t* alloc_node (sll_t* sll, void* dptr, size_t dlen) | ||||
| @ -133,7 +143,7 @@ sll_t* qse_sll_init (sll_t* sll, mmgr_t* mmgr) | ||||
| 	sll->size = 0; | ||||
| 	sll->scale = 1; | ||||
|  | ||||
| 	sll->comper = comp_data; | ||||
| 	sll->comper = default_comper; | ||||
| 	sll->copier = QSE_SLL_COPIER_SIMPLE; | ||||
| 	return sll; | ||||
| } | ||||
| @ -187,7 +197,7 @@ comper_t qse_sll_getcomper (sll_t* sll) | ||||
|  | ||||
| void qse_sll_setcomper (sll_t* sll, comper_t comper) | ||||
| { | ||||
| 	if (comper == QSE_NULL) comper = comp_data; | ||||
| 	if (comper == QSE_NULL) comper = default_comper; | ||||
| 	sll->comper = comper; | ||||
| } | ||||
|  | ||||
| @ -301,6 +311,18 @@ void qse_sll_clear (sll_t* sll) | ||||
| 	QSE_ASSERT (TAIL(sll) == QSE_NULL); | ||||
| } | ||||
|  | ||||
| void qse_sll_walk (sll_t* sll, walker_t walker, void* ctx) | ||||
| { | ||||
| 	node_t* n = HEAD(sll); | ||||
|  | ||||
| 	while (n != QSE_NULL) | ||||
| 	{ | ||||
| 		qse_sll_node_t* nxt = NEXT(n); | ||||
| 		if (walker(sll,n,ctx) == QSE_SLL_WALK_STOP) return; | ||||
| 		n = nxt; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| node_t* qse_sll_pushhead (sll_t* sll, void* data, size_t size) | ||||
| { | ||||
| 	return qse_sll_insert (sll, HEAD(sll), data, size); | ||||
| @ -321,14 +343,4 @@ void qse_sll_poptail (sll_t* sll) | ||||
| 	qse_sll_delete (sll, TAIL(sll)); | ||||
| } | ||||
|  | ||||
| void qse_sll_walk (sll_t* sll, walker_t walker, void* ctx) | ||||
| { | ||||
| 	node_t* n = HEAD(sll); | ||||
|  | ||||
| 	while (n != QSE_NULL) | ||||
| 	{ | ||||
| 		if (walker(sll,n,ctx) == QSE_SLL_WALK_STOP) return; | ||||
| 		n = NEXT(n); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| AM_CPPFLAGS = -I$(top_srcdir)/include -DNDEBUG | ||||
|  | ||||
| bin_PROGRAMS = xma fma chr str sll lda htb rbt fio pio sio time main rex01  | ||||
| bin_PROGRAMS = xma fma chr str sll dll lda htb rbt fio pio sio time main rex01  | ||||
|  | ||||
| LDFLAGS = -L../../lib/cmn  | ||||
| LDADD = -lqsecmn  | ||||
| @ -10,6 +10,7 @@ fma_SOURCES = fma.c | ||||
| chr_SOURCES = chr.c | ||||
| str_SOURCES = str.c | ||||
| sll_SOURCES = sll.c | ||||
| dll_SOURCES = dll.c | ||||
| lda_SOURCES = lda.c | ||||
| htb_SOURCES = htb.c | ||||
| rbt_SOURCES = rbt.c | ||||
|  | ||||
| @ -35,9 +35,9 @@ POST_UNINSTALL = : | ||||
| build_triplet = @build@ | ||||
| host_triplet = @host@ | ||||
| bin_PROGRAMS = xma$(EXEEXT) fma$(EXEEXT) chr$(EXEEXT) str$(EXEEXT) \ | ||||
| 	sll$(EXEEXT) lda$(EXEEXT) htb$(EXEEXT) rbt$(EXEEXT) \ | ||||
| 	fio$(EXEEXT) pio$(EXEEXT) sio$(EXEEXT) time$(EXEEXT) \ | ||||
| 	main$(EXEEXT) rex01$(EXEEXT) | ||||
| 	sll$(EXEEXT) dll$(EXEEXT) lda$(EXEEXT) htb$(EXEEXT) \ | ||||
| 	rbt$(EXEEXT) fio$(EXEEXT) pio$(EXEEXT) sio$(EXEEXT) \ | ||||
| 	time$(EXEEXT) main$(EXEEXT) rex01$(EXEEXT) | ||||
| subdir = samples/cmn | ||||
| DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in | ||||
| ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 | ||||
| @ -58,6 +58,10 @@ am_chr_OBJECTS = chr.$(OBJEXT) | ||||
| chr_OBJECTS = $(am_chr_OBJECTS) | ||||
| chr_LDADD = $(LDADD) | ||||
| chr_DEPENDENCIES = | ||||
| am_dll_OBJECTS = dll.$(OBJEXT) | ||||
| dll_OBJECTS = $(am_dll_OBJECTS) | ||||
| dll_LDADD = $(LDADD) | ||||
| dll_DEPENDENCIES = | ||||
| am_fio_OBJECTS = fio.$(OBJEXT) | ||||
| fio_OBJECTS = $(am_fio_OBJECTS) | ||||
| fio_LDADD = $(LDADD) | ||||
| @ -123,14 +127,14 @@ CCLD = $(CC) | ||||
| LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ | ||||
| 	--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ | ||||
| 	$(LDFLAGS) -o $@ | ||||
| SOURCES = $(chr_SOURCES) $(fio_SOURCES) $(fma_SOURCES) $(htb_SOURCES) \ | ||||
| 	$(lda_SOURCES) $(main_SOURCES) $(pio_SOURCES) $(rbt_SOURCES) \ | ||||
| 	$(rex01_SOURCES) $(sio_SOURCES) $(sll_SOURCES) $(str_SOURCES) \ | ||||
| 	$(time_SOURCES) $(xma_SOURCES) | ||||
| DIST_SOURCES = $(chr_SOURCES) $(fio_SOURCES) $(fma_SOURCES) \ | ||||
| SOURCES = $(chr_SOURCES) $(dll_SOURCES) $(fio_SOURCES) $(fma_SOURCES) \ | ||||
| 	$(htb_SOURCES) $(lda_SOURCES) $(main_SOURCES) $(pio_SOURCES) \ | ||||
| 	$(rbt_SOURCES) $(rex01_SOURCES) $(sio_SOURCES) $(sll_SOURCES) \ | ||||
| 	$(str_SOURCES) $(time_SOURCES) $(xma_SOURCES) | ||||
| DIST_SOURCES = $(chr_SOURCES) $(dll_SOURCES) $(fio_SOURCES) \ | ||||
| 	$(fma_SOURCES) $(htb_SOURCES) $(lda_SOURCES) $(main_SOURCES) \ | ||||
| 	$(pio_SOURCES) $(rbt_SOURCES) $(rex01_SOURCES) $(sio_SOURCES) \ | ||||
| 	$(sll_SOURCES) $(str_SOURCES) $(time_SOURCES) $(xma_SOURCES) | ||||
| ETAGS = etags | ||||
| CTAGS = ctags | ||||
| DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) | ||||
| @ -280,6 +284,7 @@ fma_SOURCES = fma.c | ||||
| chr_SOURCES = chr.c | ||||
| str_SOURCES = str.c | ||||
| sll_SOURCES = sll.c | ||||
| dll_SOURCES = dll.c | ||||
| lda_SOURCES = lda.c | ||||
| htb_SOURCES = htb.c | ||||
| rbt_SOURCES = rbt.c | ||||
| @ -369,6 +374,9 @@ clean-binPROGRAMS: | ||||
| chr$(EXEEXT): $(chr_OBJECTS) $(chr_DEPENDENCIES)  | ||||
| 	@rm -f chr$(EXEEXT) | ||||
| 	$(LINK) $(chr_OBJECTS) $(chr_LDADD) $(LIBS) | ||||
| dll$(EXEEXT): $(dll_OBJECTS) $(dll_DEPENDENCIES)  | ||||
| 	@rm -f dll$(EXEEXT) | ||||
| 	$(LINK) $(dll_OBJECTS) $(dll_LDADD) $(LIBS) | ||||
| fio$(EXEEXT): $(fio_OBJECTS) $(fio_DEPENDENCIES)  | ||||
| 	@rm -f fio$(EXEEXT) | ||||
| 	$(LINK) $(fio_OBJECTS) $(fio_LDADD) $(LIBS) | ||||
| @ -416,6 +424,7 @@ distclean-compile: | ||||
| 	-rm -f *.tab.c | ||||
|  | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chr.Po@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dll.Po@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fio.Po@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fma.Po@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb.Po@am__quote@ | ||||
|  | ||||
							
								
								
									
										165
									
								
								qse/samples/cmn/dll.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								qse/samples/cmn/dll.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,165 @@ | ||||
| #include <qse/cmn/mem.h> | ||||
| #include <qse/cmn/str.h> | ||||
| #include <qse/cmn/dll.h> | ||||
| #include <qse/cmn/stdio.h> | ||||
|  | ||||
|  | ||||
| #define R(f) \ | ||||
| 	do { \ | ||||
| 		qse_printf (QSE_T("== %s ==\n"), QSE_T(#f)); \ | ||||
| 		if (f() == -1) return -1; \ | ||||
| 	} while (0) | ||||
|  | ||||
| static qse_dll_walk_t walk_dll (qse_dll_t* dll, qse_dll_node_t* n, void* arg) | ||||
| { | ||||
| 	qse_printf (QSE_T("[%.*s]\n"), (int)QSE_DLL_DLEN(n), QSE_DLL_DPTR(n)); | ||||
| 	return QSE_DLL_WALK_FORWARD; | ||||
| } | ||||
|  | ||||
| static qse_dll_walk_t rwalk_dll (qse_dll_t* dll, qse_dll_node_t* n, void* arg) | ||||
| { | ||||
| 	qse_printf (QSE_T("[%.*s]\n"), (int)QSE_DLL_DLEN(n), QSE_DLL_DPTR(n)); | ||||
| 	return QSE_DLL_WALK_BACKWARD; | ||||
| } | ||||
|  | ||||
| static int test1 () | ||||
| { | ||||
| 	qse_dll_t* s1; | ||||
| 	qse_dll_node_t* p; | ||||
| 	qse_char_t* x[] = | ||||
| 	{ | ||||
| 		QSE_T("this is so good"), | ||||
| 		QSE_T("what the hack"), | ||||
| 		QSE_T("do you like it?") | ||||
| 	}; | ||||
| 	int i; | ||||
|  | ||||
| 	s1 = qse_dll_open (QSE_MMGR_GETDFL(), 0);	 | ||||
| 	if (s1 == QSE_NULL) | ||||
| 	{ | ||||
| 		qse_printf (QSE_T("cannot open a string\n")); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	qse_dll_setcopier (s1, QSE_DLL_COPIER_INLINE); | ||||
| 	qse_dll_setscale (s1, QSE_SIZEOF(qse_char_t)); | ||||
|  | ||||
| 	for (i = 0; i < QSE_COUNTOF(x); i++) | ||||
| 	{ | ||||
| 		qse_dll_pushtail (s1, x[i], qse_strlen(x[i])); | ||||
| 	} | ||||
| 	qse_printf (QSE_T("s1 holding [%d] nodes\n"), QSE_DLL_SIZE(s1)); | ||||
| 	qse_dll_walk (s1, walk_dll, QSE_NULL); | ||||
| 		 | ||||
|  | ||||
| 	p = qse_dll_search (s1, QSE_NULL, x[0], qse_strlen(x[0])); | ||||
| 	if (p != QSE_NULL) | ||||
| 	{ | ||||
| 		qse_dll_delete (s1, p); | ||||
| 	} | ||||
| 	qse_printf (QSE_T("s1 holding [%d] nodes\n"), QSE_DLL_SIZE(s1)); | ||||
| 	qse_dll_walk (s1, walk_dll, QSE_NULL); | ||||
|  | ||||
| 	qse_dll_close (s1); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int test2 () | ||||
| { | ||||
| 	qse_dll_t* s1; | ||||
| 	qse_dll_node_t* p; | ||||
| 	qse_char_t* x[] = | ||||
| 	{ | ||||
| 		QSE_T("this is so good"), | ||||
| 		QSE_T("what the hack"), | ||||
| 		QSE_T("do you like it?") | ||||
| 	}; | ||||
| 	int i; | ||||
|  | ||||
| 	s1 = qse_dll_open (QSE_MMGR_GETDFL(), 0);	 | ||||
| 	if (s1 == QSE_NULL) | ||||
| 	{ | ||||
| 		qse_printf (QSE_T("cannot open a string\n")); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	qse_dll_setcopier (s1, QSE_DLL_COPIER_INLINE); | ||||
| 	qse_dll_setscale (s1, QSE_SIZEOF(qse_char_t)); | ||||
|  | ||||
| 	for (i = 0; i < QSE_COUNTOF(x); i++) | ||||
| 	{ | ||||
| 		qse_dll_pushtail (s1, x[i], qse_strlen(x[i])); | ||||
| 	} | ||||
| 	qse_printf (QSE_T("s1 holding [%d] nodes\n"), QSE_DLL_SIZE(s1)); | ||||
| 	qse_dll_rwalk (s1, rwalk_dll, QSE_NULL); | ||||
| 		 | ||||
|  | ||||
| 	p = qse_dll_search (s1, QSE_NULL, x[0], qse_strlen(x[0])); | ||||
| 	if (p != QSE_NULL) | ||||
| 	{ | ||||
| 		qse_dll_delete (s1, p); | ||||
| 	} | ||||
| 	qse_printf (QSE_T("s1 holding [%d] nodes\n"), QSE_DLL_SIZE(s1)); | ||||
| 	qse_dll_rwalk (s1, rwalk_dll, QSE_NULL); | ||||
|  | ||||
| 	qse_dll_close (s1); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| typedef struct item_t item_t; | ||||
| struct item_t | ||||
| { | ||||
| 	int a; | ||||
| 	int b; | ||||
| }; | ||||
| QSE_DLL_DEFINE_SIMPLE (item_t); | ||||
|  | ||||
| static int test3 () | ||||
| { | ||||
| 	qse_size_t n; | ||||
| 	QSE_DLL_TYPE(item_t) ii; | ||||
| 	QSE_DLL_NODE_TYPE(item_t) x[30]; | ||||
| 	QSE_DLL_NODE_TYPE(item_t)* p; | ||||
|  | ||||
| 	QSE_DLL_INIT(&ii); | ||||
|  | ||||
| 	for (n = 0; n < QSE_COUNTOF(x); n++) | ||||
| 	{ | ||||
| 		x[n].data.a = n; | ||||
| 		x[n].data.b = n * 2; | ||||
| 	} | ||||
|  | ||||
| 	for (n = 0; n < QSE_COUNTOF(x)/2; n++) | ||||
| 	{ | ||||
| 		QSE_DLL_ADDHEAD (&ii, &x[n]); | ||||
| 	} | ||||
|  | ||||
| 	for (; n < QSE_COUNTOF(x); n++) | ||||
| 	{ | ||||
| 		QSE_DLL_ADDTAIL (&ii, &x[n]); | ||||
| 	} | ||||
|  | ||||
| 	qse_printf (QSE_T("total %d items\n"), (int)QSE_DLL_SIZE (&ii)); | ||||
| 	for (p = QSE_DLL_HEAD(&ii); QSE_DLL_ISMEMBER(&ii,p); p = p->next) | ||||
| 	{ | ||||
| 		qse_printf (QSE_T("%d %d\n"), p->data.a, p->data.b); | ||||
| 	} | ||||
|  | ||||
| 	QSE_DLL_UNCHAIN (&ii, QSE_DLL_TAIL(&ii)->prev); | ||||
| 	QSE_DLL_DELHEAD (&ii); | ||||
| 	qse_printf (QSE_T("total %d items. printing in reverse\n"), (int)QSE_DLL_SIZE (&ii)); | ||||
| 	for (p = QSE_DLL_TAIL(&ii); QSE_DLL_ISMEMBER(&ii,p); p = p->prev) | ||||
| 	{ | ||||
| 		qse_printf (QSE_T("%d %d\n"), p->data.a, p->data.b); | ||||
| 	} | ||||
| 	QSE_DLL_FINI (&ii); | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int main () | ||||
| { | ||||
| 	R (test1); | ||||
| 	R (test2); | ||||
| 	R (test3); | ||||
| 	return 0; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user