touched up gdl.h

This commit is contained in:
2013-11-26 13:47:58 +00:00
parent 5ba15ae2e4
commit 8e6e7f29a6
9 changed files with 370 additions and 393 deletions

View File

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

View File

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