enhanced dll

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

View File

@ -2,7 +2,7 @@ pkgincludedir = $(includedir)/qse/cmn
pkginclude_HEADERS = \ pkginclude_HEADERS = \
mem.h xma.h fma.h chr.h str.h lda.h htb.h rbt.h \ 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 fio.h pio.h sio.h time.h misc.h main.h stdio.h
if ENABLE_CXX if ENABLE_CXX

View File

@ -52,8 +52,9 @@ CONFIG_CLEAN_VPATH_FILES =
SOURCES = SOURCES =
DIST_SOURCES = DIST_SOURCES =
am__pkginclude_HEADERS_DIST = mem.h xma.h fma.h chr.h str.h lda.h \ 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 \ htb.h rbt.h rex.h sll.h gdl.h dll.h opt.h tio.h fio.h pio.h \
time.h misc.h main.h stdio.h Mmgr.hpp StdMmgr.hpp Mmged.hpp 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_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \ am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
@ -221,8 +222,8 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@ top_srcdir = @top_srcdir@
pkginclude_HEADERS = mem.h xma.h fma.h chr.h str.h lda.h htb.h rbt.h \ 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 \ rex.h sll.h gdl.h dll.h opt.h tio.h fio.h pio.h sio.h time.h \
main.h stdio.h $(am__append_1) misc.h main.h stdio.h $(am__append_1)
all: all-am all: all-am
.SUFFIXES: .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. Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -21,162 +21,216 @@
#ifndef _QSE_CMN_DLL_H_ #ifndef _QSE_CMN_DLL_H_
#define _QSE_CMN_DLL_H_ #define _QSE_CMN_DLL_H_
/** @file
* This file defines a doubly linked list interface.
*/
#include <qse/types.h> #include <qse/types.h>
#include <qse/macros.h> #include <qse/macros.h>
#include <qse/cmn/gdl.h>
/** #define QSE_DLL_DEFINE(list_type,node_type,data_define,manage_define) \
* The qse_dll_nhdr_t type defines a common node header fields used internally. typedef struct list_type list_type; \
*/ typedef struct node_type node_type; \
typedef struct qse_dll_nhdr_t qse_dll_nhdr_t; struct node_type \
struct qse_dll_nhdr_t { \
{ node_type* prev; \
qse_dll_nhdr_t* next; node_type* next; \
qse_dll_nhdr_t* prev; data_define \
}; }; \
struct list_type \
#define __QSE_DLL_WRAP(x) do { x } while(0) { \
node_type gdl; \
qse_size_t size; \
manage_define \
}
#define QSE_DLL_TYPE(data_type) qse_dll_ ## data_type ## _t #define QSE_DLL_TYPE(data_type) qse_dll_ ## data_type ## _t
#define QSE_DLL_NODE_TYPE(data_type) qse_dll_ ## data_type ## _node_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. * of the @a data_type type.
*/ */
#define QSE_DLL_DEFINE(data_type) \ #define QSE_DLL_DEFINE_SIMPLE(data_type) \
typedef struct QSE_DLL_TYPE(data_type) QSE_DLL_TYPE(data_type); \ QSE_DLL_DEFINE ( \
typedef struct QSE_DLL_NODE_TYPE(data_type) QSE_DLL_NODE_TYPE(data_type); \ QSE_DLL_TYPE(data_type), \
struct QSE_DLL_NODE_TYPE(data_type) \ QSE_DLL_NODE_TYPE(data_type), \
{ \ data_type data;, \
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; \
}
/** /**
* 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. * of the @a data_type type.
*/ */
#define QSE_DLL_DEFINE_MANAGED(data_type,manage_type) \ #define QSE_DLL_DEFINE_MANAGED(data_type,manage_type) \
typedef struct QSE_DLL_TYPE(data_type) QSE_DLL_TYPE(data_type); \ QSE_DLL_DEFINE ( \
typedef struct QSE_DLL_NODE_TYPE(data_type) QSE_DLL_NODE_TYPE(data_type); \ QSE_DLL_TYPE(data_type), \
struct QSE_DLL_NODE_TYPE(data_type) \ QSE_DLL_NODE_TYPE(data_type), \
{ \ data_type data;, \
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; \
manage_type data; \ manage_type data; \
} )
#define QSE_DLL_INIT(dll) __QSE_DLL_WRAP ( \ #define QSE_DLL_INIT(dll) \
(dll)->link.next = &(dll)->link; \ QSE_BLOCK ( \
(dll)->link.prev = &(dll)->link; \ 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); \ 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); \ * The QSE_DLL_ISEMPTY macro determines if a list @a dll is empty
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
*/ */
#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_t qse_dll_t;
typedef struct qse_dll_node_t qse_dll_node_t; typedef struct qse_dll_node_t qse_dll_node_t;
/* data copier */ /* 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 */ /* 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 */ /* node visitor */
typedef int (*qse_dll_walker_t) ( typedef qse_dll_walk_t (*qse_dll_walker_t) (
qse_dll_t* dll, qse_dll_node_t* node, void* arg); qse_dll_t* dll,
qse_dll_node_t* node,
struct qse_dll_t void* ctx
{ );
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;
};
/**
* The qse_dll_node_t type defines a doubly linked list node.
*/
struct qse_dll_node_t struct qse_dll_node_t
{ {
void* dptr; /* pointer to the beginning of data */ /* the first two fields in sync with qse_gdl_t */
qse_size_t dlen; /* length of data in bytes */ qse_dll_node_t* prev;
qse_dll_node_t* next; /* pointer to the next node */ qse_dll_node_t* next;
qse_dll_node_t* prev; /* pointer to the prev node */
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_DEFINE_COMMON_FIELDS (dll)
QSE_DLL_WALK_FORWARD = 1
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_SCALE(dll) ((dll)->scale)
#define QSE_DLL_TAIL(dll) ((dll)->tail) #define QSE_DLL_DPTR(node) ((node)->dptr)
#define QSE_DLL_SIZE(dll) ((dll)->size) #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 #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* QSE_DEFINE_COMMON_FUNCTIONS (dll)
* NAME: creates a doubly linked list with extension area
* /**
* DESCRIPTION:
* The qse_dll_open() function creates an empty doubly linked list. * The qse_dll_open() function creates an empty doubly linked list.
* If the memory manager mmgr is QSE_NULL, the function gets the default * 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. * 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 * after initializing the main area. The extension initializer is passed
* the pointer to the doubly linked list created. * the pointer to the doubly linked list created.
* *
* RETURNS: * @return
* the pointer to a newly created doubly linked list on success. * the pointer to a newly created doubly linked list on success.
* QSE_NULL on failure. * 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_dll_t* qse_dll_open (
qse_mmgr_t* mmgr /* memory manager */ , qse_mmgr_t* mmgr, /**< memory manager */
qse_size_t ext /* size of extension area in bytes */ 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 ( 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* qse_dll_init (
qse_dll_t* dll /* a singly linked list */ qse_dll_t* dll, /**< doubly linked list */
qse_mmgr_t* mmgr /**< memory manager */
); );
/* /**
* NAME specifies how to clone an element * The qse_dll_fini() function finalizes a statically initialized list.
* */
* DESCRIPTION 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 * 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 * you to copy the data inline to the internal node. No freeer is invoked
* when the node is freeed. * when the node is freeed. You may set the copier to QSE_NULL to perform
* * no special operation when the data pointer is rememebered.
* You may set the copier to QSE_NULL to perform no special operation
* when the data pointer is rememebered.
*/ */
void qse_dll_setcopier ( void qse_dll_setcopier (
qse_dll_t* dll /* a singly linked list */, qse_dll_t* dll, /**< doubly linked list */
qse_dll_copier_t copier /* a element copier */ 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_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 * The qse_dll_setfreeer() function changes the element freeer.
*
* DESCRIPTION
* The freeer is called when a node containing the element is destroyed. * The freeer is called when a node containing the element is destroyed.
*/ */
void qse_dll_setfreeer ( void qse_dll_setfreeer (
qse_dll_t* dll /* a singly linked list */, qse_dll_t* dll, /**< doubly linked list */
qse_dll_freeer_t freeer /* a element freeer */ 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_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 * The qse_dll_getsize() function returns the number of the data nodes held
* RETURN the pointer to the extension area * in a doubly linked list.
*/
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
*/ */
qse_size_t qse_dll_getsize ( 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 * The qse_dll_gethead() function gets the head node. You may use the
* RETURN the tail node of a singly linked list * #QSE_DLL_HEAD macro instead.
*/ */
qse_dll_node_t* qse_dll_gethead ( 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 * The qse_dll_gettail() function gets the head node. You may use the
* RETURN the tail node of a singly linked list * #QSE_DLL_TAIL macro instead.
*/ */
qse_dll_node_t* qse_dll_gettail ( 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 qse_dll_node_t* qse_dll_search (
* qse_dll_t* dll, /**< doubly linked list */
* DESCRIPTION qse_dll_node_t* pos, /**< positional node */
* Inserts data. 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_node_t* qse_dll_insert (
qse_dll_t* dll /* a singly linked list */, qse_dll_t* dll, /**< doubly linked list */
qse_dll_node_t* pos /* a node before which a new node is inserted */, qse_dll_node_t* pos, /**< node before which a new node is inserted */
void* dptr /* the pointer to the data */ , void* dptr, /**< data pointer */
qse_size_t dlen /* the length of the data in bytes */ qse_size_t dlen /**< data length */
);
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
); );
void qse_dll_delete ( void qse_dll_delete (
@ -320,6 +377,37 @@ void qse_dll_delete (
qse_dll_node_t* pos 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 ( void qse_dll_pophead (
qse_dll_t* dll qse_dll_t* dll
); );
@ -328,36 +416,6 @@ void qse_dll_poptail (
qse_dll_t* dll 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 #ifdef __cplusplus
} }
#endif #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. Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.

View File

@ -1,5 +1,5 @@
/* /*
* $Id: sll.h 328 2010-07-08 06:58:44Z hyunghwan.chung $ * $Id: sll.h 354 2010-09-03 12:50:08Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -25,7 +25,7 @@
#include <qse/macros.h> #include <qse/macros.h>
/** @file /** @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_STOP = 0, /**< stop traversal */
QSE_SLL_WALK_FORWARD = 1 /**< traverse to the next node */ 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_t qse_sll_t;
typedef struct qse_sll_node_t qse_sll_node_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. * The qse_sll_copier_t type defines a callback function for node construction.
@ -94,11 +95,10 @@ typedef int (*qse_sll_comper_t) (
* parameter. * parameter.
*/ */
typedef qse_sll_walk_t (*qse_sll_walker_t) ( typedef qse_sll_walk_t (*qse_sll_walker_t) (
qse_sll_t* sll, /* singly linked list */ qse_sll_t* sll, /**< singly linked list */
qse_sll_node_t* node, /* visited node */ qse_sll_node_t* node, /**< visited node */
void* arg /* user-defined data */ void* ctx /**< user-defined data */
); );
/******/
/** /**
* The qse_sll_t type defines a singly lnked list. * 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 */ 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 qse_sll_close() function destroys a singly linked list freeing up
* the memory. * the memory.
*
* SYNOPSIS
*/ */
void qse_sll_close ( 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 * The qse_sll_init() function initializes a statically declared singly
* qse_sll_init - initialize a singly linked list * 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 * @return
* 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
* The qse_sll_init() function returns the first parameter on success and * The qse_sll_init() function returns the first parameter on success and
* QSE_NULL on failure. * QSE_NULL on failure.
*
* SYNOPSIS
*/ */
qse_sll_t* qse_sll_init ( qse_sll_t* qse_sll_init (
qse_sll_t* sll /* an uninitialized singly linked list */, qse_sll_t* sll, /* singly linked list */
qse_mmgr_t* mmgr /* a memory manager */ qse_mmgr_t* mmgr /* memory manager */
); );
/******/
/****f* Common/qse_sll_fini /**
* NAME * The qse_sll_fini() function finalizes a statically initialized list.
* qse_sll_init - deinitialize a singly linked list
*
* SYNOPSIS
*/ */
void qse_sll_fini ( 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 * The qse_sll_getscale() function gets the scale factor
* 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
*/ */
int qse_sll_getscale ( 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. * 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 * 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 * linked list created with a scale factor of 1. The scale factor should be
* larger than 0 and less than 256. * 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 ( void qse_sll_setscale (
qse_sll_t* sll /* a singly linked list */, qse_sll_t* sll, /**< singly linked list */
int scale /* a scale factor */ int scale /**< scale factor */
); );
/******/
/****f* Common/qse_sll_getcopier /**
* NAME * The qse_sll_getfreeer() function gets the data copier.
* qse_sll_getfreeer - get the data copier
*
* SYNOPSIS
*/ */
qse_sll_copier_t qse_sll_getcopier ( 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 * The qse_sll_setcopier() function changes the element copier.
* qse_sll_setcopier - set a data copier
*
* DESCRIPTION
* A special copier QSE_SLL_COPIER_INLINE is provided. This copier enables * 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 * you to copy the data inline to the internal node. No freeer is invoked
* when the node is freeed. * when the node is freeed. You may set the copier to QSE_NULL to perform
* * no special operation when the data pointer is rememebered.
* You may set the copier to QSE_NULL to perform no special operation
* when the data pointer is rememebered.
*
* SYNOPSIS
*/ */
void qse_sll_setcopier ( void qse_sll_setcopier (
qse_sll_t* sll /* a singly linked list */, qse_sll_t* sll, /**< singly linked list */
qse_sll_copier_t copier /* a data copier */ qse_sll_copier_t copier /**< data copier */
); );
/******/
/****f* Common/qse_sll_getfreeer /**
* NAME * The qse_sll_getfreeer() function returns the element freeer.
* qse_sll_getfreeer - get the data freeer
*
* SYNOPSIS
*/ */
qse_sll_freeer_t qse_sll_getfreeer ( 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 * The qse_sll_setfreeer() function changes the element freeer.
* qse_sll_setfreeer - set a data freeer
*
* DESCRIPTION
* The freeer is called when a node containing the element is destroyed. * The freeer is called when a node containing the element is destroyed.
*
* SYNOPSIS
*/ */
void qse_sll_setfreeer ( void qse_sll_setfreeer (
qse_sll_t* sll /* a singly linked list */, qse_sll_t* sll, /**< singly linked list */
qse_sll_freeer_t freeer /* a data freeer */ qse_sll_freeer_t freeer /**< data freeer */
); );
/******/
/****f* Common/qse_sll_getcomper /**
* NAME * The qse_sll_getcomper() function returns the data comparator.
* qse_sll_getcomper - get the data comparator
*
* SYNOPSIS
*/ */
qse_sll_comper_t qse_sll_getcomper ( 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 * The qse_sll_setcomper() function changes the data comparator
* qse_sll_setcomper - set the data comparator
*
* SYNOPSIS
*/ */
void qse_sll_setcomper ( void qse_sll_setcomper (
qse_sll_t* sll /* a singly linked list */, qse_sll_t* sll /**< singly linked list */,
qse_sll_comper_t comper /* a comparator */ qse_sll_comper_t comper /**< comparator */
); );
/******/
/****f* Common/qse_sll_gethead /**
* NAME * The qse_sll_getsize() function returns the number of the data nodes held
* qse_sll_gethead - get the head node * in a singly linked list.
* */
* SYNOPSIS 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_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 * The qse_sll_gettail() function gets the head node. You may use the
* qse_sll_gettail - get the tail node * #QSE_SLL_TAIL macro instead.
*
* SYNOPSIS
*/ */
qse_sll_node_t* qse_sll_gettail ( 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 * 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 * from the next node of the positional node. If the positional node is
* QSE_NULL, the traversal begins from the head node. * QSE_NULL, the traversal begins from the head node.
* *
* Note that no reverse search is provided because a reverse traversal can not be * Note that no reverse search is provided because a reverse traversal can not
* achieved efficiently. * be achieved efficiently.
* *
* @return pointer to the node found. QSE_NULL if no match is found * @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_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 * 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 * 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. * immediate stop of traversal.
* *
* For each node, the walker function is called and it is passed three * 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 */ 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 #ifdef __cplusplus
} }
#endif #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. Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -25,10 +25,11 @@
#include <qse/macros.h> #include <qse/macros.h>
/** @file /** @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 */ #define QSE_STR_LEN(s) ((s)->len) /**< string length */
@ -170,17 +171,25 @@ qse_size_t qse_strxcpy (
const qse_char_t* str 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_size_t qse_strncpy (
qse_char_t* buf, qse_char_t* buf, /**< buffer with unknown length */
const qse_char_t* str, const qse_char_t* str, /**< length-bounded string */
qse_size_t len 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_size_t qse_strxncpy (
qse_char_t* buf, qse_char_t* buf, /**< length-bounded buffer */
qse_size_t bsz, qse_size_t bsz, /**< buffer length */
const qse_char_t* str, const qse_char_t* str, /**< length-bounded string */
qse_size_t len qse_size_t len /**< string length */
); );
/** /**
@ -505,12 +514,20 @@ qse_char_t* qse_strxbeg (
const qse_char_t* sub) 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 ( qse_char_t* qse_strnbeg (
const qse_char_t* str, const qse_char_t* str,
const qse_char_t* sub, 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 ( qse_char_t* qse_strxnbeg (
const qse_char_t* str, const qse_char_t* str,
qse_size_t len1, qse_size_t len1,
@ -565,25 +582,76 @@ qse_char_t* qse_strxnend (
/* /*
* string conversion * string conversion
*/ */
int qse_strtoi (const qse_char_t* str); int qse_strtoi (
long qse_strtol (const qse_char_t* str); 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_strxtoi (const qse_char_t* str, qse_size_t len); long qse_strtol (
long qse_strxtol (const qse_char_t* str, qse_size_t len); const qse_char_t* str
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); unsigned int qse_strtoui (
qse_long_t qse_strtolong (const qse_char_t* str); 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); unsigned long qse_strtoul (
qse_long_t qse_strxtolong (const qse_char_t* str, qse_size_t len); const qse_char_t* str
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);
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. * The qse_strspl() function splits a string into fields.
@ -595,7 +663,6 @@ int qse_strspl (
qse_char_t rquote, qse_char_t rquote,
qse_char_t escape qse_char_t escape
); );
/******/
/** /**
* The qse_strspltrn() function splits a string translating special * 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. Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -29,26 +29,35 @@
#if defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L) #if defined(__STDC_VERSION__) && (__STDC_VERSION__>=199901L)
# define QSE_INLINE inline # define QSE_INLINE inline
# define QSE_HAVE_INLINE
#elif defined(__GNUC__) && defined(__GNUC_GNU_INLINE__) #elif defined(__GNUC__) && defined(__GNUC_GNU_INLINE__)
# define QSE_INLINE /*extern*/ inline # define QSE_INLINE /*extern*/ inline
# define QSE_HAVE_INLINE
#else #else
# define QSE_INLINE # define QSE_INLINE
# undef QSE_HAVE_INLINE
#endif #endif
#if defined(__GNUC__) #if defined(__GNUC__)
# define QSE_INLINE_ALWAYS inline __attribute__((__always_inline__)) # define QSE_INLINE_ALWAYS inline __attribute__((__always_inline__))
# define QSE_HAVE_INLINE_ALWAYS
#elif defined(_MSC_VER) || (defined(__CC_ARM) || defined(__ARMCC__)) #elif defined(_MSC_VER) || (defined(__CC_ARM) || defined(__ARMCC__))
# define QSE_INLINE_ALWAYS __forceinline # define QSE_INLINE_ALWAYS __forceinline
# define QSE_HAVE_INLINE_ALWAYS
#else #else
# define QSE_INLINE_ALWAYS QSE_INLINE # define QSE_INLINE_ALWAYS QSE_INLINE
# undef QSE_HAVE_INLINE_ALWAYS
#endif #endif
#if defined(__GNUC__) #if defined(__GNUC__)
# define QSE_INLINE_NEVER inline __attribute__((__noinline__)) # define QSE_INLINE_NEVER inline __attribute__((__noinline__))
# define QSE_HAVE_INLINE_NEVER
#elif (defined(__CC_ARM) || defined(__ARMCC__)) #elif (defined(__CC_ARM) || defined(__ARMCC__))
# define QSE_INLINE_NEVER __declspec(noinline) # define QSE_INLINE_NEVER __declspec(noinline)
# define QSE_HAVE_INLINE_NEVER
#else #else
# define QSE_INLINE_NEVER # define QSE_INLINE_NEVER
# undef QSE_HAVE_INLINE_NEVER
#endif #endif
@ -142,14 +151,20 @@
#define QSE_TYPE_MIN(type) \ #define QSE_TYPE_MIN(type) \
((QSE_TYPE_IS_SIGNED(type)? QSE_TYPE_SIGNED_MIN(type): QSE_TYPE_UNSIGNED_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_IS_POWOF2(x) (((x) & ((x) - 1)) == 0)
#define QSE_SWAP(x,y,original_type,casting_type) \ #define QSE_SWAP(x,y,original_type,casting_type) \
do { \ QSE_BLOCK ( \
x = (original_type)((casting_type)(x) ^ (casting_type)(y)); \ x = (original_type)((casting_type)(x) ^ (casting_type)(y)); \
y = (original_type)((casting_type)(y) ^ (casting_type)(x)); \ y = (original_type)((casting_type)(y) ^ (casting_type)(x)); \
x = (original_type)((casting_type)(x) ^ (casting_type)(y)); \ x = (original_type)((casting_type)(x) ^ (casting_type)(y)); \
} while (0) )
#define QSE_ABS(x) ((x) < 0? -(x): (x)) #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_END_LOOP(id) QSE_LOOP_CONTINUE(id) } __loop_ ## id ## _end__:
#define QSE_REPEAT(n,blk) \ #define QSE_REPEAT(n,blk) \
do { \ QSE_BLOCK ( \
qse_size_t __qse_repeat_x1__ = (qse_size_t)(n); \ qse_size_t __qse_repeat_x1__ = (qse_size_t)(n); \
qse_size_t __qse_repeat_x2__ = __qse_repeat_x1__ >> 4; \ qse_size_t __qse_repeat_x2__ = __qse_repeat_x1__ >> 4; \
__qse_repeat_x1__ &= 15; \ __qse_repeat_x1__ &= 15; \
@ -171,7 +186,8 @@
blk; blk; blk; blk; blk; blk; blk; blk; \ blk; blk; blk; blk; blk; blk; blk; blk; \
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 */ /* number of characters to number of bytes */
#define QSE_NCTONB(x) ((x)*sizeof(qse_char_t)) #define QSE_NCTONB(x) ((x)*sizeof(qse_char_t))

View File

@ -7,7 +7,7 @@ libqsecmn_la_SOURCES = \
syscall.h mem.h \ syscall.h mem.h \
mem.c xma.c fma.c chr.c chr_cnv.c rex.c \ 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 \ 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 \ tio.c tio_get.c tio_put.c \
fio.c pio.c sio.c \ fio.c pio.c sio.c \
time.c \ time.c \

View File

@ -75,7 +75,7 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
libqsecmn_la_DEPENDENCIES = libqsecmn_la_DEPENDENCIES =
am_libqsecmn_la_OBJECTS = mem.lo xma.lo fma.lo chr.lo chr_cnv.lo \ 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 \ 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 \ tio_put.lo fio.lo pio.lo sio.lo time.lo misc.lo assert.lo \
main.lo stdio.lo main.lo stdio.lo
libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS) libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS)
@ -264,7 +264,7 @@ libqsecmn_la_SOURCES = \
syscall.h mem.h \ syscall.h mem.h \
mem.c xma.c fma.c chr.c chr_cnv.c rex.c \ 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 \ 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 \ tio.c tio_get.c tio_put.c \
fio.c pio.c sio.c \ fio.c pio.c sio.c \
time.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)/dll.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fio.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)/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)/htb.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lda.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@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Plo@am__quote@

View File

@ -1,5 +1,5 @@
/* /*
* $Id: dll.c 287 2009-09-15 10:01:02Z hyunghwan.chung $ * $Id: dll.c 354 2010-09-03 12:50:08Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -21,7 +21,31 @@
#include <qse/cmn/dll.h> #include <qse/cmn/dll.h>
#include "mem.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; 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; 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; if (dll == QSE_NULL) return QSE_NULL;
/* do not zero the extension */ if (qse_dll_init (dll, mmgr) == QSE_NULL)
QSE_MEMSET (dll, 0, QSE_SIZEOF(qse_dll_t)); {
dll->mmgr = mmgr; QSE_MMGR_FREE (mmgr, dll);
return QSE_NULL;
}
return dll; return dll;
} }
void qse_dll_close (qse_dll_t* dll) void qse_dll_close (qse_dll_t* dll)
{ {
qse_dll_clear (dll); qse_dll_fini (dll);
QSE_MMGR_FREE (dll->mmgr, 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); if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL();
QSE_ASSERT (dll->tail == QSE_NULL);
}
void* qse_dll_getxtn (qse_dll_t* dll) /* do not zero out the xtnsizeension */
{ QSE_MEMSET (dll, 0, QSE_SIZEOF(*dll));
return dll + 1;
}
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->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) 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) 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; dll->copier = copier;
} }
@ -107,11 +136,37 @@ void qse_dll_setfreeer (qse_dll_t* dll, qse_dll_freeer_t freeer)
dll->freeer = 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) static qse_dll_node_t* alloc_node (qse_dll_t* dll, void* dptr, qse_size_t dlen)
{ {
qse_dll_node_t* n; 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)); n = QSE_MMGR_ALLOC (dll->mmgr, QSE_SIZEOF(qse_dll_node_t));
if (n == QSE_NULL) return QSE_NULL; 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) 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; 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; n->dptr = n + 1;
} }
else 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->dlen = dlen;
n->next = QSE_NULL;
n->prev = QSE_NULL;
return n; 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_node_t* qse_dll_insert (
qse_dll_t* dll, qse_dll_node_t* pos, void* dptr, qse_size_t dlen) 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); qse_dll_node_t* n = alloc_node (dll, dptr, dlen);
if (n == QSE_NULL) return QSE_NULL; if (n)
{
if (pos == QSE_NULL) if (pos == QSE_NULL)
{ {
/* insert at the end */ /* insert at the end */
if (dll->head == QSE_NULL) QSE_DLL_ADDTAIL (dll, n);
{
QSE_ASSERT (dll->tail == QSE_NULL);
dll->head = n;
}
else dll->tail->next = n;
dll->tail = n;
} }
else else
{ {
/* insert in front of the positional node */ /* insert in front of the positional node */
n->next = pos; QSE_DLL_CHAIN (dll, pos->prev, n, 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;
} }
} }
dll->size++;
return n; 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) 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) 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); 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) 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) void qse_dll_poptail (qse_dll_t* dll)
{ {
qse_dll_delete (dll, dll->tail); QSE_ASSERT (!QSE_DLL_ISEMPTY(dll));
QSE_DLL_DELTAIL (dll);
} }
void qse_dll_walk (qse_dll_t* dll, qse_dll_walker_t walker, void* arg)
{
qse_dll_node_t* n = dll->head;
while (n != QSE_NULL)
{
if (walker(dll,n,arg) == QSE_DLL_WALK_STOP) return;
n = n->next;
}
}
void* qse_dll_copyinline (qse_dll_t* dll, void* dptr, qse_size_t dlen)
{
/* this is a dummy copier */
return QSE_NULL;
}

33
qse/lib/cmn/gdl.c Normal file
View File

@ -0,0 +1,33 @@
/*
* $Id$
*
Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE.
QSE is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
QSE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with QSE. If not, see <http://www.gnu.org/licenses/>.
*/
#include <qse/cmn/gdl.h>
void qse_gdl_chain (qse_gdl_t* p, qse_gdl_t* x, qse_gdl_t* n)
{
x->prev = p; x->next = n; n->prev = x; p->next = x;
}
void qse_gdl_unchain (qse_gdl_t* x)
{
qse_gdl_t* p = x->prev;
qse_gdl_t* n = x->next;
n->prev = p; p->next = n;
}

View File

@ -1,5 +1,5 @@
/* /*
* $Id: lda.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ * $Id: lda.c 354 2010-09-03 12:50:08Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.

View File

@ -1,5 +1,5 @@
/* /*
* $Id: sll.c 348 2010-08-26 06:26:28Z hyunghwan.chung $ * $Id: sll.c 354 2010-09-03 12:50:08Z hyunghwan.chung $
* *
Copyright 2006-2009 Chung, Hyung-Hwan. Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE. This file is part of QSE.
@ -44,13 +44,23 @@ QSE_IMPLEMENT_COMMON_FUNCTIONS (sll)
#define size_t qse_size_t #define size_t qse_size_t
#define mmgr_t qse_mmgr_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* dptr1, size_t dlen1,
const void* dptr2, size_t dlen2) const void* dptr2, size_t dlen2)
{ {
if (dlen1 == dlen2) return QSE_MEMCMP (dptr1, dptr2, TOB(sll,dlen1)); if (dlen1 == dlen2) return QSE_MEMCMP (dptr1, dptr2, TOB(sll,dlen1));
/* it just returns 1 to indicate that they are different. */ /* it just returns 1 to indicate that they are different. */
return 1; 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) 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->size = 0;
sll->scale = 1; sll->scale = 1;
sll->comper = comp_data; sll->comper = default_comper;
sll->copier = QSE_SLL_COPIER_SIMPLE; sll->copier = QSE_SLL_COPIER_SIMPLE;
return sll; return sll;
} }
@ -187,7 +197,7 @@ comper_t qse_sll_getcomper (sll_t* sll)
void qse_sll_setcomper (sll_t* sll, comper_t comper) 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; sll->comper = comper;
} }
@ -301,6 +311,18 @@ void qse_sll_clear (sll_t* sll)
QSE_ASSERT (TAIL(sll) == QSE_NULL); 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) node_t* qse_sll_pushhead (sll_t* sll, void* data, size_t size)
{ {
return qse_sll_insert (sll, HEAD(sll), data, 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)); qse_sll_delete (sll, TAIL(sll));
} }
void qse_sll_walk (sll_t* sll, walker_t walker, void* ctx)
{
node_t* n = HEAD(sll);
while (n != QSE_NULL)
{
if (walker(sll,n,ctx) == QSE_SLL_WALK_STOP) return;
n = NEXT(n);
}
}

