enhanced dll

This commit is contained in:
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_INIT(dll) \
QSE_BLOCK ( \
QSE_GDL_INIT(&(dll)->gdl); \
(dll)->size = 0; \
)
#define QSE_DLL_FINI(dll) __QSE_DLL_WRAP ( \
while (!QSE_DLL_ISEMPTY(dll)) QSE_DLL_DELHEAD(dll); \
)
#define QSE_DLL_FINI(dll) QSE_DLL_CLEAR(dll)
#define QSE_DLL_CHAIN(dll,p,x,n) __QSE_DLL_WRAP ( \
register qse_dll_nhdr_t* __qse_dll_chain_prev = (qse_dll_nhdr_t*)(p); \
register qse_dll_nhdr_t* __qse_dll_chain_next = (qse_dll_nhdr_t*)(n); \
(x)->prev = (void*)__qse_dll_chain_prev; \
(x)->next = (void*)__qse_dll_chain_next; \
__qse_dll_chain_next->prev = (void*)(x); \
__qse_dll_chain_prev->next = (void*)(x); \
)
#define QSE_DLL_CHAIN(dll,p,x,n) \
QSE_BLOCK ( \
QSE_GDL_CHAIN ((qse_gdl_t*)p, (qse_gdl_t*)x, (qse_gdl_t*)n); \
(dll)->size++; \
)
#define QSE_DLL_UNCHAIN(dll,x) __QSE_DLL_WRAP ( \
register qse_dll_nhdr_t* __qse_dll_unchain_prev = \
(qse_dll_nhdr_t*)((x)->prev); \
register qse_dll_nhdr_t* __qse_dll_unchain_next = \
(qse_dll_nhdr_t*)((x)->next); \
__qse_dll_unchain_next->prev = __qse_dll_unchain_prev; \
__qse_dll_unchain_prev->next = __qse_dll_unchain_next; \
)
#define QSE_DLL_UNCHAIN(dll,x) \
QSE_BLOCK ( \
QSE_GDL_UNCHAIN ((qse_gdl_t*)x); \
(dll)->size--; \
)
#define QSE_DLL_HEADNODE(dll) ((dll)->link.next)
#define QSE_DLL_TAILNODE(dll) ((dll)->link.prev)
#define QSE_DLL_NEXTNODE(dll,p) ((p)->next)
#define QSE_DLL_PREVNODE(dll,p) ((p)->prev)
#define QSE_DLL_ISVALIDNODE(dll,p) ((p) != &(dll)->link)
#define QSE_DLL_CLEAR(dll) \
QSE_BLOCK ( \
while (!QSE_DLL_ISEMPTY(dll)) QSE_DLL_DELHEAD(dll); \
)
#define QSE_DLL_ISEMPTY(dll) (QSE_DLL_HEADNODE(dll) == &(dll)->link)
#define QSE_DLL_ADDHEAD(dll,x) QSE_DLL_CHAIN(dll,&(dll)->link,x,QSE_DLL_HEADNODE(dll))
#define QSE_DLL_ADDTAIL(dll,x) QSE_DLL_CHAIN(dll,QSE_DLL_TAILNODE(dll),x,&(dll)->link)
#define QSE_DLL_DELHEAD(dll) QSE_DLL_UNCHAIN(dll,QSE_DLL_HEADNODE(dll))
#define QSE_DLL_DELTAIL(dll) QSE_DLL_UNCHAIN(dll,QSE_DLL_TAILNODE(dll))
/*
* Doubly Linked List
/**
* The QSE_DLL_ISEMPTY macro determines if a list @a dll is empty
*/
#define QSE_DLL_ISEMPTY(dll) QSE_GDL_ISEMPTY(&(dll)->gdl)
/**
* The QSE_DLL_ISMEMBER macro determines if a node @a x is a member
* of a list @a dll.
*/
#define QSE_DLL_ISMEMBER(dll,x) ((x) != &(dll)->gdl)
#define QSE_DLL_HEAD(dll) QSE_GDL_HEAD(&(dll)->gdl)
#define QSE_DLL_TAIL(dll) QSE_GDL_TAIL(&(dll)->gdl)
#define QSE_DLL_SIZE(dll) ((dll)->size)
/**
* The QSE_DLL_ADDHEAD macro add a member node @a x to the head of
* the list @a dll.
*/
#define QSE_DLL_ADDHEAD(dll,x) \
QSE_DLL_CHAIN(dll,&(dll)->gdl,x,QSE_DLL_HEAD(dll))
/**
* The QSE_DLL_ADDHEAD macro add a member node @a x to the tail of
* the list @a dll.
*/
#define QSE_DLL_ADDTAIL(dll,x) \
QSE_DLL_CHAIN(dll,QSE_DLL_TAIL(dll),x,&(dll)->gdl)
/**
* The QSE_DLL_DELHEAD macro deletes the head node.
*/
#define QSE_DLL_DELHEAD(dll) \
QSE_DLL_UNCHAIN(dll,QSE_DLL_HEAD(dll))
/**
* The QSE_DLL_DELTAIL macro deletes the tail node.
*/
#define QSE_DLL_DELTAIL(dll) \
QSE_DLL_UNCHAIN(dll,QSE_DLL_TAIL(dll))
/* ----------- more general implementation below ----------------- */
enum qse_dll_walk_t
{
QSE_DLL_WALK_STOP = 0,
QSE_DLL_WALK_FORWARD = 1,
QSE_DLL_WALK_BACKWARD = 2
};
typedef enum qse_dll_walk_t qse_dll_walk_t;
typedef struct qse_dll_t qse_dll_t;
typedef struct qse_dll_node_t qse_dll_node_t;
/* data copier */
typedef void* (*qse_dll_copier_t) (qse_dll_t* dll, void* dptr, qse_size_t dlen);
typedef void* (*qse_dll_copier_t) (
qse_dll_t* dll,
void* dptr,
qse_size_t dlen
);
/* data freeer */
typedef void (*qse_dll_freeer_t) (qse_dll_t* dll, void* dptr, qse_size_t dlen);
typedef void (*qse_dll_freeer_t) (
qse_dll_t* dll,
void* dptr,
qse_size_t dlen
);
/**
* The qse_dll_comper_t type defines a key comparator that is called when
* the list needs to compare data. A doubly linked list is created with a
* default comparator that performs bitwise comparison.
*
* The comparator must return 0 if the data are the same and a non-zero
* integer otherwise.
*/
typedef int (*qse_dll_comper_t) (
qse_dll_t* dll, /**< doubly linked list */
const void* dptr1, /**< data pointer */
qse_size_t dlen1, /**< data length */
const void* dptr2, /**< data pointer */
qse_size_t dlen2 /**< data length */
);
/* node visitor */
typedef int (*qse_dll_walker_t) (
qse_dll_t* dll, qse_dll_node_t* node, void* arg);
struct qse_dll_t
{
qse_mmgr_t* mmgr;
qse_dll_copier_t copier;
qse_dll_freeer_t freeer;
qse_size_t size;
qse_dll_node_t* head;
qse_dll_node_t* tail;
};
typedef qse_dll_walk_t (*qse_dll_walker_t) (
qse_dll_t* dll,
qse_dll_node_t* node,
void* ctx
);
/**
* The qse_dll_node_t type defines a doubly linked list node.
*/
struct qse_dll_node_t
{
void* dptr; /* pointer to the beginning of data */
qse_size_t dlen; /* length of data in bytes */
qse_dll_node_t* next; /* pointer to the next node */
qse_dll_node_t* prev; /* pointer to the prev node */
/* the first two fields in sync with qse_gdl_t */
qse_dll_node_t* prev;
qse_dll_node_t* next;
void* dptr; /**< data pointer */
qse_size_t dlen; /**< data length */
};
enum qse_dll_walk_t
/**
* The qse_dll_t type defines a doubly linked list.
*/
struct qse_dll_t
{
QSE_DLL_WALK_STOP = 0,
QSE_DLL_WALK_FORWARD = 1
QSE_DEFINE_COMMON_FIELDS (dll)
qse_dll_node_t gdl;
qse_size_t size;
qse_byte_t scale;
qse_dll_copier_t copier;
qse_dll_freeer_t freeer;
qse_dll_comper_t comper;
};
#define QSE_DLL_COPIER_INLINE qse_dll_copyinline
#define QSE_DLL_COPIER_SIMPLE ((qse_dll_copier_t)1)
#define QSE_DLL_COPIER_INLINE ((qse_dll_copier_t)2)
#define QSE_DLL_HEAD(dll) ((dll)->head)
#define QSE_DLL_TAIL(dll) ((dll)->tail)
#define QSE_DLL_SIZE(dll) ((dll)->size)
#define QSE_DLL_SCALE(dll) ((dll)->scale)
#define QSE_DLL_DPTR(node) ((node)->dptr)
#define QSE_DLL_DLEN(node) ((node)->dlen)
#define QSE_DLL_DPTR(n) ((n)->dptr)
#define QSE_DLL_DLEN(n) ((n)->dlen)
#define QSE_DLL_NEXT(n) ((n)->next)
#define QSE_DLL_PREV(n) ((n)->prev)
#ifdef __cplusplus
extern "C" {
#endif
/*
* NAME: creates a doubly linked list with extension area
*
* DESCRIPTION:
QSE_DEFINE_COMMON_FUNCTIONS (dll)
/**
* The qse_dll_open() function creates an empty doubly linked list.
* If the memory manager mmgr is QSE_NULL, the function gets the default
* memory manager with QSE_MMGR_GETMMGR() and uses it if it is not QSE_NULL.
@ -185,141 +239,175 @@ extern "C" {
* after initializing the main area. The extension initializer is passed
* the pointer to the doubly linked list created.
*
* RETURNS:
* @return
* the pointer to a newly created doubly linked list on success.
* QSE_NULL on failure.
*
* WARNING:
* In the debug build, it fails the assertion if QSE_MMGR_SETMMGR() returns
* QSE_NULL when QSE_NULL is passed as the first parameter. In the release
* build, it returns QSE_NULL if such a thing happens.
*/
qse_dll_t* qse_dll_open (
qse_mmgr_t* mmgr /* memory manager */ ,
qse_size_t ext /* size of extension area in bytes */
qse_mmgr_t* mmgr, /**< memory manager */
qse_size_t xtnsize /**< size of extension area in bytes */
);
/*
* NAME destroys a singly linked list
/**
* The qse_dll_close() function destroys a doubly linked list.
*/
void qse_dll_close (
qse_dll_t* dll /* a singly linked list */
qse_dll_t* dll /** doubly linked list */
);
/*
* NAME deletes all elements of a singly linked list
/**
* The qse_dll_init() function initializes a statically declared list.
*/
void qse_dll_clear (
qse_dll_t* dll /* a singly linked list */
qse_dll_t* qse_dll_init (
qse_dll_t* dll, /**< doubly linked list */
qse_mmgr_t* mmgr /**< memory manager */
);
/*
* NAME specifies how to clone an element
*
* DESCRIPTION
* A special copier QSE_DLL_COPIER_INLINE is provided. This copier enables
* you to copy the data inline to the internal node. No freeer is invoked
* when the node is freeed.
*
* You may set the copier to QSE_NULL to perform no special operation
* when the data pointer is rememebered.
/**
* The qse_dll_fini() function finalizes a statically initialized list.
*/
void qse_dll_fini (
qse_dll_t* dll /**< doubly linked list */
);
/**
* The qse_dll_getscale() function gets the scale factor
*/
int qse_dll_getscale (
qse_dll_t* dll /**< doubly linked list */
);
/**
* The qse_dll_setscale() function sets the scale factor of the data length.
* A scale factor determines the actual length of data in bytes. A doubly
* linked list created with a scale factor of 1. The scale factor should be
* larger than 0 and less than 256.
*/
void qse_dll_setscale (
qse_dll_t* dll, /**< doubly linked list */
int scale /**< scale factor */
);
/**
* The qse_dll_setcopier() function changes the element copier.
* A special copier QSE_DLL_COPIER_INLINE is provided. This copier enables
* you to copy the data inline to the internal node. No freeer is invoked
* when the node is freeed. You may set the copier to QSE_NULL to perform
* no special operation when the data pointer is rememebered.
*/
void qse_dll_setcopier (
qse_dll_t* dll /* a singly linked list */,
qse_dll_copier_t copier /* a element copier */
qse_dll_t* dll, /**< doubly linked list */
qse_dll_copier_t copier /**< element copier */
);
/**
* The qse_dll_getcopier() function returns the element copier.
*/
qse_dll_copier_t qse_dll_getcopier (
qse_dll_t* dll /* a singly linked list */
qse_dll_t* dll /**< doubly linked list */
);
/*
* NAME specifies how to destroy an element
*
* DESCRIPTION
* The freeer is called when a node containing the element is destroyed.
/**
* The qse_dll_setfreeer() function changes the element freeer.
* The freeer is called when a node containing the element is destroyed.
*/
void qse_dll_setfreeer (
qse_dll_t* dll /* a singly linked list */,
qse_dll_freeer_t freeer /* a element freeer */
qse_dll_t* dll, /**< doubly linked list */
qse_dll_freeer_t freeer /**< element freeer */
);
/**
* The qse_dll_getfreeer() function returns the element freeer.
*/
qse_dll_freeer_t qse_dll_getfreeer (
qse_dll_t* dll /* a singly linked list */
qse_dll_t* dll /**< doubly linked list */
);
/*
* NAME Gets the pointer to the extension area
* RETURN the pointer to the extension area
*/
void* qse_dll_getxtn (
qse_dll_t* dll /* a singly linked list */
);
/*
* NAME: get the pointer to the memory manager in use
*/
qse_mmgr_t* qse_dll_getmmgr (
qse_dll_t* dll /* a singly linked list */
);
void qse_dll_setmmgr (qse_dll_t* dll, qse_mmgr_t* mmgr);
/*
* NAME Gets the number of elements held in a singly linked list
* RETURN the number of elements the list holds
/**
* The qse_dll_getsize() function returns the number of the data nodes held
* in a doubly linked list.
*/
qse_size_t qse_dll_getsize (
qse_dll_t* dll /* a singly linked list */
qse_dll_t* dll /**< doubly linked list */
);
/*
* NAME Gets the head(first) node
* RETURN the tail node of a singly linked list
/**
* The qse_dll_gethead() function gets the head node. You may use the
* #QSE_DLL_HEAD macro instead.
*/
qse_dll_node_t* qse_dll_gethead (
qse_dll_t* dll /* a singly linked list */
qse_dll_t* dll /**< doubly linked list */
);
/*
* NAME Gets the tail(last) node
* RETURN the tail node of a singly linked list
/**
* The qse_dll_gettail() function gets the head node. You may use the
* #QSE_DLL_TAIL macro instead.
*/
qse_dll_node_t* qse_dll_gettail (
qse_dll_t* dll /* a singly linked list */
qse_dll_t* dll /**< doubly linked list */
);
/*
* NAME Inserts data before a positional node given
*
* DESCRIPTION
* Inserts data.
qse_dll_node_t* qse_dll_search (
qse_dll_t* dll, /**< doubly linked list */
qse_dll_node_t* pos, /**< positional node */
const void* dptr, /**< data pointer */
qse_size_t dlen /**< data length */
);
qse_dll_node_t* qse_dll_rsearch (
qse_dll_t* dll, /**< doubly linked list */
qse_dll_node_t* pos, /**< positional node */
const void* dptr, /**< data pointer */
qse_size_t dlen /**< data length */
);
/**
* The qse_dll_insert() function insert an element into a list
*/
qse_dll_node_t* qse_dll_insert (
qse_dll_t* dll /* a singly linked list */,
qse_dll_node_t* pos /* a node before which a new node is inserted */,
void* dptr /* the pointer to the data */ ,
qse_size_t dlen /* the length of the data in bytes */
qse_dll_t* dll, /**< doubly linked list */
qse_dll_node_t* pos, /**< node before which a new node is inserted */
void* dptr, /**< data pointer */
qse_size_t dlen /**< data length */
);
void qse_dll_delete (
qse_dll_t* dll,
qse_dll_node_t* pos
);
/**
* The qse_dll_clear() functions deletes all elements of a list
*/
void qse_dll_clear (
qse_dll_t* dll /**< doubly linked list */
);
void qse_dll_walk (
qse_dll_t* dll, /**< doubly linked list */
qse_dll_walker_t walker, /**< user-defined walker function */
void* ctx /**< pointer to user-defined data */
);
void qse_dll_rwalk (
qse_dll_t* dll, /**< doubly linked list */
qse_dll_walker_t walker, /**< user-defined walker function */
void* ctx /**< pointer to user-defined data */
);
qse_dll_node_t* qse_dll_pushhead (
qse_dll_t* dll /* a singly linked list */,
void* dptr,
qse_dll_t* dll, /* doubly linked list */
void* dptr,
qse_size_t dlen
);
qse_dll_node_t* qse_dll_pushtail (
qse_dll_t* dll /* a singly linked list */,
void* dptr,
qse_dll_t* dll, /* doubly linked list */
void* dptr,
qse_size_t dlen
);
void qse_dll_delete (
qse_dll_t* dll,
qse_dll_node_t* pos
);
void qse_dll_pophead (
qse_dll_t* dll
);
@ -328,36 +416,6 @@ void qse_dll_poptail (
qse_dll_t* dll
);
/*
* NAME Traverses s singly linked list
*
* DESCRIPTION
* A singly linked list allows uni-directional in-order traversal.
* The qse_dll_walk() function traverses a singly linkked list from its
* head node down to its tail node as long as the walker function returns
* QSE_DLL_WALK_FORWARD. A walker can return QSE_DLL_WALK_STOP to cause
* immediate stop of traversal.
* For each node, the walker function is called and it is passed three
* parameters: the singly linked list, the visiting node, and the
* user-defined data passed as the third parameter in a call to the
* qse_dll_walk() function.
*/
void qse_dll_walk (
qse_dll_t* dll /* a singly linked list */,
qse_dll_walker_t walker /* a user-defined walker function */,
void* arg /* pointer to user-defined data */
);
/*
* Causes a singly linked list to copy in data to a node.
* Use QSE_DLL_COPIER_INLINE instead.
*/
void* qse_dll_copyinline (
qse_dll_t* dll /* a singly linked list */,
void* data /* pointer to data to copy */ ,
qse_size_t len /* length of data in bytes */
);
#ifdef __cplusplus
}
#endif

