renamed qse_lda_t to qse_arr_t
This commit is contained in:
@ -35,6 +35,7 @@ libqsecmn_la_SOURCES = \
|
||||
alg-rand.c \
|
||||
alg-search.c \
|
||||
alg-sort.c \
|
||||
arr.c \
|
||||
assert.c \
|
||||
chr.c \
|
||||
dll.c \
|
||||
@ -46,7 +47,6 @@ libqsecmn_la_SOURCES = \
|
||||
fmt-out.c \
|
||||
hton.c \
|
||||
ipad.c \
|
||||
lda.c \
|
||||
main.c \
|
||||
mb8.c \
|
||||
mbwc.c \
|
||||
|
@ -133,8 +133,8 @@ am__DEPENDENCIES_1 =
|
||||
libqsecmn_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
|
||||
$(am__DEPENDENCIES_1)
|
||||
am__libqsecmn_la_SOURCES_DIST = alg-base64.c alg-rand.c alg-search.c \
|
||||
alg-sort.c assert.c chr.c dll.c env.c gdl.c htb.c fma.c \
|
||||
fmt-intmax.c fmt-out.c hton.c ipad.c lda.c main.c mb8.c mbwc.c \
|
||||
alg-sort.c arr.c assert.c chr.c dll.c env.c gdl.c htb.c fma.c \
|
||||
fmt-intmax.c fmt-out.c hton.c ipad.c main.c mb8.c mbwc.c \
|
||||
mbwc-str.c mem.c oht.c opt.c path-base.c path-canon.c \
|
||||
path-core.c path-merge.c pma.c rbt.c rex.c sll.c slmb.c \
|
||||
str-beg.c str-cat.c str-chr.c str-cnv.c str-cmp.c str-cpy.c \
|
||||
@ -148,8 +148,8 @@ am__libqsecmn_la_SOURCES_DIST = alg-base64.c alg-rand.c alg-search.c \
|
||||
@ENABLE_BUNDLED_UNICODE_TRUE@am__objects_1 = uni.lo
|
||||
@ENABLE_XCMGRS_TRUE@am__objects_2 = cp949.lo cp950.lo
|
||||
am_libqsecmn_la_OBJECTS = alg-base64.lo alg-rand.lo alg-search.lo \
|
||||
alg-sort.lo assert.lo chr.lo dll.lo env.lo gdl.lo htb.lo \
|
||||
fma.lo fmt-intmax.lo fmt-out.lo hton.lo ipad.lo lda.lo main.lo \
|
||||
alg-sort.lo arr.lo assert.lo chr.lo dll.lo env.lo gdl.lo \
|
||||
htb.lo fma.lo fmt-intmax.lo fmt-out.lo hton.lo ipad.lo main.lo \
|
||||
mb8.lo mbwc.lo mbwc-str.lo mem.lo oht.lo opt.lo path-base.lo \
|
||||
path-canon.lo path-core.lo path-merge.lo pma.lo rbt.lo rex.lo \
|
||||
sll.lo slmb.lo str-beg.lo str-cat.lo str-chr.lo str-cnv.lo \
|
||||
@ -467,18 +467,18 @@ noinst_HEADERS = \
|
||||
uni-trait.h
|
||||
|
||||
libqsecmn_la_SOURCES = alg-base64.c alg-rand.c alg-search.c alg-sort.c \
|
||||
assert.c chr.c dll.c env.c gdl.c htb.c fma.c fmt-intmax.c \
|
||||
fmt-out.c hton.c ipad.c lda.c main.c mb8.c mbwc.c mbwc-str.c \
|
||||
mem.c oht.c opt.c path-base.c path-canon.c path-core.c \
|
||||
path-merge.c pma.c rbt.c rex.c sll.c slmb.c str-beg.c \
|
||||
str-cat.c str-chr.c str-cnv.c str-cmp.c str-cpy.c str-del.c \
|
||||
str-dup.c str-dyn.c str-end.c str-excl.c str-fcpy.c str-fmt.c \
|
||||
str-fnmat.c str-incl.c str-join.c str-len.c str-pac.c \
|
||||
str-pbrk.c str-put.c str-rev.c str-rot.c str-set.c str-spl.c \
|
||||
str-spn.c str-str.c str-subst.c str-tok.c str-trm.c str-word.c \
|
||||
time.c tmr.c tre.c tre-ast.c tre-compile.c tre-match-bt.c \
|
||||
tre-match-pa.c tre-parse.c tre-stack.c uri.c utf8.c xma.c \
|
||||
$(am__append_1) $(am__append_2)
|
||||
arr.c assert.c chr.c dll.c env.c gdl.c htb.c fma.c \
|
||||
fmt-intmax.c fmt-out.c hton.c ipad.c main.c mb8.c mbwc.c \
|
||||
mbwc-str.c mem.c oht.c opt.c path-base.c path-canon.c \
|
||||
path-core.c path-merge.c pma.c rbt.c rex.c sll.c slmb.c \
|
||||
str-beg.c str-cat.c str-chr.c str-cnv.c str-cmp.c str-cpy.c \
|
||||
str-del.c str-dup.c str-dyn.c str-end.c str-excl.c str-fcpy.c \
|
||||
str-fmt.c str-fnmat.c str-incl.c str-join.c str-len.c \
|
||||
str-pac.c str-pbrk.c str-put.c str-rev.c str-rot.c str-set.c \
|
||||
str-spl.c str-spn.c str-str.c str-subst.c str-tok.c str-trm.c \
|
||||
str-word.c time.c tmr.c tre.c tre-ast.c tre-compile.c \
|
||||
tre-match-bt.c tre-match-pa.c tre-parse.c tre-stack.c uri.c \
|
||||
utf8.c xma.c $(am__append_1) $(am__append_2)
|
||||
libqsecmn_la_LDFLAGS = -version-info 1:0:0 -no-undefined
|
||||
libqsecmn_la_LIBADD = $(SOCKET_LIBS) $(QUADMATH_LIBS)
|
||||
@ENABLE_CXX_TRUE@libqsecmnxx_la_SOURCES = \
|
||||
@ -578,6 +578,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alg-rand.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alg-search.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/alg-sort.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arr.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/assert.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chr.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cp949.Plo@am__quote@
|
||||
@ -591,7 +592,6 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hton.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipad.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)/mb8.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbwc-str.Plo@am__quote@
|
||||
|
700
qse/lib/cmn/arr.c
Normal file
700
qse/lib/cmn/arr.c
Normal file
@ -0,0 +1,700 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <qse/cmn/arr.h>
|
||||
#include "mem-prv.h"
|
||||
|
||||
#define arr_t qse_arr_t
|
||||
#define slot_t qse_arr_slot_t
|
||||
#define copier_t qse_arr_copier_t
|
||||
#define freeer_t qse_arr_freeer_t
|
||||
#define comper_t qse_arr_comper_t
|
||||
#define sizer_t qse_arr_sizer_t
|
||||
#define keeper_t qse_arr_keeper_t
|
||||
#define walker_t qse_arr_walker_t
|
||||
|
||||
#define mmgr_t qse_mmgr_t
|
||||
#define size_t qse_size_t
|
||||
|
||||
#define TOB(arr,len) ((len)*(arr)->scale)
|
||||
#define DPTR(slot) ((slot)->val.ptr)
|
||||
#define DLEN(slot) ((slot)->val.len)
|
||||
|
||||
static int default_comparator (arr_t* arr,
|
||||
const void* dptr1, size_t dlen1,
|
||||
const void* dptr2, size_t dlen2)
|
||||
{
|
||||
/*
|
||||
if (dlen1 == dlen2) return QSE_MEMCMP (dptr1, dptr2, TOB(arr,dlen1));
|
||||
return 1;
|
||||
*/
|
||||
|
||||
size_t min = (dlen1 < dlen2)? dlen1: dlen2;
|
||||
int n = QSE_MEMCMP (dptr1, dptr2, TOB(arr,min));
|
||||
if (n == 0 && dlen1 != dlen2)
|
||||
{
|
||||
n = (dlen1 > dlen2)? 1: -1;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static QSE_INLINE slot_t* alloc_slot (arr_t* arr, void* dptr, size_t dlen)
|
||||
{
|
||||
slot_t* n;
|
||||
|
||||
if (arr->copier == QSE_ARR_COPIER_SIMPLE)
|
||||
{
|
||||
n = QSE_MMGR_ALLOC (arr->mmgr, QSE_SIZEOF(slot_t));
|
||||
if (n == QSE_NULL) return QSE_NULL;
|
||||
DPTR(n) = dptr;
|
||||
}
|
||||
else if (arr->copier == QSE_ARR_COPIER_INLINE)
|
||||
{
|
||||
n = QSE_MMGR_ALLOC (arr->mmgr,
|
||||
QSE_SIZEOF(slot_t) + TOB(arr,dlen));
|
||||
if (n == QSE_NULL) return QSE_NULL;
|
||||
|
||||
QSE_MEMCPY (n + 1, dptr, TOB(arr,dlen));
|
||||
DPTR(n) = n + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
n = QSE_MMGR_ALLOC (arr->mmgr, QSE_SIZEOF(slot_t));
|
||||
if (n == QSE_NULL) return QSE_NULL;
|
||||
DPTR(n) = arr->copier (arr, dptr, dlen);
|
||||
if (DPTR(n) == QSE_NULL)
|
||||
{
|
||||
QSE_MMGR_FREE (arr->mmgr, n);
|
||||
return QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DLEN(n) = dlen;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
arr_t* qse_arr_open (mmgr_t* mmgr, size_t xtnsize, size_t capa)
|
||||
{
|
||||
arr_t* arr;
|
||||
|
||||
arr = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(arr_t) + xtnsize);
|
||||
if (arr == QSE_NULL) return QSE_NULL;
|
||||
|
||||
if (qse_arr_init (arr, mmgr, capa) <= -1)
|
||||
{
|
||||
QSE_MMGR_FREE (mmgr, arr);
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
QSE_MEMSET (QSE_XTN(arr), 0, xtnsize);
|
||||
return arr;
|
||||
}
|
||||
|
||||
void qse_arr_close (arr_t* arr)
|
||||
{
|
||||
qse_arr_fini (arr);
|
||||
QSE_MMGR_FREE (arr->mmgr, arr);
|
||||
}
|
||||
|
||||
int qse_arr_init (arr_t* arr, mmgr_t* mmgr, size_t capa)
|
||||
{
|
||||
QSE_MEMSET (arr, 0, QSE_SIZEOF(*arr));
|
||||
|
||||
arr->mmgr = mmgr;
|
||||
arr->size = 0;
|
||||
arr->capa = 0;
|
||||
arr->slot = QSE_NULL;
|
||||
arr->scale = 1;
|
||||
|
||||
arr->copier = QSE_ARR_COPIER_SIMPLE;
|
||||
arr->comper = default_comparator;
|
||||
|
||||
return (qse_arr_setcapa (arr, capa) == QSE_NULL)? -1: 0;
|
||||
}
|
||||
|
||||
void qse_arr_fini (arr_t* arr)
|
||||
{
|
||||
qse_arr_clear (arr);
|
||||
|
||||
if (arr->slot != QSE_NULL)
|
||||
{
|
||||
QSE_MMGR_FREE (arr->mmgr, arr->slot);
|
||||
arr->slot = QSE_NULL;
|
||||
arr->capa = 0;
|
||||
}
|
||||
}
|
||||
|
||||
qse_mmgr_t* qse_arr_getmmgr (qse_arr_t* arr)
|
||||
{
|
||||
return arr->mmgr;
|
||||
}
|
||||
|
||||
void* qse_arr_getxtn (qse_arr_t* arr)
|
||||
{
|
||||
return QSE_XTN (arr);
|
||||
}
|
||||
|
||||
int qse_arr_getscale (arr_t* arr)
|
||||
{
|
||||
return arr->scale;
|
||||
}
|
||||
|
||||
void qse_arr_setscale (arr_t* arr, int scale)
|
||||
{
|
||||
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);
|
||||
|
||||
arr->scale = scale;
|
||||
}
|
||||
|
||||
copier_t qse_arr_getcopier (arr_t* arr)
|
||||
{
|
||||
return arr->copier;
|
||||
}
|
||||
|
||||
void qse_arr_setcopier (arr_t* arr, copier_t copier)
|
||||
{
|
||||
if (copier == QSE_NULL) copier = QSE_ARR_COPIER_SIMPLE;
|
||||
arr->copier = copier;
|
||||
}
|
||||
|
||||
freeer_t qse_arr_getfreeer (arr_t* arr)
|
||||
{
|
||||
return arr->freeer;
|
||||
}
|
||||
|
||||
void qse_arr_setfreeer (arr_t* arr, freeer_t freeer)
|
||||
{
|
||||
arr->freeer = freeer;
|
||||
}
|
||||
|
||||
comper_t qse_arr_getcomper (arr_t* arr)
|
||||
{
|
||||
return arr->comper;
|
||||
}
|
||||
|
||||
void qse_arr_setcomper (arr_t* arr, comper_t comper)
|
||||
{
|
||||
if (comper == QSE_NULL) comper = default_comparator;
|
||||
arr->comper = comper;
|
||||
}
|
||||
|
||||
keeper_t qse_arr_getkeeper (arr_t* arr)
|
||||
{
|
||||
return arr->keeper;
|
||||
}
|
||||
|
||||
void qse_arr_setkeeper (arr_t* arr, keeper_t keeper)
|
||||
{
|
||||
arr->keeper = keeper;
|
||||
}
|
||||
|
||||
sizer_t qse_arr_getsizer (arr_t* arr)
|
||||
{
|
||||
return arr->sizer;
|
||||
}
|
||||
|
||||
void qse_arr_setsizer (arr_t* arr, sizer_t sizer)
|
||||
{
|
||||
arr->sizer = sizer;
|
||||
}
|
||||
|
||||
size_t qse_arr_getsize (arr_t* arr)
|
||||
{
|
||||
return arr->size;
|
||||
}
|
||||
|
||||
size_t qse_arr_getcapa (arr_t* arr)
|
||||
{
|
||||
return arr->capa;
|
||||
}
|
||||
|
||||
arr_t* qse_arr_setcapa (arr_t* arr, size_t capa)
|
||||
{
|
||||
void* tmp;
|
||||
|
||||
if (capa == arr->capa) return arr;
|
||||
|
||||
if (arr->size > capa)
|
||||
{
|
||||
/* to trigger freeers on the items truncated */
|
||||
qse_arr_delete (arr, capa, arr->size - capa);
|
||||
QSE_ASSERT (arr->size <= capa);
|
||||
}
|
||||
|
||||
if (capa > 0)
|
||||
{
|
||||
if (arr->mmgr->realloc != QSE_NULL && arr->slot != QSE_NULL)
|
||||
{
|
||||
tmp = (slot_t**) QSE_MMGR_REALLOC (
|
||||
arr->mmgr, arr->slot,
|
||||
QSE_SIZEOF(*arr->slot)*capa);
|
||||
if (tmp == QSE_NULL) return QSE_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = (slot_t**) QSE_MMGR_ALLOC (
|
||||
arr->mmgr, QSE_SIZEOF(*arr->slot)*capa);
|
||||
if (tmp == QSE_NULL) return QSE_NULL;
|
||||
|
||||
if (arr->slot != QSE_NULL)
|
||||
{
|
||||
size_t x;
|
||||
x = (capa > arr->capa)? arr->capa: capa;
|
||||
QSE_MEMCPY (tmp, arr->slot,
|
||||
QSE_SIZEOF(*arr->slot)*x);
|
||||
QSE_MMGR_FREE (arr->mmgr, arr->slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (arr->slot != QSE_NULL)
|
||||
{
|
||||
qse_arr_clear (arr);
|
||||
QSE_MMGR_FREE (arr->mmgr, arr->slot);
|
||||
}
|
||||
|
||||
tmp = QSE_NULL;
|
||||
}
|
||||
|
||||
arr->slot = tmp;
|
||||
arr->capa = capa;
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
size_t qse_arr_search (arr_t* arr, size_t pos, const void* dptr, size_t dlen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = pos; i < arr->size; i++)
|
||||
{
|
||||
if (arr->slot[i] == QSE_NULL) continue;
|
||||
|
||||
if (arr->comper (arr,
|
||||
DPTR(arr->slot[i]), DLEN(arr->slot[i]),
|
||||
dptr, dlen) == 0) return i;
|
||||
}
|
||||
|
||||
return QSE_ARR_NIL;
|
||||
}
|
||||
|
||||
size_t qse_arr_rsearch (arr_t* arr, size_t pos, const void* dptr, size_t dlen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (arr->size > 0)
|
||||
{
|
||||
if (pos >= arr->size) pos = arr->size - 1;
|
||||
|
||||
for (i = pos + 1; i-- > 0; )
|
||||
{
|
||||
if (arr->slot[i] == QSE_NULL) continue;
|
||||
|
||||
if (arr->comper (arr,
|
||||
DPTR(arr->slot[i]), DLEN(arr->slot[i]),
|
||||
dptr, dlen) == 0) return i;
|
||||
}
|
||||
}
|
||||
|
||||
return QSE_ARR_NIL;
|
||||
}
|
||||
|
||||
size_t qse_arr_upsert (arr_t* arr, size_t pos, void* dptr, size_t dlen)
|
||||
{
|
||||
if (pos < arr->size) return qse_arr_update (arr, pos, dptr, dlen);
|
||||
return qse_arr_insert (arr, pos, dptr, dlen);
|
||||
}
|
||||
|
||||
size_t qse_arr_insert (arr_t* arr, size_t pos, void* dptr, size_t dlen)
|
||||
{
|
||||
size_t i;
|
||||
slot_t* slot;
|
||||
|
||||
/* allocate the slot first */
|
||||
slot = alloc_slot (arr, dptr, dlen);
|
||||
if (slot == QSE_NULL) return QSE_ARR_NIL;
|
||||
|
||||
/* do resizeing if necessary.
|
||||
* resizing is performed after slot allocation because that way, it
|
||||
* doesn't modify arr on any errors */
|
||||
if (pos >= arr->capa || arr->size >= arr->capa)
|
||||
{
|
||||
size_t capa, mincapa;
|
||||
|
||||
/* get the minimum capacity needed */
|
||||
mincapa = (pos >= arr->size)? (pos + 1): (arr->size + 1);
|
||||
|
||||
if (arr->sizer)
|
||||
{
|
||||
capa = arr->sizer (arr, mincapa);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (arr->capa <= 0)
|
||||
{
|
||||
QSE_ASSERT (arr->size <= 0);
|
||||
capa = (pos < 16)? 16: (pos + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bound = (pos >= arr->size)? pos: arr->size;
|
||||
do { capa = arr->capa * 2; } while (capa <= bound);
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (qse_arr_setcapa(arr,capa) != QSE_NULL) break;
|
||||
|
||||
if (capa <= mincapa)
|
||||
{
|
||||
if (arr->freeer)
|
||||
arr->freeer (arr, DPTR(slot), DLEN(slot));
|
||||
QSE_MMGR_FREE (arr->mmgr, slot);
|
||||
return QSE_ARR_NIL;
|
||||
}
|
||||
|
||||
capa--; /* let it retry after lowering the capacity */
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
if (pos >= arr->capa || arr->size >= arr->capa)
|
||||
{
|
||||
/* the buffer is not still enough after resizing */
|
||||
if (arr->freeer)
|
||||
arr->freeer (arr, DPTR(slot), DLEN(slot));
|
||||
QSE_MMGR_FREE (arr->mmgr, slot);
|
||||
return QSE_ARR_NIL;
|
||||
}
|
||||
|
||||
/* fill in the gap with QSE_NULL */
|
||||
for (i = arr->size; i < pos; i++) arr->slot[i] = QSE_NULL;
|
||||
|
||||
/* shift values to the next cell */
|
||||
for (i = arr->size; i > pos; i--) arr->slot[i] = arr->slot[i-1];
|
||||
|
||||
/* set the value */
|
||||
arr->slot[pos] = slot;
|
||||
|
||||
if (pos > arr->size) arr->size = pos + 1;
|
||||
else arr->size++;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
size_t qse_arr_update (arr_t* arr, size_t pos, void* dptr, size_t dlen)
|
||||
{
|
||||
slot_t* c;
|
||||
|
||||
if (pos >= arr->size) return QSE_ARR_NIL;
|
||||
|
||||
c = arr->slot[pos];
|
||||
if (c == QSE_NULL)
|
||||
{
|
||||
/* no previous data */
|
||||
arr->slot[pos] = alloc_slot (arr, dptr, dlen);
|
||||
if (arr->slot[pos] == QSE_NULL) return QSE_ARR_NIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dptr == DPTR(c) && dlen == DLEN(c))
|
||||
{
|
||||
/* updated to the same data */
|
||||
if (arr->keeper) arr->keeper (arr, dptr, dlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* updated to different data */
|
||||
slot_t* slot = alloc_slot (arr, dptr, dlen);
|
||||
if (slot == QSE_NULL) return QSE_ARR_NIL;
|
||||
|
||||
if (arr->freeer != QSE_NULL)
|
||||
arr->freeer (arr, DPTR(c), DLEN(c));
|
||||
QSE_MMGR_FREE (arr->mmgr, c);
|
||||
|
||||
arr->slot[pos] = slot;
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
size_t qse_arr_delete (arr_t* arr, size_t index, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (index >= arr->size) return 0;
|
||||
if (count > arr->size - index) count = arr->size - index;
|
||||
|
||||
i = index;
|
||||
|
||||
for (i = index; i < index + count; i++)
|
||||
{
|
||||
slot_t* c = arr->slot[i];
|
||||
|
||||
if (c != QSE_NULL)
|
||||
{
|
||||
if (arr->freeer != QSE_NULL)
|
||||
arr->freeer (arr, DPTR(c), DLEN(c));
|
||||
QSE_MMGR_FREE (arr->mmgr, c);
|
||||
|
||||
arr->slot[i] = QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = index + count; i < arr->size; i++)
|
||||
{
|
||||
arr->slot[i-count] = arr->slot[i];
|
||||
}
|
||||
arr->slot[arr->size-1] = QSE_NULL;
|
||||
|
||||
arr->size -= count;
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t qse_arr_uplete (arr_t* arr, size_t index, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (index >= arr->size) return 0;
|
||||
if (count > arr->size - index) count = arr->size - index;
|
||||
|
||||
i = index;
|
||||
|
||||
for (i = index; i < index + count; i++)
|
||||
{
|
||||
slot_t* c = arr->slot[i];
|
||||
|
||||
if (c != QSE_NULL)
|
||||
{
|
||||
if (arr->freeer != QSE_NULL)
|
||||
arr->freeer (arr, DPTR(c), DLEN(c));
|
||||
QSE_MMGR_FREE (arr->mmgr, c);
|
||||
|
||||
arr->slot[i] = QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void qse_arr_clear (arr_t* arr)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < arr->size; i++)
|
||||
{
|
||||
slot_t* c = arr->slot[i];
|
||||
if (c != QSE_NULL)
|
||||
{
|
||||
if (arr->freeer)
|
||||
arr->freeer (arr, DPTR(c), DLEN(c));
|
||||
QSE_MMGR_FREE (arr->mmgr, c);
|
||||
arr->slot[i] = QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
arr->size = 0;
|
||||
}
|
||||
|
||||
size_t qse_arr_walk (arr_t* arr, walker_t walker, void* ctx)
|
||||
{
|
||||
qse_arr_walk_t w = QSE_ARR_WALK_FORWARD;
|
||||
size_t i = 0, nwalks = 0;
|
||||
|
||||
if (arr->size <= 0) return 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (arr->slot[i] != QSE_NULL)
|
||||
{
|
||||
w = walker (arr, i, ctx);
|
||||
nwalks++;
|
||||
}
|
||||
|
||||
if (w == QSE_ARR_WALK_STOP) break;
|
||||
|
||||
if (w == QSE_ARR_WALK_FORWARD)
|
||||
{
|
||||
i++;
|
||||
if (i >= arr->size) break;
|
||||
}
|
||||
if (w == QSE_ARR_WALK_BACKWARD)
|
||||
{
|
||||
if (i <= 0) break;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
return nwalks;
|
||||
}
|
||||
|
||||
size_t qse_arr_rwalk (arr_t* arr, walker_t walker, void* ctx)
|
||||
{
|
||||
qse_arr_walk_t w = QSE_ARR_WALK_BACKWARD;
|
||||
size_t i, nwalks = 0;
|
||||
|
||||
if (arr->size <= 0) return 0;
|
||||
i = arr->size - 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (arr->slot[i] != QSE_NULL)
|
||||
{
|
||||
w = walker (arr, i, ctx);
|
||||
nwalks++;
|
||||
}
|
||||
|
||||
if (w == QSE_ARR_WALK_STOP) break;
|
||||
|
||||
if (w == QSE_ARR_WALK_FORWARD)
|
||||
{
|
||||
i++;
|
||||
if (i >= arr->size) break;
|
||||
}
|
||||
if (w == QSE_ARR_WALK_BACKWARD)
|
||||
{
|
||||
if (i <= 0) break;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
return nwalks;
|
||||
}
|
||||
|
||||
size_t qse_arr_pushstack (arr_t* arr, void* dptr, size_t dlen)
|
||||
{
|
||||
return qse_arr_insert (arr, arr->size, dptr, dlen);
|
||||
}
|
||||
|
||||
void qse_arr_popstack (arr_t* arr)
|
||||
{
|
||||
QSE_ASSERT (arr->size > 0);
|
||||
qse_arr_delete (arr, arr->size - 1, 1);
|
||||
}
|
||||
|
||||
#define HEAP_PARENT(x) (((x)-1) / 2)
|
||||
#define HEAP_LEFT(x) ((x)*2 + 1)
|
||||
#define HEAP_RIGHT(x) ((x)*2 + 2)
|
||||
|
||||
size_t qse_arr_pushheap (arr_t* arr, void* dptr, size_t dlen)
|
||||
{
|
||||
size_t cur, par;
|
||||
int n;
|
||||
|
||||
/* add a value to the bottom */
|
||||
cur = arr->size;
|
||||
if (qse_arr_insert (arr, cur, dptr, dlen) == QSE_ARR_NIL)
|
||||
return QSE_ARR_NIL;
|
||||
|
||||
while (cur != 0)
|
||||
{
|
||||
slot_t* tmp;
|
||||
|
||||
/* compare with the parent */
|
||||
par = HEAP_PARENT(cur);
|
||||
n = arr->comper (arr,
|
||||
DPTR(arr->slot[cur]), DLEN(arr->slot[cur]),
|
||||
DPTR(arr->slot[par]), DLEN(arr->slot[par]));
|
||||
if (n <= 0) break; /* ok */
|
||||
|
||||
/* swap the current with the parent */
|
||||
tmp = arr->slot[cur];
|
||||
arr->slot[cur] = arr->slot[par];
|
||||
arr->slot[par] = tmp;
|
||||
|
||||
cur = par;
|
||||
}
|
||||
|
||||
return arr->size;
|
||||
}
|
||||
|
||||
void qse_arr_popheap (arr_t* arr)
|
||||
{
|
||||
size_t cur, child;
|
||||
slot_t* tmp;
|
||||
|
||||
QSE_ASSERT (arr->size > 0);
|
||||
|
||||
/* destroy the top */
|
||||
tmp = arr->slot[0];
|
||||
if (arr->freeer) arr->freeer (arr, DPTR(tmp), DLEN(tmp));
|
||||
QSE_MMGR_FREE (arr->mmgr, tmp);
|
||||
|
||||
/* move the last item to the top position also shrink the size */
|
||||
arr->slot[0] = arr->slot[--arr->size];
|
||||
|
||||
if (arr->size <= 1) return; /* only 1 element. nothing further to do */
|
||||
|
||||
for (cur = 0; cur < arr->size; cur = child)
|
||||
{
|
||||
size_t left, right;
|
||||
int n;
|
||||
|
||||
left = HEAP_LEFT(cur);
|
||||
right = HEAP_RIGHT(cur);
|
||||
|
||||
if (left >= arr->size)
|
||||
{
|
||||
/* the left child does not exist.
|
||||
* reached the bottom. abort exchange */
|
||||
break;
|
||||
}
|
||||
|
||||
if (right >= arr->size)
|
||||
{
|
||||
/* the right child does not exist. only the left */
|
||||
child = left;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* get the larger child of the two */
|
||||
n = arr->comper (arr,
|
||||
DPTR(arr->slot[left]), DLEN(arr->slot[left]),
|
||||
DPTR(arr->slot[right]), DLEN(arr->slot[right]));
|
||||
child = (n > 0)? left: right;
|
||||
}
|
||||
|
||||
/* compare the current one with the child */
|
||||
n = arr->comper (arr,
|
||||
DPTR(arr->slot[cur]), DLEN(arr->slot[cur]),
|
||||
DPTR(arr->slot[child]), DLEN(arr->slot[child]));
|
||||
if (n > 0) break; /* current one is larger. stop exchange */
|
||||
|
||||
/* swap the current with the child */
|
||||
tmp = arr->slot[cur];
|
||||
arr->slot[cur] = arr->slot[child];
|
||||
arr->slot[child] = tmp;
|
||||
}
|
||||
}
|
@ -1,700 +0,0 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <qse/cmn/lda.h>
|
||||
#include "mem-prv.h"
|
||||
|
||||
#define lda_t qse_lda_t
|
||||
#define slot_t qse_lda_slot_t
|
||||
#define copier_t qse_lda_copier_t
|
||||
#define freeer_t qse_lda_freeer_t
|
||||
#define comper_t qse_lda_comper_t
|
||||
#define sizer_t qse_lda_sizer_t
|
||||
#define keeper_t qse_lda_keeper_t
|
||||
#define walker_t qse_lda_walker_t
|
||||
|
||||
#define mmgr_t qse_mmgr_t
|
||||
#define size_t qse_size_t
|
||||
|
||||
#define TOB(lda,len) ((len)*(lda)->scale)
|
||||
#define DPTR(slot) ((slot)->val.ptr)
|
||||
#define DLEN(slot) ((slot)->val.len)
|
||||
|
||||
static int default_comparator (lda_t* lda,
|
||||
const void* dptr1, size_t dlen1,
|
||||
const void* dptr2, size_t dlen2)
|
||||
{
|
||||
/*
|
||||
if (dlen1 == dlen2) return QSE_MEMCMP (dptr1, dptr2, TOB(lda,dlen1));
|
||||
return 1;
|
||||
*/
|
||||
|
||||
size_t min = (dlen1 < dlen2)? dlen1: dlen2;
|
||||
int n = QSE_MEMCMP (dptr1, dptr2, TOB(lda,min));
|
||||
if (n == 0 && dlen1 != dlen2)
|
||||
{
|
||||
n = (dlen1 > dlen2)? 1: -1;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static QSE_INLINE slot_t* alloc_slot (lda_t* lda, void* dptr, size_t dlen)
|
||||
{
|
||||
slot_t* n;
|
||||
|
||||
if (lda->copier == QSE_LDA_COPIER_SIMPLE)
|
||||
{
|
||||
n = QSE_MMGR_ALLOC (lda->mmgr, QSE_SIZEOF(slot_t));
|
||||
if (n == QSE_NULL) return QSE_NULL;
|
||||
DPTR(n) = dptr;
|
||||
}
|
||||
else if (lda->copier == QSE_LDA_COPIER_INLINE)
|
||||
{
|
||||
n = QSE_MMGR_ALLOC (lda->mmgr,
|
||||
QSE_SIZEOF(slot_t) + TOB(lda,dlen));
|
||||
if (n == QSE_NULL) return QSE_NULL;
|
||||
|
||||
QSE_MEMCPY (n + 1, dptr, TOB(lda,dlen));
|
||||
DPTR(n) = n + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
n = QSE_MMGR_ALLOC (lda->mmgr, QSE_SIZEOF(slot_t));
|
||||
if (n == QSE_NULL) return QSE_NULL;
|
||||
DPTR(n) = lda->copier (lda, dptr, dlen);
|
||||
if (DPTR(n) == QSE_NULL)
|
||||
{
|
||||
QSE_MMGR_FREE (lda->mmgr, n);
|
||||
return QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DLEN(n) = dlen;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
lda_t* qse_lda_open (mmgr_t* mmgr, size_t xtnsize, size_t capa)
|
||||
{
|
||||
lda_t* lda;
|
||||
|
||||
lda = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(lda_t) + xtnsize);
|
||||
if (lda == QSE_NULL) return QSE_NULL;
|
||||
|
||||
if (qse_lda_init (lda, mmgr, capa) <= -1)
|
||||
{
|
||||
QSE_MMGR_FREE (mmgr, lda);
|
||||
return QSE_NULL;
|
||||
}
|
||||
|
||||
QSE_MEMSET (QSE_XTN(lda), 0, xtnsize);
|
||||
return lda;
|
||||
}
|
||||
|
||||
void qse_lda_close (lda_t* lda)
|
||||
{
|
||||
qse_lda_fini (lda);
|
||||
QSE_MMGR_FREE (lda->mmgr, lda);
|
||||
}
|
||||
|
||||
int qse_lda_init (lda_t* lda, mmgr_t* mmgr, size_t capa)
|
||||
{
|
||||
QSE_MEMSET (lda, 0, QSE_SIZEOF(*lda));
|
||||
|
||||
lda->mmgr = mmgr;
|
||||
lda->size = 0;
|
||||
lda->capa = 0;
|
||||
lda->slot = QSE_NULL;
|
||||
lda->scale = 1;
|
||||
|
||||
lda->copier = QSE_LDA_COPIER_SIMPLE;
|
||||
lda->comper = default_comparator;
|
||||
|
||||
return (qse_lda_setcapa (lda, capa) == QSE_NULL)? -1: 0;
|
||||
}
|
||||
|
||||
void qse_lda_fini (lda_t* lda)
|
||||
{
|
||||
qse_lda_clear (lda);
|
||||
|
||||
if (lda->slot != QSE_NULL)
|
||||
{
|
||||
QSE_MMGR_FREE (lda->mmgr, lda->slot);
|
||||
lda->slot = QSE_NULL;
|
||||
lda->capa = 0;
|
||||
}
|
||||
}
|
||||
|
||||
qse_mmgr_t* qse_lda_getmmgr (qse_lda_t* lda)
|
||||
{
|
||||
return lda->mmgr;
|
||||
}
|
||||
|
||||
void* qse_lda_getxtn (qse_lda_t* lda)
|
||||
{
|
||||
return QSE_XTN (lda);
|
||||
}
|
||||
|
||||
int qse_lda_getscale (lda_t* lda)
|
||||
{
|
||||
return lda->scale;
|
||||
}
|
||||
|
||||
void qse_lda_setscale (lda_t* lda, int scale)
|
||||
{
|
||||
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);
|
||||
|
||||
lda->scale = scale;
|
||||
}
|
||||
|
||||
copier_t qse_lda_getcopier (lda_t* lda)
|
||||
{
|
||||
return lda->copier;
|
||||
}
|
||||
|
||||
void qse_lda_setcopier (lda_t* lda, copier_t copier)
|
||||
{
|
||||
if (copier == QSE_NULL) copier = QSE_LDA_COPIER_SIMPLE;
|
||||
lda->copier = copier;
|
||||
}
|
||||
|
||||
freeer_t qse_lda_getfreeer (lda_t* lda)
|
||||
{
|
||||
return lda->freeer;
|
||||
}
|
||||
|
||||
void qse_lda_setfreeer (lda_t* lda, freeer_t freeer)
|
||||
{
|
||||
lda->freeer = freeer;
|
||||
}
|
||||
|
||||
comper_t qse_lda_getcomper (lda_t* lda)
|
||||
{
|
||||
return lda->comper;
|
||||
}
|
||||
|
||||
void qse_lda_setcomper (lda_t* lda, comper_t comper)
|
||||
{
|
||||
if (comper == QSE_NULL) comper = default_comparator;
|
||||
lda->comper = comper;
|
||||
}
|
||||
|
||||
keeper_t qse_lda_getkeeper (lda_t* lda)
|
||||
{
|
||||
return lda->keeper;
|
||||
}
|
||||
|
||||
void qse_lda_setkeeper (lda_t* lda, keeper_t keeper)
|
||||
{
|
||||
lda->keeper = keeper;
|
||||
}
|
||||
|
||||
sizer_t qse_lda_getsizer (lda_t* lda)
|
||||
{
|
||||
return lda->sizer;
|
||||
}
|
||||
|
||||
void qse_lda_setsizer (lda_t* lda, sizer_t sizer)
|
||||
{
|
||||
lda->sizer = sizer;
|
||||
}
|
||||
|
||||
size_t qse_lda_getsize (lda_t* lda)
|
||||
{
|
||||
return lda->size;
|
||||
}
|
||||
|
||||
size_t qse_lda_getcapa (lda_t* lda)
|
||||
{
|
||||
return lda->capa;
|
||||
}
|
||||
|
||||
lda_t* qse_lda_setcapa (lda_t* lda, size_t capa)
|
||||
{
|
||||
void* tmp;
|
||||
|
||||
if (capa == lda->capa) return lda;
|
||||
|
||||
if (lda->size > capa)
|
||||
{
|
||||
/* to trigger freeers on the items truncated */
|
||||
qse_lda_delete (lda, capa, lda->size - capa);
|
||||
QSE_ASSERT (lda->size <= capa);
|
||||
}
|
||||
|
||||
if (capa > 0)
|
||||
{
|
||||
if (lda->mmgr->realloc != QSE_NULL && lda->slot != QSE_NULL)
|
||||
{
|
||||
tmp = (slot_t**) QSE_MMGR_REALLOC (
|
||||
lda->mmgr, lda->slot,
|
||||
QSE_SIZEOF(*lda->slot)*capa);
|
||||
if (tmp == QSE_NULL) return QSE_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = (slot_t**) QSE_MMGR_ALLOC (
|
||||
lda->mmgr, QSE_SIZEOF(*lda->slot)*capa);
|
||||
if (tmp == QSE_NULL) return QSE_NULL;
|
||||
|
||||
if (lda->slot != QSE_NULL)
|
||||
{
|
||||
size_t x;
|
||||
x = (capa > lda->capa)? lda->capa: capa;
|
||||
QSE_MEMCPY (tmp, lda->slot,
|
||||
QSE_SIZEOF(*lda->slot)*x);
|
||||
QSE_MMGR_FREE (lda->mmgr, lda->slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lda->slot != QSE_NULL)
|
||||
{
|
||||
qse_lda_clear (lda);
|
||||
QSE_MMGR_FREE (lda->mmgr, lda->slot);
|
||||
}
|
||||
|
||||
tmp = QSE_NULL;
|
||||
}
|
||||
|
||||
lda->slot = tmp;
|
||||
lda->capa = capa;
|
||||
|
||||
return lda;
|
||||
}
|
||||
|
||||
size_t qse_lda_search (lda_t* lda, size_t pos, const void* dptr, size_t dlen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = pos; i < lda->size; i++)
|
||||
{
|
||||
if (lda->slot[i] == QSE_NULL) continue;
|
||||
|
||||
if (lda->comper (lda,
|
||||
DPTR(lda->slot[i]), DLEN(lda->slot[i]),
|
||||
dptr, dlen) == 0) return i;
|
||||
}
|
||||
|
||||
return QSE_LDA_NIL;
|
||||
}
|
||||
|
||||
size_t qse_lda_rsearch (lda_t* lda, size_t pos, const void* dptr, size_t dlen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (lda->size > 0)
|
||||
{
|
||||
if (pos >= lda->size) pos = lda->size - 1;
|
||||
|
||||
for (i = pos + 1; i-- > 0; )
|
||||
{
|
||||
if (lda->slot[i] == QSE_NULL) continue;
|
||||
|
||||
if (lda->comper (lda,
|
||||
DPTR(lda->slot[i]), DLEN(lda->slot[i]),
|
||||
dptr, dlen) == 0) return i;
|
||||
}
|
||||
}
|
||||
|
||||
return QSE_LDA_NIL;
|
||||
}
|
||||
|
||||
size_t qse_lda_upsert (lda_t* lda, size_t pos, void* dptr, size_t dlen)
|
||||
{
|
||||
if (pos < lda->size) return qse_lda_update (lda, pos, dptr, dlen);
|
||||
return qse_lda_insert (lda, pos, dptr, dlen);
|
||||
}
|
||||
|
||||
size_t qse_lda_insert (lda_t* lda, size_t pos, void* dptr, size_t dlen)
|
||||
{
|
||||
size_t i;
|
||||
slot_t* slot;
|
||||
|
||||
/* allocate the slot first */
|
||||
slot = alloc_slot (lda, dptr, dlen);
|
||||
if (slot == QSE_NULL) return QSE_LDA_NIL;
|
||||
|
||||
/* do resizeing if necessary.
|
||||
* resizing is performed after slot allocation because that way, it
|
||||
* doesn't modify lda on any errors */
|
||||
if (pos >= lda->capa || lda->size >= lda->capa)
|
||||
{
|
||||
size_t capa, mincapa;
|
||||
|
||||
/* get the minimum capacity needed */
|
||||
mincapa = (pos >= lda->size)? (pos + 1): (lda->size + 1);
|
||||
|
||||
if (lda->sizer)
|
||||
{
|
||||
capa = lda->sizer (lda, mincapa);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lda->capa <= 0)
|
||||
{
|
||||
QSE_ASSERT (lda->size <= 0);
|
||||
capa = (pos < 16)? 16: (pos + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t bound = (pos >= lda->size)? pos: lda->size;
|
||||
do { capa = lda->capa * 2; } while (capa <= bound);
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (qse_lda_setcapa(lda,capa) != QSE_NULL) break;
|
||||
|
||||
if (capa <= mincapa)
|
||||
{
|
||||
if (lda->freeer)
|
||||
lda->freeer (lda, DPTR(slot), DLEN(slot));
|
||||
QSE_MMGR_FREE (lda->mmgr, slot);
|
||||
return QSE_LDA_NIL;
|
||||
}
|
||||
|
||||
capa--; /* let it retry after lowering the capacity */
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
if (pos >= lda->capa || lda->size >= lda->capa)
|
||||
{
|
||||
/* the buffer is not still enough after resizing */
|
||||
if (lda->freeer)
|
||||
lda->freeer (lda, DPTR(slot), DLEN(slot));
|
||||
QSE_MMGR_FREE (lda->mmgr, slot);
|
||||
return QSE_LDA_NIL;
|
||||
}
|
||||
|
||||
/* fill in the gap with QSE_NULL */
|
||||
for (i = lda->size; i < pos; i++) lda->slot[i] = QSE_NULL;
|
||||
|
||||
/* shift values to the next cell */
|
||||
for (i = lda->size; i > pos; i--) lda->slot[i] = lda->slot[i-1];
|
||||
|
||||
/* set the value */
|
||||
lda->slot[pos] = slot;
|
||||
|
||||
if (pos > lda->size) lda->size = pos + 1;
|
||||
else lda->size++;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
size_t qse_lda_update (lda_t* lda, size_t pos, void* dptr, size_t dlen)
|
||||
{
|
||||
slot_t* c;
|
||||
|
||||
if (pos >= lda->size) return QSE_LDA_NIL;
|
||||
|
||||
c = lda->slot[pos];
|
||||
if (c == QSE_NULL)
|
||||
{
|
||||
/* no previous data */
|
||||
lda->slot[pos] = alloc_slot (lda, dptr, dlen);
|
||||
if (lda->slot[pos] == QSE_NULL) return QSE_LDA_NIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dptr == DPTR(c) && dlen == DLEN(c))
|
||||
{
|
||||
/* updated to the same data */
|
||||
if (lda->keeper) lda->keeper (lda, dptr, dlen);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* updated to different data */
|
||||
slot_t* slot = alloc_slot (lda, dptr, dlen);
|
||||
if (slot == QSE_NULL) return QSE_LDA_NIL;
|
||||
|
||||
if (lda->freeer != QSE_NULL)
|
||||
lda->freeer (lda, DPTR(c), DLEN(c));
|
||||
QSE_MMGR_FREE (lda->mmgr, c);
|
||||
|
||||
lda->slot[pos] = slot;
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
size_t qse_lda_delete (lda_t* lda, size_t index, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (index >= lda->size) return 0;
|
||||
if (count > lda->size - index) count = lda->size - index;
|
||||
|
||||
i = index;
|
||||
|
||||
for (i = index; i < index + count; i++)
|
||||
{
|
||||
slot_t* c = lda->slot[i];
|
||||
|
||||
if (c != QSE_NULL)
|
||||
{
|
||||
if (lda->freeer != QSE_NULL)
|
||||
lda->freeer (lda, DPTR(c), DLEN(c));
|
||||
QSE_MMGR_FREE (lda->mmgr, c);
|
||||
|
||||
lda->slot[i] = QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = index + count; i < lda->size; i++)
|
||||
{
|
||||
lda->slot[i-count] = lda->slot[i];
|
||||
}
|
||||
lda->slot[lda->size-1] = QSE_NULL;
|
||||
|
||||
lda->size -= count;
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t qse_lda_uplete (lda_t* lda, size_t index, size_t count)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (index >= lda->size) return 0;
|
||||
if (count > lda->size - index) count = lda->size - index;
|
||||
|
||||
i = index;
|
||||
|
||||
for (i = index; i < index + count; i++)
|
||||
{
|
||||
slot_t* c = lda->slot[i];
|
||||
|
||||
if (c != QSE_NULL)
|
||||
{
|
||||
if (lda->freeer != QSE_NULL)
|
||||
lda->freeer (lda, DPTR(c), DLEN(c));
|
||||
QSE_MMGR_FREE (lda->mmgr, c);
|
||||
|
||||
lda->slot[i] = QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void qse_lda_clear (lda_t* lda)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < lda->size; i++)
|
||||
{
|
||||
slot_t* c = lda->slot[i];
|
||||
if (c != QSE_NULL)
|
||||
{
|
||||
if (lda->freeer)
|
||||
lda->freeer (lda, DPTR(c), DLEN(c));
|
||||
QSE_MMGR_FREE (lda->mmgr, c);
|
||||
lda->slot[i] = QSE_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
lda->size = 0;
|
||||
}
|
||||
|
||||
size_t qse_lda_walk (lda_t* lda, walker_t walker, void* ctx)
|
||||
{
|
||||
qse_lda_walk_t w = QSE_LDA_WALK_FORWARD;
|
||||
size_t i = 0, nwalks = 0;
|
||||
|
||||
if (lda->size <= 0) return 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (lda->slot[i] != QSE_NULL)
|
||||
{
|
||||
w = walker (lda, i, ctx);
|
||||
nwalks++;
|
||||
}
|
||||
|
||||
if (w == QSE_LDA_WALK_STOP) break;
|
||||
|
||||
if (w == QSE_LDA_WALK_FORWARD)
|
||||
{
|
||||
i++;
|
||||
if (i >= lda->size) break;
|
||||
}
|
||||
if (w == QSE_LDA_WALK_BACKWARD)
|
||||
{
|
||||
if (i <= 0) break;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
return nwalks;
|
||||
}
|
||||
|
||||
size_t qse_lda_rwalk (lda_t* lda, walker_t walker, void* ctx)
|
||||
{
|
||||
qse_lda_walk_t w = QSE_LDA_WALK_BACKWARD;
|
||||
size_t i, nwalks = 0;
|
||||
|
||||
if (lda->size <= 0) return 0;
|
||||
i = lda->size - 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (lda->slot[i] != QSE_NULL)
|
||||
{
|
||||
w = walker (lda, i, ctx);
|
||||
nwalks++;
|
||||
}
|
||||
|
||||
if (w == QSE_LDA_WALK_STOP) break;
|
||||
|
||||
if (w == QSE_LDA_WALK_FORWARD)
|
||||
{
|
||||
i++;
|
||||
if (i >= lda->size) break;
|
||||
}
|
||||
if (w == QSE_LDA_WALK_BACKWARD)
|
||||
{
|
||||
if (i <= 0) break;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
return nwalks;
|
||||
}
|
||||
|
||||
size_t qse_lda_pushstack (lda_t* lda, void* dptr, size_t dlen)
|
||||
{
|
||||
return qse_lda_insert (lda, lda->size, dptr, dlen);
|
||||
}
|
||||
|
||||
void qse_lda_popstack (lda_t* lda)
|
||||
{
|
||||
QSE_ASSERT (lda->size > 0);
|
||||
qse_lda_delete (lda, lda->size - 1, 1);
|
||||
}
|
||||
|
||||
#define HEAP_PARENT(x) (((x)-1) / 2)
|
||||
#define HEAP_LEFT(x) ((x)*2 + 1)
|
||||
#define HEAP_RIGHT(x) ((x)*2 + 2)
|
||||
|
||||
size_t qse_lda_pushheap (lda_t* lda, void* dptr, size_t dlen)
|
||||
{
|
||||
size_t cur, par;
|
||||
int n;
|
||||
|
||||
/* add a value to the bottom */
|
||||
cur = lda->size;
|
||||
if (qse_lda_insert (lda, cur, dptr, dlen) == QSE_LDA_NIL)
|
||||
return QSE_LDA_NIL;
|
||||
|
||||
while (cur != 0)
|
||||
{
|
||||
slot_t* tmp;
|
||||
|
||||
/* compare with the parent */
|
||||
par = HEAP_PARENT(cur);
|
||||
n = lda->comper (lda,
|
||||
DPTR(lda->slot[cur]), DLEN(lda->slot[cur]),
|
||||
DPTR(lda->slot[par]), DLEN(lda->slot[par]));
|
||||
if (n <= 0) break; /* ok */
|
||||
|
||||
/* swap the current with the parent */
|
||||
tmp = lda->slot[cur];
|
||||
lda->slot[cur] = lda->slot[par];
|
||||
lda->slot[par] = tmp;
|
||||
|
||||
cur = par;
|
||||
}
|
||||
|
||||
return lda->size;
|
||||
}
|
||||
|
||||
void qse_lda_popheap (lda_t* lda)
|
||||
{
|
||||
size_t cur, child;
|
||||
slot_t* tmp;
|
||||
|
||||
QSE_ASSERT (lda->size > 0);
|
||||
|
||||
/* destroy the top */
|
||||
tmp = lda->slot[0];
|
||||
if (lda->freeer) lda->freeer (lda, DPTR(tmp), DLEN(tmp));
|
||||
QSE_MMGR_FREE (lda->mmgr, tmp);
|
||||
|
||||
/* move the last item to the top position also shrink the size */
|
||||
lda->slot[0] = lda->slot[--lda->size];
|
||||
|
||||
if (lda->size <= 1) return; /* only 1 element. nothing further to do */
|
||||
|
||||
for (cur = 0; cur < lda->size; cur = child)
|
||||
{
|
||||
size_t left, right;
|
||||
int n;
|
||||
|
||||
left = HEAP_LEFT(cur);
|
||||
right = HEAP_RIGHT(cur);
|
||||
|
||||
if (left >= lda->size)
|
||||
{
|
||||
/* the left child does not exist.
|
||||
* reached the bottom. abort exchange */
|
||||
break;
|
||||
}
|
||||
|
||||
if (right >= lda->size)
|
||||
{
|
||||
/* the right child does not exist. only the left */
|
||||
child = left;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* get the larger child of the two */
|
||||
n = lda->comper (lda,
|
||||
DPTR(lda->slot[left]), DLEN(lda->slot[left]),
|
||||
DPTR(lda->slot[right]), DLEN(lda->slot[right]));
|
||||
child = (n > 0)? left: right;
|
||||
}
|
||||
|
||||
/* compare the current one with the child */
|
||||
n = lda->comper (lda,
|
||||
DPTR(lda->slot[cur]), DLEN(lda->slot[cur]),
|
||||
DPTR(lda->slot[child]), DLEN(lda->slot[child]));
|
||||
if (n > 0) break; /* current one is larger. stop exchange */
|
||||
|
||||
/* swap the current with the child */
|
||||
tmp = lda->slot[cur];
|
||||
lda->slot[cur] = lda->slot[child];
|
||||
lda->slot[child] = tmp;
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@
|
||||
#include <qse/cmn/rex.h>
|
||||
#include <qse/cmn/chr.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/lda.h>
|
||||
#include <qse/cmn/arr.h>
|
||||
#include "mem-prv.h"
|
||||
|
||||
#define OCC_MAX QSE_TYPE_MAX(qse_size_t)
|
||||
@ -75,7 +75,7 @@ struct exec_t
|
||||
{
|
||||
int active;
|
||||
int pending;
|
||||
qse_lda_t set[2]; /* candidate arrays */
|
||||
qse_arr_t set[2]; /* candidate arrays */
|
||||
} cand;
|
||||
|
||||
qse_size_t nmatches;
|
||||
@ -1379,9 +1379,9 @@ static int addsimplecand (
|
||||
cand.group = group;
|
||||
cand.mptr = mptr;
|
||||
|
||||
if (qse_lda_search (
|
||||
if (qse_arr_search (
|
||||
&e->cand.set[e->cand.pending],
|
||||
0, &cand, 1) != QSE_LDA_NIL)
|
||||
0, &cand, 1) != QSE_ARR_NIL)
|
||||
{
|
||||
/* exclude any existing entries in the array.
|
||||
* see comp_cand() for the equality test used.
|
||||
@ -1395,10 +1395,10 @@ static int addsimplecand (
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (qse_lda_insert (
|
||||
if (qse_arr_insert (
|
||||
&e->cand.set[e->cand.pending],
|
||||
QSE_LDA_SIZE(&e->cand.set[e->cand.pending]),
|
||||
&cand, 1) == QSE_LDA_NIL)
|
||||
QSE_ARR_SIZE(&e->cand.set[e->cand.pending]),
|
||||
&cand, 1) == QSE_ARR_NIL)
|
||||
{
|
||||
e->rex->errnum = QSE_REX_ENOMEM;
|
||||
return -1;
|
||||
@ -1704,11 +1704,11 @@ static int charset_matched (exec_t* e, qse_rex_node_t* node, qse_char_t c)
|
||||
return matched;
|
||||
}
|
||||
|
||||
static qse_lda_walk_t walk_cands_for_match (
|
||||
qse_lda_t* lda, qse_size_t index, void* ctx)
|
||||
static qse_arr_walk_t walk_cands_for_match (
|
||||
qse_arr_t* arr, qse_size_t index, void* ctx)
|
||||
{
|
||||
exec_t* e = (exec_t*)ctx;
|
||||
cand_t* cand = QSE_LDA_DPTR(lda,index);
|
||||
cand_t* cand = QSE_ARR_DPTR(arr,index);
|
||||
qse_rex_node_t* node = cand->node;
|
||||
const qse_char_t* nmptr = QSE_NULL;
|
||||
|
||||
@ -1807,7 +1807,7 @@ static qse_lda_walk_t walk_cands_for_match (
|
||||
if (cand->occ < node->occ.max && cand->group != QSE_NULL)
|
||||
{
|
||||
gx = dupgroupstack (e, cand->group);
|
||||
if (gx == QSE_NULL) return QSE_LDA_WALK_STOP;
|
||||
if (gx == QSE_NULL) return QSE_ARR_WALK_STOP;
|
||||
}
|
||||
else gx = cand->group;
|
||||
|
||||
@ -1816,7 +1816,7 @@ static qse_lda_walk_t walk_cands_for_match (
|
||||
n = addcands (e, gx, node, node->next, nmptr);
|
||||
refdowngroupstack (gx, e->rex->mmgr);
|
||||
|
||||
if (n <= -1) return QSE_LDA_WALK_STOP;
|
||||
if (n <= -1) return QSE_ARR_WALK_STOP;
|
||||
}
|
||||
|
||||
if (cand->occ < node->occ.max)
|
||||
@ -1828,11 +1828,11 @@ static qse_lda_walk_t walk_cands_for_match (
|
||||
node, cand->occ + 1, nmptr);
|
||||
refdowngroupstack (cand->group, e->rex->mmgr);
|
||||
|
||||
if (n <= -1) return QSE_LDA_WALK_STOP;
|
||||
if (n <= -1) return QSE_ARR_WALK_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
return QSE_LDA_WALK_FORWARD;
|
||||
return QSE_ARR_WALK_FORWARD;
|
||||
}
|
||||
|
||||
static int exec (exec_t* e)
|
||||
@ -1846,7 +1846,7 @@ static int exec (exec_t* e)
|
||||
e->cand.active = 1;
|
||||
|
||||
/* empty the pending set to collect the initial candidates */
|
||||
qse_lda_clear (&e->cand.set[e->cand.pending]);
|
||||
qse_arr_clear (&e->cand.set[e->cand.pending]);
|
||||
|
||||
/* the first node must be the START node */
|
||||
QSE_ASSERT (e->rex->code->id == QSE_REX_NODE_START);
|
||||
@ -1874,7 +1874,7 @@ static int exec (exec_t* e)
|
||||
e->cand.pending = e->cand.active;
|
||||
e->cand.active = tmp;
|
||||
|
||||
ncands_active = QSE_LDA_SIZE(&e->cand.set[e->cand.active]);
|
||||
ncands_active = QSE_ARR_SIZE(&e->cand.set[e->cand.active]);
|
||||
if (ncands_active <= 0)
|
||||
{
|
||||
/* we can't go on with no candidates in the
|
||||
@ -1883,7 +1883,7 @@ static int exec (exec_t* e)
|
||||
}
|
||||
|
||||
/* clear the pending set */
|
||||
qse_lda_clear (&e->cand.set[e->cand.pending]);
|
||||
qse_arr_clear (&e->cand.set[e->cand.pending]);
|
||||
|
||||
#ifdef XTRA_DEBUG
|
||||
{
|
||||
@ -1891,7 +1891,7 @@ static int exec (exec_t* e)
|
||||
qse_printf (QSE_T("SET="));
|
||||
for (i = 0; i < ncands_active; i++)
|
||||
{
|
||||
cand_t* cand = QSE_LDA_DPTR(&e->cand.set[e->cand.active],i);
|
||||
cand_t* cand = QSE_ARR_DPTR(&e->cand.set[e->cand.active],i);
|
||||
qse_rex_node_t* node = cand->node;
|
||||
|
||||
if (node->id == QSE_REX_NODE_CHAR)
|
||||
@ -1907,7 +1907,7 @@ static int exec (exec_t* e)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (qse_lda_walk (
|
||||
if (qse_arr_walk (
|
||||
&e->cand.set[e->cand.active],
|
||||
walk_cands_for_match, e) != ncands_active)
|
||||
{
|
||||
@ -1932,13 +1932,13 @@ static int exec (exec_t* e)
|
||||
return (e->nmatches > 0)? 1: 0;
|
||||
}
|
||||
|
||||
static void refdowngroupstack_incand (qse_lda_t* lda, void* dptr, qse_size_t dlen)
|
||||
static void refdowngroupstack_incand (qse_arr_t* arr, void* dptr, qse_size_t dlen)
|
||||
{
|
||||
QSE_ASSERT (dlen == 1);
|
||||
refdowngroupstack (((cand_t*)dptr)->group, lda->mmgr);
|
||||
refdowngroupstack (((cand_t*)dptr)->group, arr->mmgr);
|
||||
}
|
||||
|
||||
static int comp_cand (qse_lda_t* lda,
|
||||
static int comp_cand (qse_arr_t* arr,
|
||||
const void* dptr1, qse_size_t dlen1,
|
||||
const void* dptr2, qse_size_t dlen2)
|
||||
{
|
||||
@ -1953,37 +1953,37 @@ static int comp_cand (qse_lda_t* lda,
|
||||
static int init_exec_dds (exec_t* e, qse_mmgr_t* mmgr)
|
||||
{
|
||||
/* initializes dynamic data structures */
|
||||
if (qse_lda_init (&e->cand.set[0], mmgr, 100) <= -1)
|
||||
if (qse_arr_init (&e->cand.set[0], mmgr, 100) <= -1)
|
||||
{
|
||||
e->rex->errnum = QSE_REX_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
if (qse_lda_init (&e->cand.set[1], mmgr, 100) <= -1)
|
||||
if (qse_arr_init (&e->cand.set[1], mmgr, 100) <= -1)
|
||||
{
|
||||
e->rex->errnum = QSE_REX_ENOMEM;
|
||||
qse_lda_fini (&e->cand.set[0]);
|
||||
qse_arr_fini (&e->cand.set[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
qse_lda_setscale (&e->cand.set[0], QSE_SIZEOF(cand_t));
|
||||
qse_lda_setscale (&e->cand.set[1], QSE_SIZEOF(cand_t));
|
||||
qse_arr_setscale (&e->cand.set[0], QSE_SIZEOF(cand_t));
|
||||
qse_arr_setscale (&e->cand.set[1], QSE_SIZEOF(cand_t));
|
||||
|
||||
qse_lda_setcopier (&e->cand.set[0], QSE_LDA_COPIER_INLINE);
|
||||
qse_lda_setcopier (&e->cand.set[1], QSE_LDA_COPIER_INLINE);
|
||||
qse_arr_setcopier (&e->cand.set[0], QSE_ARR_COPIER_INLINE);
|
||||
qse_arr_setcopier (&e->cand.set[1], QSE_ARR_COPIER_INLINE);
|
||||
|
||||
qse_lda_setfreeer (&e->cand.set[0], refdowngroupstack_incand);
|
||||
qse_lda_setfreeer (&e->cand.set[1], refdowngroupstack_incand);
|
||||
qse_arr_setfreeer (&e->cand.set[0], refdowngroupstack_incand);
|
||||
qse_arr_setfreeer (&e->cand.set[1], refdowngroupstack_incand);
|
||||
|
||||
qse_lda_setcomper (&e->cand.set[0], comp_cand);
|
||||
qse_lda_setcomper (&e->cand.set[1], comp_cand);
|
||||
qse_arr_setcomper (&e->cand.set[0], comp_cand);
|
||||
qse_arr_setcomper (&e->cand.set[1], comp_cand);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fini_exec_dds (exec_t* e)
|
||||
{
|
||||
qse_lda_fini (&e->cand.set[1]);
|
||||
qse_lda_fini (&e->cand.set[0]);
|
||||
qse_arr_fini (&e->cand.set[1]);
|
||||
qse_arr_fini (&e->cand.set[0]);
|
||||
}
|
||||
|
||||
int qse_rex_exec (
|
||||
|
Reference in New Issue
Block a user