View File

@ -1,6 +1,6 @@
AM_CPPFLAGS = -I$(top_srcdir)/include -DNDEBUG 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 LDFLAGS = -L../../lib/cmn
LDADD = -lqsecmn LDADD = -lqsecmn
@ -10,6 +10,7 @@ fma_SOURCES = fma.c
chr_SOURCES = chr.c chr_SOURCES = chr.c
str_SOURCES = str.c str_SOURCES = str.c
sll_SOURCES = sll.c sll_SOURCES = sll.c
dll_SOURCES = dll.c
lda_SOURCES = lda.c lda_SOURCES = lda.c
htb_SOURCES = htb.c htb_SOURCES = htb.c
rbt_SOURCES = rbt.c rbt_SOURCES = rbt.c

View File

@ -35,9 +35,9 @@ POST_UNINSTALL = :
build_triplet = @build@ build_triplet = @build@
host_triplet = @host@ host_triplet = @host@
bin_PROGRAMS = xma$(EXEEXT) fma$(EXEEXT) chr$(EXEEXT) str$(EXEEXT) \ bin_PROGRAMS = xma$(EXEEXT) fma$(EXEEXT) chr$(EXEEXT) str$(EXEEXT) \
sll$(EXEEXT) lda$(EXEEXT) htb$(EXEEXT) rbt$(EXEEXT) \ sll$(EXEEXT) dll$(EXEEXT) lda$(EXEEXT) htb$(EXEEXT) \
fio$(EXEEXT) pio$(EXEEXT) sio$(EXEEXT) time$(EXEEXT) \ rbt$(EXEEXT) fio$(EXEEXT) pio$(EXEEXT) sio$(EXEEXT) \
main$(EXEEXT) rex01$(EXEEXT) time$(EXEEXT) main$(EXEEXT) rex01$(EXEEXT)
subdir = samples/cmn subdir = samples/cmn
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@ -58,6 +58,10 @@ am_chr_OBJECTS = chr.$(OBJEXT)
chr_OBJECTS = $(am_chr_OBJECTS) chr_OBJECTS = $(am_chr_OBJECTS)
chr_LDADD = $(LDADD) chr_LDADD = $(LDADD)
chr_DEPENDENCIES = chr_DEPENDENCIES =
am_dll_OBJECTS = dll.$(OBJEXT)
dll_OBJECTS = $(am_dll_OBJECTS)
dll_LDADD = $(LDADD)
dll_DEPENDENCIES =
am_fio_OBJECTS = fio.$(OBJEXT) am_fio_OBJECTS = fio.$(OBJEXT)
fio_OBJECTS = $(am_fio_OBJECTS) fio_OBJECTS = $(am_fio_OBJECTS)
fio_LDADD = $(LDADD) fio_LDADD = $(LDADD)
@ -123,14 +127,14 @@ CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@ $(LDFLAGS) -o $@
SOURCES = $(chr_SOURCES) $(fio_SOURCES) $(fma_SOURCES) $(htb_SOURCES) \ SOURCES = $(chr_SOURCES) $(dll_SOURCES) $(fio_SOURCES) $(fma_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) \
$(htb_SOURCES) $(lda_SOURCES) $(main_SOURCES) $(pio_SOURCES) \ $(htb_SOURCES) $(lda_SOURCES) $(main_SOURCES) $(pio_SOURCES) \
$(rbt_SOURCES) $(rex01_SOURCES) $(sio_SOURCES) $(sll_SOURCES) \ $(rbt_SOURCES) $(rex01_SOURCES) $(sio_SOURCES) $(sll_SOURCES) \
$(str_SOURCES) $(time_SOURCES) $(xma_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 ETAGS = etags
CTAGS = ctags CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@ -280,6 +284,7 @@ fma_SOURCES = fma.c
chr_SOURCES = chr.c chr_SOURCES = chr.c
str_SOURCES = str.c str_SOURCES = str.c
sll_SOURCES = sll.c sll_SOURCES = sll.c
dll_SOURCES = dll.c
lda_SOURCES = lda.c lda_SOURCES = lda.c
htb_SOURCES = htb.c htb_SOURCES = htb.c
rbt_SOURCES = rbt.c rbt_SOURCES = rbt.c
@ -369,6 +374,9 @@ clean-binPROGRAMS:
chr$(EXEEXT): $(chr_OBJECTS) $(chr_DEPENDENCIES) chr$(EXEEXT): $(chr_OBJECTS) $(chr_DEPENDENCIES)
@rm -f chr$(EXEEXT) @rm -f chr$(EXEEXT)
$(LINK) $(chr_OBJECTS) $(chr_LDADD) $(LIBS) $(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) fio$(EXEEXT): $(fio_OBJECTS) $(fio_DEPENDENCIES)
@rm -f fio$(EXEEXT) @rm -f fio$(EXEEXT)
$(LINK) $(fio_OBJECTS) $(fio_LDADD) $(LIBS) $(LINK) $(fio_OBJECTS) $(fio_LDADD) $(LIBS)
@ -416,6 +424,7 @@ distclean-compile:
-rm -f *.tab.c -rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chr.Po@am__quote@ @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)/fio.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fma.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@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb.Po@am__quote@