70
qse/include/qse/cmn/gdl.h Normal file
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.
@ -38,7 +38,7 @@ typedef struct qse_htb_pair_t qse_htb_pair_t;
*/
enum qse_htb_walk_t
{
QSE_HTB_WALK_STOP = 0,
QSE_HTB_WALK_STOP = 0,
QSE_HTB_WALK_FORWARD = 1
};
typedef enum qse_htb_walk_t qse_htb_walk_t;

View File

@ -58,7 +58,7 @@
# define qse_map_clear(map) qse_htb_clear(map)
# define qse_map_walk(map,walker,ctx) qse_htb_walk(map,walker,ctx)
# define QSE_MAP_WALK_STOP QSE_HTB_WALK_STOP
# define QSE_MAP_WALK_FORWARD QSE_HTB_WALK_FORWARD
# define QSE_MAP_WALK_FORWARD QSE_HTB_WALK_FORWARD
# define qse_map_walk_t qse_htb_walk_t
# define QSE_MAP_KEY QSE_HTB_KEY
# define QSE_MAP_VAL QSE_HTB_VAL
@ -111,7 +111,7 @@
# define qse_map_clear(map) qse_rbt_clear(map)
# define qse_map_walk(map,walker,ctx) qse_rbt_walk(map,walker,ctx)
# define QSE_MAP_WALK_STOP QSE_RBT_WALK_STOP
# define QSE_MAP_WALK_FORWARD QSE_RBT_WALK_FORWARD
# define QSE_MAP_WALK_FORWARD QSE_RBT_WALK_FORWARD
# define qse_map_walk_t qse_rbt_walk_t
# define QSE_MAP_KEY QSE_RBT_KEY
# define QSE_MAP_VAL QSE_RBT_VAL

