touched up gdl.h
This commit is contained in:
@ -29,115 +29,8 @@
|
||||
#include <qse/macros.h>
|
||||
#include <qse/cmn/gdl.h>
|
||||
|
||||
#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_SIMPLE macro defines a doubly-linked list type for data
|
||||
* of the @a data_type type.
|
||||
*/
|
||||
#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_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) \
|
||||
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_BLOCK ( \
|
||||
QSE_GDL_INIT(&(dll)->gdl); \
|
||||
(dll)->size = 0; \
|
||||
)
|
||||
|
||||
#define QSE_DLL_FINI(dll) QSE_DLL_CLEAR(dll)
|
||||
|
||||
#define QSE_DLL_CHAIN(dll,p,x,n) \
|
||||
QSE_BLOCK ( \
|
||||
QSE_GDL_CHAIN ((qse_gdl_t*)p, (qse_gdl_t*)x, (qse_gdl_t*)n); \
|
||||
(dll)->size++; \
|
||||
)
|
||||
|
||||
#define QSE_DLL_UNCHAIN(dll,x) \
|
||||
QSE_BLOCK ( \
|
||||
QSE_GDL_UNCHAIN ((qse_gdl_t*)x); \
|
||||
(dll)->size--; \
|
||||
)
|
||||
|
||||
#define QSE_DLL_CLEAR(dll) \
|
||||
QSE_BLOCK ( \
|
||||
while (!QSE_DLL_ISEMPTY(dll)) QSE_DLL_DELHEAD(dll); \
|
||||
)
|
||||
|
||||
/**
|
||||
* 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) ((const qse_size_t)(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
|
||||
{
|
||||
@ -193,8 +86,9 @@ typedef qse_dll_walk_t (*qse_dll_walker_t) (
|
||||
struct qse_dll_node_t
|
||||
{
|
||||
/* the first two fields in sync with qse_gdl_t */
|
||||
qse_dll_node_t* prev;
|
||||
qse_dll_node_t* next;
|
||||
/*qse_dll_node_t* prev;
|
||||
qse_dll_node_t* next;*/
|
||||
qse_gdl_link_t link;
|
||||
/* data */
|
||||
qse_xptl_t val;
|
||||
};
|
||||
@ -206,7 +100,8 @@ struct qse_dll_t
|
||||
{
|
||||
qse_mmgr_t* mmgr;
|
||||
|
||||
qse_dll_node_t gdl;
|
||||
/*qse_dll_node_t gdl;*/
|
||||
qse_gdl_t gdl;
|
||||
qse_size_t size;
|
||||
|
||||
qse_byte_t scale;
|
||||
|
@ -23,68 +23,186 @@
|
||||
|
||||
#include <qse/types.h>
|
||||
#include <qse/macros.h>
|
||||
|
||||
/** @file
|
||||
* This file defins a generic double link and provides basic macros to
|
||||
* manipulate a chain of links.
|
||||
* This file defines a generic doubly linked list.
|
||||
*
|
||||
* When the list is empty, the primary node points to itself.
|
||||
* +-------+
|
||||
* | gdl |
|
||||
* | tail --------+
|
||||
* | head ----+ |
|
||||
* +-------+ | |
|
||||
* ^ ^ | |
|
||||
* | +------+ |
|
||||
* +-------------+
|
||||
*
|
||||
* The list contains 1 item.
|
||||
* +----------------------------+
|
||||
* V |
|
||||
* +-------+ +-------+ |
|
||||
* | gdl | | first | |
|
||||
* | tail ------------> | prev ----+
|
||||
* | head ------------> | next ----+
|
||||
* +-------+ +-------+ |
|
||||
* ^ |
|
||||
* +---------------------------+
|
||||
*
|
||||
* The list contains 2 item.
|
||||
* +----------------------------+
|
||||
* V | +--------------------+
|
||||
* +-------+ +-------+ | | +--------+ |
|
||||
* | gdl | | first | <---+ | second | |
|
||||
* | tail ------+ | prev ----+ | prev ------+
|
||||
* | head ------|-----> | next -------------> | next ------+
|
||||
* +-------+ | +-------+ +--------+ |
|
||||
* ^ | ^ |
|
||||
* | +---------------------------------+ |
|
||||
* +------------------------------------------------------+
|
||||
*
|
||||
* gdl's tail points to the last item.
|
||||
* gdl's head points to the first item.
|
||||
* the last item's next points to gdl.
|
||||
* the first item's prev points to gdl.
|
||||
*
|
||||
*
|
||||
* \code
|
||||
* #include <qse/cmn/gdl.h>
|
||||
*
|
||||
* struct q
|
||||
* {
|
||||
* int x;
|
||||
* qse_gdl_link_t rr;
|
||||
* };
|
||||
*
|
||||
* int main ()
|
||||
* {
|
||||
* struct q a, b, c, d, e;
|
||||
* qse_gdl_link_t* x;
|
||||
* qse_gdl_t rr;
|
||||
*
|
||||
* a.x = 1;
|
||||
* b.x = 2;
|
||||
* c.x = 3;
|
||||
* d.x = 4;
|
||||
* e.x = 5;
|
||||
*
|
||||
* QSE_GDL_INIT (&rr);
|
||||
*
|
||||
* QSE_GDL_APPEND (&rr, &c.rr);
|
||||
* QSE_GDL_APPEND (&rr, &b.rr);
|
||||
* QSE_GDL_PREPEND (&rr, &a.rr);
|
||||
* QSE_GDL_APPEND (&rr, &d.rr);
|
||||
* QSE_GDL_REPLACE (&rr, &b.rr, &e.rr);
|
||||
* QSE_GDL_DELETE (&rr, QSE_GDL_TAIL(&rr));
|
||||
*
|
||||
* for (x = QSE_GDL_HEAD(&rr); QSE_GDL_ISLINK(&rr,x); x = QSE_GDL_NEXT(x))
|
||||
* {
|
||||
* struct q* qq = QSE_GDL_CONTAINER(x,struct q,rr);
|
||||
* // do something here
|
||||
* }
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
/**
|
||||
* The qse_gdl_t type defines a structure to contain forward and
|
||||
* backward links.
|
||||
* The qse_gdl_t type defines a structure to contain the pointers to
|
||||
* the head and the tail links. It maintains the same layout as the
|
||||
* #qse_gdl_link_t type despite different member names.
|
||||
*/
|
||||
typedef struct qse_gdl_t qse_gdl_t;
|
||||
|
||||
/**
|
||||
* The qse_gdl_link_t type defines a structure to contain forward and
|
||||
* backward links. It maintains the same layout as the #qse_gdl_t type
|
||||
* despite different member names.
|
||||
*/
|
||||
typedef struct qse_gdl_link_t qse_gdl_link_t;
|
||||
|
||||
struct qse_gdl_t
|
||||
{
|
||||
qse_gdl_t* prev;
|
||||
qse_gdl_t* next;
|
||||
qse_gdl_link_t* tail; /* this maps to prev of qse_gdl_link_t */
|
||||
qse_gdl_link_t* head; /* this maps to next of qse_gdl_link_t */
|
||||
};
|
||||
|
||||
struct qse_gdl_link_t
|
||||
{
|
||||
qse_gdl_link_t* prev; /* this maps to tail of qse_gdl_t */
|
||||
qse_gdl_link_t* next; /* this maps to head of qse_gdl_t */
|
||||
};
|
||||
|
||||
/**
|
||||
* The QSE_GDL_INIT macro initializes a link to be used for internal
|
||||
* management.
|
||||
*/
|
||||
#define QSE_GDL_INIT(link) QSE_BLOCK ( \
|
||||
(link)->next = (link); (link)->prev = (link); \
|
||||
#define QSE_GDL_INIT(gdl) QSE_BLOCK ( \
|
||||
(gdl)->head = (qse_gdl_link_t*)(gdl); \
|
||||
(gdl)->tail = (qse_gdl_link_t*)(gdl); \
|
||||
)
|
||||
|
||||
/**
|
||||
* 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(link) ((link)->next == (link))
|
||||
#define QSE_GDL_NEXT(link) ((link)->next)
|
||||
#define QSE_GDL_PREV(link) ((link)->prev)
|
||||
#define QSE_GDL_CONTAINER(link,type,name) \
|
||||
((type*)(((qse_uint8_t*)link) - QSE_OFFSETOF(type,name)))
|
||||
|
||||
/**
|
||||
* The QSE_GDL_HEAD macro get the first node in the chain.
|
||||
*/
|
||||
#define QSE_GDL_HEAD(link) ((link)->next)
|
||||
#define QSE_GDL_HEAD(gdl) ((gdl)->head)
|
||||
|
||||
/**
|
||||
* The QSE_GDL_TAIL macro gets the last node in the chain.
|
||||
*/
|
||||
#define QSE_GDL_TAIL(link) ((link)->prev)
|
||||
#define QSE_GDL_TAIL(gdl) ((gdl)->tail)
|
||||
|
||||
/**
|
||||
* The QSE_GDL_CHAIN macro chains a new member node \a x between
|
||||
* two nodes \a p and \a n.
|
||||
*/
|
||||
#define QSE_GDL_CHAIN(gdl,p,x,n) qse_gdl_chain(gdl,p,x,n)
|
||||
|
||||
/**
|
||||
* The QSE_GDL_UNCHAIN macro unchains a member node \a x.
|
||||
*/
|
||||
#define QSE_GDL_UNCHAIN(gdl,x) qse_gdl_unchain(gdl,x)
|
||||
|
||||
#define QSE_GDL_APPEND(gdl,x) \
|
||||
qse_gdl_chain (gdl, QSE_GDL_TAIL(gdl), (x), (qse_gdl_link_t*)(gdl))
|
||||
|
||||
#define QSE_GDL_PREPEND(gdl,x) \
|
||||
qse_gdl_chain (gdl, (qse_gdl_link_t*)(gdl), (x), QSE_GDL_HEAD(gdl))
|
||||
|
||||
#define QSE_GDL_REPLACE(gdl,x,y) qse_gdl_replace (gdl, x, y)
|
||||
|
||||
#define QSE_GDL_DELETE(gdl,x) QSE_GDL_UNCHAIN(gdl,x)
|
||||
|
||||
#define QSE_GDL_ISEMPTY(gdl) ((gdl)->head == (qse_gdl_link_t*)(gdl))
|
||||
#define QSE_GDL_ISLINK(gdl,x) ((gdl) != (qse_gdl_t*)(x))
|
||||
#define QSE_GDL_ISHEAD(gdl,x) ((x)->prev == (qse_gdl_link_t*)(gdl))
|
||||
#define QSE_GDL_ISTAIL(gdl,x) ((x)->next == (qse_gdl_link_t*)(gdl))
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
QSE_EXPORT void qse_gdl_chain (
|
||||
qse_gdl_t* p,
|
||||
qse_gdl_t* x,
|
||||
qse_gdl_t* n
|
||||
qse_gdl_t* gdl,
|
||||
qse_gdl_link_t* prev,
|
||||
qse_gdl_link_t* x,
|
||||
qse_gdl_link_t* next
|
||||
);
|
||||
|
||||
QSE_EXPORT void qse_gdl_unchain (
|
||||
qse_gdl_t* x
|
||||
qse_gdl_t* gdl,
|
||||
qse_gdl_link_t* x
|
||||
);
|
||||
|
||||
QSE_EXPORT void qse_gdl_replace (
|
||||
qse_gdl_t* gdl,
|
||||
qse_gdl_link_t* old_link,
|
||||
qse_gdl_link_t* new_link
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
Reference in New Issue
Block a user