qse/qse/lib/cmn/dll.c

346 lines
7.2 KiB
C
Raw Normal View History

2008-08-13 07:58:57 +00:00
/*
2011-09-01 09:43:46 +00:00
* $Id: dll.c 556 2011-08-31 15:43:46Z hyunghwan.chung $
2009-09-16 04:01:02 +00:00
*
2011-04-23 08:28:43 +00:00
Copyright 2006-2011 Chung, Hyung-Hwan.
2009-09-16 04:01:02 +00:00
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/>.
2008-08-13 07:58:57 +00:00
*/
2008-12-21 21:35:07 +00:00
#include <qse/cmn/dll.h>
2008-08-13 07:58:57 +00:00
#include "mem.h"
2010-09-04 06:50:08 +00:00
QSE_IMPLEMENT_COMMON_FUNCTIONS (dll)
#define TOB(dll,len) ((len)*(dll)->scale)
#define DPTR(node) QSE_DLL_DPTR(node)
#define DLEN(node) QSE_DLL_DLEN(node)
2010-09-04 06:50:08 +00:00
static int default_comper (
qse_dll_t* dll,
2011-09-01 09:43:46 +00:00
const void* dptr1, qse_size_t dlen1,
const void* dptr2, qse_size_t dlen2)
2010-09-04 06:50:08 +00:00
{
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)
2008-08-13 07:58:57 +00:00
{
2008-12-21 21:35:07 +00:00
qse_dll_t* dll;
2008-08-13 07:58:57 +00:00
2008-12-21 21:35:07 +00:00
if (mmgr == QSE_NULL)
2008-08-19 05:21:48 +00:00
{
2008-12-21 21:35:07 +00:00
mmgr = QSE_MMGR_GETDFL();
2008-08-19 05:21:48 +00:00
2008-12-21 21:35:07 +00:00
QSE_ASSERTX (mmgr != QSE_NULL,
"Set the memory manager with QSE_MMGR_SETDFL()");
2008-08-19 05:21:48 +00:00
2008-12-21 21:35:07 +00:00
if (mmgr == QSE_NULL) return QSE_NULL;
2008-08-19 05:21:48 +00:00
}
2010-09-04 06:50:08 +00:00
dll = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(qse_dll_t) + xtnsize);
2008-12-21 21:35:07 +00:00
if (dll == QSE_NULL) return QSE_NULL;
2008-08-13 07:58:57 +00:00
2011-09-01 09:43:46 +00:00
if (qse_dll_init (dll, mmgr) <= -1)
2010-09-04 06:50:08 +00:00
{
QSE_MMGR_FREE (mmgr, dll);
return QSE_NULL;
}
2008-08-13 07:58:57 +00:00
return dll;
}
2008-12-21 21:35:07 +00:00
void qse_dll_close (qse_dll_t* dll)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
qse_dll_fini (dll);
2008-12-21 21:35:07 +00:00
QSE_MMGR_FREE (dll->mmgr, dll);
2008-08-13 07:58:57 +00:00
}
2011-09-01 09:43:46 +00:00
int qse_dll_init (qse_dll_t* dll, qse_mmgr_t* mmgr)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
if (mmgr == QSE_NULL) mmgr = QSE_MMGR_GETDFL();
2008-08-13 07:58:57 +00:00
2010-09-04 06:50:08 +00:00
/* do not zero out the xtnsizeension */
QSE_MEMSET (dll, 0, QSE_SIZEOF(*dll));
2008-08-19 05:21:48 +00:00
dll->mmgr = mmgr;
2010-09-04 06:50:08 +00:00
dll->scale = 1;
dll->comper = default_comper;
dll->copier = QSE_DLL_COPIER_SIMPLE;
QSE_DLL_INIT (dll);
2011-09-01 09:43:46 +00:00
return 0;
2008-08-19 05:21:48 +00:00
}
2010-09-04 06:50:08 +00:00
void qse_dll_fini (qse_dll_t* dll)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
qse_dll_clear (dll);
2008-08-13 07:58:57 +00:00
}
2010-09-04 06:50:08 +00:00
int qse_dll_getscale (qse_dll_t* dll)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
return dll->scale;
2008-08-13 07:58:57 +00:00
}
2010-09-04 06:50:08 +00:00
void qse_dll_setscale (qse_dll_t* dll, int scale)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
QSE_ASSERTX (scale > 0 && scale <= QSE_TYPE_MAX(qse_byte_t),
2011-03-17 02:37:06 +00:00
"The scale should be larger than 0 and less than or equal to the maximum value that the qse_byte_t type can hold"
2011-03-15 09:40:35 +00:00
);
2010-09-04 06:50:08 +00:00
if (scale <= 0) scale = 1;
if (scale > QSE_TYPE_MAX(qse_byte_t)) scale = QSE_TYPE_MAX(qse_byte_t);
dll->scale = scale;
2008-08-13 07:58:57 +00:00
}
2008-12-21 21:35:07 +00:00
qse_dll_copier_t qse_dll_getcopier (qse_dll_t* dll)
2008-08-13 07:58:57 +00:00
{
return dll->copier;
}
2008-12-21 21:35:07 +00:00
void qse_dll_setcopier (qse_dll_t* dll, qse_dll_copier_t copier)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
if (copier == QSE_NULL) copier = QSE_DLL_COPIER_SIMPLE;
2008-08-13 07:58:57 +00:00
dll->copier = copier;
}
2008-12-21 21:35:07 +00:00
qse_dll_freeer_t qse_dll_getfreeer (qse_dll_t* dll)
2008-08-13 07:58:57 +00:00
{
return dll->freeer;
}
2008-12-21 21:35:07 +00:00
void qse_dll_setfreeer (qse_dll_t* dll, qse_dll_freeer_t freeer)
2008-08-13 07:58:57 +00:00
{
dll->freeer = freeer;
}
2010-09-04 06:50:08 +00:00
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);
}
2008-12-21 21:35:07 +00:00
static qse_dll_node_t* alloc_node (qse_dll_t* dll, void* dptr, qse_size_t dlen)
2008-08-13 07:58:57 +00:00
{
2008-12-21 21:35:07 +00:00
qse_dll_node_t* n;
2008-08-13 07:58:57 +00:00
2010-09-04 06:50:08 +00:00
if (dll->copier == QSE_DLL_COPIER_SIMPLE)
2008-08-13 07:58:57 +00:00
{
2008-12-21 21:35:07 +00:00
n = QSE_MMGR_ALLOC (dll->mmgr, QSE_SIZEOF(qse_dll_node_t));
if (n == QSE_NULL) return QSE_NULL;
DPTR(n) = dptr;
2008-08-13 07:58:57 +00:00
}
2008-12-21 21:35:07 +00:00
else if (dll->copier == QSE_DLL_COPIER_INLINE)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
n = QSE_MMGR_ALLOC (dll->mmgr,
QSE_SIZEOF(qse_dll_node_t) + TOB(dll,dlen));
2008-12-21 21:35:07 +00:00
if (n == QSE_NULL) return QSE_NULL;
2008-08-13 07:58:57 +00:00
2010-09-04 06:50:08 +00:00
QSE_MEMCPY (n + 1, dptr, TOB(dll,dlen));
DPTR(n) = n + 1;
2008-08-13 07:58:57 +00:00
}
else
{
2008-12-21 21:35:07 +00:00
n = QSE_MMGR_ALLOC (dll->mmgr, QSE_SIZEOF(qse_dll_node_t));
if (n == QSE_NULL) return QSE_NULL;
DPTR(n) = dll->copier (dll, dptr, dlen);
if (DPTR(n) == QSE_NULL)
2008-08-23 09:23:09 +00:00
{
2008-12-21 21:35:07 +00:00
QSE_MMGR_FREE (dll->mmgr, n);
return QSE_NULL;
2008-08-23 09:23:09 +00:00
}
2008-08-13 07:58:57 +00:00
}
DLEN(n) = dlen;
2008-08-13 07:58:57 +00:00
return n;
}
2010-09-04 06:50:08 +00:00
static QSE_INLINE void free_node (qse_dll_t* dll, qse_dll_node_t* node)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
if (dll->freeer != QSE_NULL)
{
/* free the actual data */
dll->freeer (dll, DPTR(node), DLEN(node));
2010-09-04 06:50:08 +00:00
}
/* 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);
2008-08-13 07:58:57 +00:00
2010-09-04 06:50:08 +00:00
while (QSE_DLL_ISMEMBER(dll,pos))
2008-08-13 07:58:57 +00:00
{
if (dll->comper (dll, DPTR(pos), DLEN(pos), dptr, dlen) == 0)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
return pos;
2008-08-13 07:58:57 +00:00
}
2010-09-04 06:50:08 +00:00
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, DPTR(pos), DLEN(pos), dptr, dlen) == 0)
2010-09-04 06:50:08 +00:00
{
return pos;
}
pos = pos->prev;
}
return QSE_NULL;
}
qse_dll_node_t* qse_dll_insert (
qse_dll_t* dll, qse_dll_node_t* pos, void* dptr, qse_size_t dlen)
{
qse_dll_node_t* n = alloc_node (dll, dptr, dlen);
if (n)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
if (pos == QSE_NULL)
{
/* insert at the end */
QSE_DLL_ADDTAIL (dll, n);
}
2008-08-13 07:58:57 +00:00
else
{
2010-09-04 06:50:08 +00:00
/* insert in front of the positional node */
QSE_DLL_CHAIN (dll, pos->prev, n, pos);
2008-08-13 07:58:57 +00:00
}
}
return n;
}
2010-09-04 06:50:08 +00:00
void qse_dll_delete (qse_dll_t* dll, qse_dll_node_t* pos)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
if (pos == QSE_NULL || !QSE_DLL_ISMEMBER(dll,pos)) return;
QSE_DLL_UNCHAIN (dll, pos);
free_node (dll, pos);
2008-08-13 07:58:57 +00:00
}
2010-09-04 06:50:08 +00:00
void qse_dll_clear (qse_dll_t* dll)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
while (!QSE_DLL_ISEMPTY(dll))
{
qse_dll_delete (dll, QSE_DLL_HEAD(dll));
}
2008-08-13 07:58:57 +00:00
}
2010-09-04 06:50:08 +00:00
void qse_dll_walk (qse_dll_t* dll, qse_dll_walker_t walker, void* ctx)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
qse_dll_node_t* n = QSE_DLL_HEAD(dll);
qse_dll_walk_t w = QSE_DLL_WALK_FORWARD;
2008-08-13 07:58:57 +00:00
2010-09-04 06:50:08 +00:00
while (QSE_DLL_ISMEMBER(dll,n))
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
qse_dll_node_t* nxt = n->next;
qse_dll_node_t* prv = n->prev;
2008-08-13 07:58:57 +00:00
2010-09-04 06:50:08 +00:00
w = walker (dll, n, ctx);
2008-08-13 07:58:57 +00:00
2010-09-04 06:50:08 +00:00
if (w == QSE_DLL_WALK_FORWARD) n = nxt;
else if (w == QSE_DLL_WALK_BACKWARD) n = prv;
else break;
2008-08-13 07:58:57 +00:00
}
2010-09-04 06:50:08 +00:00
}
2008-08-13 07:58:57 +00:00
2010-09-04 06:50:08 +00:00
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))
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
qse_dll_node_t* nxt = n->next;
qse_dll_node_t* prv = n->prev;
2008-08-13 07:58:57 +00:00
2010-09-04 06:50:08 +00:00
w = walker (dll, n, ctx);
2008-08-13 07:58:57 +00:00
2010-09-04 06:50:08 +00:00
if (w == QSE_DLL_WALK_FORWARD) n = nxt;
else if (w == QSE_DLL_WALK_BACKWARD) n = prv;
else break;
}
2008-08-13 07:58:57 +00:00
}
2010-09-04 06:50:08 +00:00
qse_dll_node_t* qse_dll_pushhead (qse_dll_t* dll, void* data, qse_size_t size)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
return qse_dll_insert (dll, QSE_DLL_HEAD(dll), data, size);
2008-08-13 07:58:57 +00:00
}
2010-09-04 06:50:08 +00:00
qse_dll_node_t* qse_dll_pushtail (qse_dll_t* dll, void* data, qse_size_t size)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
return qse_dll_insert (dll, QSE_NULL, data, size);
2008-08-13 07:58:57 +00:00
}
2010-09-04 06:50:08 +00:00
void qse_dll_pophead (qse_dll_t* dll)
2008-08-13 07:58:57 +00:00
{
2010-09-04 06:50:08 +00:00
QSE_ASSERT (!QSE_DLL_ISEMPTY(dll));
QSE_DLL_DELHEAD (dll);
2008-08-13 07:58:57 +00:00
}
2008-08-23 09:23:09 +00:00
2010-09-04 06:50:08 +00:00
void qse_dll_poptail (qse_dll_t* dll)
2008-08-23 09:23:09 +00:00
{
2010-09-04 06:50:08 +00:00
QSE_ASSERT (!QSE_DLL_ISEMPTY(dll));
QSE_DLL_DELTAIL (dll);
2008-08-23 09:23:09 +00:00
}
2010-09-04 06:50:08 +00:00