View File

@ -37,7 +37,7 @@ typedef struct qse_rbt_pair_t qse_rbt_pair_t;
*/
enum qse_rbt_walk_t
{
QSE_RBT_WALK_STOP = 0,
QSE_RBT_WALK_STOP = 0,
QSE_RBT_WALK_FORWARD = 1
};
typedef enum qse_rbt_walk_t qse_rbt_walk_t;

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.
*/
/**
@ -33,13 +33,14 @@
*/
enum qse_sll_walk_t
{
QSE_SLL_WALK_STOP = 0, /**< stop traversal */
QSE_SLL_WALK_FORWARD = 1 /**< traverse to the next node */
QSE_SLL_WALK_STOP = 0, /**< stop traversal */
QSE_SLL_WALK_FORWARD = 1 /**< traverse to the next node */
};
typedef enum qse_sll_walk_t qse_sll_walk_t;
typedef struct qse_sll_t qse_sll_t;
typedef struct qse_sll_node_t qse_sll_node_t;
typedef enum qse_sll_walk_t qse_sll_walk_t;
/**
* The qse_sll_copier_t type defines a callback function for node construction.
@ -89,16 +90,15 @@ typedef int (*qse_sll_comper_t) (
* The qse_sll_walker_t type defines a list traversal callback for each node.
* The qse_sll_walk() calls a callback function of the type qse_sll_walker_t
* for each node until it returns QSE_SLL_WALK_STOP. The walker should return
* QSE_SLL_WALK_FORWARD to let qse_sll_walk() continue visiting the next node.
* QSE_SLL_WALK_FORWARD to let qse_sll_walk() continue visiting the next node.
* The third parameter to qse_sll_walk() is passed to the walker as the third
* parameter.
*/
typedef qse_sll_walk_t (*qse_sll_walker_t) (
qse_sll_t* sll, /* singly linked list */
qse_sll_node_t* node, /* visited node */
void* arg /* user-defined data */
qse_sll_t* sll, /**< singly linked list */
qse_sll_node_t* node, /**< visited node */
void* ctx /**< user-defined data */
);
/******/
/**
* The qse_sll_t type defines a singly lnked list.
@ -183,203 +183,128 @@ qse_sll_t* qse_sll_open (
qse_size_t ext /* size of extension area in bytes */
);
/****f* Common/qse_sll_close
* NAME
* qse_sll_close - destroy a singly linked list
*
* DESCRIPTION
* The qse_sll_close() function destroys a singly linked list freeing up
* the memory.
*
* SYNOPSIS
/**
* The qse_sll_close() function destroys a singly linked list freeing up
* the memory.
*/
void qse_sll_close (
qse_sll_t* sll /* a singly linked list */
qse_sll_t* sll /**< singly linked list */
);
/******/
/****f* Common/qse_sll_init
* NAME
* qse_sll_init - initialize a singly linked list
*
* DESCRIPTION
* The qse_sll_init() function initializes a singly linked list. The memory
* should be allocated by a caller and be passed to it. The caller may declare
* a static variable of the qse_sll_t type and pass its address. A memory
* manager still needs to be passed for node manipulation later.
/**
* The qse_sll_init() function initializes a statically declared singly
* linked list. The memory should be allocated by a caller and be passed
* to it. The caller may declare a static variable of the qse_sll_t type
* and pass its address. A memory manager still needs to be passed for
* node manipulation later.
*
* RETURN
* @return
* The qse_sll_init() function returns the first parameter on success and
* QSE_NULL on failure.
*
* SYNOPSIS
*/
qse_sll_t* qse_sll_init (
qse_sll_t* sll /* an uninitialized singly linked list */,
qse_mmgr_t* mmgr /* a memory manager */
qse_sll_t* sll, /* singly linked list */
qse_mmgr_t* mmgr /* memory manager */
);
/******/
/****f* Common/qse_sll_fini
* NAME
* qse_sll_init - deinitialize a singly linked list
*
* SYNOPSIS
/**
* The qse_sll_fini() function finalizes a statically initialized list.
*/
void qse_sll_fini (
qse_sll_t* sll /* a singly linked list */
qse_sll_t* sll /**< singly linked list */
);
/******/
/****f* Common/qse_sll_getsize
* NAME
* qse_sll_getsize - get the number of nodes
*
* DESCRIPTION
* The qse_sll_getsize() function returns the number of the data nodes held
* in a singly linked list.
*
* SYNOPSIS
*/
qse_size_t qse_sll_getsize (
qse_sll_t* sll /* a singly linked list */
);
/******/
/****f* Common/qse_sll_getscale
* NAME
* qse_sll_getscale - get the scale factor
*
* SYNOPSIS
/**
* The qse_sll_getscale() function gets the scale factor
*/
int qse_sll_getscale (
qse_sll_t* sll /* a singly linked list */
qse_sll_t* sll /**< singly linked list */
);
/******/
/****f* Common/qse_sll_setscale
* NAME
* qse_sll_setscale - set the scale factor
*
* DESCRIPTION
/**
* The qse_sll_setscale() function sets the scale factor of the data length.
* A scale factor determines the actual length of data in bytes. A singly
* linked list created with a scale factor of 1. The scale factor should be
* larger than 0 and less than 256.
*
* NOTES
* It is a bad idea to change the scale factor when a sll is not empty.
*
* SYNOPSIS
*/
void qse_sll_setscale (
qse_sll_t* sll /* a singly linked list */,
int scale /* a scale factor */
qse_sll_t* sll, /**< singly linked list */
int scale /**< scale factor */
);
/******/
/****f* Common/qse_sll_getcopier
* NAME
* qse_sll_getfreeer - get the data copier
*
* SYNOPSIS
/**
* The qse_sll_getfreeer() function gets the data copier.
*/
qse_sll_copier_t qse_sll_getcopier (
qse_sll_t* sll /* a singly linked list */
qse_sll_t* sll /* singly linked list */
);
/******/
/****f* Common/qse_sll_setcopier
* NAME
* qse_sll_setcopier - set a data copier
*
* DESCRIPTION
* A special copier QSE_SLL_COPIER_INLINE is provided. This copier enables
* you to copy the data inline to the internal node. No freeer is invoked
* when the node is freeed.
*
* You may set the copier to QSE_NULL to perform no special operation
* when the data pointer is rememebered.
*
* SYNOPSIS
/**
* The qse_sll_setcopier() function changes the element copier.
* A special copier QSE_SLL_COPIER_INLINE is provided. This copier enables
* you to copy the data inline to the internal node. No freeer is invoked
* when the node is freeed. You may set the copier to QSE_NULL to perform
* no special operation when the data pointer is rememebered.
*/
void qse_sll_setcopier (
qse_sll_t* sll /* a singly linked list */,
qse_sll_copier_t copier /* a data copier */
qse_sll_t* sll, /**< singly linked list */
qse_sll_copier_t copier /**< data copier */
);
/******/
/****f* Common/qse_sll_getfreeer
* NAME
* qse_sll_getfreeer - get the data freeer
*
* SYNOPSIS
/**
* The qse_sll_getfreeer() function returns the element freeer.
*/
qse_sll_freeer_t qse_sll_getfreeer (
qse_sll_t* sll /* a singly linked list */
qse_sll_t* sll /**< singly linked list */
);
/******/
/****f* Common/qse_sll_setfreeer
* NAME
* qse_sll_setfreeer - set a data freeer
*
* DESCRIPTION
* The freeer is called when a node containing the element is destroyed.
*
* SYNOPSIS
/**
* The qse_sll_setfreeer() function changes the element freeer.
* The freeer is called when a node containing the element is destroyed.
*/
void qse_sll_setfreeer (
qse_sll_t* sll /* a singly linked list */,
qse_sll_freeer_t freeer /* a data freeer */
qse_sll_t* sll, /**< singly linked list */
qse_sll_freeer_t freeer /**< data freeer */
);
/******/
/****f* Common/qse_sll_getcomper
* NAME
* qse_sll_getcomper - get the data comparator
*
* SYNOPSIS
/**
* The qse_sll_getcomper() function returns the data comparator.
*/
qse_sll_comper_t qse_sll_getcomper (
qse_sll_t* sll /* a singly linked list */
qse_sll_t* sll /**< singly linked list */
);
/******/
/****f* Common/qse_sll_setcomper
* NAME
* qse_sll_setcomper - set the data comparator
*
* SYNOPSIS
/**
* The qse_sll_setcomper() function changes the data comparator
*/
void qse_sll_setcomper (
qse_sll_t* sll /* a singly linked list */,
qse_sll_comper_t comper /* a comparator */
qse_sll_t* sll /**< singly linked list */,
qse_sll_comper_t comper /**< comparator */
);
/******/
/****f* Common/qse_sll_gethead
* NAME
* qse_sll_gethead - get the head node
*
* SYNOPSIS
/**
* The qse_sll_getsize() function returns the number of the data nodes held
* in a singly linked list.
*/
qse_size_t qse_sll_getsize (
qse_sll_t* sll /** singly linked list */
);
/**
* The qse_sll_gethead() function gets the head node. You may use the
* #QSE_SLL_HEAD macro instead.
*/
qse_sll_node_t* qse_sll_gethead (
qse_sll_t* sll /* a singly linked list */
qse_sll_t* sll /**< a singly linked list */
);
/******/
/****f* Common/qse_sll_gettail
* NAME
* qse_sll_gettail - get the tail node
*
* SYNOPSIS
/**
* The qse_sll_gettail() function gets the head node. You may use the
* #QSE_SLL_TAIL macro instead.
*/
qse_sll_node_t* qse_sll_gettail (
qse_sll_t* sll /* a singly linked list */
qse_sll_t* sll /**< singly linked list */
);
/******/
/**
* The qse_sll_search() function traverses a list to find a node containing
@ -387,8 +312,8 @@ qse_sll_node_t* qse_sll_gettail (
* from the next node of the positional node. If the positional node is
* QSE_NULL, the traversal begins from the head node.
*
* Note that no reverse search is provided because a reverse traversal can not be
* achieved efficiently.
* Note that no reverse search is provided because a reverse traversal can not
* be achieved efficiently.
*
* @return pointer to the node found. QSE_NULL if no match is found
*/
@ -430,31 +355,10 @@ void qse_sll_clear (
qse_sll_t* sll /**< singly linked list */
);
qse_sll_node_t* qse_sll_pushhead (
qse_sll_t* sll /**< singly linked list */,
void* dptr,
qse_size_t dlen
);
qse_sll_node_t* qse_sll_pushtail (
qse_sll_t* sll /**< singly linked list */,
void* dptr,
qse_size_t dlen
);
void qse_sll_pophead (
qse_sll_t* sll
);
void qse_sll_poptail (
qse_sll_t* sll
);
/**
* The qse_sll_walk() function traverses a singly linkked list from its
* head node down to its tail node as long as the walker function returns
* QSE_SLL_WALK_FORWARD. A walker can return QSE_SLL_WALK_STOP to cause
* QSE_SLL_WALK_FORWARD . A walker can return QSE_SLL_WALK_STOP to cause
* immediate stop of traversal.
*
* For each node, the walker function is called and it is passed three
@ -468,6 +372,26 @@ void qse_sll_walk (
void* ctx /**< the pointer to user-defined data */
);
qse_sll_node_t* qse_sll_pushhead (
qse_sll_t* sll /**< singly linked list */,
void* dptr,
qse_size_t dlen
);
qse_sll_node_t* qse_sll_pushtail (
qse_sll_t* sll /**< singly linked list */,
void* dptr,
qse_size_t dlen
);
void qse_sll_pophead (
qse_sll_t* sll
);
void qse_sll_poptail (
qse_sll_t* sll
);
#ifdef __cplusplus
}
#endif

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 */
);
/**
@ -189,13 +198,13 @@ qse_size_t qse_strxncpy (
* buffer.
*/
qse_size_t qse_strxput (
qse_char_t* buf,
qse_char_t* buf,
qse_size_t bsz,
const qse_char_t* str
);
qse_size_t qse_strxnput (
qse_char_t* buf,
qse_char_t* buf,
qse_size_t bsz,
const qse_char_t* str,
qse_size_t len
@ -226,8 +235,8 @@ qse_size_t qse_strfcpy (
* @sa qse_strfcpy, qse_strxfcpy, qse_strxfncpy
*/
qse_size_t qse_strfncpy (
qse_char_t* buf,
const qse_char_t* fmt,
qse_char_t* buf,
const qse_char_t* fmt,
const qse_cstr_t str[]
);
@ -256,9 +265,9 @@ qse_size_t qse_strxfcpy (
* @sa qse_strfcpy, qse_strfncpy, qse_strxfcpy
*/
qse_size_t qse_strxfncpy (
qse_char_t* buf,
qse_char_t* buf,
qse_size_t bsz,
const qse_char_t* fmt,
const qse_char_t* fmt,
const qse_cstr_t str[]
);
@ -281,11 +290,11 @@ qse_size_t qse_strxfncpy (
* @endcode
*/
qse_size_t qse_strxsubst (
qse_char_t* buf,
qse_char_t* buf,
qse_size_t bsz,
const qse_char_t* fmt,
qse_strxsubst_subst_t subst,
void* ctx
void* ctx
);
qse_size_t qse_strxcat (
@ -308,15 +317,15 @@ int qse_strcmp (
int qse_strxcmp (
const qse_char_t* s1,
qse_size_t len1,
qse_size_t len1,
const qse_char_t* s2
);
int qse_strxncmp (
const qse_char_t* s1,
qse_size_t len1,
qse_size_t len1,
const qse_char_t* s2,
qse_size_t len2
qse_size_t len2
);
int qse_strcasecmp (
@ -505,17 +514,25 @@ qse_char_t* qse_strxbeg (
const qse_char_t* sub)
;
/*
* The qse_strbeg() function checks if the a string begins with a substring.
* @return @a str on match, QSE_NULL on no match
*/
qse_char_t* qse_strnbeg (
const qse_char_t* str,
const qse_char_t* sub,
qse_size_t len
qse_size_t len
);
/*
* The qse_strbeg() function checks if the a string begins with a substring.
* @return @a str on match, QSE_NULL on no match
*/
qse_char_t* qse_strxnbeg (
const qse_char_t* str,
qse_size_t len1,
qse_size_t len1,
const qse_char_t* sub,
qse_size_t len2
qse_size_t len2
);
/**
@ -565,25 +582,76 @@ qse_char_t* qse_strxnend (
/*
* string conversion
*/
int qse_strtoi (const qse_char_t* str);
long qse_strtol (const qse_char_t* str);
unsigned int qse_strtoui (const qse_char_t* str);
unsigned long qse_strtoul (const qse_char_t* str);
int qse_strtoi (
const qse_char_t* str
);
int qse_strxtoi (const qse_char_t* str, qse_size_t len);
long qse_strxtol (const qse_char_t* str, qse_size_t len);
unsigned int qse_strxtoui (const qse_char_t* str, qse_size_t len);
unsigned long qse_strxtoul (const qse_char_t* str, qse_size_t len);
long qse_strtol (
const qse_char_t* str
);
qse_int_t qse_strtoint (const qse_char_t* str);
qse_long_t qse_strtolong (const qse_char_t* str);
qse_uint_t qse_strtouint (const qse_char_t* str);
qse_ulong_t qse_strtoulong (const qse_char_t* str);
unsigned int qse_strtoui (
const qse_char_t* str
);
qse_int_t qse_strxtoint (const qse_char_t* str, qse_size_t len);
qse_long_t qse_strxtolong (const qse_char_t* str, qse_size_t len);
qse_uint_t qse_strxtouint (const qse_char_t* str, qse_size_t len);
qse_ulong_t qse_strxtoulong (const qse_char_t* str, qse_size_t len);
unsigned long qse_strtoul (
const qse_char_t* str
);
int qse_strxtoi (
const qse_char_t* str,
qse_size_t len
);
long qse_strxtol (
const qse_char_t* str,
qse_size_t len
);
unsigned int qse_strxtoui (
const qse_char_t* str,
qse_size_t len
);
unsigned long qse_strxtoul (
const qse_char_t* str,
qse_size_t len
);
qse_int_t qse_strtoint (
const qse_char_t* str
);
qse_long_t qse_strtolong (
const qse_char_t* str
);
qse_uint_t qse_strtouint (
const qse_char_t* str
);
qse_ulong_t qse_strtoulong (
const qse_char_t* str
);
qse_int_t qse_strxtoint (
const qse_char_t* str, qse_size_t len
);
qse_long_t qse_strxtolong (
const qse_char_t* str,
qse_size_t len
);
qse_uint_t qse_strxtouint (
const qse_char_t* str,
qse_size_t len
);
qse_ulong_t qse_strxtoulong (
const qse_char_t* str,
qse_size_t len
);
/**
* The qse_strspl() function splits a string into fields.
@ -595,7 +663,6 @@ int qse_strspl (
qse_char_t rquote,
qse_char_t escape
);
/******/
/**
* The qse_strspltrn() function splits a string translating special

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