enhanced dll

This commit is contained in:
hyung-hwan 2010-09-04 06:50:08 +00:00
parent 6094a21e5e
commit af72767aa5
19 changed files with 1041 additions and 598 deletions

View File

@ -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

View File

@ -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:

View File

@ -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_FINI(dll) __QSE_DLL_WRAP ( \
#define QSE_DLL_INIT(dll) \
QSE_BLOCK ( \
QSE_GDL_INIT(&(dll)->gdl); \
(dll)->size = 0; \
)
#define QSE_DLL_FINI(dll) QSE_DLL_CLEAR(dll)
#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_BLOCK ( \
QSE_GDL_UNCHAIN ((qse_gdl_t*)x); \
(dll)->size--; \
)
#define QSE_DLL_CLEAR(dll) \
QSE_BLOCK ( \
while (!QSE_DLL_ISEMPTY(dll)) QSE_DLL_DELHEAD(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_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_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_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,134 +239,137 @@ 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
/**
* 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.
* 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 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_node_t* qse_dll_pushhead (
qse_dll_t* dll /* a singly 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_size_t dlen
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 (
@ -320,6 +377,37 @@ void qse_dll_delete (
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, /* doubly linked list */
void* dptr,
qse_size_t dlen
);
qse_dll_node_t* qse_dll_pushtail (
qse_dll_t* dll, /* doubly linked list */
void* dptr,
qse_size_t dlen
);
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
View 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

View File

@ -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.

View File

@ -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.
*/
/**
@ -36,10 +36,11 @@ enum qse_sll_walk_t
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.
@ -94,11 +95,10 @@ typedef int (*qse_sll_comper_t) (
* 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
*/
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
/**
* 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.
*
* 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.
*
* 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
/**
* 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.
*
* SYNOPSIS
* 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 qse_sll_setfreeer() function changes the element freeer.
* The freeer is called when a node containing the element is destroyed.
*
* SYNOPSIS
*/
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,27 +355,6 @@ 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
@ -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

View File

@ -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 */
);
/**
@ -505,12 +514,20 @@ 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
);
/*
* 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,
@ -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

View File

@ -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))

View File

@ -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 \

View File

@ -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@

View File

@ -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 (n)
{
if (pos == QSE_NULL)
{
/* insert at the end */
if (dll->head == QSE_NULL)
{
QSE_ASSERT (dll->tail == QSE_NULL);
dll->head = n;
}
else dll->tail->next = n;
dll->tail = n;
QSE_DLL_ADDTAIL (dll, 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;
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
View 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;
}

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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

View File

@ -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
View 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;
}