enhanced dll
This commit is contained in:
parent
6094a21e5e
commit
af72767aa5
@ -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 ( \
|
||||
#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
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.
|
||||
|
@ -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,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 */
|
||||
);
|
||||
|
||||
/**
|
||||
@ -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
|
||||
|
@ -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 (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
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.
|
||||
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user