165
qse/samples/cmn/dll.c Normal file
View File

@ -0,0 +1,165 @@
#include <qse/cmn/mem.h>
#include <qse/cmn/str.h>
#include <qse/cmn/dll.h>
#include <qse/cmn/stdio.h>
#define R(f) \
do { \
qse_printf (QSE_T("== %s ==\n"), QSE_T(#f)); \
if (f() == -1) return -1; \
} while (0)
static qse_dll_walk_t walk_dll (qse_dll_t* dll, qse_dll_node_t* n, void* arg)
{
qse_printf (QSE_T("[%.*s]\n"), (int)QSE_DLL_DLEN(n), QSE_DLL_DPTR(n));
return QSE_DLL_WALK_FORWARD;
}
static qse_dll_walk_t rwalk_dll (qse_dll_t* dll, qse_dll_node_t* n, void* arg)
{
qse_printf (QSE_T("[%.*s]\n"), (int)QSE_DLL_DLEN(n), QSE_DLL_DPTR(n));
return QSE_DLL_WALK_BACKWARD;
}
static int test1 ()
{
qse_dll_t* s1;
qse_dll_node_t* p;
qse_char_t* x[] =
{
QSE_T("this is so good"),
QSE_T("what the hack"),
QSE_T("do you like it?")
};
int i;
s1 = qse_dll_open (QSE_MMGR_GETDFL(), 0);
if (s1 == QSE_NULL)
{
qse_printf (QSE_T("cannot open a string\n"));
return -1;
}
qse_dll_setcopier (s1, QSE_DLL_COPIER_INLINE);
qse_dll_setscale (s1, QSE_SIZEOF(qse_char_t));
for (i = 0; i < QSE_COUNTOF(x); i++)
{
qse_dll_pushtail (s1, x[i], qse_strlen(x[i]));
}
qse_printf (QSE_T("s1 holding [%d] nodes\n"), QSE_DLL_SIZE(s1));
qse_dll_walk (s1, walk_dll, QSE_NULL);
p = qse_dll_search (s1, QSE_NULL, x[0], qse_strlen(x[0]));
if (p != QSE_NULL)
{
qse_dll_delete (s1, p);
}
qse_printf (QSE_T("s1 holding [%d] nodes\n"), QSE_DLL_SIZE(s1));
qse_dll_walk (s1, walk_dll, QSE_NULL);
qse_dll_close (s1);
return 0;
}
static int test2 ()
{
qse_dll_t* s1;
qse_dll_node_t* p;
qse_char_t* x[] =
{
QSE_T("this is so good"),
QSE_T("what the hack"),
QSE_T("do you like it?")
};
int i;
s1 = qse_dll_open (QSE_MMGR_GETDFL(), 0);
if (s1 == QSE_NULL)
{
qse_printf (QSE_T("cannot open a string\n"));
return -1;
}
qse_dll_setcopier (s1, QSE_DLL_COPIER_INLINE);
qse_dll_setscale (s1, QSE_SIZEOF(qse_char_t));
for (i = 0; i < QSE_COUNTOF(x); i++)
{
qse_dll_pushtail (s1, x[i], qse_strlen(x[i]));
}
qse_printf (QSE_T("s1 holding [%d] nodes\n"), QSE_DLL_SIZE(s1));
qse_dll_rwalk (s1, rwalk_dll, QSE_NULL);
p = qse_dll_search (s1, QSE_NULL, x[0], qse_strlen(x[0]));
if (p != QSE_NULL)
{
qse_dll_delete (s1, p);
}
qse_printf (QSE_T("s1 holding [%d] nodes\n"), QSE_DLL_SIZE(s1));
qse_dll_rwalk (s1, rwalk_dll, QSE_NULL);
qse_dll_close (s1);
return 0;
}
typedef struct item_t item_t;
struct item_t
{
int a;
int b;
};
QSE_DLL_DEFINE_SIMPLE (item_t);
static int test3 ()
{
qse_size_t n;
QSE_DLL_TYPE(item_t) ii;
QSE_DLL_NODE_TYPE(item_t) x[30];
QSE_DLL_NODE_TYPE(item_t)* p;
QSE_DLL_INIT(&ii);
for (n = 0; n < QSE_COUNTOF(x); n++)
{
x[n].data.a = n;
x[n].data.b = n * 2;
}
for (n = 0; n < QSE_COUNTOF(x)/2; n++)
{
QSE_DLL_ADDHEAD (&ii, &x[n]);
}
for (; n < QSE_COUNTOF(x); n++)
{
QSE_DLL_ADDTAIL (&ii, &x[n]);
}
qse_printf (QSE_T("total %d items\n"), (int)QSE_DLL_SIZE (&ii));
for (p = QSE_DLL_HEAD(&ii); QSE_DLL_ISMEMBER(&ii,p); p = p->next)
{
qse_printf (QSE_T("%d %d\n"), p->data.a, p->data.b);
}
QSE_DLL_UNCHAIN (&ii, QSE_DLL_TAIL(&ii)->prev);
QSE_DLL_DELHEAD (&ii);
qse_printf (QSE_T("total %d items. printing in reverse\n"), (int)QSE_DLL_SIZE (&ii));
for (p = QSE_DLL_TAIL(&ii); QSE_DLL_ISMEMBER(&ii,p); p = p->prev)
{
qse_printf (QSE_T("%d %d\n"), p->data.a, p->data.b);
}
QSE_DLL_FINI (&ii);
return 0;
}
int main ()
{
R (test1);
R (test2);
R (test3);
return 0;
}