From 5db7ddc770507939ca88042a787b5749d4ef9eda Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 30 Nov 2017 05:46:42 +0000 Subject: [PATCH] added another new hash table implementation based on fr --- qse/Makefile.in | 9 +- qse/cmd/Makefile.in | 1 - qse/cmd/awk/Makefile.in | 1 - qse/cmd/http/Makefile.in | 1 - qse/cmd/sed/Makefile.in | 1 - qse/cmd/xli/Makefile.in | 1 - qse/configure | 14 +- qse/doc/Makefile.in | 1 - qse/include/Makefile.in | 1 - qse/include/qse/Makefile.in | 1 - qse/include/qse/awk/Makefile.in | 1 - qse/include/qse/cmn/Makefile.am | 1 + qse/include/qse/cmn/Makefile.in | 21 +- qse/include/qse/cmn/htl.h | 302 +++++++++ qse/include/qse/cry/Makefile.in | 1 - qse/include/qse/http/Makefile.in | 1 - qse/include/qse/rad/Makefile.in | 1 - qse/include/qse/rad/raddic.h | 40 +- qse/include/qse/sed/Makefile.in | 1 - qse/include/qse/si/AppRoot.hpp | 22 +- qse/include/qse/si/Makefile.in | 1 - qse/include/qse/si/log.h | 12 + qse/include/qse/xli/Makefile.in | 1 - qse/lib/Makefile.in | 1 - qse/lib/awk/Makefile.in | 1 - qse/lib/cmn/Makefile.am | 1 + qse/lib/cmn/Makefile.in | 34 +- qse/lib/cmn/htl.c | 856 +++++++++++++++++++++++ qse/lib/cry/Makefile.in | 1 - qse/lib/http/Makefile.in | 1 - qse/lib/rad/Makefile.in | 1 - qse/lib/rad/raddic.c | 1093 ++++++++++++++++-------------- qse/lib/sed/Makefile.in | 1 - qse/lib/si/AppRoot.cpp | 81 +-- qse/lib/si/Makefile.in | 1 - qse/lib/xli/Makefile.in | 1 - qse/regress/Makefile.in | 1 - qse/regress/awk/Makefile.in | 1 - qse/regress/sed/Makefile.in | 1 - qse/samples/Makefile.in | 1 - qse/samples/awk/Makefile.in | 1 - qse/samples/cmn/Makefile.am | 1 + qse/samples/cmn/Makefile.in | 31 +- qse/samples/cmn/htl01.c | 209 ++++++ qse/samples/cry/Makefile.in | 1 - qse/samples/http/Makefile.in | 1 - qse/samples/sed/Makefile.in | 1 - qse/samples/si/Makefile.in | 1 - qse/tools/Makefile.in | 1 - 49 files changed, 2113 insertions(+), 647 deletions(-) create mode 100644 qse/include/qse/cmn/htl.h create mode 100644 qse/lib/cmn/htl.c create mode 100644 qse/samples/cmn/htl01.c diff --git a/qse/Makefile.in b/qse/Makefile.in index 45ffb204..9ab14d3b 100644 --- a/qse/Makefile.in +++ b/qse/Makefile.in @@ -380,7 +380,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -619,7 +618,7 @@ distdir: $(DISTFILES) ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(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) dist-bzip2: distdir @@ -645,7 +644,7 @@ dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&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) dist-zip: distdir @@ -663,7 +662,7 @@ dist dist-all: distcheck: dist case '$(DIST_ARCHIVES)' in \ *.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*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ @@ -673,7 +672,7 @@ distcheck: dist *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac diff --git a/qse/cmd/Makefile.in b/qse/cmd/Makefile.in index e6641c47..22f51485 100644 --- a/qse/cmd/Makefile.in +++ b/qse/cmd/Makefile.in @@ -355,7 +355,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/cmd/awk/Makefile.in b/qse/cmd/awk/Makefile.in index 98a54874..2529247f 100644 --- a/qse/cmd/awk/Makefile.in +++ b/qse/cmd/awk/Makefile.in @@ -362,7 +362,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/cmd/http/Makefile.in b/qse/cmd/http/Makefile.in index e5b30333..16238da9 100644 --- a/qse/cmd/http/Makefile.in +++ b/qse/cmd/http/Makefile.in @@ -388,7 +388,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/cmd/sed/Makefile.in b/qse/cmd/sed/Makefile.in index 2299b0c8..3ef2bc08 100644 --- a/qse/cmd/sed/Makefile.in +++ b/qse/cmd/sed/Makefile.in @@ -353,7 +353,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/cmd/xli/Makefile.in b/qse/cmd/xli/Makefile.in index 730cfbe8..064af9d7 100644 --- a/qse/cmd/xli/Makefile.in +++ b/qse/cmd/xli/Makefile.in @@ -353,7 +353,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/configure b/qse/configure index e125b7ad..48dc593f 100755 --- a/qse/configure +++ b/qse/configure @@ -821,7 +821,6 @@ infodir docdir oldincludedir includedir -runstatedir localstatedir sharedstatedir sysconfdir @@ -924,7 +923,6 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1177,15 +1175,6 @@ do | -silent | --silent | --silen | --sile | --sil) 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) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1323,7 +1312,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir + libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1476,7 +1465,6 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] diff --git a/qse/doc/Makefile.in b/qse/doc/Makefile.in index 7d2f574e..e2dba765 100644 --- a/qse/doc/Makefile.in +++ b/qse/doc/Makefile.in @@ -298,7 +298,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/include/Makefile.in b/qse/include/Makefile.in index 6db9fb11..db4f5e83 100644 --- a/qse/include/Makefile.in +++ b/qse/include/Makefile.in @@ -356,7 +356,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/include/qse/Makefile.in b/qse/include/qse/Makefile.in index b80b2cad..5c908b20 100644 --- a/qse/include/qse/Makefile.in +++ b/qse/include/qse/Makefile.in @@ -396,7 +396,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/include/qse/awk/Makefile.in b/qse/include/qse/awk/Makefile.in index ecdca6e1..a55cfd3d 100644 --- a/qse/include/qse/awk/Makefile.in +++ b/qse/include/qse/awk/Makefile.in @@ -347,7 +347,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/include/qse/cmn/Makefile.am b/qse/include/qse/cmn/Makefile.am index 61c6a5c3..16162c96 100644 --- a/qse/include/qse/cmn/Makefile.am +++ b/qse/include/qse/cmn/Makefile.am @@ -12,6 +12,7 @@ pkginclude_HEADERS = \ fmt.h \ gdl.h \ htb.h \ + htl.h \ hton.h \ hwad.h \ ipad.h \ diff --git a/qse/include/qse/cmn/Makefile.in b/qse/include/qse/cmn/Makefile.in index 97c23a4f..ba735754 100644 --- a/qse/include/qse/cmn/Makefile.in +++ b/qse/include/qse/cmn/Makefile.in @@ -133,13 +133,13 @@ am__can_run_installinfo = \ *) (install-info --version) >/dev/null 2>&1;; \ esac 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 \ - map.h mb8.h mbwc.h mem.h oht.h opt.h path.h pma.h rbt.h rex.h \ - sll.h slmb.h str.h time.h tmr.h tre.h uni.h uri.h utf8.h xma.h \ - Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp ScopedPtr.hpp \ - SharedPtr.hpp StrBase.hpp String.hpp Mpool.hpp Association.hpp \ - LinkedList.hpp HashList.hpp HashTable.hpp RedBlackTree.hpp \ - RedBlackTable.hpp Array.hpp BinaryHeap.hpp + env.h fma.h fmt.h gdl.h htb.h htl.h hton.h hwad.h ipad.h \ + main.h map.h mb8.h mbwc.h mem.h oht.h opt.h path.h pma.h rbt.h \ + rex.h sll.h slmb.h str.h time.h tmr.h tre.h uni.h uri.h utf8.h \ + xma.h Mmgr.hpp StdMmgr.hpp HeapMmgr.hpp Mmged.hpp \ + ScopedPtr.hpp SharedPtr.hpp StrBase.hpp String.hpp Mpool.hpp \ + Association.hpp LinkedList.hpp HashList.hpp HashTable.hpp \ + RedBlackTree.hpp RedBlackTable.hpp Array.hpp BinaryHeap.hpp am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -361,7 +361,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -373,9 +372,9 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ 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 \ - mb8.h mbwc.h mem.h oht.h opt.h path.h pma.h rbt.h rex.h sll.h \ - slmb.h str.h time.h tmr.h tre.h uni.h uri.h utf8.h xma.h \ + fma.h fmt.h gdl.h htb.h htl.h hton.h hwad.h ipad.h main.h \ + map.h mb8.h mbwc.h mem.h oht.h opt.h path.h pma.h rbt.h rex.h \ + sll.h slmb.h str.h time.h tmr.h tre.h uni.h uri.h utf8.h xma.h \ $(am__append_1) all: all-am diff --git a/qse/include/qse/cmn/htl.h b/qse/include/qse/cmn/htl.h new file mode 100644 index 00000000..727154da --- /dev/null +++ b/qse/include/qse/cmn/htl.h @@ -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 +#include + +/** + * 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 diff --git a/qse/include/qse/cry/Makefile.in b/qse/include/qse/cry/Makefile.in index 37ec9489..69eca69c 100644 --- a/qse/include/qse/cry/Makefile.in +++ b/qse/include/qse/cry/Makefile.in @@ -345,7 +345,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/include/qse/http/Makefile.in b/qse/include/qse/http/Makefile.in index 2e404494..495364cb 100644 --- a/qse/include/qse/http/Makefile.in +++ b/qse/include/qse/http/Makefile.in @@ -345,7 +345,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/include/qse/rad/Makefile.in b/qse/include/qse/rad/Makefile.in index d85ee794..c1ddc51c 100644 --- a/qse/include/qse/rad/Makefile.in +++ b/qse/include/qse/rad/Makefile.in @@ -345,7 +345,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/include/qse/rad/raddic.h b/qse/include/qse/rad/raddic.h index e491614f..e5ff82c4 100644 --- a/qse/include/qse/rad/raddic.h +++ b/qse/include/qse/rad/raddic.h @@ -46,16 +46,52 @@ #define QSE_RAD_ATTR_TYPE_COMBO_IP 13 #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 { int attr; int type; int vendor; -/* ATTR_FLAGS flags;*/ - char name[1]; + qse_raddic_attr_flags_t flags; + qse_char_t name[1]; }; 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; #if defined(__cplusplus) diff --git a/qse/include/qse/sed/Makefile.in b/qse/include/qse/sed/Makefile.in index c409e45b..8df41228 100644 --- a/qse/include/qse/sed/Makefile.in +++ b/qse/include/qse/sed/Makefile.in @@ -347,7 +347,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/include/qse/si/AppRoot.hpp b/qse/include/qse/si/AppRoot.hpp index 70061078..beef3d26 100644 --- a/qse/include/qse/si/AppRoot.hpp +++ b/qse/include/qse/si/AppRoot.hpp @@ -29,25 +29,39 @@ #include #include +#include ///////////////////////////////// QSE_BEGIN_NAMESPACE(QSE) ///////////////////////////////// -class AppRoot: QSE::Uncopyable +class AppRoot: Uncopyable, public Types, public Mmged { public: - AppRoot (): _root_only (false) {} + AppRoot (Mmgr* mmgr): Mmged(mmgr), _root_only(false) {} virtual ~AppRoot () {} 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; - static int chroot (const qse_mchar_t* mpath) QSE_CPP_NOEXCEPT; + 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: 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; +#endif }; ///////////////////////////////// diff --git a/qse/include/qse/si/Makefile.in b/qse/include/qse/si/Makefile.in index 5a7ac3fa..57f0499e 100644 --- a/qse/include/qse/si/Makefile.in +++ b/qse/include/qse/si/Makefile.in @@ -354,7 +354,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/include/qse/si/log.h b/qse/include/qse/si/log.h index 8b03faf2..c776b20c 100644 --- a/qse/include/qse/si/log.h +++ b/qse/include/qse/si/log.h @@ -278,6 +278,18 @@ QSE_EXPORT void qse_log_fini ( 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_log_t* log, const qse_char_t* ident diff --git a/qse/include/qse/xli/Makefile.in b/qse/include/qse/xli/Makefile.in index cd78fba9..6b647ace 100644 --- a/qse/include/qse/xli/Makefile.in +++ b/qse/include/qse/xli/Makefile.in @@ -345,7 +345,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/lib/Makefile.in b/qse/lib/Makefile.in index 1e396f4e..d67318b6 100644 --- a/qse/lib/Makefile.in +++ b/qse/lib/Makefile.in @@ -390,7 +390,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/lib/awk/Makefile.in b/qse/lib/awk/Makefile.in index 25f7b039..f4054100 100644 --- a/qse/lib/awk/Makefile.in +++ b/qse/lib/awk/Makefile.in @@ -546,7 +546,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/lib/cmn/Makefile.am b/qse/lib/cmn/Makefile.am index 3f37728f..1dbb4a62 100644 --- a/qse/lib/cmn/Makefile.am +++ b/qse/lib/cmn/Makefile.am @@ -43,6 +43,7 @@ libqsecmn_la_SOURCES = \ env.c \ gdl.c \ htb.c \ + htl.c \ fma.c \ fmt-intmax.c \ fmt-out.c \ diff --git a/qse/lib/cmn/Makefile.in b/qse/lib/cmn/Makefile.in index e8342e6a..623e9a17 100644 --- a/qse/lib/cmn/Makefile.in +++ b/qse/lib/cmn/Makefile.in @@ -143,8 +143,8 @@ am__DEPENDENCIES_1 = libqsecmn_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am__libqsecmn_la_SOURCES_DIST = alg-base64.c alg-rand.c alg-search.c \ - alg-sort.c arr.c assert.c chr.c dll.c env.c gdl.c htb.c fma.c \ - fmt-intmax.c fmt-out.c hton.c hwad.c ipad.c main.c mb8.c \ + alg-sort.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 \ mbwc.c mbwc-str.c mem.c oht.c opt.c path-base.c path-canon.c \ path-core.c path-merge.c pma.c rbt.c rex.c sll.c slmb.c \ str-beg.c str-cat.c str-chr.c str-cnv.c str-cmp.c str-cpy.c \ @@ -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 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 \ - htb.lo fma.lo fmt-intmax.lo fmt-out.lo hton.lo hwad.lo ipad.lo \ - main.lo mb8.lo mbwc.lo mbwc-str.lo mem.lo oht.lo opt.lo \ - path-base.lo path-canon.lo path-core.lo path-merge.lo pma.lo \ - rbt.lo rex.lo sll.lo slmb.lo str-beg.lo str-cat.lo str-chr.lo \ - str-cnv.lo str-cmp.lo str-cpy.lo str-del.lo str-dup.lo \ - str-dyn.lo str-end.lo str-excl.lo str-fcpy.lo str-fmt.lo \ - str-fnmat.lo str-incl.lo str-join.lo str-len.lo str-pac.lo \ - str-pbrk.lo str-put.lo str-rev.lo str-rot.lo str-set.lo \ - str-spl.lo str-spn.lo str-str.lo str-subst.lo str-tok.lo \ - str-trm.lo str-word.lo time.lo tmr.lo tre.lo tre-ast.lo \ - tre-compile.lo tre-match-bt.lo tre-match-pa.lo tre-parse.lo \ - tre-stack.lo uri.lo utf8.lo xma.lo $(am__objects_1) \ - $(am__objects_2) + htb.lo htl.lo fma.lo fmt-intmax.lo fmt-out.lo hton.lo hwad.lo \ + ipad.lo main.lo mb8.lo mbwc.lo mbwc-str.lo mem.lo oht.lo \ + opt.lo path-base.lo path-canon.lo path-core.lo path-merge.lo \ + pma.lo rbt.lo rex.lo sll.lo slmb.lo str-beg.lo str-cat.lo \ + str-chr.lo str-cnv.lo str-cmp.lo str-cpy.lo str-del.lo \ + str-dup.lo str-dyn.lo str-end.lo str-excl.lo str-fcpy.lo \ + str-fmt.lo str-fnmat.lo str-incl.lo str-join.lo str-len.lo \ + str-pac.lo str-pbrk.lo str-put.lo str-rev.lo str-rot.lo \ + str-set.lo str-spl.lo str-spn.lo str-str.lo str-subst.lo \ + str-tok.lo str-trm.lo str-word.lo time.lo tmr.lo tre.lo \ + tre-ast.lo tre-compile.lo tre-match-bt.lo tre-match-pa.lo \ + tre-parse.lo tre-stack.lo uri.lo utf8.lo xma.lo \ + $(am__objects_1) $(am__objects_2) libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) @@ -443,7 +443,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -486,7 +485,7 @@ noinst_HEADERS = \ va_copy.h 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 \ 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 \ @@ -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)/gdl.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)/hwad.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipad.Plo@am__quote@ diff --git a/qse/lib/cmn/htl.c b/qse/lib/cmn/htl.c new file mode 100644 index 00000000..dfe1ef8b --- /dev/null +++ b/qse/lib/cmn/htl.c @@ -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 +#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 diff --git a/qse/lib/cry/Makefile.in b/qse/lib/cry/Makefile.in index 5c89a84a..638095ee 100644 --- a/qse/lib/cry/Makefile.in +++ b/qse/lib/cry/Makefile.in @@ -377,7 +377,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/lib/http/Makefile.in b/qse/lib/http/Makefile.in index b9fe3203..23d87b3b 100644 --- a/qse/lib/http/Makefile.in +++ b/qse/lib/http/Makefile.in @@ -384,7 +384,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/lib/rad/Makefile.in b/qse/lib/rad/Makefile.in index e5391f81..8fcf8011 100644 --- a/qse/lib/rad/Makefile.in +++ b/qse/lib/rad/Makefile.in @@ -377,7 +377,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/lib/rad/raddic.c b/qse/lib/rad/raddic.c index bee64504..7ec6e6d0 100644 --- a/qse/lib/rad/raddic.c +++ b/qse/lib/rad/raddic.c @@ -62,6 +62,8 @@ struct qse_raddic_t qse_rbt_t attributes_byvalue; qse_rbt_t values_byvalue; qse_rbt_t values_byname; + + qse_raddic_attr_t *last_attr; }; @@ -92,6 +94,57 @@ static const name_id_t type_table[] = { QSE_NULL, 0 } }; +static int comp_xxx (const qse_rbt_t* rbt, const void* kptr, qse_size_t klen, const void* vptr, qse_size_t vlen) +{ + return 0; +} + +static qse_rbt_style_t vendors_byname_style = +{ + { + QSE_RBT_COPIER_INLINE, + QSE_RBT_COPIER_DEFAULT + }, + { + QSE_RBT_FREEER_DEFAULT, + QSE_RBT_FREEER_DEFAULT + }, + comp_xxx, + QSE_RBT_KEEPER_DEFAULT, +}; + +static qse_rbt_style_t vendors_byvalue_style = +{ + { + QSE_RBT_COPIER_INLINE, + QSE_RBT_COPIER_DEFAULT + }, + { + QSE_RBT_FREEER_DEFAULT, + QSE_RBT_FREEER_DEFAULT + }, + QSE_RBT_COMPER_DEFAULT, + QSE_RBT_KEEPER_DEFAULT, +}; + +/* +static qse_rbt_style_t attr_by_name_style = +{ + { + QSE_RBT_COPIER_INLINE, + QSE_RBT_COPIER_DEFAULT + }, + { + QSE_RBT_FREEER_DEFAULT, + QSE_RBT_FREEER_DEFAULT + }, + QSE_RBT_COMPER_DEFAULT, + QSE_RBT_KEEPER_DEFAULT, + QSE_RBT_SIZER_DEFAULT, + QSE_RBT_HASHER_DEFAULT +}; +*/ + int qse_raddic_init (qse_raddic_t* dic, qse_mmgr_t* mmgr) { QSE_MEMSET (dic, 0, QSE_SIZEOF(*dic)); @@ -104,6 +157,8 @@ int qse_raddic_init (qse_raddic_t* dic, qse_mmgr_t* mmgr) qse_rbt_init (&dic->values_byname, mmgr, 1, 1); qse_rbt_init (&dic->values_byvalue, mmgr, 1, 1); + qse_rbt_setstyle (&dic->vendors_byname, &vendors_byname_style); + qse_rbt_setstyle (&dic->vendors_byvalue, &vendors_byvalue_style); return 0; } @@ -117,7 +172,6 @@ void qse_raddic_fini (qse_raddic_t* dic) qse_rbt_fini (&dic->values_byname); } - qse_raddic_t* qse_raddic_open (qse_mmgr_t* mmgr, qse_size_t xtnsize) { qse_raddic_t* dic; @@ -143,12 +197,364 @@ void qse_raddic_close (qse_raddic_t* dic) } -static int str2argv (qse_mchar_t *str, qse_mchar_t* argv[], int max_argc) + +#if 0 +int qse_raddic_addvendor (qse_raddic_t* dic, const qse_char_t *name, int value) +{ + qse_size_t length; + qse_raddic_vendor_t* dv; + + if (value >= 65535) + { + //fr_strerror_printf("dict_addvendor: Cannot handle vendor ID larger than 65535"); + return -1; + } + + /*if ((length = qse_strlen(name)) >= qse_raddic_vendor_t_MAX_NAME_LEN) { + fr_strerror_printf("dict_addvendor: vendor name too long"); + return -1; + }*/ + + if ((dv = QSE_MMGR_ALLOC(dic->mmgr, QSE_SIZEOF(*dv) + (length * QSE_SIZEOF(*name)))) == QSE_NULL) + { + // fr_strerror_printf("dict_addvendor: out of memory"); + return -1; + } + + qse_strcpy(dv->name, name); + dv->vendorpec = value; + dv->type = dv->length = 1; /* defaults */ + + qse_rbt_insert (dic->vendors_byname, + if (!fr_hash_table_insert(vendors_byname, dv)) + { + qse_raddic_vendor_t *old_dv; + + old_dv = fr_hash_table_finddata(vendors_byname, dv); + if (!old_dv) { + fr_strerror_printf("dict_addvendor: Failed inserting vendor name %s", name); + return -1; + } + if (old_dv->vendorpec != dv->vendorpec) { + fr_strerror_printf("dict_addvendor: Duplicate vendor name %s", name); + return -1; + } + + /* + * Already inserted. Discard the duplicate entry. + */ + fr_pool_free(dv); + return 0; + } + + /* + * Insert the SAME pointer (not free'd when this table is + * deleted), into another table. + * + * We want this behaviour because we want OLD names for + * the attributes to be read from the configuration + * files, but when we're printing them, (and looking up + * by value) we want to use the NEW name. + */ + if (!fr_hash_table_replace(vendors_byvalue, dv)) { + fr_strerror_printf("dict_addvendor: Failed inserting vendor %s", + name); + return -1; + } + + return 0; +} +#endif + + +#if 0 // XXX +/* + * Get an attribute by its numerical value. + */ +qse_raddic_attr_t *dict_attrbyvalue(qse_raddic_t* dic, int attr) +{ + qse_raddic_attr_t dattr; + +#if 0 + if ((attr > 0) && (attr < 256)) return dict_base_attrs[attr]; +#endif + + dattr.attr = attr; + dattr.vendor = VENDOR(attr) /*& 0x7fff*/; + + return fr_hash_table_finddata(dic->attributes_byvalue, &dattr); +} + +/* + * Get an attribute by its name. + */ +qse_raddic_attr_t *dict_attrbyname(const char *name) +{ + qse_raddic_attr_t *da; + uint32_t buffer[(QSE_SIZEOF(*da) + qse_raddic_attr_t_MAX_NAME_LEN + 3)/4]; + + if (!name) return QSE_NULL; + + da = (qse_raddic_attr_t *) buffer; + strlcpy(da->name, name, qse_raddic_attr_t_MAX_NAME_LEN + 1); + + return fr_hash_table_finddata(attributes_byname, da); +} + +/* + * Associate a value with an attribute and return it. + */ +qse_raddic_value_t *dict_valbyattr(qse_raddic_t* dic, int attr, int value) +{ + qse_raddic_value_t dval, *dv; + + /* + * First, look up aliases. + */ + dval.attr = attr; + dval.name[0] = '\0'; + + /* + * Look up the attribute alias target, and use + * the correct attribute number if found. + */ + dv = fr_hash_table_finddata(values_byname, &dval); + if (dv) dval.attr = dv->value; + + dval.value = value; + + return fr_hash_table_finddata(values_byvalue, &dval); +} + +/* + * Get a value by its name, keyed off of an attribute. + */ +qse_raddic_value_t *dict_valbyname(qse_raddic_t* dic, int attr, const char *name) +{ + qse_raddic_value_t *my_dv, *dv; + uint32_t buffer[(QSE_SIZEOF(*my_dv) + qse_raddic_value_t_MAX_NAME_LEN + 3)/4]; + + if (!name) return QSE_NULL; + + my_dv = (qse_raddic_value_t *) buffer; + my_dv->attr = attr; + my_dv->name[0] = '\0'; + + /* + * Look up the attribute alias target, and use + * the correct attribute number if found. + */ + dv = fr_hash_table_finddata(values_byname, my_dv); + if (dv) my_dv->attr = dv->value; + + strlcpy(my_dv->name, name, qse_raddic_value_t_MAX_NAME_LEN + 1); + + return fr_hash_table_finddata(values_byname, my_dv); +} + +/* + * Get the vendor PEC based on the vendor name + * + * This is efficient only for small numbers of vendors. + */ +int dict_vendorbyname(const char *name) +{ + qse_raddic_vendor_t *dv; + uint32_t buffer[(QSE_SIZEOF(*dv) + qse_raddic_vendor_t_MAX_NAME_LEN + 3)/4]; + + if (!name) return 0; + + dv = (qse_raddic_vendor_t *) buffer; + strlcpy(dv->name, name, qse_raddic_vendor_t_MAX_NAME_LEN + 1); + + dv = fr_hash_table_finddata(vendors_byname, dv); + if (!dv) return 0; + + return dv->vendorpec; +} + +/* + * Return the vendor struct based on the PEC. + */ +qse_raddic_vendor_t *dict_vendorbyvalue(int vendorpec) +{ + qse_raddic_vendor_t dv; + + dv.vendorpec = vendorpec; + + return fr_hash_table_finddata(vendors_byvalue, &dv); +} + +/* + * Add a value for an attribute to the dictionary. + */ +int dict_addvalue(qse_raddic_t* dic, const qse_char_t* namestr, const qse_char_t* attrstr, int value) +{ + qse_size_t length; + qse_raddic_attr_t* dattr; + qse_raddic_value_t* dval; + + if (!*namestr) + { + //fr_strerror_printf("dict_addvalue: empty names are not permitted"); + return -1; + } + + length = qse_strlen(namestr); + + /* no +1 to length when allocating the space because dval has space for one character */ + if ((dval = QSE_MMGR_ALLOC (dic->mmgr, QSE_SIZEOF(*dval) + (length * QSE_SIZEOF(*namestr)))) == QSE_NULL) + { + //fr_strerror_printf("dict_addvalue: out of memory"); + return -1; + } + QSE_MEMSET(dval, 0, QSE_SIZEOF(*dval)); + + qse_strcpy(dval->name, namestr); + dval->value = value; + + /* + * Most VALUEs are bunched together by ATTRIBUTE. We can + * save a lot of lookups on dictionary initialization by + * caching the last attribute. + */ + if (dic->last_attr && (qse_strcasecmp(attrstr, dic->last_attr->name) == 0)) + { + dattr = dic->last_attr; + } + else + { + dattr = dict_attrbyname(attrstr); + dic->last_attr = dattr; + } + + /* + * Remember which attribute is associated with this + * value, if possible. + */ + if (dattr) + { + if (dattr->flags.has_value_alias) + { + //fr_strerror_printf("dict_addvalue: Cannot add VALUE for ATTRIBUTE \"%s\": It already has a VALUE-ALIAS", attrstr); + return -1; + } + + dval->attr = dattr->attr; + + /* + * Enforce valid values + * + * Don't worry about fixups... + */ + switch (dattr->type) + { + case QSE_RAD_ATTR_TYPE_BYTE: + if (value > 255) + { + fr_pool_free(dval); + fr_strerror_printf("dict_addvalue: ATTRIBUTEs of type 'byte' cannot have VALUEs larger than 255"); + return -1; + } + break; + case QSE_RAD_ATTR_TYPE_SHORT: + if (value > 65535) + { + fr_pool_free(dval); + fr_strerror_printf("dict_addvalue: ATTRIBUTEs of type 'short' cannot have VALUEs larger than 65535"); + return -1; + } + break; + + /* + * Allow octets for now, because + * of dictionary.cablelabs + */ + case QSE_RAD_ATTR_TYPE_OCTETS: + case QSE_RAD_ATTR_TYPE_INTEGER: + break; + + default: + fr_pool_free(dval); + fr_strerror_printf("dict_addvalue: VALUEs cannot be defined for attributes of type '%s'", + fr_int2str(type_table, dattr->type, "?Unknown?")); + return -1; + } + + dattr->flags.has_value = 1; + } + else + { + value_fixup_t *fixup; + + fixup = (value_fixup_t *) malloc(QSE_SIZEOF(*fixup)); + if (!fixup) { + fr_pool_free(dval); + fr_strerror_printf("dict_addvalue: out of memory"); + return -1; + } + QSE_MEMSET(fixup, 0, QSE_SIZEOF(*fixup)); + + strlcpy(fixup->attrstr, attrstr, QSE_SIZEOF(fixup->attrstr)); + fixup->dval = dval; + + /* + * Insert to the head of the list. + */ + fixup->next = value_fixup; + value_fixup = fixup; + + return 0; + } + + /* + * Add the value into the dictionary. + */ + if (!fr_hash_table_insert(values_byname, dval)) + { + if (dattr) + { + qse_raddic_value_t *old; + + /* + * Suppress duplicates with the same + * name and value. There are lots in + * dictionary.ascend. + */ + old = dict_valbyname(dattr->attr, namestr); + if (old && (old->value == dval->value)) + { + fr_pool_free(dval); + return 0; + } + } + + fr_pool_free(dval); + fr_strerror_printf("dict_addvalue: Duplicate value name %s for attribute %s", namestr, attrstr); + return -1; + } + + /* + * There are multiple VALUE's, keyed by attribute, so we + * take care of that here. + */ + if (!fr_hash_table_replace(values_byvalue, dval)) + { + fr_strerror_printf("dict_addvalue: Failed inserting value %s", namestr); + return -1; + } + + return 0; +} + + + +static int str2argv (qse_char_t *str, qse_char_t* argv[], int max_argc) { int nflds, i; - qse_mchar_t* ptr; + qse_char_t* ptr; - nflds = qse_mbsspl (str, QSE_MT(""), QSE_MT('\0'), QSE_MT('\0'), QSE_MT('\0')); + nflds = qse_strspl (str, QSE_T(""), QSE_T('\0'), QSE_T('\0'), QSE_T('\0')); if (nflds <= 0) { return -1; @@ -158,17 +564,56 @@ static int str2argv (qse_mchar_t *str, qse_mchar_t* argv[], int max_argc) for (i = 0; i < nflds; i++) { argv[i] = ptr; - while (*ptr != QSE_MT('\0')) ptr++; + while (*ptr != QSE_T('\0')) ptr++; ptr++; } return nflds; } - - +static int sscanf_i(const qse_char_t *str, int *pvalue) +{ #if 0 -static int process_value(const char* fn, qse_size_t line, qse_mchar_t* argv[], int argc) + int rcode = 0; + int base = 10; + const char *tab = "0123456789"; + + if ((str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X'))) + { + tab = "0123456789abcdef"; + base = 16; + + str += 2; + } + + while (*str) + { + const char *c; + + c = memchr(tab, tolower((int) *str), base); + if (!c) return 0; + + rcode *= base; + rcode += (c - tab); + str++; + } + + *pvalue = rcode; + return 1; +#else + qse_long_t v; + const qse_char_t* end; + QSE_STRTONUM (v, str, &end, 0); + if (*end != '\0') return 0; + *pvalue = v; + return 1; +#endif +} + + + + +static int process_value(const qse_char_t* fn, qse_size_t line, qse_char_t* argv[], int argc) { /* Process the VALUE command */ @@ -176,33 +621,33 @@ static int process_value(const char* fn, qse_size_t line, qse_mchar_t* argv[], i if (argc != 3) { - fr_strerror_printf("dict_init: %s[%d]: invalid VALUE line", fn, line); + /*fr_strerror_printf("dict_init: %s[%d]: invalid VALUE line", fn, line);*/ return -1; } /* For Compatibility, skip "Server-Config" */ - if (qse_mbscasecmp(argv[0], "Server-Config") == 0) return 0; + if (qse_strcasecmp(argv[0], QSE_T("Server-Config")) == 0) return 0; /* Validate all entries */ if (!sscanf_i(argv[2], &value)) { - fr_strerror_printf("dict_init: %s[%d]: invalid value", fn, line); + //fr_strerror_printf("dict_init: %s[%d]: invalid value", fn, line); return -1; } if (dict_addvalue(argv[1], argv[0], value) < 0) { - fr_strerror_printf("dict_init: %s[%d]: %s", fn, line, fr_strerror()); + //fr_strerror_printf("dict_init: %s[%d]: %s", fn, line, fr_strerror()); return -1; } return 0; } -static int load_file (qse_raddic_t* dic, const char *dir, const char *fn, const char *src_file, int src_line) +static int load_file (qse_raddic_t* dic, const qse_char_t *dir, const qse_char_t *fn, const qse_char_t *src_file, int src_line) { qse_sio_t* sio = QSE_NULL; - char dirtmp[256]; + qse_char_t dirtmp[256]; /* TODO: longer path */ char buf[256]; char* p; qse_size_t line = 0; @@ -216,8 +661,8 @@ static int load_file (qse_raddic_t* dic, const char *dir, const char *fn, const qse_raddic_attr_t* da, * block_tlv = QSE_NULL; #if 0 - if (qse_mbslen(fn) >= sizeof(dirtmp) / 2 || - qse_mbslen(dir) >= sizeof(dirtmp) / 2) + if (qse_strlen(fn) >= QSE_SIZEOF(dirtmp) / 2 || + qse_strlen(dir) >= QSE_SIZEOF(dirtmp) / 2) { fr_strerror_printf("dict_init: filename name too long"); return -1; @@ -227,15 +672,15 @@ static int load_file (qse_raddic_t* dic, const char *dir, const char *fn, const * First see if fn is relative to dir. If so, create * new filename. If not, remember the absolute dir. */ - if ((p = strrchr(fn, FR_DIR_SEP)) != NULL) + if ((p = qse_strrchr(fn, FR_DIR_SEP)) != QSE_NULL) { - qse_mbscpy(dirtmp, fn); + qse_strcpy(dirtmp, fn); dirtmp[p - fn] = 0; dir = dirtmp; } - else if (dir && dir[0] && qse_mbscmp(dir, ".") != 0) + else if (dir && dir[0] && qse_strcmp(dir, ".") != 0) { - snprintf(dirtmp, sizeof(dirtmp), "%s/%s", dir, fn); + snprintf(dirtmp, QSE_SIZEOF(dirtmp), "%s/%s", dir, fn); fn = dirtmp; } #endif @@ -270,7 +715,7 @@ static int load_file (qse_raddic_t* dic, const char *dir, const char *fn, const /* * Seed the random pool with data. */ - fr_rand_seed(&statbuf, sizeof(statbuf)); + fr_rand_seed(&statbuf, QSE_SIZEOF(statbuf)); #endif block_vendor = 0; @@ -279,14 +724,14 @@ static int load_file (qse_raddic_t* dic, const char *dir, const char *fn, const { line++; - qse_mbspac (buf); + qse_strpac (buf); if (buf[0] == QSE_MT('\0') || buf[0] == QSE_MT('#')) continue; /* * Comment characters should NOT be appearing anywhere but * as start of a comment; */ - p = qse_mbschr (buf, QSE_MT('#')); + p = qse_strchr (buf, QSE_MT('#')); if (p) *p = '\0'; argc = str2argv(buf, argv, QSE_COUNTOF(argv)); @@ -301,7 +746,7 @@ static int load_file (qse_raddic_t* dic, const char *dir, const char *fn, const /* * Process VALUE lines. */ - if (qse_mbscasecmp(argv[0], "VALUE") == 0) + if (qse_strcasecmp(argv[0], QSE_T("VALUE")) == 0) { if (process_value(fn, line, argv + 1, argc - 1) == -1) goto oops; continue; @@ -310,7 +755,7 @@ static int load_file (qse_raddic_t* dic, const char *dir, const char *fn, const /* * Perhaps this is an attribute. */ - if (qse_mbscasecmp(argv[0], "ATTRIBUTE") == 0) + if (qse_strcasecmp(argv[0], QSE_T("ATTRIBUTE")) == 0) { if (process_attribute(fn, line, block_vendor, block_tlv, argv + 1, argc - 1) == -1) goto oops; continue; @@ -319,13 +764,13 @@ static int load_file (qse_raddic_t* dic, const char *dir, const char *fn, const /* * See if we need to import another dictionary. */ - if (qse_mbscasecmp(argv[0], "$INCLUDE") == 0) + if (qse_strcasecmp(argv[0], QSE_T("$INCLUDE")) == 0) { - if (my_dict_init(dir, argv[1], fn, line) < 0) goto oops; + if (load_file(dir, argv[1], fn, line) < 0) goto oops; continue; } /* $INCLUDE */ - if (qse_mbscasecmp(argv[0], "VALUE-ALIAS") == 0) + if (qse_strcasecmp(argv[0], QSE_T("VALUE-ALIAS")) == 0) { if (process_value_alias(fn, line, argv + 1, argc - 1) == -1) goto oops; continue; @@ -334,13 +779,13 @@ static int load_file (qse_raddic_t* dic, const char *dir, const char *fn, const /* * Process VENDOR lines. */ - if (qse_mbscasecmp(argv[0], "VENDOR") == 0) + if (qse_strcasecmp(argv[0], QSE_T("VENDOR")) == 0) { if (process_vendor(fn, line, argv + 1, argc - 1) == -1) goto oops; continue; } - if (qse_mbscasecmp(argv[0], "BEGIN-TLV") == 0) + if (qse_strcasecmp(argv[0], QSE_T("BEGIN-TLV")) == 0) { if (argc != 2) { @@ -365,7 +810,7 @@ static int load_file (qse_raddic_t* dic, const char *dir, const char *fn, const continue; } /* BEGIN-TLV */ - if (qse_mbscasecmp(argv[0], "END-TLV") == 0) + if (qse_strcasecmp(argv[0], "END-TLV") == 0) { if (argc != 2) { @@ -385,11 +830,11 @@ static int load_file (qse_raddic_t* dic, const char *dir, const char *fn, const fr_strerror_printf("dict_init: %s[%d]: END-TLV %s does not match any previous BEGIN-TLV", fn, line, argv[1]); goto oops; } - block_tlv = NULL; + block_tlv = QSE_NULL; continue; } /* END-VENDOR */ - if (qse_mbscasecmp(argv[0], "BEGIN-VENDOR") == 0) { + if (qse_strcasecmp(argv[0], "BEGIN-VENDOR") == 0) { if (argc != 2) { fr_strerror_printf("dict_init: %s[%d] invalid BEGIN-VENDOR entry", fn, line); goto oops; @@ -404,7 +849,7 @@ static int load_file (qse_raddic_t* dic, const char *dir, const char *fn, const continue; } /* BEGIN-VENDOR */ - if (qse_mbscasecmp(argv[0], "END-VENDOR") == 0) + if (qse_strcasecmp(argv[0], QSE_T("END-VENDOR")) == 0) { if (argc != 2) { fr_strerror_printf("dict_init: %s[%d] invalid END-VENDOR entry", fn, line); @@ -445,43 +890,27 @@ oops: return -1; } - -#endif - - - - - - - - - - - - - - - - - - +static int qse_raddic_load (qse_raddic_t* dic, const qse_char_t* file) +{ + return load_file (dic, QSE_NULL, file, QSE_NULL, 0); +} #if 0 -#define DICT_VALUE_MAX_NAME_LEN (128) -#define DICT_VENDOR_MAX_NAME_LEN (128) -#define DICT_ATTR_MAX_NAME_LEN (128) +#define qse_raddic_value_t_MAX_NAME_LEN (128) +#define qse_raddic_vendor_t_MAX_NAME_LEN (128) +#define qse_raddic_attr_t_MAX_NAME_LEN (128) -static fr_hash_table_t *vendors_byname = NULL; -static fr_hash_table_t *vendors_byvalue = NULL; +static fr_hash_table_t *vendors_byname = QSE_NULL; +static fr_hash_table_t *vendors_byvalue = QSE_NULL; -static fr_hash_table_t *attributes_byname = NULL; -static fr_hash_table_t *attributes_byvalue = NULL; +static fr_hash_table_t *attributes_byname = QSE_NULL; +static fr_hash_table_t *attributes_byvalue = QSE_NULL; -static fr_hash_table_t *values_byvalue = NULL; -static fr_hash_table_t *values_byname = NULL; +static fr_hash_table_t *values_byvalue = QSE_NULL; +static fr_hash_table_t *values_byname = QSE_NULL; -static DICT_ATTR *dict_base_attrs[256]; +static qse_raddic_attr_t *dict_base_attrs[256]; /* * For faster HUP's, we cache the stat information for @@ -493,15 +922,15 @@ typedef struct dict_stat_t { time_t mtime; } dict_stat_t; -static char *stat_root_dir = NULL; -static char *stat_root_file = NULL; +static char *stat_root_dir = QSE_NULL; +static char *stat_root_file = QSE_NULL; -static dict_stat_t *stat_head = NULL; -static dict_stat_t *stat_tail = NULL; +static dict_stat_t *stat_head = QSE_NULL; +static dict_stat_t *stat_tail = QSE_NULL; typedef struct value_fixup_t { - char attrstr[DICT_ATTR_MAX_NAME_LEN]; - DICT_VALUE *dval; + char attrstr[qse_raddic_attr_t_MAX_NAME_LEN]; + qse_raddic_value_t *dval; struct value_fixup_t *next; } value_fixup_t; @@ -509,7 +938,7 @@ typedef struct value_fixup_t { /* * So VALUEs in the dictionary can have forward references. */ -static value_fixup_t *value_fixup = NULL; +static value_fixup_t *value_fixup = QSE_NULL; static const FR_NAME_NUMBER type_table[] = { { "integer", QSE_RAD_ATTR_TYPE_INTEGER }, @@ -527,7 +956,7 @@ static const FR_NAME_NUMBER type_table[] = { { "combo-ip", QSE_RAD_ATTR_TYPE_COMBO_IP }, { "tlv", QSE_RAD_ATTR_TYPE_TLV }, { "signed", QSE_RAD_ATTR_TYPE_SIGNED }, - { NULL, 0 } + { QSE_NULL, 0 } }; @@ -561,13 +990,13 @@ static uint32_t dict_hashname(const char *name) */ static uint32_t dict_attr_name_hash(const void *data) { - return dict_hashname(((const DICT_ATTR *)data)->name); + return dict_hashname(((const qse_raddic_attr_t *)data)->name); } static int dict_attr_name_cmp(const void *one, const void *two) { - const DICT_ATTR *a = one; - const DICT_ATTR *b = two; + const qse_raddic_attr_t *a = one; + const qse_raddic_attr_t *b = two; return qse_mbscasecmp(a->name, b->name); } @@ -575,16 +1004,16 @@ static int dict_attr_name_cmp(const void *one, const void *two) static uint32_t dict_attr_value_hash(const void *data) { uint32_t hash; - const DICT_ATTR *attr = data; + const qse_raddic_attr_t *attr = data; - hash = fr_hash(&attr->vendor, sizeof(attr->vendor)); - return fr_hash_update(&attr->attr, sizeof(attr->attr), hash); + hash = fr_hash(&attr->vendor, QSE_SIZEOF(attr->vendor)); + return fr_hash_update(&attr->attr, QSE_SIZEOF(attr->attr), hash); } static int dict_attr_value_cmp(const void *one, const void *two) { - const DICT_ATTR *a = one; - const DICT_ATTR *b = two; + const qse_raddic_attr_t *a = one; + const qse_raddic_attr_t *b = two; if (a->vendor < b->vendor) return -1; if (a->vendor > b->vendor) return +1; @@ -594,27 +1023,27 @@ static int dict_attr_value_cmp(const void *one, const void *two) static uint32_t dict_vendor_name_hash(const void *data) { - return dict_hashname(((const DICT_VENDOR *)data)->name); + return dict_hashname(((const qse_raddic_vendor_t *)data)->name); } static int dict_vendor_name_cmp(const void *one, const void *two) { - const DICT_VENDOR *a = one; - const DICT_VENDOR *b = two; + const qse_raddic_vendor_t *a = one; + const qse_raddic_vendor_t *b = two; return qse_mbscasecmp(a->name, b->name); } static uint32_t dict_vendor_value_hash(const void *data) { - return fr_hash(&(((const DICT_VENDOR *)data)->vendorpec), - sizeof(((const DICT_VENDOR *)data)->vendorpec)); + return fr_hash(&(((const qse_raddic_vendor_t *)data)->vendorpec), + QSE_SIZEOF(((const qse_raddic_vendor_t *)data)->vendorpec)); } static int dict_vendor_value_cmp(const void *one, const void *two) { - const DICT_VENDOR *a = one; - const DICT_VENDOR *b = two; + const qse_raddic_vendor_t *a = one; + const qse_raddic_vendor_t *b = two; return a->vendorpec - b->vendorpec; } @@ -622,17 +1051,17 @@ static int dict_vendor_value_cmp(const void *one, const void *two) static uint32_t dict_value_name_hash(const void *data) { uint32_t hash; - const DICT_VALUE *dval = data; + const qse_raddic_value_t *dval = data; hash = dict_hashname(dval->name); - return fr_hash_update(&dval->attr, sizeof(dval->attr), hash); + return fr_hash_update(&dval->attr, QSE_SIZEOF(dval->attr), hash); } static int dict_value_name_cmp(const void *one, const void *two) { int rcode; - const DICT_VALUE *a = one; - const DICT_VALUE *b = two; + const qse_raddic_value_t *a = one; + const qse_raddic_value_t *b = two; rcode = a->attr - b->attr; if (rcode != 0) return rcode; @@ -643,17 +1072,17 @@ static int dict_value_name_cmp(const void *one, const void *two) static uint32_t dict_value_value_hash(const void *data) { uint32_t hash; - const DICT_VALUE *dval = data; + const qse_raddic_value_t *dval = data; - hash = fr_hash(&dval->attr, sizeof(dval->attr)); - return fr_hash_update(&dval->value, sizeof(dval->value), hash); + hash = fr_hash(&dval->attr, QSE_SIZEOF(dval->attr)); + return fr_hash_update(&dval->value, QSE_SIZEOF(dval->value), hash); } static int dict_value_value_cmp(const void *one, const void *two) { int rcode; - const DICT_VALUE *a = one; - const DICT_VALUE *b = two; + const qse_raddic_value_t *a = one; + const qse_raddic_value_t *b = two; rcode = a->attr - b->attr; if (rcode != 0) return rcode; @@ -670,22 +1099,22 @@ static void dict_stat_free(void) dict_stat_t *this, *next; free(stat_root_dir); - stat_root_dir = NULL; + stat_root_dir = QSE_NULL; free(stat_root_file); - stat_root_file = NULL; + stat_root_file = QSE_NULL; if (!stat_head) { - stat_tail = NULL; + stat_tail = QSE_NULL; return; } - for (this = stat_head; this != NULL; this = next) { + for (this = stat_head; this != QSE_NULL; this = next) { next = this->next; free(this->name); free(this); } - stat_head = stat_tail = NULL; + stat_head = stat_tail = QSE_NULL; } @@ -696,9 +1125,9 @@ static void dict_stat_add(const char *name, const struct stat *stat_buf) { dict_stat_t *this; - this = malloc(sizeof(*this)); + this = malloc(QSE_SIZEOF(*this)); if (!this) return; - QSE_MEMSET(this, 0, sizeof(*this)); + QSE_MEMSET(this, 0, QSE_SIZEOF(*this)); this->name = strdup(name); this->mtime = stat_buf->st_mtime; @@ -729,7 +1158,7 @@ static int dict_stat_check(const char *root_dir, const char *root_file) if (!stat_head) return 0; /* changed, reload */ - for (this = stat_head; this != NULL; this = this->next) { + for (this = stat_head; this != QSE_NULL; this = this->next) { if (stat(this->name, &buf) < 0) return 0; if (buf.st_mtime != this->mtime) return 0; @@ -748,20 +1177,20 @@ typedef struct fr_pool_t { #define FR_POOL_SIZE (32768) #define FR_ALLOC_ALIGN (8) -static fr_pool_t *dict_pool = NULL; +static fr_pool_t *dict_pool = QSE_NULL; static fr_pool_t *fr_pool_create(void) { fr_pool_t *fp = malloc(FR_POOL_SIZE); - if (!fp) return NULL; + if (!fp) return QSE_NULL; QSE_MEMSET(fp, 0, FR_POOL_SIZE); fp->page_end = ((uint8_t *) fp) + FR_POOL_SIZE; - fp->free_ptr = ((uint8_t *) fp) + sizeof(*fp); + fp->free_ptr = ((uint8_t *) fp) + QSE_SIZEOF(*fp); fp->page_free = fp; - fp->page_next = NULL; + fp->page_next = QSE_NULL; return fp; } @@ -771,7 +1200,7 @@ static void fr_pool_delete(fr_pool_t **pfp) if (!pfp || !*pfp) return; - for (fp = *pfp; fp != NULL; fp = next) { + for (fp = *pfp; fp != QSE_NULL; fp = next) { next = fp->page_next; free(fp); } @@ -782,13 +1211,13 @@ static void *fr_pool_alloc(size_t size) { void *ptr; - if (size == 0) return NULL; + if (size == 0) return QSE_NULL; - if (size > 256) return NULL; /* shouldn't happen */ + if (size > 256) return QSE_NULL; /* shouldn't happen */ if (!dict_pool) { dict_pool = fr_pool_create(); - if (!dict_pool) return NULL; + if (!dict_pool) return QSE_NULL; } if ((size & (FR_ALLOC_ALIGN - 1)) != 0) { @@ -797,7 +1226,7 @@ static void *fr_pool_alloc(size_t size) if ((((uint8_t *) dict_pool->page_free->free_ptr) + size) > (uint8_t *) dict_pool->page_free->page_end) { dict_pool->page_free->page_next = fr_pool_create(); - if (!dict_pool->page_free->page_next) return NULL; + if (!dict_pool->page_free->page_next) return QSE_NULL; dict_pool->page_free = dict_pool->page_free->page_next; } @@ -825,20 +1254,20 @@ void dict_free(void) */ fr_hash_table_free(vendors_byname); fr_hash_table_free(vendors_byvalue); - vendors_byname = NULL; - vendors_byvalue = NULL; + vendors_byname = QSE_NULL; + vendors_byvalue = QSE_NULL; fr_hash_table_free(attributes_byname); fr_hash_table_free(attributes_byvalue); - attributes_byname = NULL; - attributes_byvalue = NULL; + attributes_byname = QSE_NULL; + attributes_byvalue = QSE_NULL; fr_hash_table_free(values_byname); fr_hash_table_free(values_byvalue); - values_byname = NULL; - values_byvalue = NULL; + values_byname = QSE_NULL; + values_byvalue = QSE_NULL; - QSE_MEMSET(dict_base_attrs, 0, sizeof(dict_base_attrs)); + QSE_MEMSET(dict_base_attrs, 0, QSE_SIZEOF(dict_base_attrs)); fr_pool_delete(&dict_pool); @@ -846,73 +1275,6 @@ void dict_free(void) } -/* - * Add vendor to the list. - */ -int dict_addvendor(const char *name, int value) -{ - size_t length; - DICT_VENDOR *dv; - - /* BACON */ - /*if (value >= 32767) {*/ - if (value >= 65535) { - /* END BACON */ - fr_strerror_printf("dict_addvendor: Cannot handle vendor ID larger than 65535"); - return -1; - } - - if ((length = qse_mbslen(name)) >= DICT_VENDOR_MAX_NAME_LEN) { - fr_strerror_printf("dict_addvendor: vendor name too long"); - return -1; - } - - if ((dv = fr_pool_alloc(sizeof(*dv) + length)) == NULL) { - fr_strerror_printf("dict_addvendor: out of memory"); - return -1; - } - - qse_mbscpy(dv->name, name); - dv->vendorpec = value; - dv->type = dv->length = 1; /* defaults */ - - if (!fr_hash_table_insert(vendors_byname, dv)) { - DICT_VENDOR *old_dv; - - old_dv = fr_hash_table_finddata(vendors_byname, dv); - if (!old_dv) { - fr_strerror_printf("dict_addvendor: Failed inserting vendor name %s", name); - return -1; - } - if (old_dv->vendorpec != dv->vendorpec) { - fr_strerror_printf("dict_addvendor: Duplicate vendor name %s", name); - return -1; - } - - /* - * Already inserted. Discard the duplicate entry. - */ - fr_pool_free(dv); - return 0; - } - - /* - * Insert the SAME pointer (not free'd when this table is - * deleted), into another table. - * - * We want this behaviour because we want OLD names for - * the attributes to be read from the configuration - * files, but when we're printing them, (and looking up - * by value) we want to use the NEW name. - */ - if (!fr_hash_table_replace(vendors_byvalue, dv)) { - fr_strerror_printf("dict_addvendor: Failed inserting vendor %s", - name); - return -1; - } - - return 0; -} /* * Add an attribute to the dictionary. @@ -922,10 +1284,10 @@ int dict_addattr(const char *name, int vendor, int type, int value, { size_t namelen; static int max_attr = 0; - DICT_ATTR *attr; + qse_raddic_attr_t *attr; namelen = qse_mbslen(name); - if (namelen >= DICT_ATTR_MAX_NAME_LEN) { + if (namelen >= qse_raddic_attr_t_MAX_NAME_LEN) { fr_strerror_printf("dict_addattr: attribute name too long"); return -1; } @@ -963,8 +1325,8 @@ int dict_addattr(const char *name, int vendor, int type, int value, } if (vendor) { - DICT_VENDOR *dv; - static DICT_VENDOR *last_vendor = NULL; + qse_raddic_vendor_t *dv; + static qse_raddic_vendor_t *last_vendor = QSE_NULL; if (flags.is_tlv && (flags.encrypt != FLAG_ENCRYPT_NONE)) { fr_strerror_printf("Sub-TLV's cannot be encrypted"); @@ -1020,7 +1382,7 @@ int dict_addattr(const char *name, int vendor, int type, int value, /* * Create a new attribute for the list */ - if ((attr = fr_pool_alloc(sizeof(*attr) + namelen)) == NULL) { + if ((attr = fr_pool_alloc(QSE_SIZEOF(*attr) + namelen)) == QSE_NULL) { fr_strerror_printf("dict_addattr: out of memory"); return -1; } @@ -1038,7 +1400,7 @@ int dict_addattr(const char *name, int vendor, int type, int value, * Insert the attribute, only if it's not a duplicate. */ if (!fr_hash_table_insert(attributes_byname, attr)) { - DICT_ATTR *a; + qse_raddic_attr_t *a; /* * If the attribute has identical number, then @@ -1092,169 +1454,6 @@ int dict_addattr(const char *name, int vendor, int type, int value, } -/* - * Add a value for an attribute to the dictionary. - */ -int dict_addvalue(const char *namestr, const char *attrstr, int value) -{ - qse_size_t length; - DICT_ATTR* dattr; - DICT_VALUE* dval; - - static DICT_ATTR *last_attr = NULL; - - if (!*namestr) - { - fr_strerror_printf("dict_addvalue: empty names are not permitted"); - return -1; - } - - if ((length = qse_mbslen(namestr)) >= DICT_VALUE_MAX_NAME_LEN) - { - fr_strerror_printf("dict_addvalue: value name too long"); - return -1; - } - - if ((dval = fr_pool_alloc(sizeof(*dval) + length)) == NULL) - { - fr_strerror_printf("dict_addvalue: out of memory"); - return -1; - } - QSE_MEMSET(dval, 0, sizeof(*dval)); - - qse_mbscpy(dval->name, namestr); - dval->value = value; - - /* - * Most VALUEs are bunched together by ATTRIBUTE. We can - * save a lot of lookups on dictionary initialization by - * caching the last attribute. - */ - if (last_attr && (qse_mbscasecmp(attrstr, last_attr->name) == 0)) { - dattr = last_attr; - } else { - dattr = dict_attrbyname(attrstr); - last_attr = dattr; - } - - /* - * Remember which attribute is associated with this - * value, if possible. - */ - if (dattr) - { - if (dattr->flags.has_value_alias) - { - fr_strerror_printf("dict_addvalue: Cannot add VALUE for ATTRIBUTE \"%s\": It already has a VALUE-ALIAS", attrstr); - return -1; - } - - dval->attr = dattr->attr; - - /* - * Enforce valid values - * - * Don't worry about fixups... - */ - switch (dattr->type) - { - case QSE_RAD_ATTR_TYPE_BYTE: - if (value > 255) - { - fr_pool_free(dval); - fr_strerror_printf("dict_addvalue: ATTRIBUTEs of type 'byte' cannot have VALUEs larger than 255"); - return -1; - } - break; - case QSE_RAD_ATTR_TYPE_SHORT: - if (value > 65535) - { - fr_pool_free(dval); - fr_strerror_printf("dict_addvalue: ATTRIBUTEs of type 'short' cannot have VALUEs larger than 65535"); - return -1; - } - break; - - /* - * Allow octets for now, because - * of dictionary.cablelabs - */ - case QSE_RAD_ATTR_TYPE_OCTETS: - case QSE_RAD_ATTR_TYPE_INTEGER: - break; - - default: - fr_pool_free(dval); - fr_strerror_printf("dict_addvalue: VALUEs cannot be defined for attributes of type '%s'", - fr_int2str(type_table, dattr->type, "?Unknown?")); - return -1; - } - - dattr->flags.has_value = 1; - } - else - { - value_fixup_t *fixup; - - fixup = (value_fixup_t *) malloc(sizeof(*fixup)); - if (!fixup) { - fr_pool_free(dval); - fr_strerror_printf("dict_addvalue: out of memory"); - return -1; - } - QSE_MEMSET(fixup, 0, sizeof(*fixup)); - - strlcpy(fixup->attrstr, attrstr, sizeof(fixup->attrstr)); - fixup->dval = dval; - - /* - * Insert to the head of the list. - */ - fixup->next = value_fixup; - value_fixup = fixup; - - return 0; - } - - /* - * Add the value into the dictionary. - */ - if (!fr_hash_table_insert(values_byname, dval)) - { - if (dattr) - { - DICT_VALUE *old; - - /* - * Suppress duplicates with the same - * name and value. There are lots in - * dictionary.ascend. - */ - old = dict_valbyname(dattr->attr, namestr); - if (old && (old->value == dval->value)) - { - fr_pool_free(dval); - return 0; - } - } - - fr_pool_free(dval); - fr_strerror_printf("dict_addvalue: Duplicate value name %s for attribute %s", namestr, attrstr); - return -1; - } - - /* - * There are multiple VALUE's, keyed by attribute, so we - * take care of that here. - */ - if (!fr_hash_table_replace(values_byvalue, dval)) - { - fr_strerror_printf("dict_addvalue: Failed inserting value %s", namestr); - return -1; - } - - return 0; -} static int sscanf_i(const char *str, int *pvalue) { @@ -1291,7 +1490,7 @@ static int sscanf_i(const char *str, int *pvalue) */ static int process_attribute ( const char* fn, const qse_size_t line, - const int block_vendor, DICT_ATTR *block_tlv, + const int block_vendor, qse_raddic_attr_t *block_tlv, char **argv, int argc) { int vendor = 0; @@ -1328,7 +1527,7 @@ static int process_attribute ( * Only look up the vendor if the string * is non-empty. */ - QSE_MEMSET (&flags, 0, sizeof(flags)); + QSE_MEMSET (&flags, 0, QSE_SIZEOF(flags)); if (argc == 4) { char *key, *next, *last; @@ -1465,21 +1664,18 @@ static int process_value(const char* fn, const qse_size_t line, char **argv, /* * For Compatibility, skip "Server-Config" */ - if (qse_mbscasecmp(argv[0], "Server-Config") == 0) - return 0; + if (qse_mbscasecmp(argv[0], "Server-Config") == 0) return 0; /* * Validate all entries */ if (!sscanf_i(argv[2], &value)) { - fr_strerror_printf("dict_init: %s[%d]: invalid value", - fn, line); + fr_strerror_printf("dict_init: %s[%d]: invalid value", fn, line); return -1; } if (dict_addvalue(argv[1], argv[0], value) < 0) { - fr_strerror_printf("dict_init: %s[%d]: %s", - fn, line, fr_strerror()); + fr_strerror_printf("dict_init: %s[%d]: %s", fn, line, fr_strerror()); return -1; } @@ -1496,12 +1692,11 @@ static int process_value(const char* fn, const qse_size_t line, char **argv, static int process_value_alias(const char* fn, const qse_size_t line, char **argv, int argc) { - DICT_ATTR *my_da, *da; - DICT_VALUE *dval; + qse_raddic_attr_t *my_da, *da; + qse_raddic_value_t *dval; if (argc != 2) { - fr_strerror_printf("dict_init: %s[%d]: invalid VALUE-ALIAS line", - fn, line); + fr_strerror_printf("dict_init: %s[%d]: invalid VALUE-ALIAS line", fn, line); return -1; } @@ -1549,7 +1744,7 @@ static int process_value_alias(const char* fn, const qse_size_t line, char **arg return -1; } - if ((dval = fr_pool_alloc(sizeof(*dval))) == NULL) { + if ((dval = fr_pool_alloc(QSE_SIZEOF(*dval))) == QSE_NULL) { fr_strerror_printf("dict_addvalue: out of memory"); return -1; } @@ -1577,7 +1772,7 @@ static int process_vendor(const char* fn, const qse_size_t line, char **argv, { int value; int continuation = 0; - const char *format = NULL; + const char *format = QSE_NULL; if ((argc < 2) || (argc > 3)) { fr_strerror_printf( "dict_init: %s[%d] invalid VENDOR entry", @@ -1622,7 +1817,7 @@ static int process_vendor(const char* fn, const qse_size_t line, char **argv, if (format) { int type, length; const char *p; - DICT_VENDOR *dv; + qse_raddic_vendor_t *dv; if (strncasecmp(format, "format=", 7) != 0) { fr_strerror_printf("dict_init: %s[%d]: Invalid format for VENDOR. Expected \"format=\", got \"%s\"", @@ -1738,10 +1933,10 @@ static int my_dict_init(const char *dir, const char *fn, struct stat statbuf; char *argv[MAX_ARGV]; int argc; - DICT_ATTR *da, *block_tlv = NULL; + qse_raddic_attr_t *da, *block_tlv = QSE_NULL; - if (qse_mbslen(fn) >= sizeof(dirtmp) / 2 || - qse_mbslen(dir) >= sizeof(dirtmp) / 2) { + if (qse_mbslen(fn) >= QSE_SIZEOF(dirtmp) / 2 || + qse_mbslen(dir) >= QSE_SIZEOF(dirtmp) / 2) { fr_strerror_printf("dict_init: filename name too long"); return -1; } @@ -1750,16 +1945,16 @@ static int my_dict_init(const char *dir, const char *fn, * First see if fn is relative to dir. If so, create * new filename. If not, remember the absolute dir. */ - if ((p = strrchr(fn, FR_DIR_SEP)) != NULL) { + if ((p = strrchr(fn, FR_DIR_SEP)) != QSE_NULL) { qse_mbscpy(dirtmp, fn); dirtmp[p - fn] = 0; dir = dirtmp; } else if (dir && dir[0] && qse_mbscmp(dir, ".") != 0) { - snprintf(dirtmp, sizeof(dirtmp), "%s/%s", dir, fn); + snprintf(dirtmp, QSE_SIZEOF(dirtmp), "%s/%s", dir, fn); fn = dirtmp; } - if ((fp = fopen(fn, "r")) == NULL) { + if ((fp = fopen(fn, "r")) == QSE_NULL) { if (!src_file) { fr_strerror_printf("dict_init: Couldn't open dictionary \"%s\": %s", fn, strerror(errno)); @@ -1796,11 +1991,11 @@ static int my_dict_init(const char *dir, const char *fn, /* * Seed the random pool with data. */ - fr_rand_seed(&statbuf, sizeof(statbuf)); + fr_rand_seed(&statbuf, QSE_SIZEOF(statbuf)); block_vendor = 0; - while (fgets(buf, sizeof(buf), fp) != NULL) { + while (fgets(buf, QSE_SIZEOF(buf), fp) != QSE_NULL) { line++; if (buf[0] == '#' || buf[0] == 0 || buf[0] == '\n' || buf[0] == '\r') @@ -1935,7 +2130,7 @@ static int my_dict_init(const char *dir, const char *fn, fclose(fp); return -1; } - block_tlv = NULL; + block_tlv = QSE_NULL; continue; } /* END-VENDOR */ @@ -2099,16 +2294,16 @@ int dict_init(const char *dir, const char *fn) return -1; } - value_fixup = NULL; /* just to be safe. */ + value_fixup = QSE_NULL; /* just to be safe. */ - if (my_dict_init(dir, fn, NULL, 0) < 0) + if (my_dict_init(dir, fn, QSE_NULL, 0) < 0) return -1; if (value_fixup) { - DICT_ATTR *a; + qse_raddic_attr_t *a; value_fixup_t *this, *next; - for (this = value_fixup; this != NULL; this = next) { + for (this = value_fixup; this != QSE_NULL; this = next) { next = this->next; a = dict_attrbyname(this->attrstr); @@ -2154,132 +2349,20 @@ int dict_init(const char *dir, const char *fn) * lookups, and we don't want multi-threaded re-ordering * of the table entries. That would be bad. */ - fr_hash_table_walk(vendors_byname, null_callback, NULL); - fr_hash_table_walk(vendors_byvalue, null_callback, NULL); + fr_hash_table_walk(vendors_byname, null_callback, QSE_NULL); + fr_hash_table_walk(vendors_byvalue, null_callback, QSE_NULL); - fr_hash_table_walk(attributes_byname, null_callback, NULL); - fr_hash_table_walk(attributes_byvalue, null_callback, NULL); + fr_hash_table_walk(attributes_byname, null_callback, QSE_NULL); + fr_hash_table_walk(attributes_byvalue, null_callback, QSE_NULL); - fr_hash_table_walk(values_byvalue, null_callback, NULL); - fr_hash_table_walk(values_byname, null_callback, NULL); + fr_hash_table_walk(values_byvalue, null_callback, QSE_NULL); + fr_hash_table_walk(values_byname, null_callback, QSE_NULL); return 0; } -/* - * Get an attribute by its numerical value. - */ -DICT_ATTR *dict_attrbyvalue(int attr) -{ - DICT_ATTR dattr; - if ((attr > 0) && (attr < 256)) return dict_base_attrs[attr]; - - dattr.attr = attr; - /* BACON */ - dattr.vendor = VENDOR(attr) /*& 0x7fff*/; - /* END BACON */ - - return fr_hash_table_finddata(attributes_byvalue, &dattr); -} - -/* - * Get an attribute by its name. - */ -DICT_ATTR *dict_attrbyname(const char *name) -{ - DICT_ATTR *da; - uint32_t buffer[(sizeof(*da) + DICT_ATTR_MAX_NAME_LEN + 3)/4]; - - if (!name) return NULL; - - da = (DICT_ATTR *) buffer; - strlcpy(da->name, name, DICT_ATTR_MAX_NAME_LEN + 1); - - return fr_hash_table_finddata(attributes_byname, da); -} - -/* - * Associate a value with an attribute and return it. - */ -DICT_VALUE *dict_valbyattr(int attr, int value) -{ - DICT_VALUE dval, *dv; - - /* - * First, look up aliases. - */ - dval.attr = attr; - dval.name[0] = '\0'; - - /* - * Look up the attribute alias target, and use - * the correct attribute number if found. - */ - dv = fr_hash_table_finddata(values_byname, &dval); - if (dv) dval.attr = dv->value; - - dval.value = value; - - return fr_hash_table_finddata(values_byvalue, &dval); -} - -/* - * Get a value by its name, keyed off of an attribute. - */ -DICT_VALUE *dict_valbyname(int attr, const char *name) -{ - DICT_VALUE *my_dv, *dv; - uint32_t buffer[(sizeof(*my_dv) + DICT_VALUE_MAX_NAME_LEN + 3)/4]; - - if (!name) return NULL; - - my_dv = (DICT_VALUE *) buffer; - my_dv->attr = attr; - my_dv->name[0] = '\0'; - - /* - * Look up the attribute alias target, and use - * the correct attribute number if found. - */ - dv = fr_hash_table_finddata(values_byname, my_dv); - if (dv) my_dv->attr = dv->value; - - strlcpy(my_dv->name, name, DICT_VALUE_MAX_NAME_LEN + 1); - - return fr_hash_table_finddata(values_byname, my_dv); -} - -/* - * Get the vendor PEC based on the vendor name - * - * This is efficient only for small numbers of vendors. - */ -int dict_vendorbyname(const char *name) -{ - DICT_VENDOR *dv; - uint32_t buffer[(sizeof(*dv) + DICT_VENDOR_MAX_NAME_LEN + 3)/4]; - - if (!name) return 0; - - dv = (DICT_VENDOR *) buffer; - strlcpy(dv->name, name, DICT_VENDOR_MAX_NAME_LEN + 1); - - dv = fr_hash_table_finddata(vendors_byname, dv); - if (!dv) return 0; - - return dv->vendorpec; -} - -/* - * Return the vendor struct based on the PEC. - */ -DICT_VENDOR *dict_vendorbyvalue(int vendorpec) -{ - DICT_VENDOR dv; - - dv.vendorpec = vendorpec; - - return fr_hash_table_finddata(vendors_byvalue, &dv); -} #endif + + +#endif //XXX diff --git a/qse/lib/sed/Makefile.in b/qse/lib/sed/Makefile.in index 00ee4a3d..796bb95c 100644 --- a/qse/lib/sed/Makefile.in +++ b/qse/lib/sed/Makefile.in @@ -408,7 +408,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/lib/si/AppRoot.cpp b/qse/lib/si/AppRoot.cpp index f81f89c9..22dc9e91 100644 --- a/qse/lib/si/AppRoot.cpp +++ b/qse/lib/si/AppRoot.cpp @@ -26,9 +26,8 @@ #include #include -#include -#include #include "../cmn/syscall.h" +#include ///////////////////////////////// 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) { - struct sigaction sa; int n = QSE_FORK(); if (n == -1) return -1; 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; } -#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 orgdirfd; - - 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; + return QSE_CHROOT (mpath); } int AppRoot::chroot (const qse_wchar_t* wpath) QSE_CPP_NOEXCEPT { qse_mchar_t* mpath; - - mpath = qse_wcstombsdup (wpath, QSE_NULL, QSE_MMGR_GETDFL()); + mpath = qse_wcstombsdup (wpath, QSE_NULL, this->getMmgr()); if (!mpath) return -1; - int n = AppRoot::chroot ((const qse_mchar_t*)mpath); - QSE_MMGR_FREE (QSE_MMGR_GETDFL(), mpath); + this->getMmgr()->dispose (mpath); 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 int main () @@ -168,8 +155,10 @@ int main () AppRoot app; app.daemonize(); - app.switchUser ("nobody", "nobody"); - app.switchUser (10, 20); + app.chuser (); + app.chgroup (); + app.chroot (); + app.catchSignal (SIGINT, xxxxx); app.catchSignal (SIGTERM, xxx); diff --git a/qse/lib/si/Makefile.in b/qse/lib/si/Makefile.in index d3797848..caacbb13 100644 --- a/qse/lib/si/Makefile.in +++ b/qse/lib/si/Makefile.in @@ -423,7 +423,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/lib/xli/Makefile.in b/qse/lib/xli/Makefile.in index 8e995ea1..b34dc5ae 100644 --- a/qse/lib/xli/Makefile.in +++ b/qse/lib/xli/Makefile.in @@ -377,7 +377,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/regress/Makefile.in b/qse/regress/Makefile.in index 041e0da5..745de5f2 100644 --- a/qse/regress/Makefile.in +++ b/qse/regress/Makefile.in @@ -356,7 +356,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/regress/awk/Makefile.in b/qse/regress/awk/Makefile.in index 64e905e6..d44c78e7 100644 --- a/qse/regress/awk/Makefile.in +++ b/qse/regress/awk/Makefile.in @@ -298,7 +298,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/regress/sed/Makefile.in b/qse/regress/sed/Makefile.in index 31f90fed..c506023a 100644 --- a/qse/regress/sed/Makefile.in +++ b/qse/regress/sed/Makefile.in @@ -300,7 +300,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/samples/Makefile.in b/qse/samples/Makefile.in index 43678e60..b8a19497 100644 --- a/qse/samples/Makefile.in +++ b/qse/samples/Makefile.in @@ -356,7 +356,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/samples/awk/Makefile.in b/qse/samples/awk/Makefile.in index c5c41351..3701082a 100644 --- a/qse/samples/awk/Makefile.in +++ b/qse/samples/awk/Makefile.in @@ -480,7 +480,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/samples/cmn/Makefile.am b/qse/samples/cmn/Makefile.am index fba43fb7..02a3c4b4 100644 --- a/qse/samples/cmn/Makefile.am +++ b/qse/samples/cmn/Makefile.am @@ -15,6 +15,7 @@ bin_PROGRAMS = \ fmt01 \ fmt02 \ htb01 \ + htl01 \ ipad01 \ main01 \ main02 \ diff --git a/qse/samples/cmn/Makefile.in b/qse/samples/cmn/Makefile.in index 25fd7013..cafbf499 100644 --- a/qse/samples/cmn/Makefile.in +++ b/qse/samples/cmn/Makefile.in @@ -90,11 +90,12 @@ build_triplet = @build@ host_triplet = @host@ bin_PROGRAMS = arr01$(EXEEXT) chr01$(EXEEXT) dll$(EXEEXT) \ env01$(EXEEXT) fma$(EXEEXT) fmt01$(EXEEXT) fmt02$(EXEEXT) \ - htb01$(EXEEXT) ipad01$(EXEEXT) main01$(EXEEXT) main02$(EXEEXT) \ - mbwc01$(EXEEXT) mbwc02$(EXEEXT) oht$(EXEEXT) path01$(EXEEXT) \ - pma$(EXEEXT) rex01$(EXEEXT) rbt01$(EXEEXT) sll$(EXEEXT) \ - slmb01$(EXEEXT) str01$(EXEEXT) str02$(EXEEXT) time$(EXEEXT) \ - tre01$(EXEEXT) uri01$(EXEEXT) xma$(EXEEXT) $(am__EXEEXT_1) + htb01$(EXEEXT) htl01$(EXEEXT) ipad01$(EXEEXT) main01$(EXEEXT) \ + main02$(EXEEXT) mbwc01$(EXEEXT) mbwc02$(EXEEXT) oht$(EXEEXT) \ + path01$(EXEEXT) pma$(EXEEXT) rex01$(EXEEXT) rbt01$(EXEEXT) \ + sll$(EXEEXT) slmb01$(EXEEXT) str01$(EXEEXT) str02$(EXEEXT) \ + time$(EXEEXT) tre01$(EXEEXT) uri01$(EXEEXT) xma$(EXEEXT) \ + $(am__EXEEXT_1) @WCHAR_TRUE@@WIN32_TRUE@am__append_1 = $(UNICOWS_LIBS) #bin_PROGRAMS += rex02 @@ -188,6 +189,10 @@ am__htb02_SOURCES_DIST = htb02.cpp @ENABLE_CXX_TRUE@am_htb02_OBJECTS = htb02.$(OBJEXT) htb02_OBJECTS = $(am_htb02_OBJECTS) @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) ipad01_OBJECTS = $(am_ipad01_OBJECTS) ipad01_LDADD = $(LDADD) @@ -332,7 +337,7 @@ SOURCES = $(arr01_SOURCES) $(arr02_SOURCES) $(arr03_SOURCES) \ $(bh01_SOURCES) $(bh02_SOURCES) $(chr01_SOURCES) \ $(dll_SOURCES) $(env01_SOURCES) $(fma_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) \ $(mbwc02_SOURCES) $(oht_SOURCES) $(path01_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) \ $(env01_SOURCES) $(fma_SOURCES) $(fmt01_SOURCES) \ $(fmt02_SOURCES) $(am__hl01_SOURCES_DIST) $(htb01_SOURCES) \ - $(am__htb02_SOURCES_DIST) $(ipad01_SOURCES) $(main01_SOURCES) \ - $(main02_SOURCES) $(mbwc01_SOURCES) $(mbwc02_SOURCES) \ - $(oht_SOURCES) $(path01_SOURCES) $(pma_SOURCES) \ - $(rbt01_SOURCES) $(am__rbt02_SOURCES_DIST) \ + $(am__htb02_SOURCES_DIST) htl01.c $(ipad01_SOURCES) \ + $(main01_SOURCES) $(main02_SOURCES) $(mbwc01_SOURCES) \ + $(mbwc02_SOURCES) $(oht_SOURCES) $(path01_SOURCES) \ + $(pma_SOURCES) $(rbt01_SOURCES) $(am__rbt02_SOURCES_DIST) \ $(am__rbt03_SOURCES_DIST) $(rex01_SOURCES) $(sll_SOURCES) \ $(slmb01_SOURCES) $(am__sp01_SOURCES_DIST) \ $(am__sp02_SOURCES_DIST) $(str01_SOURCES) \ @@ -550,7 +555,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -754,6 +758,10 @@ htb02$(EXEEXT): $(htb02_OBJECTS) $(htb02_DEPENDENCIES) $(EXTRA_htb02_DEPENDENCIE @rm -f htb02$(EXEEXT) $(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) @rm -f ipad01$(EXEEXT) $(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)/htb01.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)/main01.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main02.Po@am__quote@ diff --git a/qse/samples/cmn/htl01.c b/qse/samples/cmn/htl01.c new file mode 100644 index 00000000..c1cf6cdd --- /dev/null +++ b/qse/samples/cmn/htl01.c @@ -0,0 +1,209 @@ +#include +#include +#include +#include + +#define R(f) \ + do { \ + qse_printf (QSE_T("== %s ==\n"), QSE_T(#f)); \ + if (f() == -1) return -1; \ + } while (0) + +typedef struct item_t item_t; +struct item_t +{ + long a; + long x; + long y; +}; + +static qse_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; +} diff --git a/qse/samples/cry/Makefile.in b/qse/samples/cry/Makefile.in index 2852a522..b8db5759 100644 --- a/qse/samples/cry/Makefile.in +++ b/qse/samples/cry/Makefile.in @@ -351,7 +351,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/samples/http/Makefile.in b/qse/samples/http/Makefile.in index c55ccea3..ce79b939 100644 --- a/qse/samples/http/Makefile.in +++ b/qse/samples/http/Makefile.in @@ -352,7 +352,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/samples/sed/Makefile.in b/qse/samples/sed/Makefile.in index 14e78002..2beae321 100644 --- a/qse/samples/sed/Makefile.in +++ b/qse/samples/sed/Makefile.in @@ -391,7 +391,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/samples/si/Makefile.in b/qse/samples/si/Makefile.in index a4552fb0..d7d4d11c 100644 --- a/qse/samples/si/Makefile.in +++ b/qse/samples/si/Makefile.in @@ -433,7 +433,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff --git a/qse/tools/Makefile.in b/qse/tools/Makefile.in index 8776e70e..6d2a1436 100644 --- a/qse/tools/Makefile.in +++ b/qse/tools/Makefile.in @@ -298,7 +298,6 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ -runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@