added open-addressed hash table

This commit is contained in:
hyung-hwan 2010-09-08 04:57:43 +00:00
parent af72767aa5
commit 95e975f514
14 changed files with 719 additions and 60 deletions

View File

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

View File

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

View File

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

194
qse/include/qse/cmn/oht.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
/** @file
* This file provides the open-addressed hash table for fixed-size data.
*/
#ifndef _QSE_OHT_T_
#define _QSE_OHT_T_
#include <qse/types.h>
#include <qse/macros.h>
#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

View File

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

View File

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

View File

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

View File

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

322
qse/lib/cmn/oht.c Normal file
View File

@ -0,0 +1,322 @@
#include <qse/cmn/oht.h>
#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;
}
}
}

View File

@ -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("<XMA DUMP>\n"));
dumper (target, QSE_T("<XMA DUMP>\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);

View File

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

View File

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

127
qse/samples/cmn/oht.c Normal file
View File

@ -0,0 +1,127 @@
#include <qse/cmn/mem.h>
#include <qse/cmn/str.h>
#include <qse/cmn/oht.h>
#include <qse/cmn/stdio.h>
#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;
}

View File

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