diff --git a/qse/include/qse/cmn/Makefile.am b/qse/include/qse/cmn/Makefile.am
index b0d5d5c3..e82e9166 100644
--- a/qse/include/qse/cmn/Makefile.am
+++ b/qse/include/qse/cmn/Makefile.am
@@ -1,7 +1,7 @@
pkgincludedir = $(includedir)/qse/cmn
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 oht.h htb.h rbt.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
diff --git a/qse/include/qse/cmn/Makefile.in b/qse/include/qse/cmn/Makefile.in
index 93c24dd9..b7b77324 100644
--- a/qse/include/qse/cmn/Makefile.in
+++ b/qse/include/qse/cmn/Makefile.in
@@ -52,8 +52,8 @@ CONFIG_CLEAN_VPATH_FILES =
SOURCES =
DIST_SOURCES =
am__pkginclude_HEADERS_DIST = mem.h xma.h fma.h chr.h str.h lda.h \
- htb.h rbt.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 Mmgr.hpp StdMmgr.hpp \
+ oht.h htb.h rbt.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 Mmgr.hpp StdMmgr.hpp \
Mmged.hpp
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
@@ -221,9 +221,9 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-pkginclude_HEADERS = mem.h xma.h fma.h chr.h str.h lda.h htb.h rbt.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 $(am__append_1)
+pkginclude_HEADERS = mem.h xma.h fma.h chr.h str.h lda.h oht.h htb.h \
+ rbt.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 $(am__append_1)
all: all-am
.SUFFIXES:
diff --git a/qse/include/qse/cmn/htb.h b/qse/include/qse/cmn/htb.h
index 456efac8..8871486b 100644
--- a/qse/include/qse/cmn/htb.h
+++ b/qse/include/qse/cmn/htb.h
@@ -1,5 +1,5 @@
/*
- * $Id: htb.h 354 2010-09-03 12:50:08Z hyunghwan.chung $
+ * $Id: htb.h 355 2010-09-07 10:57:43Z hyunghwan.chung $
*
Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE.
@@ -157,7 +157,7 @@ struct qse_htb_t
qse_htb_sizer_t sizer; /**< bucket capacity recalculator */
qse_byte_t scale[2]; /**< length scale */
- qse_byte_t factor; /**< load factor */
+ qse_byte_t factor; /**< load factor in percentage */
qse_byte_t filler0;
qse_size_t size;
diff --git a/qse/include/qse/cmn/oht.h b/qse/include/qse/cmn/oht.h
new file mode 100644
index 00000000..22272f7f
--- /dev/null
+++ b/qse/include/qse/cmn/oht.h
@@ -0,0 +1,194 @@
+/*
+ * $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 toht 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 .
+ */
+
+/** @file
+ * This file provides the open-addressed hash table for fixed-size data.
+ */
+#ifndef _QSE_OHT_T_
+#define _QSE_OHT_T_
+
+#include
+#include
+
+#define QSE_OHT_INVALID_INDEX ((qse_size_t)-1)
+
+enum qse_oht_mark_t
+{
+ QSE_OHT_EMPTY = 0,
+ QSE_OHT_OCCUPIED = 1 /*,
+ QSE_OHT_DELETED = 2 */
+};
+typedef enum qse_oht_mark_t qse_oht_mark_t;
+
+enum qse_oht_walk_t
+{
+ QSE_OHT_WALK_STOP = 0,
+ QSE_OHT_WALK_FORWARD = 1,
+};
+typedef enum qse_oht_walk_t qse_oht_walk_t;
+
+typedef struct qse_oht_t qse_oht_t;
+
+/**
+ * The qse_oht_comper_t type defines a key comparator that is called when
+ * the list needs to compare data. The comparator must return 0 if the data
+ * are the same and a non-zero integer otherwise.
+ */
+typedef int (*qse_oht_comper_t) (
+ qse_oht_t* oht, /**< open-addressed hash table */
+ const void* data1, /**< data pointer */
+ const void* data2 /**< data pointer */
+);
+
+typedef void (*qse_oht_copier_t) (
+ qse_oht_t* oht,
+ void* dst,
+ const void* src
+);
+
+typedef qse_size_t (*qse_oht_hasher_t) (
+ qse_oht_t* oht,
+ const void* data
+);
+
+struct qse_oht_t
+{
+ QSE_DEFINE_COMMON_FIELDS(oht)
+
+ struct
+ {
+ qse_size_t hard;
+ qse_size_t soft;
+ } capa;
+ qse_size_t size;
+ qse_size_t scale;
+
+ qse_oht_hasher_t hasher;
+ qse_oht_comper_t comper;
+ qse_oht_copier_t copier;
+
+ qse_oht_mark_t* mark;
+ void* data;
+};
+
+typedef qse_oht_walk_t (*qse_oht_walker_t) (
+ qse_oht_t* oht,
+ void* data,
+ void* ctx
+);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+QSE_DEFINE_COMMON_FUNCTIONS (oht)
+
+qse_oht_t* qse_oht_open (
+ qse_mmgr_t* mmgr,
+ qse_size_t xtnsize,
+ qse_size_t scale,
+ qse_size_t capa,
+ qse_size_t limit
+);
+
+void qse_oht_close (
+ qse_oht_t* oht
+);
+
+qse_oht_t* qse_oht_init (
+ qse_oht_t* oht,
+ qse_mmgr_t* mmgr,
+ qse_size_t scale,
+ qse_size_t capa,
+ qse_size_t limit
+);
+
+void qse_oht_fini (
+ qse_oht_t* oht
+);
+
+qse_oht_hasher_t qse_oht_gethasher (
+ qse_oht_t* oht
+);
+
+void qse_oht_sethasher (
+ qse_oht_t* oht,
+ qse_oht_hasher_t hahser
+);
+
+qse_oht_comper_t qse_oht_getcomper (
+ qse_oht_t* oht
+);
+
+void qse_oht_setcomper (
+ qse_oht_t* oht,
+ qse_oht_comper_t hahser
+);
+
+qse_oht_copier_t qse_oht_getcopier (
+ qse_oht_t* oht
+);
+
+void qse_oht_setcopier (
+ qse_oht_t* oht,
+ qse_oht_copier_t hahser
+);
+
+qse_size_t qse_oht_search (
+ qse_oht_t* oht,
+ void* data
+);
+
+qse_size_t qse_oht_insert (
+ qse_oht_t* oht,
+ const void* data
+);
+
+qse_size_t qse_oht_upsert (
+ qse_oht_t* oht,
+ const void* data
+);
+
+qse_size_t qse_oht_update (
+ qse_oht_t* oht,
+ const void* data
+);
+
+qse_size_t qse_oht_delete (
+ qse_oht_t* oht,
+ const void* data
+);
+
+void qse_oht_clear (
+ qse_oht_t* oht
+);
+
+
+void qse_oht_walk (
+ qse_oht_t* oht, /**< open-addressed hash table */
+ qse_oht_walker_t walker, /**< walker function */
+ void* ctx /**< context */
+);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/qse/include/qse/cmn/sll.h b/qse/include/qse/cmn/sll.h
index 2611b02d..f262ef15 100644
--- a/qse/include/qse/cmn/sll.h
+++ b/qse/include/qse/cmn/sll.h
@@ -1,5 +1,5 @@
/*
- * $Id: sll.h 354 2010-09-03 12:50:08Z hyunghwan.chung $
+ * $Id: sll.h 355 2010-09-07 10:57:43Z hyunghwan.chung $
*
Copyright 2006-2009 Chung, Hyung-Hwan.
This file is part of QSE.
@@ -123,9 +123,9 @@ struct qse_sll_t
*/
struct qse_sll_node_t
{
- void* dptr; /* the pointer to data */
- qse_size_t dlen; /* the length of data */
- qse_sll_node_t* next; /* the pointer to the next node */
+ qse_sll_node_t* next; /* point to the next node */
+ void* dptr; /* data pointer */
+ qse_size_t dlen; /* data length */
};
#define QSE_SLL_COPIER_SIMPLE ((qse_sll_copier_t)1)
diff --git a/qse/include/qse/cmn/xma.h b/qse/include/qse/cmn/xma.h
index 09c52906..46160c9e 100644
--- a/qse/include/qse/cmn/xma.h
+++ b/qse/include/qse/cmn/xma.h
@@ -46,7 +46,7 @@
* ptr2 = qse_xma_alloc (xma, 1000); // allocate a 1K block from the zone
* ptr1 = qse_xma_realloc (xma, ptr1, 6000); // resize the 5K block to 6K.
*
- * qse_xma_dump (xma, qse_printf); // dump memory blocks
+ * qse_xma_dump (xma, qse_fprintf, QSE_STDOUT); // dump memory blocks
*
* // the following two lines are not actually needed as the allocator
* // is closed after them.
@@ -104,6 +104,8 @@ struct qse_xma_t
#endif
};
+typedef int (*qse_xma_dumper_t) (void* target, const qse_char_t* fmt,...);
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -189,8 +191,9 @@ void qse_xma_free (
* more statistical counters.
*/
void qse_xma_dump (
- qse_xma_t* xma, /**< memory allocator */
- int (*printf)(const qse_char_t* fmt,...) /**< output function */
+ qse_xma_t* xma, /**< memory allocator */
+ qse_xma_dumper_t dumper, /**< output function */
+ void* target /**< first parameter to output function */
);
#ifdef __cplusplus
diff --git a/qse/lib/cmn/Makefile.am b/qse/lib/cmn/Makefile.am
index bdcd37d9..1155d3ea 100644
--- a/qse/lib/cmn/Makefile.am
+++ b/qse/lib/cmn/Makefile.am
@@ -7,7 +7,7 @@ libqsecmn_la_SOURCES = \
syscall.h mem.h \
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 \
- lda.c htb.c rbt.c sll.c gdl.c dll.c opt.c \
+ lda.c oht.c htb.c rbt.c sll.c gdl.c dll.c opt.c \
tio.c tio_get.c tio_put.c \
fio.c pio.c sio.c \
time.c \
diff --git a/qse/lib/cmn/Makefile.in b/qse/lib/cmn/Makefile.in
index 517144ca..473a0c8c 100644
--- a/qse/lib/cmn/Makefile.in
+++ b/qse/lib/cmn/Makefile.in
@@ -75,9 +75,9 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
libqsecmn_la_DEPENDENCIES =
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 \
- 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 \
- main.lo stdio.lo
+ oht.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 main.lo stdio.lo
libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS)
libqsecmn_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -264,7 +264,7 @@ libqsecmn_la_SOURCES = \
syscall.h mem.h \
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 \
- lda.c htb.c rbt.c sll.c gdl.c dll.c opt.c \
+ lda.c oht.c htb.c rbt.c sll.c gdl.c dll.c opt.c \
tio.c tio_get.c tio_put.c \
fio.c pio.c sio.c \
time.c \
@@ -369,6 +369,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oht.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pio.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rbt.Plo@am__quote@
diff --git a/qse/lib/cmn/oht.c b/qse/lib/cmn/oht.c
new file mode 100644
index 00000000..932db5d7
--- /dev/null
+++ b/qse/lib/cmn/oht.c
@@ -0,0 +1,322 @@
+#include
+#include "mem.h"
+
+#define DATA_PTR(oht,index) \
+ ((void*)(((qse_byte_t*)(oht)->data) + ((index) * (oht)->scale)))
+
+QSE_IMPLEMENT_COMMON_FUNCTIONS (oht)
+
+static QSE_INLINE_ALWAYS qse_size_t default_hasher (
+ qse_oht_t* oht, const void* data)
+{
+ size_t h = 5381;
+ const qse_byte_t* p = (const qse_byte_t*)data;
+ const qse_byte_t* bound = p + oht->scale;
+ while (p < bound) h = ((h << 5) + h) + *p++;
+ return h ;
+}
+
+static QSE_INLINE_ALWAYS int default_comper (
+ qse_oht_t* oht, const void* data1, const void* data2)
+{
+ return QSE_MEMCMP(data1, data2, oht->scale);
+}
+
+static QSE_INLINE_ALWAYS void default_copier (
+ qse_oht_t* oht, void* dst, const void* src)
+{
+ QSE_MEMCPY (dst, src, oht->scale);
+}
+
+#define HASH_DATA(oht,data) \
+ ((oht)->hasher? (oht)->hasher ((oht), (data)): \
+ default_hasher (oht, data))
+
+#define COMP_DATA(oht,d1,d2) \
+ ((oht)->comper? (oht)->comper ((oht), (d1), (d2)): \
+ QSE_MEMCMP ((d1), (d2), (oht)->scale))
+
+#define COPY_DATA(oht,dst,src) \
+ QSE_BLOCK ( \
+ if ((oht)->copier) (oht)->copier ((oht), (dst), (src)); \
+ else QSE_MEMCPY ((dst), (src), (oht)->scale); \
+ )
+
+qse_oht_t* qse_oht_open (
+ qse_mmgr_t* mmgr, qse_size_t xtnsize,
+ qse_size_t scale, qse_size_t capa, qse_size_t limit)
+{
+ qse_oht_t* oht;
+
+ if (mmgr == QSE_NULL)
+ {
+ mmgr = QSE_MMGR_GETDFL();
+
+ QSE_ASSERTX (mmgr != QSE_NULL,
+ "Set the memory manager with QSE_MMGR_SETDFL()");
+
+ if (mmgr == QSE_NULL) return QSE_NULL;
+ }
+
+ oht = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(qse_oht_t) + xtnsize);
+ if (oht == QSE_NULL) return QSE_NULL;
+
+ if (qse_oht_init (oht, mmgr, scale, capa, limit) == QSE_NULL)
+ {
+ QSE_MMGR_FREE (mmgr, oht);
+ return QSE_NULL;
+ }
+
+ return oht;
+}
+
+void qse_oht_close (qse_oht_t* oht)
+{
+ qse_oht_fini (oht);
+ QSE_MMGR_FREE (oht->mmgr, oht);
+}
+
+qse_oht_t* qse_oht_init (
+ qse_oht_t* oht, qse_mmgr_t* mmgr,
+ qse_size_t scale, qse_size_t capa, qse_size_t limit)
+{
+ qse_size_t i;
+
+ if (scale <= 0) scale = 1;
+ if (capa >= QSE_OHT_INVALID_INDEX - 1) capa = QSE_OHT_INVALID_INDEX - 1;
+ if (limit > capa || limit <= 0) limit = capa;
+
+ QSE_MEMSET (oht, 0, QSE_SIZEOF(*oht));
+
+ oht->mmgr = mmgr;
+ oht->capa.hard = capa;
+ oht->capa.soft = limit;
+ oht->scale = scale;
+ oht->size = 0;
+
+ /*oht->hasher = default_hasher;
+ oht->comper = default_comper;
+ oht->copier = default_copier;*/
+
+ oht->mark = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(qse_oht_mark_t) * capa);
+ if (!oht->mark) return QSE_NULL;
+
+ oht->data = QSE_MMGR_ALLOC (mmgr, scale * capa);
+ if (!oht->data)
+ {
+ QSE_MMGR_FREE (mmgr, oht->mark);
+ return QSE_NULL;
+ }
+
+ for (i = 0; i < capa; i++) oht->mark[i] = QSE_OHT_EMPTY;
+ return oht;
+}
+
+void qse_oht_fini (qse_oht_t* oht)
+{
+ QSE_MMGR_FREE (oht->mmgr, oht->mark);
+ QSE_MMGR_FREE (oht->mmgr, oht->data);
+ oht->size = 0;
+}
+
+qse_oht_hasher_t qse_oht_gethasher (qse_oht_t* oht)
+{
+ return oht->hasher? oht->hasher: default_hasher;
+}
+
+void qse_oht_sethasher (qse_oht_t* oht, qse_oht_hasher_t hasher)
+{
+ oht->hasher = hasher;
+}
+
+qse_oht_comper_t qse_oht_getcomper (qse_oht_t* oht)
+{
+ return oht->comper? oht->comper: default_comper;
+}
+
+void qse_oht_setcomper (qse_oht_t* oht, qse_oht_comper_t comper)
+{
+ oht->comper = comper;
+}
+
+qse_oht_copier_t qse_oht_getcopier (qse_oht_t* oht)
+{
+ return oht->copier? oht->copier: default_copier;
+}
+
+void qse_oht_setcopier (qse_oht_t* oht, qse_oht_copier_t copier)
+{
+ oht->copier = copier;
+}
+
+static QSE_INLINE qse_size_t search (
+ qse_oht_t* oht, const void* data, qse_size_t hash)
+{
+ qse_size_t i;
+
+ for (i = 0; i < oht->capa.hard; i++)
+ {
+ qse_size_t index = (hash + i) % oht->capa.hard;
+ if (oht->mark[index] == QSE_OHT_EMPTY) break;
+ if (oht->mark[index] == QSE_OHT_OCCUPIED)
+ {
+ if (COMP_DATA (oht, data, DATA_PTR(oht,index)) == 0)
+ return index;
+ }
+ }
+
+ return QSE_OHT_INVALID_INDEX;
+}
+
+qse_size_t qse_oht_search (qse_oht_t* oht, void* data)
+{
+ qse_size_t i = search (oht, data, HASH_DATA(oht,data));
+ if (i != QSE_OHT_INVALID_INDEX && data)
+ COPY_DATA (oht, data, DATA_PTR(oht,i));
+ return i;
+}
+
+qse_size_t qse_oht_update (qse_oht_t* oht, const void* data)
+{
+ qse_size_t i = search (oht, data, HASH_DATA(oht,data));
+ if (i != QSE_OHT_INVALID_INDEX)
+ COPY_DATA (oht, DATA_PTR(oht,i), data);
+ return i;
+}
+
+qse_size_t qse_oht_upsert (qse_oht_t* oht, const void* data)
+{
+ qse_size_t i, hash = HASH_DATA (oht, data);
+
+ /* find the existing item */
+ i = search (oht, data, hash);
+ if (i != QSE_OHT_INVALID_INDEX)
+ {
+ COPY_DATA (oht, DATA_PTR(oht,i), data);
+ return i;
+ }
+
+ /* check if there is a free slot to insert data into */
+ if (oht->size >= oht->capa.soft) return QSE_OHT_INVALID_INDEX;
+
+ /* get the unoccupied slot and insert the data into it.
+ * iterate at most 'the number of items (oht->size)' times + 1. */
+ for (i = 0; i <= oht->size; i++)
+ {
+ qse_size_t index = (hash + i) % oht->capa.hard;
+ if (oht->mark[index] != QSE_OHT_OCCUPIED)
+ {
+ oht->mark[index] = QSE_OHT_OCCUPIED;
+ COPY_DATA (oht, DATA_PTR(oht,index), data);
+ oht->size++;
+ return index;
+ }
+ }
+
+ return QSE_OHT_INVALID_INDEX;
+}
+
+qse_size_t qse_oht_insert (qse_oht_t* oht, const void* data)
+{
+ qse_size_t i, hash;
+
+ /* check if there is a free slot to insert data into */
+ if (oht->size >= oht->capa.soft) return QSE_OHT_INVALID_INDEX;
+
+ hash = HASH_DATA (oht, data);
+
+ /* check if the item already exits */
+ i = search (oht, data, hash);
+ if (i != QSE_OHT_INVALID_INDEX) return QSE_OHT_INVALID_INDEX;
+
+ /* get the unoccupied slot and insert the data into it.
+ * iterate at most 'the number of items (oht->size)' times + 1. */
+ for (i = 0; i <= oht->size; i++)
+ {
+ qse_size_t index = (hash + i) % oht->capa.hard;
+ if (oht->mark[index] != QSE_OHT_OCCUPIED)
+ {
+ oht->mark[index] = QSE_OHT_OCCUPIED;
+ COPY_DATA (oht, DATA_PTR(oht,index), data);
+ oht->size++;
+ return index;
+ }
+ }
+
+ return QSE_OHT_INVALID_INDEX;
+}
+
+qse_size_t qse_oht_delete (qse_oht_t* oht, const void* data)
+{
+#if 0
+ qse_size_t index;
+
+ if (oht->size <= 0) return QSE_OHT_INVALID_INDEX;
+
+ index = search (oht, data, HASH_DATA(oht,data));
+ if (index != QSE_OHT_INVALID_INDEX)
+ {
+ oht->mark[index] = QSE_OHT_DELETED;
+ oht->size--;
+ }
+
+ return index;
+#endif
+
+ qse_size_t index, i, x, y, z;
+
+ /* check if the oht is empty. if so, do nothing */
+ if (oht->size <= 0) return QSE_OHT_INVALID_INDEX;
+
+ /* check if the item exists. otherwise, do nothing. */
+ index = search (oht, data, HASH_DATA(oht,data));
+ if (index == QSE_OHT_INVALID_INDEX) return QSE_OHT_INVALID_INDEX;
+
+ /* compact the cluster */
+ for (i = 0, x = index, y = index; i < oht->size; i++)
+ {
+ y = (y + 1) % oht->capa.hard;
+
+ /* done if the slot at the current hash index is empty */
+ if (oht->mark[y] == QSE_OHT_EMPTY) break;
+
+ /* get the natural hash index for the data in the slot at
+ * the current hash index */
+ z = HASH_DATA(oht,DATA_PTR(oht,y)) % oht->capa.hard;
+
+ /* move an element if necesary */
+ if ((y > x && (z <= x || z > y)) ||
+ (y < x && (z <= x && z > y)))
+ {
+ COPY_DATA (oht, DATA_PTR(oht,x), DATA_PTR(oht,y));
+ x = y;
+ }
+ }
+
+ oht->mark[x] = QSE_OHT_EMPTY;
+ oht->size--;
+
+ return index;
+}
+
+void qse_oht_clear (qse_oht_t* oht)
+{
+ qse_size_t i;
+ for (i = 0; i < oht->capa.hard; i++)
+ oht->mark[i] = QSE_OHT_EMPTY;
+ oht->size = 0;
+}
+
+void qse_oht_walk (qse_oht_t* oht, qse_oht_walker_t walker, void* ctx)
+{
+ qse_size_t i;
+
+ for (i = 0; i < oht->capa.hard; i++)
+ {
+ if (oht->mark[i] == QSE_OHT_OCCUPIED)
+ {
+ if (walker (oht, DATA_PTR(oht,i), ctx) == QSE_OHT_WALK_STOP)
+ return;
+ }
+ }
+}
diff --git a/qse/lib/cmn/xma.c b/qse/lib/cmn/xma.c
index fe1113c0..b698b676 100644
--- a/qse/lib/cmn/xma.c
+++ b/qse/lib/cmn/xma.c
@@ -702,7 +702,7 @@ void qse_xma_free (qse_xma_t* xma, void* b)
}
}
-void qse_xma_dump (qse_xma_t* xma, int (*printf)(const qse_char_t* fmt,...))
+void qse_xma_dump (qse_xma_t* xma, qse_xma_dumper_t dumper, void* target)
{
qse_xma_blk_t* tmp;
unsigned long long fsum, asum;
@@ -710,19 +710,19 @@ void qse_xma_dump (qse_xma_t* xma, int (*printf)(const qse_char_t* fmt,...))
unsigned long long isum;
#endif
- printf (QSE_T("\n"));
+ dumper (target, QSE_T("\n"));
#ifdef QSE_XMA_ENABLE_STAT
- printf (QSE_T("== statistics ==\n"));
- printf (QSE_T("total = %llu\n"), (unsigned long long)xma->stat.total);
- printf (QSE_T("alloc = %llu\n"), (unsigned long long)xma->stat.alloc);
- printf (QSE_T("avail = %llu\n"), (unsigned long long)xma->stat.avail);
+ dumper (target, QSE_T("== statistics ==\n"));
+ dumper (target, QSE_T("total = %llu\n"), (unsigned long long)xma->stat.total);
+ dumper (target, QSE_T("alloc = %llu\n"), (unsigned long long)xma->stat.alloc);
+ dumper (target, QSE_T("avail = %llu\n"), (unsigned long long)xma->stat.avail);
#endif
- printf (QSE_T("== blocks ==\n"));
- printf (QSE_T(" size avail address\n"));
+ dumper (target, QSE_T("== blocks ==\n"));
+ dumper (target, QSE_T(" size avail address\n"));
for (tmp = xma->head, fsum = 0, asum = 0; tmp; tmp = tmp->b.next)
{
- printf (QSE_T(" %-18llu %-5d %p\n"), (unsigned long long)tmp->size, tmp->avail, tmp);
+ dumper (target, QSE_T(" %-18llu %-5d %p\n"), (unsigned long long)tmp->size, tmp->avail, tmp);
if (tmp->avail) fsum += tmp->size;
else asum += tmp->size;
}
@@ -731,12 +731,12 @@ void qse_xma_dump (qse_xma_t* xma, int (*printf)(const qse_char_t* fmt,...))
isum = (xma->stat.nfree + xma->stat.nused) * HDRSIZE;
#endif
- printf (QSE_T("---------------------------------------\n"));
- printf (QSE_T("Allocated blocks: %18llu bytes\n"), asum);
- printf (QSE_T("Available blocks: %18llu bytes\n"), fsum);
+ dumper (target, QSE_T("---------------------------------------\n"));
+ dumper (target, QSE_T("Allocated blocks: %18llu bytes\n"), asum);
+ dumper (target, QSE_T("Available blocks: %18llu bytes\n"), fsum);
#ifdef QSE_XMA_ENABLE_STAT
- printf (QSE_T("Internal use : %18llu bytes\n"), isum);
- printf (QSE_T("Total : %18llu bytes\n"), asum + fsum + isum);
+ dumper (target, QSE_T("Internal use : %18llu bytes\n"), isum);
+ dumper (target, QSE_T("Total : %18llu bytes\n"), asum + fsum + isum);
#endif
QSE_ASSERT (asum == xma->stat.alloc);
diff --git a/qse/samples/cmn/Makefile.am b/qse/samples/cmn/Makefile.am
index afe80d3c..8570263f 100644
--- a/qse/samples/cmn/Makefile.am
+++ b/qse/samples/cmn/Makefile.am
@@ -1,6 +1,6 @@
AM_CPPFLAGS = -I$(top_srcdir)/include -DNDEBUG
-bin_PROGRAMS = xma fma chr str sll dll lda htb rbt fio pio sio time main rex01
+bin_PROGRAMS = xma fma chr str sll dll lda oht htb rbt fio pio sio time main rex01
LDFLAGS = -L../../lib/cmn
LDADD = -lqsecmn
@@ -12,6 +12,7 @@ str_SOURCES = str.c
sll_SOURCES = sll.c
dll_SOURCES = dll.c
lda_SOURCES = lda.c
+oht_SOURCES = oht.c
htb_SOURCES = htb.c
rbt_SOURCES = rbt.c
fio_SOURCES = fio.c
diff --git a/qse/samples/cmn/Makefile.in b/qse/samples/cmn/Makefile.in
index a90d27de..206afa57 100644
--- a/qse/samples/cmn/Makefile.in
+++ b/qse/samples/cmn/Makefile.in
@@ -35,9 +35,9 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = xma$(EXEEXT) fma$(EXEEXT) chr$(EXEEXT) str$(EXEEXT) \
- sll$(EXEEXT) dll$(EXEEXT) lda$(EXEEXT) htb$(EXEEXT) \
- rbt$(EXEEXT) fio$(EXEEXT) pio$(EXEEXT) sio$(EXEEXT) \
- time$(EXEEXT) main$(EXEEXT) rex01$(EXEEXT)
+ sll$(EXEEXT) dll$(EXEEXT) lda$(EXEEXT) oht$(EXEEXT) \
+ htb$(EXEEXT) rbt$(EXEEXT) fio$(EXEEXT) pio$(EXEEXT) \
+ sio$(EXEEXT) time$(EXEEXT) main$(EXEEXT) rex01$(EXEEXT)
subdir = samples/cmn
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -82,6 +82,10 @@ am_main_OBJECTS = main.$(OBJEXT)
main_OBJECTS = $(am_main_OBJECTS)
main_LDADD = $(LDADD)
main_DEPENDENCIES =
+am_oht_OBJECTS = oht.$(OBJEXT)
+oht_OBJECTS = $(am_oht_OBJECTS)
+oht_LDADD = $(LDADD)
+oht_DEPENDENCIES =
am_pio_OBJECTS = pio.$(OBJEXT)
pio_OBJECTS = $(am_pio_OBJECTS)
pio_LDADD = $(LDADD)
@@ -128,13 +132,14 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
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)
-DIST_SOURCES = $(chr_SOURCES) $(dll_SOURCES) $(fio_SOURCES) \
- $(fma_SOURCES) $(htb_SOURCES) $(lda_SOURCES) $(main_SOURCES) \
+ $(htb_SOURCES) $(lda_SOURCES) $(main_SOURCES) $(oht_SOURCES) \
$(pio_SOURCES) $(rbt_SOURCES) $(rex01_SOURCES) $(sio_SOURCES) \
$(sll_SOURCES) $(str_SOURCES) $(time_SOURCES) $(xma_SOURCES)
+DIST_SOURCES = $(chr_SOURCES) $(dll_SOURCES) $(fio_SOURCES) \
+ $(fma_SOURCES) $(htb_SOURCES) $(lda_SOURCES) $(main_SOURCES) \
+ $(oht_SOURCES) $(pio_SOURCES) $(rbt_SOURCES) $(rex01_SOURCES) \
+ $(sio_SOURCES) $(sll_SOURCES) $(str_SOURCES) $(time_SOURCES) \
+ $(xma_SOURCES)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
@@ -286,6 +291,7 @@ str_SOURCES = str.c
sll_SOURCES = sll.c
dll_SOURCES = dll.c
lda_SOURCES = lda.c
+oht_SOURCES = oht.c
htb_SOURCES = htb.c
rbt_SOURCES = rbt.c
fio_SOURCES = fio.c
@@ -392,6 +398,9 @@ lda$(EXEEXT): $(lda_OBJECTS) $(lda_DEPENDENCIES)
main$(EXEEXT): $(main_OBJECTS) $(main_DEPENDENCIES)
@rm -f main$(EXEEXT)
$(LINK) $(main_OBJECTS) $(main_LDADD) $(LIBS)
+oht$(EXEEXT): $(oht_OBJECTS) $(oht_DEPENDENCIES)
+ @rm -f oht$(EXEEXT)
+ $(LINK) $(oht_OBJECTS) $(oht_LDADD) $(LIBS)
pio$(EXEEXT): $(pio_OBJECTS) $(pio_DEPENDENCIES)
@rm -f pio$(EXEEXT)
$(LINK) $(pio_OBJECTS) $(pio_LDADD) $(LIBS)
@@ -430,6 +439,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lda.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/oht.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pio.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rbt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rex01.Po@am__quote@
diff --git a/qse/samples/cmn/oht.c b/qse/samples/cmn/oht.c
new file mode 100644
index 00000000..c5d6ebd9
--- /dev/null
+++ b/qse/samples/cmn/oht.c
@@ -0,0 +1,127 @@
+#include
+#include
+#include
+#include
+
+
+#define R(f) \
+ do { \
+ qse_printf (QSE_T("== %s ==\n"), QSE_T(#f)); \
+ if (f() == -1) return -1; \
+ } while (0)
+
+typedef struct item_t item_t;
+struct item_t
+{
+ long a;
+ long x;
+ long y;
+};
+
+static qse_oht_walk_t walk1 (qse_oht_t* oht, void* data, void* ctx)
+{
+ qse_printf (QSE_T("[%ld]\n"), *(long*)data);
+ return QSE_OHT_WALK_FORWARD;
+}
+
+static qse_oht_walk_t walk2 (qse_oht_t* oht, void* data, void* ctx)
+{
+ item_t* item = (item_t*)data;
+ qse_printf (QSE_T("a [%ld] x [%ld] y [%ld]\n"), item->a, item->x, item->y);
+ return QSE_OHT_WALK_FORWARD;
+}
+
+static qse_size_t hash (qse_oht_t* oht, void* data)
+{
+ item_t* item = (item_t*)data;
+ return item->a;
+}
+
+static int comp (qse_oht_t* oht, void* data1, void* data2)
+{
+ return ((item_t*)data1)->a != ((item_t*)data2)->a;
+}
+
+static int test1 ()
+{
+ long x;
+ qse_oht_t* oht;
+
+ oht = qse_oht_open (QSE_NULL, 0, QSE_SIZEOF(x), 10, 5);
+ if (oht == QSE_NULL)
+ {
+ qse_printf (QSE_T("failed to open a table\n"));
+ return -1;
+ }
+
+ for (x = 9; x < 20; x++)
+ {
+ qse_printf (QSE_T("inserting %ld => %lu\n"),
+ x, (unsigned long)qse_oht_insert (oht, &x));
+ }
+
+ x = 10;
+ qse_printf (QSE_T("searching for %ld => %lu\n"),
+ x, (unsigned long)qse_oht_search (oht, &x));
+
+ x = 10;
+ qse_printf (QSE_T("deleting %ld => %lu\n"),
+ x, (unsigned long)qse_oht_delete (oht, &x));
+
+ x = 10;
+ qse_printf (QSE_T("searching for %ld => %lu\n"),
+ x, (unsigned long)qse_oht_search (oht, &x));
+
+
+ qse_oht_walk (oht, walk1, QSE_NULL);
+ qse_oht_close (oht);
+ return 0;
+}
+
+static int test2 ()
+{
+ item_t x;
+ qse_oht_t* oht;
+
+ oht = qse_oht_open (QSE_NULL, 0, QSE_SIZEOF(x), 10, 5);
+ if (oht == QSE_NULL)
+ {
+ qse_printf (QSE_T("failed to open a table\n"));
+ return -1;
+ }
+
+ qse_oht_sethasher (oht, hash);
+ qse_oht_setcomper (oht, comp);
+
+ for (x.a = 9; x.a < 20; x.a++)
+ {
+ x.x = x.a * 10;
+ x.y = x.a * 100;
+ qse_printf (QSE_T("inserting %ld => %lu\n"),
+ x.a, (unsigned long)qse_oht_insert (oht, &x));
+ }
+
+ x.a = 10;
+ qse_printf (QSE_T("searching for %ld => %lu\n"),
+ x.a, (unsigned long)qse_oht_search (oht, &x));
+
+ x.a = 10;
+ qse_printf (QSE_T("deleting %ld => %lu\n"),
+ x.a, (unsigned long)qse_oht_delete (oht, &x));
+
+ x.a = 10;
+ qse_printf (QSE_T("searching for %ld => %lu\n"),
+ x.a, (unsigned long)qse_oht_search (oht, &x));
+
+
+ qse_oht_walk (oht, walk2, QSE_NULL);
+ qse_oht_close (oht);
+ return 0;
+}
+
+int main ()
+{
+ R (test1);
+ R (test2);
+ return 0;
+}
diff --git a/qse/samples/cmn/xma.c b/qse/samples/cmn/xma.c
index 7b95d30e..82c765a7 100644
--- a/qse/samples/cmn/xma.c
+++ b/qse/samples/cmn/xma.c
@@ -27,10 +27,10 @@ static int test1 ()
//qse_xma_free (xma, ptr[2]);
//qse_xma_free (xma, ptr[3]);
- qse_xma_dump (xma, qse_printf);
+ qse_xma_dump (xma, (qse_xma_dumper_t)qse_fprintf, QSE_STDOUT);
qse_xma_realloc (xma, ptr[0], 500);
qse_xma_realloc (xma, ptr[3], 500);
- qse_xma_dump (xma, qse_printf);
+ qse_xma_dump (xma, (qse_xma_dumper_t)qse_fprintf, QSE_STDOUT);
qse_xma_close (xma);
return 0;
@@ -51,13 +51,13 @@ static int test2 ()
ptr[1] = qse_xma_alloc (xma, 1000);
ptr[2] = qse_xma_alloc (xma, 3000);
ptr[3] = qse_xma_alloc (xma, 1000);
- qse_xma_dump (xma, qse_printf);
+ qse_xma_dump (xma, (qse_xma_dumper_t)qse_fprintf, QSE_STDOUT);
qse_xma_free (xma, ptr[0]);
qse_xma_free (xma, ptr[2]);
- qse_xma_dump (xma, qse_printf);
+ qse_xma_dump (xma, (qse_xma_dumper_t)qse_fprintf, QSE_STDOUT);
qse_xma_realloc (xma, ptr[1], 500);
- qse_xma_dump (xma, qse_printf);
+ qse_xma_dump (xma, (qse_xma_dumper_t)qse_fprintf, QSE_STDOUT);
qse_xma_close (xma);
return 0;
@@ -78,15 +78,15 @@ static int test3 ()
ptr[1] = qse_xma_alloc (xma, 1000);
ptr[2] = qse_xma_alloc (xma, 3000);
ptr[3] = qse_xma_alloc (xma, 1000);
- qse_xma_dump (xma, qse_printf);
+ qse_xma_dump (xma, (qse_xma_dumper_t)qse_fprintf, QSE_STDOUT);
qse_xma_free (xma, ptr[0]);
qse_xma_free (xma, ptr[2]);
- qse_xma_dump (xma, qse_printf);
+ qse_xma_dump (xma, (qse_xma_dumper_t)qse_fprintf, QSE_STDOUT);
ptr[1] = qse_xma_realloc (xma, ptr[1], 3000);
- qse_xma_dump (xma, qse_printf);
+ qse_xma_dump (xma, (qse_xma_dumper_t)qse_fprintf, QSE_STDOUT);
qse_xma_free (xma, ptr[1]);
- qse_xma_dump (xma, qse_printf);
+ qse_xma_dump (xma, (qse_xma_dumper_t)qse_fprintf, QSE_STDOUT);
qse_xma_close (xma);
return 0;
@@ -140,20 +140,19 @@ static int test4 ()
x = qse_xma_alloc (xma, 10);
y = qse_xma_alloc (xma, 40);
}
- qse_xma_dump (xma, qse_printf);
+ qse_xma_dump (xma, (qse_xma_dumper_t)qse_fprintf, QSE_STDOUT);
qse_xma_close (xma);
return 0;
}
static int test5 ()
{
- int i;
void* ptr[100];
qse_mmgr_t xmammgr =
{
- qse_xma_alloc,
- qse_xma_realloc,
- qse_xma_free,
+ (qse_mmgr_alloc_t)qse_xma_alloc,
+ (qse_mmgr_realloc_t)qse_xma_realloc,
+ (qse_mmgr_free_t)qse_xma_free,
QSE_NULL
};
@@ -189,13 +188,15 @@ static int test5 ()
qse_xma_alloc (xma3, 8);
qse_xma_realloc (xma3, ptr[0], 40000);
- qse_xma_dump (xma3, qse_printf);
- qse_xma_dump (xma2, qse_printf);
- qse_xma_dump (xma1, qse_printf);
+ qse_xma_dump (xma3, (qse_xma_dumper_t)qse_fprintf, QSE_STDOUT);
+ qse_xma_dump (xma2, (qse_xma_dumper_t)qse_fprintf, QSE_STDOUT);
+ qse_xma_dump (xma1, (qse_xma_dumper_t)qse_fprintf, QSE_STDOUT);
qse_xma_close (xma3);
qse_xma_close (xma2);
qse_xma_close (xma1);
+
+ return 0;
}
int main ()