added another new hash table implementation based on fr
This commit is contained in:
parent
02f3adf134
commit
5db7ddc770
@ -380,7 +380,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
@ -619,7 +618,7 @@ distdir: $(DISTFILES)
|
|||||||
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
|
||||||
|| chmod -R a+r "$(distdir)"
|
|| chmod -R a+r "$(distdir)"
|
||||||
dist-gzip: distdir
|
dist-gzip: distdir
|
||||||
tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
|
tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz
|
||||||
$(am__post_remove_distdir)
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
dist-bzip2: distdir
|
dist-bzip2: distdir
|
||||||
@ -645,7 +644,7 @@ dist-shar: distdir
|
|||||||
@echo WARNING: "Support for shar distribution archives is" \
|
@echo WARNING: "Support for shar distribution archives is" \
|
||||||
"deprecated." >&2
|
"deprecated." >&2
|
||||||
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
|
||||||
shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
|
shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz
|
||||||
$(am__post_remove_distdir)
|
$(am__post_remove_distdir)
|
||||||
|
|
||||||
dist-zip: distdir
|
dist-zip: distdir
|
||||||
@ -663,7 +662,7 @@ dist dist-all:
|
|||||||
distcheck: dist
|
distcheck: dist
|
||||||
case '$(DIST_ARCHIVES)' in \
|
case '$(DIST_ARCHIVES)' in \
|
||||||
*.tar.gz*) \
|
*.tar.gz*) \
|
||||||
GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
|
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\
|
||||||
*.tar.bz2*) \
|
*.tar.bz2*) \
|
||||||
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
|
bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
|
||||||
*.tar.lz*) \
|
*.tar.lz*) \
|
||||||
@ -673,7 +672,7 @@ distcheck: dist
|
|||||||
*.tar.Z*) \
|
*.tar.Z*) \
|
||||||
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
|
||||||
*.shar.gz*) \
|
*.shar.gz*) \
|
||||||
GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
|
eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\
|
||||||
*.zip*) \
|
*.zip*) \
|
||||||
unzip $(distdir).zip ;;\
|
unzip $(distdir).zip ;;\
|
||||||
esac
|
esac
|
||||||
|
@ -355,7 +355,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -362,7 +362,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -388,7 +388,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -353,7 +353,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -353,7 +353,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
14
qse/configure
vendored
14
qse/configure
vendored
@ -821,7 +821,6 @@ infodir
|
|||||||
docdir
|
docdir
|
||||||
oldincludedir
|
oldincludedir
|
||||||
includedir
|
includedir
|
||||||
runstatedir
|
|
||||||
localstatedir
|
localstatedir
|
||||||
sharedstatedir
|
sharedstatedir
|
||||||
sysconfdir
|
sysconfdir
|
||||||
@ -924,7 +923,6 @@ datadir='${datarootdir}'
|
|||||||
sysconfdir='${prefix}/etc'
|
sysconfdir='${prefix}/etc'
|
||||||
sharedstatedir='${prefix}/com'
|
sharedstatedir='${prefix}/com'
|
||||||
localstatedir='${prefix}/var'
|
localstatedir='${prefix}/var'
|
||||||
runstatedir='${localstatedir}/run'
|
|
||||||
includedir='${prefix}/include'
|
includedir='${prefix}/include'
|
||||||
oldincludedir='/usr/include'
|
oldincludedir='/usr/include'
|
||||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||||
@ -1177,15 +1175,6 @@ do
|
|||||||
| -silent | --silent | --silen | --sile | --sil)
|
| -silent | --silent | --silen | --sile | --sil)
|
||||||
silent=yes ;;
|
silent=yes ;;
|
||||||
|
|
||||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
|
||||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
|
||||||
| --run | --ru | --r)
|
|
||||||
ac_prev=runstatedir ;;
|
|
||||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
|
||||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
|
||||||
| --run=* | --ru=* | --r=*)
|
|
||||||
runstatedir=$ac_optarg ;;
|
|
||||||
|
|
||||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||||
ac_prev=sbindir ;;
|
ac_prev=sbindir ;;
|
||||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||||
@ -1323,7 +1312,7 @@ fi
|
|||||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||||
libdir localedir mandir runstatedir
|
libdir localedir mandir
|
||||||
do
|
do
|
||||||
eval ac_val=\$$ac_var
|
eval ac_val=\$$ac_var
|
||||||
# Remove trailing slashes.
|
# Remove trailing slashes.
|
||||||
@ -1476,7 +1465,6 @@ Fine tuning of the installation directories:
|
|||||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
|
||||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||||
--includedir=DIR C header files [PREFIX/include]
|
--includedir=DIR C header files [PREFIX/include]
|
||||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||||
|
@ -298,7 +298,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -356,7 +356,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -396,7 +396,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -347,7 +347,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -12,6 +12,7 @@ pkginclude_HEADERS = \
|
|||||||
fmt.h \
|
fmt.h \
|
||||||
gdl.h \
|
gdl.h \
|
||||||
htb.h \
|
htb.h \
|
||||||
|
htl.h \
|
||||||
hton.h \
|
hton.h \
|
||||||
hwad.h \
|
hwad.h \
|
||||||
ipad.h \
|
ipad.h \
|
||||||
|
@ -133,13 +133,13 @@ am__can_run_installinfo = \
|
|||||||
*) (install-info --version) >/dev/null 2>&1;; \
|
*) (install-info --version) >/dev/null 2>&1;; \
|
||||||
esac
|
esac
|
||||||
am__pkginclude_HEADERS_DIST = alg.h arr.h chr.h cp949.h cp950.h dll.h \
|
am__pkginclude_HEADERS_DIST = alg.h arr.h chr.h cp949.h cp950.h dll.h \
|
||||||
env.h fma.h fmt.h gdl.h htb.h hton.h hwad.h ipad.h main.h \
|
env.h fma.h fmt.h gdl.h htb.h htl.h hton.h hwad.h ipad.h \
|
||||||
map.h mb8.h mbwc.h mem.h oht.h opt.h path.h pma.h rbt.h rex.h \
|
main.h map.h mb8.h mbwc.h mem.h oht.h opt.h path.h pma.h rbt.h \
|
||||||
sll.h slmb.h str.h time.h tmr.h tre.h uni.h uri.h utf8.h xma.h \
|
rex.h sll.h slmb.h str.h time.h tmr.h tre.h uni.h uri.h utf8.h \
|
||||||
Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp ScopedPtr.hpp \
|
xma.h Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \
|
||||||
SharedPtr.hpp StrBase.hpp String.hpp Mpool.hpp Association.hpp \
|
ScopedPtr.hpp SharedPtr.hpp StrBase.hpp String.hpp Mpool.hpp \
|
||||||
LinkedList.hpp HashList.hpp HashTable.hpp RedBlackTree.hpp \
|
Association.hpp LinkedList.hpp HashList.hpp HashTable.hpp \
|
||||||
RedBlackTable.hpp Array.hpp BinaryHeap.hpp
|
RedBlackTree.hpp RedBlackTable.hpp Array.hpp BinaryHeap.hpp
|
||||||
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
|
||||||
am__vpath_adj = case $$p in \
|
am__vpath_adj = case $$p in \
|
||||||
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
|
||||||
@ -361,7 +361,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
@ -373,9 +372,9 @@ top_build_prefix = @top_build_prefix@
|
|||||||
top_builddir = @top_builddir@
|
top_builddir = @top_builddir@
|
||||||
top_srcdir = @top_srcdir@
|
top_srcdir = @top_srcdir@
|
||||||
pkginclude_HEADERS = alg.h arr.h chr.h cp949.h cp950.h dll.h env.h \
|
pkginclude_HEADERS = alg.h arr.h chr.h cp949.h cp950.h dll.h env.h \
|
||||||
fma.h fmt.h gdl.h htb.h hton.h hwad.h ipad.h main.h map.h \
|
fma.h fmt.h gdl.h htb.h htl.h hton.h hwad.h ipad.h main.h \
|
||||||
mb8.h mbwc.h mem.h oht.h opt.h path.h pma.h rbt.h rex.h sll.h \
|
map.h mb8.h mbwc.h mem.h oht.h opt.h path.h pma.h rbt.h rex.h \
|
||||||
slmb.h str.h time.h tmr.h tre.h uni.h uri.h utf8.h xma.h \
|
sll.h slmb.h str.h time.h tmr.h tre.h uni.h uri.h utf8.h xma.h \
|
||||||
$(am__append_1)
|
$(am__append_1)
|
||||||
all: all-am
|
all: all-am
|
||||||
|
|
||||||
|
302
qse/include/qse/cmn/htl.h
Normal file
302
qse/include/qse/cmn/htl.h
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
/*
|
||||||
|
* $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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _QSE_HTL_T_
|
||||||
|
#define _QSE_HTL_T_
|
||||||
|
|
||||||
|
/** \file
|
||||||
|
* This file provides the hash table for fixed-size data.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <qse/types.h>
|
||||||
|
#include <qse/macros.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The #qse_htl_walk_t type defines walking directions.
|
||||||
|
*/
|
||||||
|
enum qse_htl_walk_t
|
||||||
|
{
|
||||||
|
QSE_HTL_WALK_STOP = 0,
|
||||||
|
QSE_HTL_WALK_FORWARD = 1,
|
||||||
|
};
|
||||||
|
typedef enum qse_htl_walk_t qse_htl_walk_t;
|
||||||
|
|
||||||
|
typedef struct qse_htl_t qse_htl_t;
|
||||||
|
typedef struct qse_htl_node_t qse_htl_node_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The #qse_htl_hasher_t type defines a data hasher function.
|
||||||
|
*/
|
||||||
|
typedef qse_size_t (*qse_htl_hasher_t) (
|
||||||
|
qse_htl_t* htl,
|
||||||
|
const void* data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The #qse_htl_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_htl_comper_t) (
|
||||||
|
qse_htl_t* htl, /**< hash table */
|
||||||
|
const void* data1, /**< data pointer */
|
||||||
|
const void* data2 /**< data pointer */
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The #qse_htl_feeeer_t type defines a data deallocation function.
|
||||||
|
*/
|
||||||
|
typedef void (*qse_htl_freeer_t) (
|
||||||
|
qse_htl_t* htl,
|
||||||
|
void* data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The #qse_htl_copier_t type defines a data copier function.
|
||||||
|
*/
|
||||||
|
typedef void* (*qse_htl_copier_t) (
|
||||||
|
qse_htl_t* htl,
|
||||||
|
void* data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The #qse_htl_walker_t function defines a callback function
|
||||||
|
* for qse_htl_walk().
|
||||||
|
*/
|
||||||
|
typedef qse_htl_walk_t (*qse_htl_walker_t) (
|
||||||
|
qse_htl_t* htl,
|
||||||
|
void* data,
|
||||||
|
void* ctx
|
||||||
|
);
|
||||||
|
|
||||||
|
struct qse_htl_node_t
|
||||||
|
{
|
||||||
|
struct qse_htl_node_t* next;
|
||||||
|
qse_uint32_t reversed;
|
||||||
|
qse_uint32_t key;
|
||||||
|
void* data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct qse_htl_t
|
||||||
|
{
|
||||||
|
qse_mmgr_t* mmgr;
|
||||||
|
|
||||||
|
int keysize; /* default key size */
|
||||||
|
|
||||||
|
int num_elements;
|
||||||
|
int num_buckets; /* power of 2 */
|
||||||
|
int next_grow;
|
||||||
|
int mask;
|
||||||
|
|
||||||
|
qse_htl_hasher_t hasher;
|
||||||
|
qse_htl_comper_t comper;
|
||||||
|
qse_htl_freeer_t freeer;
|
||||||
|
qse_htl_copier_t copier;
|
||||||
|
|
||||||
|
qse_htl_node_t null;
|
||||||
|
qse_htl_node_t** buckets;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_htl_open() function creates an hash table.
|
||||||
|
*/
|
||||||
|
QSE_EXPORT qse_htl_t* qse_htl_open (
|
||||||
|
qse_mmgr_t* mmgr,
|
||||||
|
qse_size_t xtnsize,
|
||||||
|
int scale
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_htl_close() function destroys an hash table.
|
||||||
|
*/
|
||||||
|
QSE_EXPORT void qse_htl_close (
|
||||||
|
qse_htl_t* htl /**< hash table */
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_htl_open() function initializes an hash table.
|
||||||
|
*/
|
||||||
|
QSE_EXPORT int qse_htl_init (
|
||||||
|
qse_htl_t* htl,
|
||||||
|
qse_mmgr_t* mmgr,
|
||||||
|
int scale
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_htl_close() function finalizes an hash table.
|
||||||
|
*/
|
||||||
|
QSE_EXPORT void qse_htl_fini (
|
||||||
|
qse_htl_t* htl /**< hash table */
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(QSE_HAVE_INLINE)
|
||||||
|
static QSE_INLINE qse_mmgr_t* qse_htl_getmmgr (qse_htl_t* htl) { return (htl)->mmgr; }
|
||||||
|
#else
|
||||||
|
#define qse_htl_getmmgr(htl) ((htl)->mmgr))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(QSE_HAVE_INLINE)
|
||||||
|
static QSE_INLINE void* qse_htl_getxtn (qse_htl_t* htl) { return QSE_XTN(htl); }
|
||||||
|
#else
|
||||||
|
#define qse_htl_getxtn(htl) (QSE_XTN(htl))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(QSE_HAVE_INLINE)
|
||||||
|
static QSE_INLINE int qse_htl_getsize (qse_htl_t* htl) { return htl->num_elements; }
|
||||||
|
#else
|
||||||
|
#define qse_htl_getsize(htl) ((htl)->num_elements)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(QSE_HAVE_INLINE)
|
||||||
|
static QSE_INLINE qse_htl_hasher_t qse_htl_gethasher (qse_htl_t* htl) { return htl->hasher; }
|
||||||
|
static QSE_INLINE qse_htl_comper_t qse_htl_getcomper (qse_htl_t* htl) { return htl->comper; }
|
||||||
|
static QSE_INLINE qse_htl_freeer_t qse_htl_getfreeer (qse_htl_t* htl) { return htl->freeer; }
|
||||||
|
|
||||||
|
static QSE_INLINE void qse_htl_sethasher (qse_htl_t* htl, qse_htl_hasher_t _hasher) { htl->hasher = _hasher; }
|
||||||
|
static QSE_INLINE void qse_htl_setcomper (qse_htl_t* htl, qse_htl_comper_t _comper) { htl->comper = _comper; }
|
||||||
|
static QSE_INLINE void qse_htl_setfreeer (qse_htl_t* htl, qse_htl_freeer_t _freeer) { htl->freeer = _freeer; }
|
||||||
|
static QSE_INLINE void qse_htl_setcopier (qse_htl_t* htl, qse_htl_copier_t _copier) { htl->copier = _copier; }
|
||||||
|
#else
|
||||||
|
#define qse_htl_gethasher(htl) ((htl)->hasher)
|
||||||
|
#define qse_htl_getcomper(htl) ((htl)->comper)
|
||||||
|
#define qse_htl_getfreeer(htl) ((htl)->freeer)
|
||||||
|
|
||||||
|
#define qse_htl_sethasher(htl,_hahser) ((htl)->hasher = _hasher)
|
||||||
|
#define qse_htl_setcomper(htl,_comper) ((htl)->comper = _comper)
|
||||||
|
#define qse_htl_setfreeer(htl,_freeer) ((htl)->freeer = _freeer)
|
||||||
|
#define qse_htl_setcopier(htl,_copier) ((htl)->copier = _copier)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_htl_search() function searches a hash table to find a
|
||||||
|
* matching datum. It returns the index to the slot of an internal array
|
||||||
|
* where the matching datum is found.
|
||||||
|
* \return slot index if a match if found,
|
||||||
|
* #QSE_HTL_NIL if no match is found.
|
||||||
|
*/
|
||||||
|
QSE_EXPORT qse_htl_node_t* qse_htl_search (
|
||||||
|
qse_htl_t* htl, /**< hash table */
|
||||||
|
void* data /**< data pointer */
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_htl_insert() function inserts a new datum. It fails if it finds
|
||||||
|
* an existing datum.
|
||||||
|
* \return slot index where the new datum is inserted on success,
|
||||||
|
* #QSE_HTL_NIL on failure.
|
||||||
|
*/
|
||||||
|
QSE_EXPORT qse_htl_node_t* qse_htl_insert (
|
||||||
|
qse_htl_t* htl, /**< hash table */
|
||||||
|
void* data /**< data pointer */
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_htl_upsert() function inserts a new datum if it finds no matching
|
||||||
|
* datum or updates an exsting datum if finds a matching datum.
|
||||||
|
* \return slot index where the datum is inserted or updated.
|
||||||
|
*/
|
||||||
|
QSE_EXPORT qse_htl_node_t* qse_htl_upsert (
|
||||||
|
qse_htl_t* htl, /**< hash table */
|
||||||
|
void* data /**< data pointer */
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_htl_update() function updates an existing datum. It fails if it finds
|
||||||
|
* no existing datum.
|
||||||
|
* \return slot index where an existing datum is updated on success,
|
||||||
|
* #QSE_HTL_NIL on failure.
|
||||||
|
*/
|
||||||
|
QSE_EXPORT qse_htl_node_t* qse_htl_update (
|
||||||
|
qse_htl_t* htl, /**< hash table */
|
||||||
|
void* data /**< data pointer */
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_htl_ensert() function inserts a new item if one is not found.
|
||||||
|
* It returns an existing item otherwise.
|
||||||
|
*/
|
||||||
|
QSE_EXPORT qse_htl_node_t* qse_htl_ensert (
|
||||||
|
qse_htl_t* htl, /**< hash table */
|
||||||
|
void* data /**< data pointer */
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_htl_delete() function deletes an existing datum. It fails if it finds
|
||||||
|
* no existing datum.
|
||||||
|
* \return 0 on success, -1 on failure
|
||||||
|
*/
|
||||||
|
QSE_EXPORT int qse_htl_delete (
|
||||||
|
qse_htl_t* htl, /**< hash table */
|
||||||
|
void* data /**< data pointer */
|
||||||
|
);
|
||||||
|
|
||||||
|
QSE_EXPORT void* qse_htl_yank (
|
||||||
|
qse_htl_t* ht,
|
||||||
|
void* data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_htl_clear() functions deletes all data items.
|
||||||
|
*/
|
||||||
|
QSE_EXPORT void qse_htl_clear (
|
||||||
|
qse_htl_t* htl /**< hash table */
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_htl_walk() function executes the callback function @a walker for
|
||||||
|
* each valid data item.
|
||||||
|
*/
|
||||||
|
QSE_EXPORT void qse_htl_walk (
|
||||||
|
qse_htl_t* htl, /**< hash table */
|
||||||
|
qse_htl_walker_t walker, /**< callback function */
|
||||||
|
void* ctx /**< context */
|
||||||
|
);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
QSE_EXPORT qse_uint32_t qse_genhash_update (const void* data, qse_size_t size, qse_uint32_t hash);
|
||||||
|
QSE_EXPORT qse_uint32_t qse_genhash (const void *data, qse_size_t size);
|
||||||
|
/*qse_uint32_t qse_foldhash (qse_uint32_t hash, int bits);*/
|
||||||
|
|
||||||
|
QSE_EXPORT qse_uint32_t qse_mbshash (const qse_mchar_t* p);
|
||||||
|
QSE_EXPORT qse_uint32_t qse_wcshash (const qse_wchar_t* p);
|
||||||
|
|
||||||
|
#if defined(QSE_CHAR_IS_WCHAR)
|
||||||
|
# define qse_strhash(x) qse_wcshash (x)
|
||||||
|
#else
|
||||||
|
# define qse_strhash(x) qse_mbshash (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -345,7 +345,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -345,7 +345,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -345,7 +345,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -46,16 +46,52 @@
|
|||||||
#define QSE_RAD_ATTR_TYPE_COMBO_IP 13
|
#define QSE_RAD_ATTR_TYPE_COMBO_IP 13
|
||||||
#define QSE_RAD_ATTR_TYPE_TLV 14
|
#define QSE_RAD_ATTR_TYPE_TLV 14
|
||||||
|
|
||||||
|
struct qse_raddic_attr_flags_t
|
||||||
|
{
|
||||||
|
unsigned int addport : 1; /* add NAS-Port to IP address */
|
||||||
|
unsigned int has_tag : 1; /* tagged attribute */
|
||||||
|
unsigned int do_xlat : 1; /* strvalue is dynamic */
|
||||||
|
unsigned int unknown_attr : 1; /* not in dictionary */
|
||||||
|
unsigned int array : 1; /* pack multiples into 1 attr */
|
||||||
|
unsigned int has_value : 1; /* has a value */
|
||||||
|
unsigned int has_value_alias : 1; /* has a value alias */
|
||||||
|
unsigned int has_tlv : 1; /* has sub attributes */
|
||||||
|
unsigned int is_tlv : 1; /* is a sub attribute */
|
||||||
|
unsigned int encoded : 1; /* has been put into packet */
|
||||||
|
qse_int8_t tag; /* tag for tunneled attributes */
|
||||||
|
qse_uint8_t encrypt; /* encryption method */
|
||||||
|
};
|
||||||
|
typedef struct qse_raddic_attr_flags_t qse_raddic_attr_flags_t;
|
||||||
|
|
||||||
struct qse_raddic_attr_t
|
struct qse_raddic_attr_t
|
||||||
{
|
{
|
||||||
int attr;
|
int attr;
|
||||||
int type;
|
int type;
|
||||||
int vendor;
|
int vendor;
|
||||||
/* ATTR_FLAGS flags;*/
|
qse_raddic_attr_flags_t flags;
|
||||||
char name[1];
|
qse_char_t name[1];
|
||||||
};
|
};
|
||||||
typedef struct qse_raddic_attr_t qse_raddic_attr_t;
|
typedef struct qse_raddic_attr_t qse_raddic_attr_t;
|
||||||
|
|
||||||
|
|
||||||
|
struct qse_raddic_value_t
|
||||||
|
{
|
||||||
|
int attr;
|
||||||
|
int value;
|
||||||
|
qse_char_t name[1];
|
||||||
|
};
|
||||||
|
typedef struct qse_raddic_value_t qse_raddic_value_t;
|
||||||
|
|
||||||
|
struct qse_raddic_vendor_t
|
||||||
|
{
|
||||||
|
int vendorpec;
|
||||||
|
int type;
|
||||||
|
int length;
|
||||||
|
int flags;
|
||||||
|
qse_char_t name[1];
|
||||||
|
};
|
||||||
|
typedef struct qse_raddic_vendor_t qse_raddic_vendor_t;
|
||||||
|
|
||||||
typedef struct qse_raddic_t qse_raddic_t;
|
typedef struct qse_raddic_t qse_raddic_t;
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
|
@ -347,7 +347,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -29,25 +29,39 @@
|
|||||||
|
|
||||||
#include <qse/Types.hpp>
|
#include <qse/Types.hpp>
|
||||||
#include <qse/Uncopyable.hpp>
|
#include <qse/Uncopyable.hpp>
|
||||||
|
#include <qse/cmn/Mmged.hpp>
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
QSE_BEGIN_NAMESPACE(QSE)
|
QSE_BEGIN_NAMESPACE(QSE)
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
|
||||||
class AppRoot: QSE::Uncopyable
|
class AppRoot: Uncopyable, public Types, public Mmged
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AppRoot (): _root_only (false) {}
|
AppRoot (Mmgr* mmgr): Mmged(mmgr), _root_only(false) {}
|
||||||
virtual ~AppRoot () {}
|
virtual ~AppRoot () {}
|
||||||
|
|
||||||
int daemonize (bool chdir_to_root = true, int fork_count = 1) QSE_CPP_NOEXCEPT;
|
int daemonize (bool chdir_to_root = true, int fork_count = 1) QSE_CPP_NOEXCEPT;
|
||||||
|
|
||||||
static int chroot (const qse_wchar_t* wpath) QSE_CPP_NOEXCEPT;
|
int chroot (const qse_mchar_t* mpath) QSE_CPP_NOEXCEPT;
|
||||||
static int chroot (const qse_mchar_t* mpath) QSE_CPP_NOEXCEPT;
|
int chroot (const qse_wchar_t* wpath) QSE_CPP_NOEXCEPT;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int switchUser (uid_t uid, gid_t gid, bool permanently) QSE_CPP_NOEXCEPT;
|
||||||
|
int restoreUser () QSE_CPP_NOEXCEPT;
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool _root_only;
|
bool _root_only;
|
||||||
|
#if 0
|
||||||
|
uid_t saved_uid;
|
||||||
|
gid_t saved_gid;
|
||||||
|
gid_t saved_groups[NGROUPS_MAX];
|
||||||
|
qse_size_t saved_ngroups;
|
||||||
|
|
||||||
void on_signal () QSE_CPP_NOEXCEPT;
|
void on_signal () QSE_CPP_NOEXCEPT;
|
||||||
|
void on_signal () QSE_CPP_NOEXCEPT;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
|
@ -354,7 +354,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -278,6 +278,18 @@ QSE_EXPORT void qse_log_fini (
|
|||||||
qse_log_t* log
|
qse_log_t* log
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#if defined(QSE_HAVE_INLINE)
|
||||||
|
static QSE_INLINE qse_mmgr_t* qse_log_getmmgr (qse_log_t* log) { return (log)->mmgr; }
|
||||||
|
#else
|
||||||
|
#define qse_log_getmmgr(log) ((log)->mmgr))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(QSE_HAVE_INLINE)
|
||||||
|
static QSE_INLINE void* qse_log_getxtn (qse_log_t* log) { return QSE_XTN(log); }
|
||||||
|
#else
|
||||||
|
#define qse_log_getxtn(log) (QSE_XTN(log))
|
||||||
|
#endif
|
||||||
|
|
||||||
QSE_EXPORT void qse_log_setident (
|
QSE_EXPORT void qse_log_setident (
|
||||||
qse_log_t* log,
|
qse_log_t* log,
|
||||||
const qse_char_t* ident
|
const qse_char_t* ident
|
||||||
|
@ -345,7 +345,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -390,7 +390,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -546,7 +546,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -43,6 +43,7 @@ libqsecmn_la_SOURCES = \
|
|||||||
env.c \
|
env.c \
|
||||||
gdl.c \
|
gdl.c \
|
||||||
htb.c \
|
htb.c \
|
||||||
|
htl.c \
|
||||||
fma.c \
|
fma.c \
|
||||||
fmt-intmax.c \
|
fmt-intmax.c \
|
||||||
fmt-out.c \
|
fmt-out.c \
|
||||||
|
@ -143,8 +143,8 @@ am__DEPENDENCIES_1 =
|
|||||||
libqsecmn_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
|
libqsecmn_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
|
||||||
$(am__DEPENDENCIES_1)
|
$(am__DEPENDENCIES_1)
|
||||||
am__libqsecmn_la_SOURCES_DIST = alg-base64.c alg-rand.c alg-search.c \
|
am__libqsecmn_la_SOURCES_DIST = alg-base64.c alg-rand.c alg-search.c \
|
||||||
alg-sort.c arr.c assert.c chr.c dll.c env.c gdl.c htb.c fma.c \
|
alg-sort.c arr.c assert.c chr.c dll.c env.c gdl.c htb.c htl.c \
|
||||||
fmt-intmax.c fmt-out.c hton.c hwad.c ipad.c main.c mb8.c \
|
fma.c fmt-intmax.c fmt-out.c hton.c hwad.c ipad.c main.c mb8.c \
|
||||||
mbwc.c mbwc-str.c mem.c oht.c opt.c path-base.c path-canon.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 \
|
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-beg.c str-cat.c str-chr.c str-cnv.c str-cmp.c str-cpy.c \
|
||||||
@ -159,19 +159,19 @@ am__libqsecmn_la_SOURCES_DIST = alg-base64.c alg-rand.c alg-search.c \
|
|||||||
@ENABLE_XCMGRS_TRUE@am__objects_2 = cp949.lo cp950.lo
|
@ENABLE_XCMGRS_TRUE@am__objects_2 = cp949.lo cp950.lo
|
||||||
am_libqsecmn_la_OBJECTS = alg-base64.lo alg-rand.lo alg-search.lo \
|
am_libqsecmn_la_OBJECTS = alg-base64.lo alg-rand.lo alg-search.lo \
|
||||||
alg-sort.lo arr.lo assert.lo chr.lo dll.lo env.lo gdl.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 hwad.lo ipad.lo \
|
htb.lo htl.lo fma.lo fmt-intmax.lo fmt-out.lo hton.lo hwad.lo \
|
||||||
main.lo mb8.lo mbwc.lo mbwc-str.lo mem.lo oht.lo opt.lo \
|
ipad.lo main.lo mb8.lo mbwc.lo mbwc-str.lo mem.lo oht.lo \
|
||||||
path-base.lo path-canon.lo path-core.lo path-merge.lo pma.lo \
|
opt.lo path-base.lo path-canon.lo path-core.lo path-merge.lo \
|
||||||
rbt.lo rex.lo sll.lo slmb.lo str-beg.lo str-cat.lo str-chr.lo \
|
pma.lo rbt.lo rex.lo sll.lo slmb.lo str-beg.lo str-cat.lo \
|
||||||
str-cnv.lo str-cmp.lo str-cpy.lo str-del.lo str-dup.lo \
|
str-chr.lo str-cnv.lo str-cmp.lo str-cpy.lo str-del.lo \
|
||||||
str-dyn.lo str-end.lo str-excl.lo str-fcpy.lo str-fmt.lo \
|
str-dup.lo str-dyn.lo str-end.lo str-excl.lo str-fcpy.lo \
|
||||||
str-fnmat.lo str-incl.lo str-join.lo str-len.lo str-pac.lo \
|
str-fmt.lo str-fnmat.lo str-incl.lo str-join.lo str-len.lo \
|
||||||
str-pbrk.lo str-put.lo str-rev.lo str-rot.lo str-set.lo \
|
str-pac.lo str-pbrk.lo str-put.lo str-rev.lo str-rot.lo \
|
||||||
str-spl.lo str-spn.lo str-str.lo str-subst.lo str-tok.lo \
|
str-set.lo str-spl.lo str-spn.lo str-str.lo str-subst.lo \
|
||||||
str-trm.lo str-word.lo time.lo tmr.lo tre.lo tre-ast.lo \
|
str-tok.lo str-trm.lo str-word.lo time.lo tmr.lo tre.lo \
|
||||||
tre-compile.lo tre-match-bt.lo tre-match-pa.lo tre-parse.lo \
|
tre-ast.lo tre-compile.lo tre-match-bt.lo tre-match-pa.lo \
|
||||||
tre-stack.lo uri.lo utf8.lo xma.lo $(am__objects_1) \
|
tre-parse.lo tre-stack.lo uri.lo utf8.lo xma.lo \
|
||||||
$(am__objects_2)
|
$(am__objects_1) $(am__objects_2)
|
||||||
libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS)
|
libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS)
|
||||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||||
@ -443,7 +443,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
@ -486,7 +485,7 @@ noinst_HEADERS = \
|
|||||||
va_copy.h
|
va_copy.h
|
||||||
|
|
||||||
libqsecmn_la_SOURCES = alg-base64.c alg-rand.c alg-search.c alg-sort.c \
|
libqsecmn_la_SOURCES = alg-base64.c alg-rand.c alg-search.c alg-sort.c \
|
||||||
arr.c assert.c chr.c dll.c env.c gdl.c htb.c fma.c \
|
arr.c assert.c chr.c dll.c env.c gdl.c htb.c htl.c fma.c \
|
||||||
fmt-intmax.c fmt-out.c hton.c hwad.c ipad.c main.c mb8.c \
|
fmt-intmax.c fmt-out.c hton.c hwad.c ipad.c main.c mb8.c \
|
||||||
mbwc.c mbwc-str.c mem.c oht.c opt.c path-base.c path-canon.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 \
|
path-core.c path-merge.c pma.c rbt.c rex.c sll.c slmb.c \
|
||||||
@ -608,6 +607,7 @@ distclean-compile:
|
|||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmt-out.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fmt-out.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gdl.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gdl.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb.Plo@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htl.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hton.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hton.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hwad.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hwad.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipad.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipad.Plo@am__quote@
|
||||||
|
856
qse/lib/cmn/htl.c
Normal file
856
qse/lib/cmn/htl.c
Normal file
@ -0,0 +1,856 @@
|
|||||||
|
/*
|
||||||
|
* $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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hash.c Non-thread-safe split-ordered hash table.
|
||||||
|
*
|
||||||
|
* The weird "reverse" function is based on an idea from
|
||||||
|
* "Split-Ordered Lists - Lock-free Resizable Hash Tables", with
|
||||||
|
* modifications so that they're not lock-free. :(
|
||||||
|
*
|
||||||
|
* However, the split-order idea allows a fast & easy splitting of the
|
||||||
|
* hash bucket chain when the hash table is resized. Without it, we'd
|
||||||
|
* have to check & update the pointers for every node in the buck chain,
|
||||||
|
* rather than being able to move 1/2 of the entries in the chain with
|
||||||
|
* one update.
|
||||||
|
*
|
||||||
|
* Version: $Id$
|
||||||
|
*
|
||||||
|
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*
|
||||||
|
* Copyright 2005,2006 The FreeRADIUS server project
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <qse/cmn/htl.h>
|
||||||
|
#include "mem-prv.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A reasonable number of buckets to start off with.
|
||||||
|
* Should be a power of two.
|
||||||
|
*/
|
||||||
|
#define QSE_HTL_NUM_BUCKETS (64)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* perl -e 'foreach $i (0..255) {$r = 0; foreach $j (0 .. 7 ) { if (($i & ( 1<< $j)) != 0) { $r |= (1 << (7 - $j));}} print $r, ", ";if (($i & 7) == 7) {print "\n";}}'
|
||||||
|
*/
|
||||||
|
static const qse_uint8_t reversed_byte[256] =
|
||||||
|
{
|
||||||
|
0, 128, 64, 192, 32, 160, 96, 224,
|
||||||
|
16, 144, 80, 208, 48, 176, 112, 240,
|
||||||
|
8, 136, 72, 200, 40, 168, 104, 232,
|
||||||
|
24, 152, 88, 216, 56, 184, 120, 248,
|
||||||
|
4, 132, 68, 196, 36, 164, 100, 228,
|
||||||
|
20, 148, 84, 212, 52, 180, 116, 244,
|
||||||
|
12, 140, 76, 204, 44, 172, 108, 236,
|
||||||
|
28, 156, 92, 220, 60, 188, 124, 252,
|
||||||
|
2, 130, 66, 194, 34, 162, 98, 226,
|
||||||
|
18, 146, 82, 210, 50, 178, 114, 242,
|
||||||
|
10, 138, 74, 202, 42, 170, 106, 234,
|
||||||
|
26, 154, 90, 218, 58, 186, 122, 250,
|
||||||
|
6, 134, 70, 198, 38, 166, 102, 230,
|
||||||
|
22, 150, 86, 214, 54, 182, 118, 246,
|
||||||
|
14, 142, 78, 206, 46, 174, 110, 238,
|
||||||
|
30, 158, 94, 222, 62, 190, 126, 254,
|
||||||
|
1, 129, 65, 193, 33, 161, 97, 225,
|
||||||
|
17, 145, 81, 209, 49, 177, 113, 241,
|
||||||
|
9, 137, 73, 201, 41, 169, 105, 233,
|
||||||
|
25, 153, 89, 217, 57, 185, 121, 249,
|
||||||
|
5, 133, 69, 197, 37, 165, 101, 229,
|
||||||
|
21, 149, 85, 213, 53, 181, 117, 245,
|
||||||
|
13, 141, 77, 205, 45, 173, 109, 237,
|
||||||
|
29, 157, 93, 221, 61, 189, 125, 253,
|
||||||
|
3, 131, 67, 195, 35, 163, 99, 227,
|
||||||
|
19, 147, 83, 211, 51, 179, 115, 243,
|
||||||
|
11, 139, 75, 203, 43, 171, 107, 235,
|
||||||
|
27, 155, 91, 219, 59, 187, 123, 251,
|
||||||
|
7, 135, 71, 199, 39, 167, 103, 231,
|
||||||
|
23, 151, 87, 215, 55, 183, 119, 247,
|
||||||
|
15, 143, 79, 207, 47, 175, 111, 239,
|
||||||
|
31, 159, 95, 223, 63, 191, 127, 255
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* perl -e 'foreach $i (0..255) {$r = 0;foreach $j (0 .. 7) { $r = $i & (1 << (7 - $j)); last if ($r)} print $i & ~($r), ", ";if (($i & 7) == 7) {print "\n";}}'
|
||||||
|
*/
|
||||||
|
static qse_uint8_t parent_byte[256] =
|
||||||
|
{
|
||||||
|
0, 0, 0, 1, 0, 1, 2, 3,
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7,
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7,
|
||||||
|
8, 9, 10, 11, 12, 13, 14, 15,
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7,
|
||||||
|
8, 9, 10, 11, 12, 13, 14, 15,
|
||||||
|
16, 17, 18, 19, 20, 21, 22, 23,
|
||||||
|
24, 25, 26, 27, 28, 29, 30, 31,
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7,
|
||||||
|
8, 9, 10, 11, 12, 13, 14, 15,
|
||||||
|
16, 17, 18, 19, 20, 21, 22, 23,
|
||||||
|
24, 25, 26, 27, 28, 29, 30, 31,
|
||||||
|
32, 33, 34, 35, 36, 37, 38, 39,
|
||||||
|
40, 41, 42, 43, 44, 45, 46, 47,
|
||||||
|
48, 49, 50, 51, 52, 53, 54, 55,
|
||||||
|
56, 57, 58, 59, 60, 61, 62, 63,
|
||||||
|
0, 1, 2, 3, 4, 5, 6, 7,
|
||||||
|
8, 9, 10, 11, 12, 13, 14, 15,
|
||||||
|
16, 17, 18, 19, 20, 21, 22, 23,
|
||||||
|
24, 25, 26, 27, 28, 29, 30, 31,
|
||||||
|
32, 33, 34, 35, 36, 37, 38, 39,
|
||||||
|
40, 41, 42, 43, 44, 45, 46, 47,
|
||||||
|
48, 49, 50, 51, 52, 53, 54, 55,
|
||||||
|
56, 57, 58, 59, 60, 61, 62, 63,
|
||||||
|
64, 65, 66, 67, 68, 69, 70, 71,
|
||||||
|
72, 73, 74, 75, 76, 77, 78, 79,
|
||||||
|
80, 81, 82, 83, 84, 85, 86, 87,
|
||||||
|
88, 89, 90, 91, 92, 93, 94, 95,
|
||||||
|
96, 97, 98, 99, 100, 101, 102, 103,
|
||||||
|
104, 105, 106, 107, 108, 109, 110, 111,
|
||||||
|
112, 113, 114, 115, 116, 117, 118, 119,
|
||||||
|
120, 121, 122, 123, 124, 125, 126, 127
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reverse a key.
|
||||||
|
*/
|
||||||
|
static qse_uint32_t reverse (qse_uint32_t key)
|
||||||
|
{
|
||||||
|
return ((reversed_byte[key & 0xff] << 24) |
|
||||||
|
(reversed_byte[(key >> 8) & 0xff] << 16) |
|
||||||
|
(reversed_byte[(key >> 16) & 0xff] << 8) |
|
||||||
|
(reversed_byte[(key >> 24) & 0xff]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Take the parent by discarding the highest bit that is set.
|
||||||
|
*/
|
||||||
|
static qse_uint32_t parent_of (qse_uint32_t key)
|
||||||
|
{
|
||||||
|
if (key > 0x00ffffff)
|
||||||
|
return (key & 0x00ffffff) | (parent_byte[key >> 24] << 24);
|
||||||
|
|
||||||
|
if (key > 0x0000ffff)
|
||||||
|
return (key & 0x0000ffff) | (parent_byte[key >> 16] << 16);
|
||||||
|
|
||||||
|
if (key > 0x000000ff)
|
||||||
|
return (key & 0x000000ff) | (parent_byte[key >> 8] << 8);
|
||||||
|
|
||||||
|
return parent_byte[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static qse_htl_node_t *list_find (qse_htl_t* ht, qse_htl_node_t* head, qse_uint32_t reversed, const void* data)
|
||||||
|
{
|
||||||
|
qse_htl_node_t *cur;
|
||||||
|
|
||||||
|
for (cur = head; cur != &ht->null; cur = cur->next)
|
||||||
|
{
|
||||||
|
if (cur->reversed == reversed)
|
||||||
|
{
|
||||||
|
if (ht->comper)
|
||||||
|
{
|
||||||
|
int cmp = ht->comper(ht, data, cur->data);
|
||||||
|
if (cmp > 0) break;
|
||||||
|
if (cmp < 0) continue;
|
||||||
|
}
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
if (cur->reversed > reversed) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inserts a new entry into the list, in order.
|
||||||
|
*/
|
||||||
|
static int list_insert (qse_htl_t* ht, qse_htl_node_t** head, qse_htl_node_t* node)
|
||||||
|
{
|
||||||
|
qse_htl_node_t **last, *cur;
|
||||||
|
|
||||||
|
last = head;
|
||||||
|
|
||||||
|
for (cur = *head; cur != &ht->null; cur = cur->next)
|
||||||
|
{
|
||||||
|
if (cur->reversed > node->reversed) break;
|
||||||
|
last = &(cur->next);
|
||||||
|
|
||||||
|
if (cur->reversed == node->reversed)
|
||||||
|
{
|
||||||
|
if (ht->comper)
|
||||||
|
{
|
||||||
|
int cmp = ht->comper(ht, node->data, cur->data);
|
||||||
|
if (cmp > 0) break;
|
||||||
|
if (cmp < 0) continue;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node->next = *last;
|
||||||
|
*last = node;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete an entry from the list.
|
||||||
|
*/
|
||||||
|
static int list_delete (qse_htl_t* ht, qse_htl_node_t** head, qse_htl_node_t* node)
|
||||||
|
{
|
||||||
|
qse_htl_node_t **last, *cur;
|
||||||
|
|
||||||
|
last = head;
|
||||||
|
|
||||||
|
for (cur = *head; cur != &ht->null; cur = cur->next)
|
||||||
|
{
|
||||||
|
if (cur == node) break;
|
||||||
|
last = &(cur->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
*last = node->next;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
static QSE_INLINE_ALWAYS qse_size_t default_hasher (qse_htl_t* htl, const void* data)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
qse_size_t h = 5381;
|
||||||
|
const qse_byte_t* p = (const qse_byte_t*)data;
|
||||||
|
const qse_byte_t* bound = p + htl->keysize;
|
||||||
|
while (p < bound) h = ((h << 5) + h) + *p++;
|
||||||
|
return h ;
|
||||||
|
#else
|
||||||
|
return qse_genhash (data, htl->keysize);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static QSE_INLINE_ALWAYS int default_comper (qse_htl_t* htl, const void* data1, const void* data2)
|
||||||
|
{
|
||||||
|
return QSE_MEMCMP(data1, data2, htl->keysize);
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_htl_t* qse_htl_open (qse_mmgr_t* mmgr, qse_size_t xtnsize, int keysize)
|
||||||
|
{
|
||||||
|
qse_htl_t* htl;
|
||||||
|
|
||||||
|
htl = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(qse_htl_t) + xtnsize);
|
||||||
|
if (htl == QSE_NULL) return QSE_NULL;
|
||||||
|
|
||||||
|
if (qse_htl_init (htl, mmgr, keysize) <= -1)
|
||||||
|
{
|
||||||
|
QSE_MMGR_FREE (mmgr, htl);
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_MEMSET (htl + 1, 0, xtnsize);
|
||||||
|
return htl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qse_htl_close (qse_htl_t* htl)
|
||||||
|
{
|
||||||
|
qse_htl_fini (htl);
|
||||||
|
QSE_MMGR_FREE (htl->mmgr, htl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the table.
|
||||||
|
*
|
||||||
|
* Memory usage in bytes is (20/3) * number of entries.
|
||||||
|
*/
|
||||||
|
int qse_htl_init (qse_htl_t* ht, qse_mmgr_t* mmgr, int keysize)
|
||||||
|
{
|
||||||
|
QSE_MEMSET (ht, 0, sizeof(*ht));
|
||||||
|
ht->mmgr = mmgr;
|
||||||
|
ht->keysize = keysize;
|
||||||
|
|
||||||
|
ht->hasher = default_hasher;
|
||||||
|
ht->comper = default_comper;
|
||||||
|
ht->freeer = QSE_NULL;
|
||||||
|
ht->copier = QSE_NULL;
|
||||||
|
ht->num_buckets = QSE_HTL_NUM_BUCKETS;
|
||||||
|
ht->mask = ht->num_buckets - 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Have a default load factor of 2.5. In practice this
|
||||||
|
* means that the average load will hit 3 before the
|
||||||
|
* table grows.
|
||||||
|
*/
|
||||||
|
ht->next_grow = (ht->num_buckets << 1) + (ht->num_buckets >> 1);
|
||||||
|
|
||||||
|
ht->buckets = QSE_MMGR_ALLOC (ht->mmgr, QSE_SIZEOF(*ht->buckets) * ht->num_buckets);
|
||||||
|
if (!ht->buckets) return -1;
|
||||||
|
|
||||||
|
QSE_MEMSET (ht->buckets, 0, sizeof(*ht->buckets) * ht->num_buckets);
|
||||||
|
|
||||||
|
ht->null.reversed = ~0;
|
||||||
|
ht->null.key = ~0;
|
||||||
|
ht->null.next = &ht->null;
|
||||||
|
|
||||||
|
ht->buckets[0] = &ht->null;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qse_htl_fini (qse_htl_t* ht)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
qse_htl_node_t *node, *next;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk over the buckets, freeing them all.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < ht->num_buckets; i++)
|
||||||
|
{
|
||||||
|
if (ht->buckets[i])
|
||||||
|
{
|
||||||
|
for (node = ht->buckets[i]; node != &ht->null; node = next)
|
||||||
|
{
|
||||||
|
next = node->next;
|
||||||
|
|
||||||
|
if (!node->data) continue; /* dummy entry */
|
||||||
|
|
||||||
|
if (ht->freeer) ht->freeer (ht, node->data);
|
||||||
|
QSE_MMGR_FREE (ht->mmgr, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QSE_MMGR_FREE (ht->mmgr, ht->buckets);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the current bucket is uninitialized, initialize it
|
||||||
|
* by recursively copying information from the parent.
|
||||||
|
*
|
||||||
|
* We may have a situation where entry E is a parent to 2 other
|
||||||
|
* entries E' and E". If we split E into E and E', then the
|
||||||
|
* nodes meant for E" end up in E or E', either of which is
|
||||||
|
* wrong. To solve that problem, we walk down the whole chain,
|
||||||
|
* inserting the elements into the correct place.
|
||||||
|
*/
|
||||||
|
static void fixup (qse_htl_t *ht, qse_uint32_t entry)
|
||||||
|
{
|
||||||
|
qse_uint32_t parent_entry;
|
||||||
|
qse_htl_node_t** last, * cur;
|
||||||
|
qse_uint32_t thiss;
|
||||||
|
|
||||||
|
parent_entry = parent_of(entry);
|
||||||
|
|
||||||
|
/* parent_entry == entry if and only if entry == 0 */
|
||||||
|
|
||||||
|
if (!ht->buckets[parent_entry])
|
||||||
|
{
|
||||||
|
fixup(ht, parent_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Keep walking down cur, trying to find entries that
|
||||||
|
* don't belong here any more. There may be multiple
|
||||||
|
* ones, so we can't have a naive algorithm...
|
||||||
|
*/
|
||||||
|
last = &ht->buckets[parent_entry];
|
||||||
|
thiss = parent_entry;
|
||||||
|
|
||||||
|
for (cur = *last; cur != &ht->null; cur = cur->next)
|
||||||
|
{
|
||||||
|
qse_uint32_t real_entry;
|
||||||
|
|
||||||
|
real_entry = cur->key & ht->mask;
|
||||||
|
if (real_entry != thiss)
|
||||||
|
{ /* ht->buckets[real_entry] == QSE_NULL */
|
||||||
|
*last = &ht->null;
|
||||||
|
ht->buckets[real_entry] = cur;
|
||||||
|
thiss = real_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
last = &(cur->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We may NOT have initialized this bucket, so do it now.
|
||||||
|
*/
|
||||||
|
if (!ht->buckets[entry]) ht->buckets[entry] = &ht->null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This should be a power of two. Changing it to 4 doesn't seem
|
||||||
|
* to make any difference.
|
||||||
|
*/
|
||||||
|
#define GROW_FACTOR (2)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Grow the hash table.
|
||||||
|
*/
|
||||||
|
static void grow (qse_htl_t *ht)
|
||||||
|
{
|
||||||
|
qse_htl_node_t **buckets;
|
||||||
|
|
||||||
|
buckets = QSE_MMGR_ALLOC (ht->mmgr, QSE_SIZEOF(*buckets) * GROW_FACTOR * ht->num_buckets);
|
||||||
|
if (!buckets) return;
|
||||||
|
|
||||||
|
QSE_MEMCPY (buckets, ht->buckets, QSE_SIZEOF(*buckets) * ht->num_buckets);
|
||||||
|
QSE_MEMSET (&buckets[ht->num_buckets], 0, QSE_SIZEOF(*buckets) * ht->num_buckets);
|
||||||
|
|
||||||
|
QSE_MMGR_FREE (ht->mmgr, ht->buckets);
|
||||||
|
ht->buckets = buckets;
|
||||||
|
ht->num_buckets *= GROW_FACTOR;
|
||||||
|
ht->next_grow *= GROW_FACTOR;
|
||||||
|
ht->mask = ht->num_buckets - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_htl_node_t *qse_htl_search (qse_htl_t* ht, void* data)
|
||||||
|
{
|
||||||
|
qse_uint32_t key;
|
||||||
|
qse_uint32_t entry;
|
||||||
|
qse_uint32_t reversed;
|
||||||
|
|
||||||
|
key = ht->hasher(ht, data);
|
||||||
|
entry = key & ht->mask;
|
||||||
|
reversed = reverse(key);
|
||||||
|
|
||||||
|
if (!ht->buckets[entry]) fixup(ht, entry);
|
||||||
|
return list_find(ht, ht->buckets[entry], reversed, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Insert data.
|
||||||
|
*/
|
||||||
|
qse_htl_node_t* qse_htl_insert (qse_htl_t* ht, void* data)
|
||||||
|
{
|
||||||
|
qse_uint32_t key;
|
||||||
|
qse_uint32_t entry;
|
||||||
|
qse_uint32_t reversed;
|
||||||
|
qse_htl_node_t *node;
|
||||||
|
|
||||||
|
key = ht->hasher(ht, data);
|
||||||
|
entry = key & ht->mask;
|
||||||
|
reversed = reverse(key);
|
||||||
|
|
||||||
|
if (!ht->buckets[entry]) fixup(ht, entry);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we try to do our own memory allocation here, the
|
||||||
|
* speedup is only ~15% or so, which isn't worth it.
|
||||||
|
*/
|
||||||
|
node = QSE_MMGR_ALLOC(ht->mmgr, QSE_SIZEOF(*node));
|
||||||
|
if (!node) return QSE_NULL;
|
||||||
|
QSE_MEMSET (node, 0, QSE_SIZEOF(*node));
|
||||||
|
|
||||||
|
node->next = &ht->null;
|
||||||
|
node->reversed = reversed;
|
||||||
|
node->key = key;
|
||||||
|
|
||||||
|
if (ht->copier)
|
||||||
|
{
|
||||||
|
node->data = ht->copier (ht, data);
|
||||||
|
if (!node->data)
|
||||||
|
{
|
||||||
|
QSE_MMGR_FREE (ht->mmgr, node);
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else node->data = data;
|
||||||
|
|
||||||
|
/* already in the table, can't insert it */
|
||||||
|
if (!list_insert(ht, &ht->buckets[entry], node))
|
||||||
|
{
|
||||||
|
if (ht->freeer) ht->freeer (ht, node->data);
|
||||||
|
QSE_MMGR_FREE (ht->mmgr, node);
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the load factor, and grow the table if
|
||||||
|
* necessary.
|
||||||
|
*/
|
||||||
|
ht->num_elements++;
|
||||||
|
if (ht->num_elements >= ht->next_grow) grow(ht);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Replace old data with new data, OR insert if there is no old.
|
||||||
|
*/
|
||||||
|
qse_htl_node_t* qse_htl_upsert (qse_htl_t* ht, void* data)
|
||||||
|
{
|
||||||
|
qse_htl_node_t *node;
|
||||||
|
void* datap;
|
||||||
|
|
||||||
|
node = qse_htl_search(ht, data);
|
||||||
|
if (!node) return qse_htl_insert(ht, data);
|
||||||
|
|
||||||
|
if (ht->copier)
|
||||||
|
{
|
||||||
|
datap = ht->copier (ht, data);
|
||||||
|
if (!datap) return QSE_NULL;
|
||||||
|
}
|
||||||
|
else datap = data;
|
||||||
|
|
||||||
|
if (ht->freeer) ht->freeer(ht, node->data);
|
||||||
|
node->data = datap;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_htl_node_t* qse_htl_update (qse_htl_t* ht, void* data)
|
||||||
|
{
|
||||||
|
qse_htl_node_t *node;
|
||||||
|
void* datap;
|
||||||
|
|
||||||
|
node = qse_htl_search(ht, data);
|
||||||
|
if (!node) return QSE_NULL;
|
||||||
|
|
||||||
|
if (ht->copier)
|
||||||
|
{
|
||||||
|
datap = ht->copier (ht, data);
|
||||||
|
if (!datap) return QSE_NULL;
|
||||||
|
}
|
||||||
|
else datap = data;
|
||||||
|
|
||||||
|
if (ht->freeer) ht->freeer(ht, node->data);
|
||||||
|
node->data = datap;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_htl_node_t* qse_htl_ensert (qse_htl_t* ht, void* data)
|
||||||
|
{
|
||||||
|
qse_htl_node_t *node;
|
||||||
|
|
||||||
|
node = qse_htl_search(ht, data);
|
||||||
|
if (!node) return qse_htl_insert(ht, data);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Yank an entry from the hash table, without freeing the data.
|
||||||
|
*/
|
||||||
|
void* qse_htl_yank (qse_htl_t* ht, void* data)
|
||||||
|
{
|
||||||
|
qse_uint32_t key;
|
||||||
|
qse_uint32_t entry;
|
||||||
|
qse_uint32_t reversed;
|
||||||
|
void *old;
|
||||||
|
qse_htl_node_t* node;
|
||||||
|
|
||||||
|
if (!ht) return QSE_NULL;
|
||||||
|
|
||||||
|
key = ht->hasher(ht, data);
|
||||||
|
entry = key & ht->mask;
|
||||||
|
reversed = reverse(key);
|
||||||
|
|
||||||
|
if (!ht->buckets[entry]) fixup(ht, entry);
|
||||||
|
|
||||||
|
node = list_find(ht, ht->buckets[entry], reversed, data);
|
||||||
|
if (!node) return QSE_NULL;
|
||||||
|
|
||||||
|
list_delete(ht, &ht->buckets[entry], node);
|
||||||
|
ht->num_elements--;
|
||||||
|
|
||||||
|
old = node->data;
|
||||||
|
QSE_MMGR_FREE (ht->mmgr, node);
|
||||||
|
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete a piece of data from the hash table.
|
||||||
|
*/
|
||||||
|
int qse_htl_delete(qse_htl_t *ht, void* data)
|
||||||
|
{
|
||||||
|
void* old;
|
||||||
|
|
||||||
|
old = qse_htl_yank(ht, data);
|
||||||
|
if (!old) return -1;
|
||||||
|
|
||||||
|
if (ht->freeer) ht->freeer(ht, old);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Walk over the nodes, allowing deletes & inserts to happen.
|
||||||
|
*/
|
||||||
|
void qse_htl_walk (qse_htl_t *ht, qse_htl_walker_t walker, void *ctx)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = ht->num_buckets - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
qse_htl_node_t* node, * next;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure that the current bucket is filled.
|
||||||
|
*/
|
||||||
|
if (!ht->buckets[i]) fixup(ht, i);
|
||||||
|
|
||||||
|
for (node = ht->buckets[i]; node != &ht->null; node = next)
|
||||||
|
{
|
||||||
|
next = node->next;
|
||||||
|
if (walker(ht, node->data, ctx) == QSE_HTL_WALK_STOP) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* Find data from a template
|
||||||
|
*/
|
||||||
|
void *qse_htl_finddata(qse_htl_t *ht, const void *data)
|
||||||
|
{
|
||||||
|
qse_htl_node_t *node;
|
||||||
|
|
||||||
|
node = qse_htl_find(ht, data);
|
||||||
|
if (!node) return NULL;
|
||||||
|
|
||||||
|
return node->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TESTING
|
||||||
|
/*
|
||||||
|
* Show what the hash table is doing.
|
||||||
|
*/
|
||||||
|
int qse_htl_info(qse_htl_t *ht)
|
||||||
|
{
|
||||||
|
int i, a, collisions, uninitialized;
|
||||||
|
int array[256];
|
||||||
|
|
||||||
|
if (!ht) return 0;
|
||||||
|
|
||||||
|
uninitialized = collisions = 0;
|
||||||
|
memset(array, 0, sizeof(array));
|
||||||
|
|
||||||
|
for (i = 0; i < ht->num_buckets; i++) {
|
||||||
|
qse_uint32_t key;
|
||||||
|
int load;
|
||||||
|
qse_htl_node_t *node, *next;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we haven't inserted or looked up an entry
|
||||||
|
* in a bucket, it's uninitialized.
|
||||||
|
*/
|
||||||
|
if (!ht->buckets[i]) {
|
||||||
|
uninitialized++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
load = 0;
|
||||||
|
key = ~0;
|
||||||
|
for (node = ht->buckets[i]; node != &ht->null; node = next) {
|
||||||
|
if (node->reversed == key) {
|
||||||
|
collisions++;
|
||||||
|
} else {
|
||||||
|
key = node->reversed;
|
||||||
|
}
|
||||||
|
next = node->next;
|
||||||
|
load++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (load > 255) load = 255;
|
||||||
|
array[load]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("HASH TABLE %p\tbuckets: %d\t(%d uninitialized)\n", ht,
|
||||||
|
ht->num_buckets, uninitialized);
|
||||||
|
printf("\tnum entries %d\thash collisions %d\n",
|
||||||
|
ht->num_elements, collisions);
|
||||||
|
|
||||||
|
a = 0;
|
||||||
|
for (i = 1; i < 256; i++) {
|
||||||
|
if (!array[i]) continue;
|
||||||
|
printf("%d\t%d\n", i, array[i]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since the entries are ordered, the lookup cost
|
||||||
|
* for any one element in a chain is (on average)
|
||||||
|
* the cost of walking half of the chain.
|
||||||
|
*/
|
||||||
|
if (i > 1) {
|
||||||
|
a += array[i] * i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a /= 2;
|
||||||
|
a += array[1];
|
||||||
|
|
||||||
|
printf("\texpected lookup cost = %d/%d or %f\n\n",
|
||||||
|
ht->num_elements, a,
|
||||||
|
(float) ht->num_elements / (float) a);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
#define FNV_MAGIC_INIT (0x811c9dc5)
|
||||||
|
#define FNV_MAGIC_PRIME (0x01000193)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A fast hash function. For details, see:
|
||||||
|
*
|
||||||
|
* http://www.isthe.com/chongo/tech/comp/fnv/
|
||||||
|
*
|
||||||
|
* Which also includes public domain source. We've re-written
|
||||||
|
* it here for our purposes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Continue hashing data.
|
||||||
|
*/
|
||||||
|
QSE_INLINE qse_uint32_t qse_genhash_update (const void* data, qse_size_t size, qse_uint32_t hash)
|
||||||
|
{
|
||||||
|
const qse_uint8_t *p = data;
|
||||||
|
const qse_uint8_t *q = p + size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FNV-1 hash each octet in the buffer
|
||||||
|
*/
|
||||||
|
while (p != q)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* XOR the 8-bit quantity into the bottom of
|
||||||
|
* the hash.
|
||||||
|
*/
|
||||||
|
hash ^= (qse_uint32_t) (*p++);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Multiple by 32-bit magic FNV prime, mod 2^32
|
||||||
|
*/
|
||||||
|
hash *= FNV_MAGIC_PRIME;
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* Potential optimization.
|
||||||
|
*/
|
||||||
|
hash += (hash<<1) + (hash<<4) + (hash<<7) + (hash<<8) + (hash<<24);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_uint32_t qse_genhash (const void *data, qse_size_t size)
|
||||||
|
{
|
||||||
|
return qse_genhash_update (data, size, FNV_MAGIC_INIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hash a C string, so we loop over it once.
|
||||||
|
*/
|
||||||
|
qse_uint32_t qse_mbshash (const qse_mchar_t* p)
|
||||||
|
{
|
||||||
|
qse_uint32_t hash = FNV_MAGIC_INIT;
|
||||||
|
|
||||||
|
while (*p)
|
||||||
|
{
|
||||||
|
hash ^= (qse_uint32_t) (*p++);
|
||||||
|
hash *= FNV_MAGIC_PRIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_uint32_t qse_wcshash (const qse_wchar_t* p)
|
||||||
|
{
|
||||||
|
|
||||||
|
qse_uint32_t hash = FNV_MAGIC_INIT;
|
||||||
|
|
||||||
|
while (*p)
|
||||||
|
{
|
||||||
|
#if (QSE_SIZEOF_WCHAR_T <= QSE_SIZEOF_UINT32_T)
|
||||||
|
hash ^= (qse_uint32_t)(*p);
|
||||||
|
hash *= FNV_MAGIC_PRIME;
|
||||||
|
#else
|
||||||
|
hash = qse_genhash_update (*p, QSE_SIZEOF(*p), hash);
|
||||||
|
#endif
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* Return a "folded" hash, where the lower "bits" are the
|
||||||
|
* hash, and the upper bits are zero.
|
||||||
|
*
|
||||||
|
* If you need a non-power-of-two hash, cope.
|
||||||
|
*/
|
||||||
|
qse_uint32_t qse_foldhash (qse_uint32_t hash, int bits)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
qse_uint32_t result;
|
||||||
|
|
||||||
|
if ((bits <= 0) || (bits >= 32)) return hash;
|
||||||
|
|
||||||
|
result = hash;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Never use the same bits twice in an xor.
|
||||||
|
*/
|
||||||
|
for (count = 0; count < 32; count += bits)
|
||||||
|
{
|
||||||
|
hash >>= bits;
|
||||||
|
result ^= hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result & (((qse_uint32_t) (1 << bits)) - 1);
|
||||||
|
}
|
||||||
|
#endif
|
@ -377,7 +377,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -384,7 +384,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -377,7 +377,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
1093
qse/lib/rad/raddic.c
1093
qse/lib/rad/raddic.c
File diff suppressed because it is too large
Load Diff
@ -408,7 +408,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -26,9 +26,8 @@
|
|||||||
|
|
||||||
#include <qse/si/AppRoot.hpp>
|
#include <qse/si/AppRoot.hpp>
|
||||||
#include <qse/si/sinfo.h>
|
#include <qse/si/sinfo.h>
|
||||||
#include <qse/cmn/mem.h>
|
|
||||||
#include <qse/cmn/mbwc.h>
|
|
||||||
#include "../cmn/syscall.h"
|
#include "../cmn/syscall.h"
|
||||||
|
#include <qse/cmn/mbwc.h>
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
QSE_BEGIN_NAMESPACE(QSE)
|
QSE_BEGIN_NAMESPACE(QSE)
|
||||||
@ -42,7 +41,6 @@ int AppRoot::daemonize (bool chdir_to_root, int fork_count) QSE_CPP_NOEXCEPT
|
|||||||
{
|
{
|
||||||
if (fork_count >= 2)
|
if (fork_count >= 2)
|
||||||
{
|
{
|
||||||
struct sigaction sa;
|
|
||||||
int n = QSE_FORK();
|
int n = QSE_FORK();
|
||||||
if (n == -1) return -1;
|
if (n == -1) return -1;
|
||||||
if (n != 0) QSE_EXIT(0);
|
if (n != 0) QSE_EXIT(0);
|
||||||
@ -103,64 +101,53 @@ int AppRoot::daemonize (bool chdir_to_root, int fork_count) QSE_CPP_NOEXCEPT
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
int AppRoot::switchUser () QSE_CPP_NOEXCEPT
|
|
||||||
{
|
|
||||||
struct passwd* pw;
|
|
||||||
|
|
||||||
pw = getpwnam (username);
|
|
||||||
if (!pw)
|
|
||||||
|
|
||||||
|
|
||||||
if (QSE_SETGID(pw->pw_gid) == -1)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QSE_SETEGID(gid);
|
|
||||||
QSE_SETUID(uid);
|
|
||||||
QSE_SETEUID(uid);
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
int AppRoot::chroot (const qse_mchar_t* mpath) QSE_CPP_NOEXCEPT
|
int AppRoot::chroot (const qse_mchar_t* mpath) QSE_CPP_NOEXCEPT
|
||||||
{
|
{
|
||||||
int orgdirfd;
|
return QSE_CHROOT (mpath);
|
||||||
|
|
||||||
orgdirfd = QSE_OPEN (".", O_RDONLY, 0);
|
|
||||||
if (orgdirfd == -1) return -1;
|
|
||||||
|
|
||||||
if (QSE_CHDIR(mpath) == -1) return -1;
|
|
||||||
if (QSE_CHROOT(mpath) == -1)
|
|
||||||
{
|
|
||||||
QSE_FCHDIR (orgdirfd);
|
|
||||||
QSE_CLOSE (orgdirfd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSE_CLOSE (orgdirfd);
|
|
||||||
QSE_CHROOT ("/");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int AppRoot::chroot (const qse_wchar_t* wpath) QSE_CPP_NOEXCEPT
|
int AppRoot::chroot (const qse_wchar_t* wpath) QSE_CPP_NOEXCEPT
|
||||||
{
|
{
|
||||||
qse_mchar_t* mpath;
|
qse_mchar_t* mpath;
|
||||||
|
mpath = qse_wcstombsdup (wpath, QSE_NULL, this->getMmgr());
|
||||||
mpath = qse_wcstombsdup (wpath, QSE_NULL, QSE_MMGR_GETDFL());
|
|
||||||
if (!mpath) return -1;
|
if (!mpath) return -1;
|
||||||
|
|
||||||
int n = AppRoot::chroot ((const qse_mchar_t*)mpath);
|
int n = AppRoot::chroot ((const qse_mchar_t*)mpath);
|
||||||
QSE_MMGR_FREE (QSE_MMGR_GETDFL(), mpath);
|
this->getMmgr()->dispose (mpath);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppRoot::on_signal () QSE_CPP_NOEXCEPT
|
#if 0
|
||||||
|
int AppRoot::switchPrivilege (int gid, int uid, bool permanently)
|
||||||
{
|
{
|
||||||
|
gid = QSE_GETGID();
|
||||||
|
uid = QSE_GETUID();
|
||||||
|
|
||||||
|
this->saved_egid = QSE_GETEGID();
|
||||||
|
this->saved_euid = QSE_GETEUID();
|
||||||
|
this->saved_ngroups = getgroups (QSE_COUNTOF(this->saved_groups), this->saved_groups);
|
||||||
|
|
||||||
|
if (this->saved_euid == 0) setgrops (1, gid);
|
||||||
|
|
||||||
|
setegid (gid);
|
||||||
|
//setregid (-1, gid);
|
||||||
|
|
||||||
|
if (uid != this->saved_euid)
|
||||||
|
{
|
||||||
|
seteuid (uid);
|
||||||
|
//setreuid (-1, uid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AppRoot::restorePrivilege ()
|
||||||
|
{
|
||||||
|
if (QSE_GETEUID() != this->saved_euid) seteuid (this->saved_euid);
|
||||||
|
if (QSE_GETEGID() != this->saved_egid) setegid (this->saved_egid);
|
||||||
|
if (this->saved_euid == 0) setgroups (this->saved_ngroups, this->saved_groups);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
int main ()
|
int main ()
|
||||||
@ -168,8 +155,10 @@ int main ()
|
|||||||
AppRoot app;
|
AppRoot app;
|
||||||
|
|
||||||
app.daemonize();
|
app.daemonize();
|
||||||
app.switchUser ("nobody", "nobody");
|
app.chuser ();
|
||||||
app.switchUser (10, 20);
|
app.chgroup ();
|
||||||
|
app.chroot ();
|
||||||
|
|
||||||
app.catchSignal (SIGINT, xxxxx);
|
app.catchSignal (SIGINT, xxxxx);
|
||||||
app.catchSignal (SIGTERM, xxx);
|
app.catchSignal (SIGTERM, xxx);
|
||||||
|
|
||||||
|
@ -423,7 +423,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -377,7 +377,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -356,7 +356,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -298,7 +298,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -300,7 +300,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -356,7 +356,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -480,7 +480,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -15,6 +15,7 @@ bin_PROGRAMS = \
|
|||||||
fmt01 \
|
fmt01 \
|
||||||
fmt02 \
|
fmt02 \
|
||||||
htb01 \
|
htb01 \
|
||||||
|
htl01 \
|
||||||
ipad01 \
|
ipad01 \
|
||||||
main01 \
|
main01 \
|
||||||
main02 \
|
main02 \
|
||||||
|
@ -90,11 +90,12 @@ build_triplet = @build@
|
|||||||
host_triplet = @host@
|
host_triplet = @host@
|
||||||
bin_PROGRAMS = arr01$(EXEEXT) chr01$(EXEEXT) dll$(EXEEXT) \
|
bin_PROGRAMS = arr01$(EXEEXT) chr01$(EXEEXT) dll$(EXEEXT) \
|
||||||
env01$(EXEEXT) fma$(EXEEXT) fmt01$(EXEEXT) fmt02$(EXEEXT) \
|
env01$(EXEEXT) fma$(EXEEXT) fmt01$(EXEEXT) fmt02$(EXEEXT) \
|
||||||
htb01$(EXEEXT) ipad01$(EXEEXT) main01$(EXEEXT) main02$(EXEEXT) \
|
htb01$(EXEEXT) htl01$(EXEEXT) ipad01$(EXEEXT) main01$(EXEEXT) \
|
||||||
mbwc01$(EXEEXT) mbwc02$(EXEEXT) oht$(EXEEXT) path01$(EXEEXT) \
|
main02$(EXEEXT) mbwc01$(EXEEXT) mbwc02$(EXEEXT) oht$(EXEEXT) \
|
||||||
pma$(EXEEXT) rex01$(EXEEXT) rbt01$(EXEEXT) sll$(EXEEXT) \
|
path01$(EXEEXT) pma$(EXEEXT) rex01$(EXEEXT) rbt01$(EXEEXT) \
|
||||||
slmb01$(EXEEXT) str01$(EXEEXT) str02$(EXEEXT) time$(EXEEXT) \
|
sll$(EXEEXT) slmb01$(EXEEXT) str01$(EXEEXT) str02$(EXEEXT) \
|
||||||
tre01$(EXEEXT) uri01$(EXEEXT) xma$(EXEEXT) $(am__EXEEXT_1)
|
time$(EXEEXT) tre01$(EXEEXT) uri01$(EXEEXT) xma$(EXEEXT) \
|
||||||
|
$(am__EXEEXT_1)
|
||||||
@WCHAR_TRUE@@WIN32_TRUE@am__append_1 = $(UNICOWS_LIBS)
|
@WCHAR_TRUE@@WIN32_TRUE@am__append_1 = $(UNICOWS_LIBS)
|
||||||
|
|
||||||
#bin_PROGRAMS += rex02
|
#bin_PROGRAMS += rex02
|
||||||
@ -188,6 +189,10 @@ am__htb02_SOURCES_DIST = htb02.cpp
|
|||||||
@ENABLE_CXX_TRUE@am_htb02_OBJECTS = htb02.$(OBJEXT)
|
@ENABLE_CXX_TRUE@am_htb02_OBJECTS = htb02.$(OBJEXT)
|
||||||
htb02_OBJECTS = $(am_htb02_OBJECTS)
|
htb02_OBJECTS = $(am_htb02_OBJECTS)
|
||||||
@ENABLE_CXX_TRUE@htb02_DEPENDENCIES = $(am__DEPENDENCIES_3)
|
@ENABLE_CXX_TRUE@htb02_DEPENDENCIES = $(am__DEPENDENCIES_3)
|
||||||
|
htl01_SOURCES = htl01.c
|
||||||
|
htl01_OBJECTS = htl01.$(OBJEXT)
|
||||||
|
htl01_LDADD = $(LDADD)
|
||||||
|
htl01_DEPENDENCIES = $(am__DEPENDENCIES_2)
|
||||||
am_ipad01_OBJECTS = ipad01.$(OBJEXT)
|
am_ipad01_OBJECTS = ipad01.$(OBJEXT)
|
||||||
ipad01_OBJECTS = $(am_ipad01_OBJECTS)
|
ipad01_OBJECTS = $(am_ipad01_OBJECTS)
|
||||||
ipad01_LDADD = $(LDADD)
|
ipad01_LDADD = $(LDADD)
|
||||||
@ -332,7 +337,7 @@ SOURCES = $(arr01_SOURCES) $(arr02_SOURCES) $(arr03_SOURCES) \
|
|||||||
$(bh01_SOURCES) $(bh02_SOURCES) $(chr01_SOURCES) \
|
$(bh01_SOURCES) $(bh02_SOURCES) $(chr01_SOURCES) \
|
||||||
$(dll_SOURCES) $(env01_SOURCES) $(fma_SOURCES) \
|
$(dll_SOURCES) $(env01_SOURCES) $(fma_SOURCES) \
|
||||||
$(fmt01_SOURCES) $(fmt02_SOURCES) $(hl01_SOURCES) \
|
$(fmt01_SOURCES) $(fmt02_SOURCES) $(hl01_SOURCES) \
|
||||||
$(htb01_SOURCES) $(htb02_SOURCES) $(ipad01_SOURCES) \
|
$(htb01_SOURCES) $(htb02_SOURCES) htl01.c $(ipad01_SOURCES) \
|
||||||
$(main01_SOURCES) $(main02_SOURCES) $(mbwc01_SOURCES) \
|
$(main01_SOURCES) $(main02_SOURCES) $(mbwc01_SOURCES) \
|
||||||
$(mbwc02_SOURCES) $(oht_SOURCES) $(path01_SOURCES) \
|
$(mbwc02_SOURCES) $(oht_SOURCES) $(path01_SOURCES) \
|
||||||
$(pma_SOURCES) $(rbt01_SOURCES) $(rbt02_SOURCES) \
|
$(pma_SOURCES) $(rbt01_SOURCES) $(rbt02_SOURCES) \
|
||||||
@ -345,10 +350,10 @@ DIST_SOURCES = $(arr01_SOURCES) $(am__arr02_SOURCES_DIST) \
|
|||||||
$(am__bh02_SOURCES_DIST) $(chr01_SOURCES) $(dll_SOURCES) \
|
$(am__bh02_SOURCES_DIST) $(chr01_SOURCES) $(dll_SOURCES) \
|
||||||
$(env01_SOURCES) $(fma_SOURCES) $(fmt01_SOURCES) \
|
$(env01_SOURCES) $(fma_SOURCES) $(fmt01_SOURCES) \
|
||||||
$(fmt02_SOURCES) $(am__hl01_SOURCES_DIST) $(htb01_SOURCES) \
|
$(fmt02_SOURCES) $(am__hl01_SOURCES_DIST) $(htb01_SOURCES) \
|
||||||
$(am__htb02_SOURCES_DIST) $(ipad01_SOURCES) $(main01_SOURCES) \
|
$(am__htb02_SOURCES_DIST) htl01.c $(ipad01_SOURCES) \
|
||||||
$(main02_SOURCES) $(mbwc01_SOURCES) $(mbwc02_SOURCES) \
|
$(main01_SOURCES) $(main02_SOURCES) $(mbwc01_SOURCES) \
|
||||||
$(oht_SOURCES) $(path01_SOURCES) $(pma_SOURCES) \
|
$(mbwc02_SOURCES) $(oht_SOURCES) $(path01_SOURCES) \
|
||||||
$(rbt01_SOURCES) $(am__rbt02_SOURCES_DIST) \
|
$(pma_SOURCES) $(rbt01_SOURCES) $(am__rbt02_SOURCES_DIST) \
|
||||||
$(am__rbt03_SOURCES_DIST) $(rex01_SOURCES) $(sll_SOURCES) \
|
$(am__rbt03_SOURCES_DIST) $(rex01_SOURCES) $(sll_SOURCES) \
|
||||||
$(slmb01_SOURCES) $(am__sp01_SOURCES_DIST) \
|
$(slmb01_SOURCES) $(am__sp01_SOURCES_DIST) \
|
||||||
$(am__sp02_SOURCES_DIST) $(str01_SOURCES) \
|
$(am__sp02_SOURCES_DIST) $(str01_SOURCES) \
|
||||||
@ -550,7 +555,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
@ -754,6 +758,10 @@ htb02$(EXEEXT): $(htb02_OBJECTS) $(htb02_DEPENDENCIES) $(EXTRA_htb02_DEPENDENCIE
|
|||||||
@rm -f htb02$(EXEEXT)
|
@rm -f htb02$(EXEEXT)
|
||||||
$(AM_V_CXXLD)$(CXXLINK) $(htb02_OBJECTS) $(htb02_LDADD) $(LIBS)
|
$(AM_V_CXXLD)$(CXXLINK) $(htb02_OBJECTS) $(htb02_LDADD) $(LIBS)
|
||||||
|
|
||||||
|
htl01$(EXEEXT): $(htl01_OBJECTS) $(htl01_DEPENDENCIES) $(EXTRA_htl01_DEPENDENCIES)
|
||||||
|
@rm -f htl01$(EXEEXT)
|
||||||
|
$(AM_V_CCLD)$(LINK) $(htl01_OBJECTS) $(htl01_LDADD) $(LIBS)
|
||||||
|
|
||||||
ipad01$(EXEEXT): $(ipad01_OBJECTS) $(ipad01_DEPENDENCIES) $(EXTRA_ipad01_DEPENDENCIES)
|
ipad01$(EXEEXT): $(ipad01_OBJECTS) $(ipad01_DEPENDENCIES) $(EXTRA_ipad01_DEPENDENCIES)
|
||||||
@rm -f ipad01$(EXEEXT)
|
@rm -f ipad01$(EXEEXT)
|
||||||
$(AM_V_CCLD)$(LINK) $(ipad01_OBJECTS) $(ipad01_LDADD) $(LIBS)
|
$(AM_V_CCLD)$(LINK) $(ipad01_OBJECTS) $(ipad01_LDADD) $(LIBS)
|
||||||
@ -862,6 +870,7 @@ distclean-compile:
|
|||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hl01.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hl01.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb01.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb01.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb02.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb02.Po@am__quote@
|
||||||
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htl01.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipad01.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipad01.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main01.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main01.Po@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main02.Po@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main02.Po@am__quote@
|
||||||
|
209
qse/samples/cmn/htl01.c
Normal file
209
qse/samples/cmn/htl01.c
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
#include <qse/cmn/mem.h>
|
||||||
|
#include <qse/cmn/str.h>
|
||||||
|
#include <qse/cmn/htl.h>
|
||||||
|
#include <qse/si/sio.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_htl_walk_t walk1 (qse_htl_t* htl, void* data, void* ctx)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("[%ld]\n"), *(long*)data);
|
||||||
|
return QSE_HTL_WALK_FORWARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static qse_htl_walk_t walk2 (qse_htl_t* htl, 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_HTL_WALK_FORWARD;
|
||||||
|
}
|
||||||
|
|
||||||
|
static qse_size_t hash_item (qse_htl_t* htl, const void* data)
|
||||||
|
{
|
||||||
|
item_t* item = (item_t*)data;
|
||||||
|
//return item->a + 123445;
|
||||||
|
return qse_genhash (&item->a, QSE_SIZEOF(item->a));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int comp_item (qse_htl_t* htl, const void* data1, const void* data2)
|
||||||
|
{
|
||||||
|
return ((item_t*)data1)->a != ((item_t*)data2)->a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* copy_item (qse_htl_t* htl, void* data)
|
||||||
|
{
|
||||||
|
item_t* x = (item_t*)QSE_MMGR_ALLOC (htl->mmgr, QSE_SIZEOF(item_t));
|
||||||
|
if (x) *x = *(item_t*)data;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_item (qse_htl_t* htl, void* data)
|
||||||
|
{
|
||||||
|
QSE_MMGR_FREE (htl->mmgr, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* copy_long (qse_htl_t* htl, void* data)
|
||||||
|
{
|
||||||
|
long* x = (long*)QSE_MMGR_ALLOC (htl->mmgr, QSE_SIZEOF(long));
|
||||||
|
if (x) *x = *(long*)data;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_long (qse_htl_t* htl, void* data)
|
||||||
|
{
|
||||||
|
QSE_MMGR_FREE (htl->mmgr, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test1 ()
|
||||||
|
{
|
||||||
|
long x;
|
||||||
|
qse_htl_t* htl;
|
||||||
|
qse_htl_node_t* np;
|
||||||
|
|
||||||
|
htl = qse_htl_open (QSE_MMGR_GETDFL(), 0, QSE_SIZEOF(x));
|
||||||
|
if (htl == QSE_NULL)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("failed to open a table\n"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_htl_setcopier (htl, copy_long);
|
||||||
|
qse_htl_setfreeer (htl, free_long);
|
||||||
|
|
||||||
|
for (x = 9; x < 20; x++)
|
||||||
|
{
|
||||||
|
if (qse_htl_insert(htl, &x))
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("SUCCESS: inserted %ld\n"), x);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("FAILURE: failed to insert %ld\n"), x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
x = 10;
|
||||||
|
if ((np = qse_htl_search(htl, &x)))
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("SUCCESS: found %ld\n"), *(long*)np->data);
|
||||||
|
QSE_ASSERT (*(long*)np->data == x);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("FAILURE: failed to found %ld\n"), x);
|
||||||
|
}
|
||||||
|
|
||||||
|
x = 10;
|
||||||
|
if (qse_htl_delete(htl, &x) == 0)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("SUCCESS: deleted %ld\n"), x);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("FAILURE: failed to delete %ld\n"), x);
|
||||||
|
}
|
||||||
|
|
||||||
|
x = 10;
|
||||||
|
qse_printf (QSE_T("searching for %ld\n"), x);
|
||||||
|
np = qse_htl_search(htl, &x);
|
||||||
|
QSE_ASSERT (np == QSE_NULL);
|
||||||
|
if (np)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("FAILURE: found something that must not be found - %ld\n"), x);
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_printf (QSE_T("total %lu items\n"), (unsigned long)qse_htl_getsize(htl));
|
||||||
|
qse_htl_walk (htl, walk1, QSE_NULL);
|
||||||
|
qse_htl_close (htl);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test2 ()
|
||||||
|
{
|
||||||
|
item_t x;
|
||||||
|
qse_htl_t* htl;
|
||||||
|
qse_htl_node_t* np;
|
||||||
|
|
||||||
|
htl = qse_htl_open (QSE_MMGR_GETDFL(), 0, QSE_SIZEOF(x));
|
||||||
|
if (htl == QSE_NULL)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("failed to open a table\n"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_htl_sethasher (htl, hash_item);
|
||||||
|
qse_htl_setcomper (htl, comp_item);
|
||||||
|
qse_htl_setcopier (htl, copy_item);
|
||||||
|
qse_htl_setfreeer (htl, free_item);
|
||||||
|
|
||||||
|
for (x.a = 9; x.a < 20; x.a++)
|
||||||
|
{
|
||||||
|
x.x = x.a * 10;
|
||||||
|
x.y = x.a * 100;
|
||||||
|
|
||||||
|
if (qse_htl_insert(htl, &x))
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("SUCCESS: inserted %ld\n"), x.a);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("FAILURE: failed to insert %ld\n"), x.a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
x.a = 10;
|
||||||
|
if ((np = qse_htl_search(htl, &x)))
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("SUCCESS: found %ld\n"), *(long*)np->data);
|
||||||
|
QSE_ASSERT (*(long*)np->data == x.a);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("FAILURE: failed to found %ld\n"), x.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
x.a = 10;
|
||||||
|
if (qse_htl_delete(htl, &x) == 0)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("SUCCESS: deleted %ld\n"), x.a);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("FAILURE: failed to delete %ld\n"), x.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
x.a = 10;
|
||||||
|
qse_printf (QSE_T("searching for %ld\n"), x.a);
|
||||||
|
np = qse_htl_search(htl, &x);
|
||||||
|
QSE_ASSERT (np == QSE_NULL);
|
||||||
|
if (np)
|
||||||
|
{
|
||||||
|
qse_printf (QSE_T("FAILURE: found something that must not be found - %ld\n"), x.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_printf (QSE_T("total %lu items\n"), (unsigned long)qse_htl_getsize(htl));
|
||||||
|
qse_htl_walk (htl, walk2, QSE_NULL);
|
||||||
|
qse_htl_close (htl);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main ()
|
||||||
|
{
|
||||||
|
qse_open_stdsios ();
|
||||||
|
R (test1);
|
||||||
|
R (test2);
|
||||||
|
qse_close_stdsios ();
|
||||||
|
return 0;
|
||||||
|
}
|
@ -351,7 +351,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -352,7 +352,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -391,7 +391,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -433,7 +433,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
@ -298,7 +298,6 @@ pdfdir = @pdfdir@
|
|||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
program_transform_name = @program_transform_name@
|
program_transform_name = @program_transform_name@
|
||||||
psdir = @psdir@
|
psdir = @psdir@
|
||||||
runstatedir = @runstatedir@
|
|
||||||
sbindir = @sbindir@
|
sbindir = @sbindir@
|
||||||
sharedstatedir = @sharedstatedir@
|
sharedstatedir = @sharedstatedir@
|
||||||
srcdir = @srcdir@
|
srcdir = @srcdir@
|
||||||
|
Loading…
x
Reference in New Issue
Block a user