From 99c72b17552b4117b4e9cca66c8641cf64335f7f Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Fri, 9 Jul 2010 00:58:44 +0000 Subject: [PATCH] * renamed map to htb * added qse_awk_findgbl() * added Awk::findGlobal() * began working on red-black tree --- qse/cmd/awk/awk.c | 62 +-- qse/include/qse/awk/Awk.hpp | 19 +- qse/include/qse/awk/awk.h | 21 +- qse/include/qse/cmn/Makefile.am | 2 +- qse/include/qse/cmn/Makefile.in | 12 +- qse/include/qse/cmn/htb.h | 486 +++++++++++++++++++++ qse/include/qse/cmn/map.h | 509 ---------------------- qse/include/qse/cmn/rbt.h | 140 +++++++ qse/include/qse/cmn/rex.h | 36 +- qse/include/qse/cmn/sll.h | 115 ++--- qse/include/qse/sed/sed.h | 15 +- qse/lib/awk/Awk.cpp | 62 +-- qse/lib/awk/StdAwk.cpp | 10 +- qse/lib/awk/awk.c | 122 +++--- qse/lib/awk/awk.h | 20 +- qse/lib/awk/fnc.c | 38 +- qse/lib/awk/parse.c | 126 +++--- qse/lib/awk/run.c | 158 +++---- qse/lib/awk/std.c | 10 +- qse/lib/awk/val.c | 36 +- qse/lib/cmn/Makefile.am | 2 +- qse/lib/cmn/Makefile.in | 11 +- qse/lib/cmn/htb.c | 696 ++++++++++++++++++++++++++++++ qse/lib/cmn/map.c | 700 ------------------------------- qse/lib/cmn/rbt.c | 691 ++++++++++++++++++++++++++++++ qse/lib/cmn/rex.c | 13 +- qse/lib/cmn/sll.c | 6 +- qse/lib/sed/sed.c | 108 ++--- qse/lib/sed/sed.h | 8 +- qse/samples/cmn/Makefile.am | 5 +- qse/samples/cmn/Makefile.in | 44 +- qse/samples/cmn/chr.c | 1 - qse/samples/cmn/{map.c => htb.c} | 108 ++--- qse/samples/cmn/rbt.c | 94 +++++ 34 files changed, 2709 insertions(+), 1777 deletions(-) create mode 100644 qse/include/qse/cmn/htb.h delete mode 100644 qse/include/qse/cmn/map.h create mode 100644 qse/include/qse/cmn/rbt.h create mode 100644 qse/lib/cmn/htb.c delete mode 100644 qse/lib/cmn/map.c create mode 100644 qse/lib/cmn/rbt.c rename qse/samples/cmn/{map.c => htb.c} (60%) create mode 100644 qse/samples/cmn/rbt.c diff --git a/qse/cmd/awk/awk.c b/qse/cmd/awk/awk.c index 73efded2..d4302430 100644 --- a/qse/cmd/awk/awk.c +++ b/qse/cmd/awk/awk.c @@ -1,5 +1,5 @@ /* - * $Id: awk.c 306 2009-11-22 13:58:53Z hyunghwan.chung $ + * $Id: awk.c 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -62,7 +62,7 @@ struct arg_t qse_char_t** icf; /* input console files */ qse_size_t icfl; /* the number of input console files */ - qse_map_t* gvm; /* global variable map */ + qse_htb_t* gvm; /* global variable map */ qse_char_t* fs; /* field separator */ qse_char_t* call; /* function to call */ @@ -154,8 +154,8 @@ static void unset_intr_run (void) #endif } -static qse_map_walk_t print_awk_value ( - qse_map_t* map, qse_map_pair_t* pair, void* arg) +static qse_htb_walk_t print_awk_value ( + qse_htb_t* map, qse_htb_pair_t* pair, void* arg) { qse_awk_rtx_t* rtx = (qse_awk_rtx_t*)arg; qse_char_t* str; @@ -164,13 +164,13 @@ static qse_map_walk_t print_awk_value ( qse_awk_rtx_geterrinf (rtx, &oerrinf); - str = qse_awk_rtx_valtocpldup (rtx, QSE_MAP_VPTR(pair), &len); + str = qse_awk_rtx_valtocpldup (rtx, QSE_HTB_VPTR(pair), &len); if (str == QSE_NULL) { if (qse_awk_rtx_geterrnum(rtx) == QSE_AWK_EVALTYPE) { dprint (QSE_T("%.*s = [not printable]\n"), - (int)QSE_MAP_KLEN(pair), QSE_MAP_KPTR(pair)); + (int)QSE_HTB_KLEN(pair), QSE_HTB_KPTR(pair)); qse_awk_rtx_seterrinf (rtx, &oerrinf); } @@ -182,29 +182,29 @@ static qse_map_walk_t print_awk_value ( else { dprint (QSE_T("%.*s = %.*s\n"), - (int)QSE_MAP_KLEN(pair), QSE_MAP_KPTR(pair), + (int)QSE_HTB_KLEN(pair), QSE_HTB_KPTR(pair), (int)len, str); qse_awk_free (qse_awk_rtx_getawk(rtx), str); } - return QSE_MAP_WALK_FORWARD; + return QSE_HTB_WALK_FORWARD; } -static qse_map_walk_t set_global ( - qse_map_t* map, qse_map_pair_t* pair, void* arg) +static qse_htb_walk_t set_global ( + qse_htb_t* map, qse_htb_pair_t* pair, void* arg) { qse_awk_val_t* v; qse_awk_rtx_t* rtx = (qse_awk_rtx_t*)arg; - struct gvmv_t* gvmv = (struct gvmv_t*)QSE_MAP_VPTR(pair); + struct gvmv_t* gvmv = (struct gvmv_t*)QSE_HTB_VPTR(pair); v = qse_awk_rtx_makenstrval (rtx, gvmv->ptr, gvmv->len); - if (v == QSE_NULL) return QSE_MAP_WALK_STOP; + if (v == QSE_NULL) return QSE_HTB_WALK_STOP; qse_awk_rtx_refupval (rtx, v); qse_awk_rtx_setgbl (rtx, gvmv->idx, v); qse_awk_rtx_refdownval (rtx, v); - return QSE_MAP_WALK_FORWARD; + return QSE_HTB_WALK_FORWARD; } static int apply_fs_and_gvm (qse_awk_rtx_t* rtx, struct arg_t* arg) @@ -228,7 +228,7 @@ static int apply_fs_and_gvm (qse_awk_rtx_t* rtx, struct arg_t* arg) /* set the value of user-defined global variables * to a runtime context */ qse_awk_rtx_seterrnum (rtx, QSE_AWK_ENOERR, QSE_NULL); - qse_map_walk (arg->gvm, set_global, rtx); + qse_htb_walk (arg->gvm, set_global, rtx); if (qse_awk_rtx_geterrnum(rtx) != QSE_AWK_ENOERR) return -1; } @@ -259,7 +259,7 @@ static void dprint_return (qse_awk_rtx_t* rtx, qse_awk_val_t* ret) } dprint (QSE_T("[NAMED VARIABLES]\n")); - qse_map_walk (qse_awk_rtx_getnvmap(rtx), print_awk_value, rtx); + qse_htb_walk (qse_awk_rtx_getnvmap(rtx), print_awk_value, rtx); dprint (QSE_T("[END NAMED VARIABLES]\n")); } @@ -413,7 +413,7 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg) qse_char_t* osf = QSE_NULL; /* output source file */ qse_char_t** icf = QSE_NULL; /* input console files */ - qse_map_t* gvm = QSE_NULL; /* global variable map */ + qse_htb_t* gvm = QSE_NULL; /* global variable map */ qse_char_t* fs = QSE_NULL; /* field separator */ qse_char_t* call = QSE_NULL; /* function to call */ @@ -426,16 +426,16 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg) goto oops; } - gvm = qse_map_open (QSE_NULL, 0, 30, 70); + gvm = qse_htb_open (QSE_NULL, 0, 30, 70); if (gvm == QSE_NULL) { print_err (QSE_T("out of memory\n")); goto oops; } - /*qse_map_setcopier (gvm, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE);*/ - qse_map_setscale (gvm, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); - qse_map_setcopier (gvm, QSE_MAP_VAL, QSE_MAP_COPIER_INLINE); - qse_map_setscale (gvm, QSE_MAP_VAL, QSE_SIZEOF(struct gvmv_t)); + /*qse_htb_setcopier (gvm, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE);*/ + qse_htb_setscale (gvm, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier (gvm, QSE_HTB_VAL, QSE_HTB_COPIER_INLINE); + qse_htb_setscale (gvm, QSE_HTB_VAL, QSE_SIZEOF(struct gvmv_t)); while ((c = qse_getopt (argc, argv, &opt)) != QSE_CHAR_EOF) { @@ -443,7 +443,7 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg) { case QSE_T('h'): if (isf != QSE_NULL) free (isf); - if (gvm != QSE_NULL) qse_map_close (gvm); + if (gvm != QSE_NULL) qse_htb_close (gvm); return 0; case QSE_T('d'): @@ -511,7 +511,7 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg) gvmv.ptr = ++eq; gvmv.len = qse_strlen(eq); - if (qse_map_upsert (gvm, opt.arg, qse_strlen(opt.arg), &gvmv, 1) == QSE_NULL) + if (qse_htb_upsert (gvm, opt.arg, qse_strlen(opt.arg), &gvmv, 1) == QSE_NULL) { print_err (QSE_T("out of memory\n")); goto oops; @@ -626,7 +626,7 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg) return 1; oops: - if (gvm != QSE_NULL) qse_map_close (gvm); + if (gvm != QSE_NULL) qse_htb_close (gvm); if (icf != QSE_NULL) free (icf); if (isf != QSE_NULL) free (isf); return -1; @@ -638,7 +638,7 @@ static void freearg (struct arg_t* arg) arg->isp.files != QSE_NULL) free (arg->isp.files); /*if (arg->osf != QSE_NULL) free (arg->osf);*/ if (arg->icf != QSE_NULL) free (arg->icf); - if (arg->gvm != QSE_NULL) qse_map_close (arg->gvm); + if (arg->gvm != QSE_NULL) qse_htb_close (arg->gvm); } static void print_awkerr (qse_awk_t* awk) @@ -673,18 +673,18 @@ static void print_rtxerr (qse_awk_rtx_t* rtx) ); } -qse_map_walk_t add_global (qse_map_t* map, qse_map_pair_t* pair, void* arg) +qse_htb_walk_t add_global (qse_htb_t* map, qse_htb_pair_t* pair, void* arg) { qse_awk_t* awk = (qse_awk_t*)arg; - struct gvmv_t* gvmv = (struct gvmv_t*)QSE_MAP_VPTR(pair); + struct gvmv_t* gvmv = (struct gvmv_t*)QSE_HTB_VPTR(pair); - gvmv->idx = qse_awk_addgbl (awk, QSE_MAP_KPTR(pair), QSE_MAP_KLEN(pair)); + gvmv->idx = qse_awk_addgbl (awk, QSE_HTB_KPTR(pair), QSE_HTB_KLEN(pair)); if (gvmv->idx <= -1) { - return QSE_MAP_WALK_STOP; + return QSE_HTB_WALK_STOP; } - return QSE_MAP_WALK_FORWARD; + return QSE_HTB_WALK_FORWARD; } static int awk_main (int argc, qse_char_t* argv[]) @@ -751,7 +751,7 @@ static int awk_main (int argc, qse_char_t* argv[]) } qse_awk_seterrnum (awk, QSE_AWK_ENOERR, QSE_NULL); - qse_map_walk (arg.gvm, add_global, awk); + qse_htb_walk (arg.gvm, add_global, awk); if (qse_awk_geterrnum(awk) != QSE_AWK_ENOERR) { print_awkerr (awk); diff --git a/qse/include/qse/awk/Awk.hpp b/qse/include/qse/awk/Awk.hpp index 0c07a0f2..316be11e 100644 --- a/qse/include/qse/awk/Awk.hpp +++ b/qse/include/qse/awk/Awk.hpp @@ -1,5 +1,5 @@ /* - * $Id: Awk.hpp 318 2009-12-18 12:34:42Z hyunghwan.chung $ + * $Id: Awk.hpp 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -22,7 +22,7 @@ #define _QSE_AWK_AWK_HPP_ #include -#include +#include #include #include #include @@ -42,8 +42,8 @@ QSE_BEGIN_NAMESPACE(QSE) class Awk: public Mmged { public: - typedef qse_map_t map_t; - typedef qse_map_pair_t pair_t; + typedef qse_htb_t htb_t; + typedef qse_htb_pair_t pair_t; /** Defines a primitive handle */ typedef qse_awk_t awk_t; @@ -912,6 +912,15 @@ public: const char_t* name ///< variable name ); + /// + /// The addGlobal() function returns the numeric ID of an intrinsic + // global variable. + /// @return integer >= 0 on success, -1 on failure. + /// + int findGlobal ( + const char_t* name ///> variable name + ); + /// /// The setGlobal() function sets the value of a global variable /// identified by @a id. The @a id is either a value returned by @@ -1069,7 +1078,7 @@ protected: errstr_t dflerrstr; errinf_t errinf; - map_t* functionMap; + htb_t* functionMap; Source* sourceReader; Source* sourceWriter; diff --git a/qse/include/qse/awk/awk.h b/qse/include/qse/awk/awk.h index 6b53c473..93a042e0 100644 --- a/qse/include/qse/awk/awk.h +++ b/qse/include/qse/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h 311 2009-12-09 11:35:54Z hyunghwan.chung $ + * $Id: awk.h 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -23,7 +23,7 @@ #include #include -#include +#include #include /** @file @@ -216,7 +216,7 @@ struct qse_awk_val_map_t * integers switch to map dynamically once the * non-integral index is seen. */ - qse_map_t* map; + qse_htb_t* map; }; typedef struct qse_awk_val_map_t qse_awk_val_map_t; @@ -1216,7 +1216,7 @@ int qse_awk_addgbl ( ); /** - * The qse_awk_delgbl() function deletes an instrinsic global variable by name. + * The qse_awk_delgbl() function deletes an intrinsic global variable by name. * @return 0 on success, -1 on failure */ int qse_awk_delgbl ( @@ -1225,6 +1225,17 @@ int qse_awk_delgbl ( qse_size_t len /**< name length */ ); +/** + * The qse_awk_findgbl function returns the numeric ID of an intrinsic global + * variable. + * @return number >= 0 on success, -1 on failure + */ +int qse_awk_findgbl ( + qse_awk_t* awk, /**< awk */ + const qse_char_t* name, /**< variable name */ + qse_size_t len /**< name length */ +); + /** * The qse_awk_addfnc() function adds an intrinsic function. */ @@ -1605,7 +1616,7 @@ void* qse_awk_rtx_getxtn ( /** * The qse_awk_rtx_getnvmap() gets the map of named variables */ -qse_map_t* qse_awk_rtx_getnvmap ( +qse_htb_t* qse_awk_rtx_getnvmap ( qse_awk_rtx_t* rtx /**< runtime context */ ); diff --git a/qse/include/qse/cmn/Makefile.am b/qse/include/qse/cmn/Makefile.am index f0cbcc7c..f6318351 100644 --- a/qse/include/qse/cmn/Makefile.am +++ b/qse/include/qse/cmn/Makefile.am @@ -1,7 +1,7 @@ pkgincludedir = $(includedir)/qse/cmn pkginclude_HEADERS = \ - mem.h chr.h str.h lda.h map.h \ + mem.h chr.h str.h lda.h htb.h rbt.h \ rex.h sll.h dll.h opt.h tio.h \ fio.h pio.h sio.h time.h misc.h main.h stdio.h diff --git a/qse/include/qse/cmn/Makefile.in b/qse/include/qse/cmn/Makefile.in index 4336bb48..9e0e5d0c 100644 --- a/qse/include/qse/cmn/Makefile.in +++ b/qse/include/qse/cmn/Makefile.in @@ -51,9 +51,9 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = SOURCES = DIST_SOURCES = -am__pkginclude_HEADERS_DIST = mem.h chr.h str.h lda.h map.h rex.h \ - sll.h dll.h opt.h tio.h fio.h pio.h sio.h time.h misc.h main.h \ - stdio.h Mmgr.hpp StdMmgr.hpp Mmged.hpp +am__pkginclude_HEADERS_DIST = mem.h chr.h str.h lda.h htb.h rbt.h \ + rex.h sll.h dll.h opt.h tio.h fio.h pio.h sio.h time.h misc.h \ + main.h stdio.h Mmgr.hpp StdMmgr.hpp Mmged.hpp am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -220,9 +220,9 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -pkginclude_HEADERS = mem.h chr.h str.h lda.h map.h rex.h sll.h dll.h \ - opt.h tio.h fio.h pio.h sio.h time.h misc.h main.h stdio.h \ - $(am__append_1) +pkginclude_HEADERS = mem.h chr.h str.h lda.h htb.h rbt.h rex.h sll.h \ + dll.h opt.h tio.h fio.h pio.h sio.h time.h misc.h main.h \ + stdio.h $(am__append_1) all: all-am .SUFFIXES: diff --git a/qse/include/qse/cmn/htb.h b/qse/include/qse/cmn/htb.h new file mode 100644 index 00000000..6bf0fc85 --- /dev/null +++ b/qse/include/qse/cmn/htb.h @@ -0,0 +1,486 @@ +/* + * $Id: htb.h 328 2010-07-08 06:58:44Z hyunghwan.chung $ + * + Copyright 2006-2009 Chung, Hyung-Hwan. + This file is part of QSE. + + QSE is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + QSE is distributed in the hope 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 QSE. If not, see . + */ + +#ifndef _QSE_CMN_HTB_H_ +#define _QSE_CMN_HTB_H_ + +#include +#include + +/**@file + * A hash table maintains buckets for key/value pairs with the same key hash + * chained under the same bucket. + */ + +/* values that can be returned by qse_htb_walker_t */ +enum qse_htb_walk_t +{ + QSE_HTB_WALK_STOP = 0, + QSE_HTB_WALK_FORWARD = 1 +}; + +enum qse_htb_id_t +{ + QSE_HTB_KEY = 0, + QSE_HTB_VAL = 1 +}; + +typedef struct qse_htb_t qse_htb_t; +typedef struct qse_htb_pair_t qse_htb_pair_t; +typedef enum qse_htb_walk_t qse_htb_walk_t; +typedef enum qse_htb_id_t qse_htb_id_t; + +/** + * The qse_htb_copier_t type defines a pair contruction callback + */ +typedef void* (*qse_htb_copier_t) ( + qse_htb_t* htb /* hash table */, + void* dptr /* the pointer to a key or a value */, + qse_size_t dlen /* the length of a key or a value */ +); + +/** + * The qse_htb_freeer_t defines a key/value destruction callback + */ +typedef void (*qse_htb_freeer_t) ( + qse_htb_t* htb, /**< hash table */ + void* dptr, /**< the pointer to a key or a value */ + qse_size_t dlen /**< the length of a key or a value */ +); + +/* key hasher */ +typedef qse_size_t (*qse_htb_hasher_t) ( + qse_htb_t* htb, /**< hash table */ + const void* kptr, /**< the pointer to a key */ + qse_size_t klen /**< the length of a key in bytes */ +); + +/** + * The qse_htb_comper_t type defines a key comparator that is called when + * the htb needs to compare keys. A htb is created with a default comparator + * which performs bitwise comparison between two keys. + * + * The comparator should return 0 if the keys are the same and a non-zero + * integer otherwise. + */ +typedef int (*qse_htb_comper_t) ( + qse_htb_t* htb, /**< hash table */ + const void* kptr1, /**< the pointer to a key */ + qse_size_t klen1, /**< the length of a key */ + const void* kptr2, /**< the pointer to a key */ + qse_size_t klen2 /**< the length of a key */ +); + +/** + * The qse_htb_keeper_t type defines a value keeper that is called when + * a value is retained in the context that it should be destroyed because + * it is identical to a new value. Two values are identical if their beginning + * pointers and their lengths are equal. + */ +typedef void (*qse_htb_keeper_t) ( + qse_htb_t* htb, /**< hash table */ + void* vptr, /**< value pointer */ + qse_size_t vlen /**< value length */ +); + +/** + * The qse_htb_sizer_T type defines a bucket size claculator that is called + * when hash table should resize the bucket. The current bucket size +1 is passed + * as the hint. + */ +typedef qse_size_t (*qse_htb_sizer_t) ( + qse_htb_t* htb, /**< htb */ + qse_size_t hint /**< sizing hint */ +); + +/** + * The qse_htb_walker_t defines a pair visitor. + */ +typedef qse_htb_walk_t (*qse_htb_walker_t) ( + qse_htb_t* htb, /**< htb */ + qse_htb_pair_t* pair, /**< pointer to a key/value pair */ + void* ctx /**< pointer to user-defined data */ +); + +/** + * The qse_htb_pair_t type defines hash table pair. A pair is composed of a key + * and a value. It maintains pointers to the beginning of a key and a value + * plus their length. The length is scaled down with the scale factor + * specified in an owning htb. Use macros defined in the + */ +struct qse_htb_pair_t +{ + void* kptr; /**< the pointer to a key */ + qse_size_t klen; /**< the length of a key */ + void* vptr; /**< the pointer to a value */ + qse_size_t vlen; /**< the length of a value */ + qse_htb_pair_t* next; /**< the next pair under the same slot */ +}; + +/** + * The qse_htb_t type defines a hash table. + */ +struct qse_htb_t +{ + QSE_DEFINE_COMMON_FIELDS (htb) + + qse_htb_copier_t copier[2]; + qse_htb_freeer_t freeer[2]; + qse_htb_hasher_t hasher; /**< key hasher */ + qse_htb_comper_t comper; /**< key comparator */ + qse_htb_keeper_t keeper; /**< value keeper */ + qse_htb_sizer_t sizer; /**< bucket capacity recalculator */ + + qse_byte_t scale[2]; /**< length scale */ + qse_byte_t factor; /**< load factor */ + qse_byte_t filler0; + + qse_size_t size; + qse_size_t capa; + qse_size_t threshold; + + qse_htb_pair_t** bucket; +}; + +#define QSE_HTB_COPIER_SIMPLE ((qse_htb_copier_t)1) +#define QSE_HTB_COPIER_INLINE ((qse_htb_copier_t)2) + +/****m* Common/QSE_HTB_SIZE + * NAME + * QSE_HTB_SIZE - get the number of pairs + * DESCRIPTION + * The QSE_HTB_SIZE() macro returns the number of pairs in hash table. + * SYNOPSIS + */ +#define QSE_HTB_SIZE(m) ((m)->size) +/*****/ + +/****m* Common/QSE_HTB_CAPA + * NAME + * QSE_HTB_CAPA - get the capacity of hash table + * + * DESCRIPTION + * The QSE_HTB_CAPA() macro returns the maximum number of pairs hash table can hold. + * + * SYNOPSIS + */ +#define QSE_HTB_CAPA(m) ((m)->capa) +/*****/ + +#define QSE_HTB_KCOPIER(m) ((m)->copier[QSE_HTB_KEY]) +#define QSE_HTB_VCOPIER(m) ((m)->copier[QSE_HTB_VAL]) +#define QSE_HTB_KFREEER(m) ((m)->freeer[QSE_HTB_KEY]) +#define QSE_HTB_VFREEER(m) ((m)->freeer[QSE_HTB_VAL]) +#define QSE_HTB_HASHER(m) ((m)->hasher) +#define QSE_HTB_COMPER(m) ((m)->comper) +#define QSE_HTB_KEEPER(m) ((m)->keeper) +#define QSE_HTB_SIZER(m) ((m)->sizer) + +#define QSE_HTB_FACTOR(m) ((m)->factor) +#define QSE_HTB_KSCALE(m) ((m)->scale[QSE_HTB_KEY]) +#define QSE_HTB_VSCALE(m) ((m)->scale[QSE_HTB_VAL]) + +#define QSE_HTB_KPTR(p) ((p)->kptr) +#define QSE_HTB_KLEN(p) ((p)->klen) +#define QSE_HTB_VPTR(p) ((p)->vptr) +#define QSE_HTB_VLEN(p) ((p)->vlen) +#define QSE_HTB_NEXT(p) ((p)->next) + +#ifdef __cplusplus +extern "C" { +#endif + +QSE_DEFINE_COMMON_FUNCTIONS (htb) + +/** + * The qse_htb_open() function creates a hash table with a dynamic array + * bucket and a list of values chained. The initial capacity should be larger + * than 0. The load factor should be between 0 and 100 inclusive and the load + * factor of 0 disables bucket resizing. If you need extra space associated + * with hash table, you may pass a non-zero value as the second parameter. + * The QSE_HTB_XTN() macro and the qse_htb_getxtn() function return the + * pointer to the beginning of the extension. + * @return qse_htb_t pointer on success, QSE_NULL on failure. + */ +qse_htb_t* qse_htb_open ( + qse_mmgr_t* mmgr, /**< memory manager */ + qse_size_t ext, /**< extension size in bytes */ + qse_size_t capa, /**< initial capacity */ + int factor /**< load factor */ +); + + +/** + * The qse_htb_close() function destroys a hash table. + */ +void qse_htb_close ( + qse_htb_t* htb /**< hash table */ +); + +/** + * The qse_htb_init() function initializes a hash table + */ +qse_htb_t* qse_htb_init ( + qse_htb_t* htb, + qse_mmgr_t* mmgr, + qse_size_t capa, + int factor +); + +/** + * The qse_htb_fini() funtion finalizes a hash table + */ +void qse_htb_fini ( + qse_htb_t* htb +); + +/** + * The qse_htb_getsize() function gets the number of pairs in hash table. + */ +qse_size_t qse_htb_getsize ( + qse_htb_t* htb +); + +/** + * The qse_htb_getcapa() function gets the number of slots allocated + * in a hash bucket. + */ +qse_size_t qse_htb_getcapa ( + qse_htb_t* htb /**< hash table */ +); + +/** + * The qse_htb_getscale() function returns the scale factor + */ +int qse_htb_getscale ( + qse_htb_t* htb, /**< hash table */ + qse_htb_id_t id /**< QSE_HTB_KEY or QSE_HTB_VAL */ +); + +/** + * The qse_htb_setscale() function sets the scale factor of the length + * of a key and a value. A scale factor determines the actual length of + * a key and a value in bytes. A htb is created with a scale factor of 1. + * The scale factor should be larger than 0 and less than 256. + * Note that it is a bad idea to change the scale factor while a hash table + * is not empty. + */ +void qse_htb_setscale ( + qse_htb_t* htb, /**< hash table */ + qse_htb_id_t id, /**< QSE_HTB_KEY or QSE_HTB_VAL */ + int scale /* scale factor in bytes */ +); + +/** + * The qse_htb_getcopier() function gets a data copier. + */ +qse_htb_copier_t qse_htb_getcopier ( + qse_htb_t* htb, + qse_htb_id_t id /**< QSE_HTB_KEY or QSE_HTB_VAL */ +); + +/** + * The qse_htb_setcopier() function specifies how to clone an element. + * A special copier QSE_HTB_COPIER_INLINE is provided. This copier enables + * you to copy the data inline to the internal node. No freeer is invoked + * when the node is freeed. + * + * You may set the copier to QSE_NULL to perform no special operation + * when the data pointer is rememebered. + */ +void qse_htb_setcopier ( + qse_htb_t* htb, /**< hash table */ + qse_htb_id_t id, /**< QSE_HTB_KEY or QSE_HTB_VAL */ + qse_htb_copier_t copier /**< element copier */ +); + +qse_htb_freeer_t qse_htb_getfreeer ( + qse_htb_t* htb, /**< htb */ + qse_htb_id_t id /**< QSE_HTB_KEY or QSE_HTB_VAL */ +); + +/** + * The qse_htb_setfreeer() function specifies how to destroy an element. + * The @a freeer is called when a node containing the element is destroyed. + */ +void qse_htb_setfreeer ( + qse_htb_t* htb, /**< hash table */ + qse_htb_id_t id, /**< QSE_HTB_KEY or QSE_HTB_VAL */ + qse_htb_freeer_t freeer /**< an element freeer */ +); + + +qse_htb_hasher_t qse_htb_gethasher ( + qse_htb_t* htb +); + +void qse_htb_sethasher ( + qse_htb_t* htb, + qse_htb_hasher_t hasher +); + +qse_htb_comper_t qse_htb_getcomper ( + qse_htb_t* htb +); + +void qse_htb_setcomper ( + qse_htb_t* htb, + qse_htb_comper_t comper +); + +qse_htb_keeper_t qse_htb_getkeeper ( + qse_htb_t* htb +); + +void qse_htb_setkeeper ( + qse_htb_t* htb, + qse_htb_keeper_t keeper +); + +qse_htb_sizer_t qse_htb_getsizer ( + qse_htb_t* htb +); + +/* the sizer function is passed hash table object and htb->capa + 1 */ +void qse_htb_setsizer ( + qse_htb_t* htb, + qse_htb_sizer_t sizer +); + +/** + * The qse_htb_search() function searches hash table to find a pair with a + * matching key. It returns the pointer to the pair found. If it fails + * to find one, it returns QSE_NULL. + * @return pointer to the pair with a maching key, + * or QSE_NULL if no match is found. + */ +qse_htb_pair_t* qse_htb_search ( + qse_htb_t* htb, /**< hash table */ + const void* kptr, /**< the pointer to a key */ + qse_size_t klen /**< the size of the key */ +); + +/** + * The qse_htb_upsert() function searches hash table for the pair with a + * matching key. If one is found, it updates the pair. Otherwise, it inserts + * a new pair with the key and value given. It returns the pointer to the + * pair updated or inserted. + * @return a pointer to the updated or inserted pair on success, + * QSE_NULL on failure. + */ +qse_htb_pair_t* qse_htb_upsert ( + qse_htb_t* htb, /**< hash table */ + void* kptr, /**< the pointer to a key */ + qse_size_t klen, /**< the length of the key */ + void* vptr, /**< the pointer to a value */ + qse_size_t vlen /**< the length of the value */ +); + +/** + * The qse_htb_ensert() function inserts a new pair with the key and the value + * given. If there exists a pair with the key given, the function returns + * the pair containing the key. + * @return pointer to a pair on success, QSE_NULL on failure. + */ +qse_htb_pair_t* qse_htb_ensert ( + qse_htb_t* htb, /**< hash table */ + void* kptr, /**< the pointer to a key */ + qse_size_t klen, /**< the length of the key */ + void* vptr, /**< the pointer to a value */ + qse_size_t vlen /**< the length of the value */ +); + +/** + * The qse_htb_insert() function inserts a new pair with the key and the value + * given. If there exists a pair with the key given, the function returns + * QSE_NULL without channging the value. + * @return pointer to the pair created on success, QSE_NULL on failure. + */ +qse_htb_pair_t* qse_htb_insert ( + qse_htb_t* htb, /**< hash table */ + void* kptr, /**< the pointer to a key */ + qse_size_t klen, /**< the length of the key */ + void* vptr, /**< the pointer to a value */ + qse_size_t vlen /**< the length of the value */ +); + +/** + * The qse_htb_update() function updates the value of an existing pair + * with a matching key. + * @return pointer to the pair on success, QSE_NULL on no matching pair + */ +qse_htb_pair_t* qse_htb_update ( + qse_htb_t* htb, /**< hash table */ + void* kptr, /**< the pointer to a key */ + qse_size_t klen, /**< the length of the key */ + void* vptr, /**< the pointer to a value */ + qse_size_t vlen /**< the length of the value */ +); + +/** + * The qse_htb_delete() function deletes a pair with a matching key + * @return 0 on success, -1 on failure + */ +int qse_htb_delete ( + qse_htb_t* htb, /**< hash table */ + const void* kptr, /**< the pointer to a key */ + qse_size_t klen /**< the size of the key */ +); + +/* + * The qse_htb_clear() function empties a hash table + */ +void qse_htb_clear ( + qse_htb_t* htb /**< hash table */ +); + +/** + * The qse_htb_walk() function traverses a hash table. + */ +void qse_htb_walk ( + qse_htb_t* htb, /**< hash table */ + qse_htb_walker_t walker, /**< pointer to the function for each pair */ + void* ctx /**< pointer to user-specific data */ +); + +/** + * The qse_htb_getfirstpair() function returns the pointer to the first pair + * in a hash table. + */ +qse_htb_pair_t* qse_htb_getfirstpair ( + qse_htb_t* htb, /**< hash table */ + qse_size_t* buckno /**< bucket number */ +); + +/** + * The qse_htb_getnextpair() function returns the pointer to the next pair + * to the current pair @a pair in a hash table. + */ +qse_htb_pair_t* qse_htb_getnextpair ( + qse_htb_t* htb, /**< hash table */ + qse_htb_pair_t* pair, /**< current pair */ + qse_size_t* buckno /**< bucket number */ +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/qse/include/qse/cmn/map.h b/qse/include/qse/cmn/map.h deleted file mode 100644 index cd8e1acc..00000000 --- a/qse/include/qse/cmn/map.h +++ /dev/null @@ -1,509 +0,0 @@ -/* - * $Id: map.h 327 2010-05-10 13:15:55Z hyunghwan.chung $ - * - Copyright 2006-2009 Chung, Hyung-Hwan. - This file is part of QSE. - - QSE is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - QSE is distributed in the hope 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 QSE. If not, see . - */ - -#ifndef _QSE_CMN_MAP_H_ -#define _QSE_CMN_MAP_H_ - -#include -#include - -/**@file - * A hash map maintains buckets for key/value pairs with the same key hash - * chained under the same bucket. - */ - -/* values that can be returned by qse_map_walker_t */ -enum qse_map_walk_t -{ - QSE_MAP_WALK_STOP = 0, - QSE_MAP_WALK_FORWARD = 1 -}; - -enum qse_map_id_t -{ - QSE_MAP_KEY = 0, - QSE_MAP_VAL = 1 -}; - -typedef struct qse_map_t qse_map_t; -typedef struct qse_map_pair_t qse_map_pair_t; -typedef enum qse_map_walk_t qse_map_walk_t; -typedef enum qse_map_id_t qse_map_id_t; - -/** - * The qse_map_copier_t type defines a pair contruction callback - */ -typedef void* (*qse_map_copier_t) ( - qse_map_t* map /* a map */, - void* dptr /* the pointer to a key or a value */, - qse_size_t dlen /* the length of a key or a value */ -); - -/** - * The qse_map_freeer_t defines a key/value destruction callback - */ -typedef void (*qse_map_freeer_t) ( - qse_map_t* map /* a map */, - void* dptr /* the pointer to a key or a value */, - qse_size_t dlen /* the length of a key or a value */ -); - -/* key hasher */ -typedef qse_size_t (*qse_map_hasher_t) ( - qse_map_t* map /* a map */, - const void* kptr /* the pointer to a key */, - qse_size_t klen /* the length of a key in bytes */ -); - -/** - * The qse_map_comper_t type defines a key comparator that is called when - * the map needs to compare keys. A map is created with a default comparator - * which performs bitwise comparison between two keys. - * - * The comparator should return 0 if the keys are the same and a non-zero - * integer otherwise. - */ -typedef int (*qse_map_comper_t) ( - qse_map_t* map, /**< a map */ - const void* kptr1, /**< the pointer to a key */ - qse_size_t klen1, /**< the length of a key */ - const void* kptr2, /**< the pointer to a key */ - qse_size_t klen2 /**< the length of a key */ -); - -/** - * The qse_map_keeper_t type defines a value keeper that is called when - * a value is retained in the context that it should be destroyed because - * it is identical to a new value. Two values are identical if their beginning - * pointers and their lengths are equal. - */ -typedef void (*qse_map_keeper_t) ( - qse_map_t* map, /**< a map */ - void* vptr, /**< value pointer */ - qse_size_t vlen /**< value length */ -); - -/** - * The qse_map_sizer_T type defines a bucket size claculator that is called - * when a map should resize the bucket. The current bucket size +1 is passed - * as the hint. - */ -typedef qse_size_t (*qse_map_sizer_t) ( - qse_map_t* map, /**< a map */ - qse_size_t hint /**< a sizing hint */ -); - -/** - * The qse_map_walker_t defines a pair visitor. - */ -typedef qse_map_walk_t (*qse_map_walker_t) ( - qse_map_t* map, /**< a map */ - qse_map_pair_t* pair, /**< the pointer to a key/value pair */ - void* arg /**< the pointer to user-defined data */ -); - -/** - * The qse_map_pair_t type defines a map pair. A pair is composed of a key - * and a value. It maintains pointers to the beginning of a key and a value - * plus their length. The length is scaled down with the scale factor - * specified in an owning map. Use macros defined in the - */ -struct qse_map_pair_t -{ - void* kptr; /**< the pointer to a key */ - qse_size_t klen; /**< the length of a key */ - void* vptr; /**< the pointer to a value */ - qse_size_t vlen; /**< the length of a value */ - qse_map_pair_t* next; /**< the next pair under the same slot */ -}; - -/** - * The qse_map_t type defines a hash map. - */ -struct qse_map_t -{ - QSE_DEFINE_COMMON_FIELDS (map) - - qse_map_copier_t copier[2]; - qse_map_freeer_t freeer[2]; - qse_map_hasher_t hasher; /* key hasher */ - qse_map_comper_t comper; /* key comparator */ - qse_map_keeper_t keeper; /* value keeper */ - qse_map_sizer_t sizer; /* bucket capacity recalculator */ - qse_byte_t scale[2]; /* length scale */ - qse_byte_t factor; /* load factor */ - qse_byte_t filler0; - qse_size_t size; - qse_size_t capa; - qse_size_t threshold; - qse_map_pair_t** bucket; -}; - -#define QSE_MAP_COPIER_SIMPLE ((qse_map_copier_t)1) -#define QSE_MAP_COPIER_INLINE ((qse_map_copier_t)2) - -/****m* Common/QSE_MAP_SIZE - * NAME - * QSE_MAP_SIZE - get the number of pairs - * DESCRIPTION - * The QSE_MAP_SIZE() macro returns the number of pairs in a map. - * SYNOPSIS - */ -#define QSE_MAP_SIZE(m) ((m)->size) -/*****/ - -/****m* Common/QSE_MAP_CAPA - * NAME - * QSE_MAP_CAPA - get the capacity of a map - * - * DESCRIPTION - * The QSE_MAP_CAPA() macro returns the maximum number of pairs a map can hold. - * - * SYNOPSIS - */ -#define QSE_MAP_CAPA(m) ((m)->capa) -/*****/ - -#define QSE_MAP_KCOPIER(m) ((m)->copier[QSE_MAP_KEY]) -#define QSE_MAP_VCOPIER(m) ((m)->copier[QSE_MAP_VAL]) -#define QSE_MAP_KFREEER(m) ((m)->freeer[QSE_MAP_KEY]) -#define QSE_MAP_VFREEER(m) ((m)->freeer[QSE_MAP_VAL]) -#define QSE_MAP_HASHER(m) ((m)->hasher) -#define QSE_MAP_COMPER(m) ((m)->comper) -#define QSE_MAP_KEEPER(m) ((m)->keeper) -#define QSE_MAP_SIZER(m) ((m)->sizer) - -#define QSE_MAP_FACTOR(m) ((m)->factor) -#define QSE_MAP_KSCALE(m) ((m)->scale[QSE_MAP_KEY]) -#define QSE_MAP_VSCALE(m) ((m)->scale[QSE_MAP_VAL]) - -#define QSE_MAP_KPTR(p) ((p)->kptr) -#define QSE_MAP_KLEN(p) ((p)->klen) -#define QSE_MAP_VPTR(p) ((p)->vptr) -#define QSE_MAP_VLEN(p) ((p)->vlen) -#define QSE_MAP_NEXT(p) ((p)->next) - -#ifdef __cplusplus -extern "C" { -#endif - -QSE_DEFINE_COMMON_FUNCTIONS (map) - -/****f* Common/qse_map_open - * NAME - * qse_map_open - creates a hash map - * DESCRIPTION - * The qse_map_open() function creates a hash map with a dynamic array - * bucket and a list of values chained. The initial capacity should be larger - * than 0. The load factor should be between 0 and 100 inclusive and the load - * factor of 0 disables bucket resizing. If you need extra space associated - * with a map, you may pass a non-zero value as the second parameter. - * The QSE_MAP_XTN() macro and the qse_map_getxtn() function return the - * pointer to the beginning of the extension. - * RETURN - * The qse_map_open() function returns an qse_map_t pointer on success and - * QSE_NULL on failure. - * SEE ALSO - * QSE_MAP_XTN, qse_map_getxtn - * SYNOPSIS - */ -qse_map_t* qse_map_open ( - qse_mmgr_t* mmgr /* a memory manager */, - qse_size_t ext /* extension size in bytes */, - qse_size_t capa /* initial capacity */, - int factor /* load factor */ -); -/******/ - - -/****f* Common/qse_map_close - * NAME - * qse_map_close - destroy a hash map - * DESCRIPTION - * The qse_map_close() function destroys a hash map. - * SYNOPSIS - */ -void qse_map_close ( - qse_map_t* map /* a map */ -); -/******/ - -/****f* Common/qse_map_init - * NAME - * qse_map_init - initialize a hash map - * SYNOPSIS - */ -qse_map_t* qse_map_init ( - qse_map_t* map, - qse_mmgr_t* mmgr, - qse_size_t capa, - int factor -); -/******/ - -/****f* Common/qse_map_fini - * NAME - * qse_map_fini - finalize a hash map - * SYNOPSIS - */ -void qse_map_fini ( - qse_map_t* map -); -/******/ - -/****f* Common/qse_map_getsize - * NAME - * qse_map_getsize - get the number of pairs in a map - * SYNOPSIS - */ -qse_size_t qse_map_getsize ( - qse_map_t* map -); -/******/ - -/****f* Common/qse_map_getcapa - * NAME - * qse_map_getcapa - get the number of slots in a hash bucket - * SYNOPSIS - */ -qse_size_t qse_map_getcapa ( - qse_map_t* map -); -/******/ - -/****f* Common/qse_map_getscale - * NAME - * qse_map_getscale - get the scale factor - * PARAMETERS - * * id - QSE_MAP_KEY or QSE_MAP_VAL - * SYNOPSIS - */ -int qse_map_getscale ( - qse_map_t* map, - qse_map_id_t id /* QSE_MAP_KEY or QSE_MAP_VAL */ -); -/******/ - -/****f* Common/qse_map_setscale - * NAME - * qse_map_setscale - set the scale factor - * DESCRIPTION - * The qse_map_setscale() function sets the scale factor of the length - * of a key and a value. A scale factor determines the actual length of - * a key and a value in bytes. A map is created with a scale factor of 1. - * The scale factor should be larger than 0 and less than 256. - * PARAMETERS - * * id - QSE_MAP_KEY or QSE_MAP_VAL - * * scale - a scale factor in bytes - * NOTES - * It is a bad idea to change the scale factor when a map is not empty. - * SYNOPSIS - */ -void qse_map_setscale ( - qse_map_t* map, - qse_map_id_t id, - int scale -); -/******/ - -/** - * The qse_map_getcopier() function gets a data copier. - */ -qse_map_copier_t qse_map_getcopier ( - qse_map_t* map, - qse_map_id_t id /**< QSE_MAP_KEY or QSE_MAP_VAL */ -); - -/** - * The qse_map_setcopier() function specifies how to clone an element. - * A special copier QSE_MAP_COPIER_INLINE is provided. This copier enables - * you to copy the data inline to the internal node. No freeer is invoked - * when the node is freeed. - * - * You may set the copier to QSE_NULL to perform no special operation - * when the data pointer is rememebered. - */ -void qse_map_setcopier ( - qse_map_t* map, /**< a map */ - qse_map_id_t id, /**< QSE_MAP_KEY or QSE_MAP_VAL */ - qse_map_copier_t copier /**< element copier */ -); - -qse_map_freeer_t qse_map_getfreeer ( - qse_map_t* map, /**< map */ - qse_map_id_t id /**< QSE_MAP_KEY or QSE_MAP_VAL */ -); - -/** - * The qse_map_setfreeer() function specifies how to destroy an element. - * The @a freeer is called when a node containing the element is destroyed. - */ -void qse_map_setfreeer ( - qse_map_t* map, /**< a map */ - qse_map_id_t id, /**< QSE_MAP_KEY or QSE_MAP_VAL */ - qse_map_freeer_t freeer /**< an element freeer */ -); - - -qse_map_hasher_t qse_map_gethasher ( - qse_map_t* map -); - -void qse_map_sethasher ( - qse_map_t* map, - qse_map_hasher_t hasher -); - -qse_map_comper_t qse_map_getcomper ( - qse_map_t* map -); - -void qse_map_setcomper ( - qse_map_t* map, - qse_map_comper_t comper -); - -qse_map_keeper_t qse_map_getkeeper ( - qse_map_t* map -); - -void qse_map_setkeeper ( - qse_map_t* map, - qse_map_keeper_t keeper -); - -qse_map_sizer_t qse_map_getsizer ( - qse_map_t* map -); - -/* the sizer function is passed a map object and map->capa + 1 */ -void qse_map_setsizer ( - qse_map_t* map, - qse_map_sizer_t sizer -); - -/** - * The qse_map_search() function searches a map to find a pair with a - * matching key. It returns the pointer to the pair found. If it fails - * to find one, it returns QSE_NULL. - * @return pointer to the pair with a maching key, - * or QSE_NULL if no match is found. - */ -qse_map_pair_t* qse_map_search ( - qse_map_t* map, /**< a map */ - const void* kptr, /**< the pointer to a key */ - qse_size_t klen /**< the size of the key */ -); - -/** - * The qse_map_upsert() function searches a map for the pair with a matching - * key. If one is found, it updates the pair. Otherwise, it inserts a new - * pair with a key and a value. It returns the pointer to the pair updated - * or inserted. - * @return a pointer to the updated or inserted pair on success, - * QSE_NULL on failure. - * SYNOPSIS - */ -qse_map_pair_t* qse_map_upsert ( - qse_map_t* map, /**< a map */ - void* kptr, /**< the pointer to a key */ - qse_size_t klen, /**< the length of the key */ - void* vptr, /**< the pointer to a value */ - qse_size_t vlen /**< the length of the value */ -); - -/** - * The qse_map_ensert() function inserts a new pair with the key and the value - * given. If there exists a pair with the key given, the function returns - * the pair containing the key. - * @return pointer to a pair on success, QSE_NULL on failure. - */ -qse_map_pair_t* qse_map_ensert ( - qse_map_t* map, /**< a map */ - void* kptr, /**< the pointer to a key */ - qse_size_t klen, /**< the length of the key */ - void* vptr, /**< the pointer to a value */ - qse_size_t vlen /**< the length of the value */ -); - -/** - * The qse_map_insert() function inserts a new pair with the key and the value - * given. If there exists a pair with the key given, the function returns - * QSE_NULL without channging the value. - * @return pointer to the pair created on success, QSE_NULL on failure. - */ -qse_map_pair_t* qse_map_insert ( - qse_map_t* map, /**< a map */ - void* kptr, /**< the pointer to a key */ - qse_size_t klen, /**< the length of the key */ - void* vptr, /**< the pointer to a value */ - qse_size_t vlen /**< the length of the value */ -); - -/** - * The qse_map_update() function updates the value of an existing pair - * with a matching key. - * @return pointer to the pair on success, QSE_NULL on no matching pair - */ -qse_map_pair_t* qse_map_update ( - qse_map_t* map, /**< a map */ - void* kptr, /**< the pointer to a key */ - qse_size_t klen, /**< the length of the key */ - void* vptr, /**< the pointer to a value */ - qse_size_t vlen /**< the length of the value */ -); - -/* delete a pair with a matching key */ -int qse_map_delete ( - qse_map_t* map /* a map */, - const void* kptr /* the pointer to a key */, - qse_size_t klen /* the size of the key in bytes */ -); - -/* clear a map */ -void qse_map_clear ( - qse_map_t* map /* a map */ -); - -/* traverse a map */ -qse_size_t qse_map_walk ( - qse_map_t* map /* a map */, - qse_map_walker_t walker /* the pointer to the function for each pair */, - void* ctx /* a pointer to user-specific data */ -); - -/* get the pointer to the first pair in the map. */ -qse_map_pair_t* qse_map_getfirstpair ( - qse_map_t* map /* a map */, - qse_size_t* buckno -); - -/* get the pointer to the next pair in the map. */ -qse_map_pair_t* qse_map_getnextpair ( - qse_map_t* map /* a map */, - qse_map_pair_t* pair, - qse_size_t* buckno -); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/qse/include/qse/cmn/rbt.h b/qse/include/qse/cmn/rbt.h new file mode 100644 index 00000000..7ebc6e29 --- /dev/null +++ b/qse/include/qse/cmn/rbt.h @@ -0,0 +1,140 @@ +/* + * $Id$ + * + Copyright 2006-2009 Chung, Hyung-Hwan. + This file is part of QSE. + + QSE is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + QSE is distributed in the hope 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 QSE. If not, see . + */ + +#ifndef _QSE_CMN_RBT_H_ +#define _QSE_CMN_RBT_H_ + +#include +#include + +enum qse_rbt_id_t +{ + QSE_RBT_KEY = 0, + QSE_RBT_VAL = 1 +}; + +typedef struct qse_rbt_t qse_rbt_t; +typedef struct qse_rbt_node_t qse_rbt_node_t; +typedef enum qse_rbt_id_t qse_rbt_id_t; + +typedef void* (*qse_rbt_copier_t) ( + qse_rbt_t* rbt, /**< red-black tree */ + void* dptr, /**< the pointer to a key or a value */ + qse_size_t dlen /**< the length of a key or a value */ +); + +typedef void (*qse_rbt_freeer_t) ( + qse_rbt_t* rbt, /**< red-black tree */ + void* dptr, /**< the pointer to a key or a value */ + qse_size_t dlen /**< the length of a key or a value */ +); + +typedef int (*qse_rbt_comper_t) ( + qse_rbt_t* rbt, /**< red-black tree */ + const void* kptr1, /**< the pointer to a key */ + qse_size_t klen1, /**< the length of a key */ + const void* kptr2, /**< the pointer to a key */ + qse_size_t klen2 /**< the length of a key */ +); + +struct qse_rbt_node_t +{ + int key; + int value; + + enum + { + QSE_RBT_RED, + QSE_RBT_BLACK + } color; + + qse_rbt_node_t* parent; + qse_rbt_node_t* child[2]; /* left and right */ +}; + +struct qse_rbt_t +{ + QSE_DEFINE_COMMON_FIELDS (rbt) + + qse_rbt_node_t nil; /**< internal nil node */ + + qse_byte_t scale[2]; /**< scale factor */ + + qse_rbt_copier_t copier[2]; + qse_rbt_freeer_t freeer[2]; + qse_rbt_comper_t comper; + + qse_size_t size; /**< number of nodes */ + qse_rbt_node_t* root; +}; + +enum qse_rbt_walk_t +{ + QSE_RBT_WALK_STOP = 0, + QSE_RBT_WALK_FORWARD = 1 +}; + +typedef enum qse_rbt_walk_t qse_rbt_walk_t; + +/** + * The qse_rbt_walker_t defines a pair visitor. + */ +typedef qse_rbt_walk_t (*qse_rbt_walker_t) ( + qse_rbt_t* rbt, /**< tree */ + qse_rbt_node_t* node, /**< pointer to a node */ + void* ctx /**< pointer to user-defined context */ +); + +#define QSE_RBT_COPIER_SIMPLE ((qse_rbt_copier_t)1) +#define QSE_RBT_COPIER_INLINE ((qse_rbt_copier_t)2) + +#ifdef __cplusplus +extern "C" { +#endif + +qse_rbt_t* qse_rbt_open ( + qse_mmgr_t* mmgr, /**< memory manager */ + qse_size_t ext /**< size of extension area in bytes */ +); + +void qse_rbt_close ( + qse_rbt_t* rbt /**< red-black tree */ +); + + +qse_rbt_t* qse_rbt_init ( + qse_rbt_t* rbt, /**< red-black tree */ + qse_mmgr_t* mmgr /**< a memory manager */ +); + +void qse_rbt_fini ( + qse_rbt_t* rbt /**< red-black tree */ +); + +void qse_rbt_clear ( + qse_rbt_t* rbt /**< red-black tree */ +); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/qse/include/qse/cmn/rex.h b/qse/include/qse/cmn/rex.h index 20e1e424..eb1b3f6f 100644 --- a/qse/include/qse/cmn/rex.h +++ b/qse/include/qse/cmn/rex.h @@ -1,5 +1,5 @@ /* - * $Id: rex.h 326 2010-05-09 13:44:39Z hyunghwan.chung $ + * $Id: rex.h 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -86,16 +86,16 @@ enum qse_rex_errnum_t QSE_REX_ENOERR = 0, QSE_REX_ENOMEM, /**< no sufficient memory available */ QSE_REX_ENOCOMP, /**< no expression compiled */ - QSE_REX_ERECUR, /**< recursion too deep */ - QSE_REX_ERPAREN, /**< right parenthesis expected */ - QSE_REX_ERBRACK, /**< right bracket expected */ - QSE_REX_ERBRACE, /**< right brace expected */ - QSE_REX_ECOLON, /**< colon expected */ - QSE_REX_ECRANGE, /**< invalid character range */ - QSE_REX_ECCLASS, /**< invalid character class */ - QSE_REX_EBOUND, /**< invalid occurrence bound */ - QSE_REX_ESPCAWP, /**< special character at wrong position */ - QSE_REX_EPREEND /**< premature expression end */ + QSE_REX_ERECUR, /**< recursion too deep */ + QSE_REX_ERPAREN, /**< right parenthesis expected */ + QSE_REX_ERBRACK, /**< right bracket expected */ + QSE_REX_ERBRACE, /**< right brace expected */ + QSE_REX_ECOLON, /**< colon expected */ + QSE_REX_ECRANGE, /**< invalid character range */ + QSE_REX_ECCLASS, /**< invalid character class */ + QSE_REX_EBOUND, /**< invalid occurrence bound */ + QSE_REX_ESPCAWP, /**< special character at wrong position */ + QSE_REX_EPREEND /**< premature expression end */ }; typedef enum qse_rex_errnum_t qse_rex_errnum_t; @@ -111,7 +111,8 @@ enum qse_rex_node_id_t QSE_REX_NODE_CSET, /* character set */ QSE_REX_NODE_BRANCH, QSE_REX_NODE_GROUP, - QSE_REX_NODE_GROUPEND + QSE_REX_NODE_GROUPEND, + QSE_REX_NODE_BACKREF /* back reference */ }; typedef enum qse_rex_node_id_t qse_rex_node_id_t; @@ -159,6 +160,11 @@ struct qse_rex_node_t qse_rex_node_t* group; int pseudo; } ge; + + struct + { + int index; + } bref; } u; struct @@ -195,9 +201,9 @@ extern "C" { QSE_DEFINE_COMMON_FUNCTIONS (rex) qse_rex_t* qse_rex_open ( - qse_mmgr_t* mmgr, - qse_size_t xtn, - qse_rex_node_t* code + qse_mmgr_t* mmgr, /**< memory manager */ + qse_size_t xtn, /**< extension size */ + qse_rex_node_t* code /**< compiled regular expression code */ ); void qse_rex_close ( diff --git a/qse/include/qse/cmn/sll.h b/qse/include/qse/cmn/sll.h index 4fcabf81..1bd21ea6 100644 --- a/qse/include/qse/cmn/sll.h +++ b/qse/include/qse/cmn/sll.h @@ -1,5 +1,5 @@ /* - * $Id: sll.h 287 2009-09-15 10:01:02Z hyunghwan.chung $ + * $Id: sll.h 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -381,94 +381,63 @@ qse_sll_node_t* qse_sll_gettail ( ); /******/ -/****f* Common/qse_sll_search - * NAME - * qse_sll_search - find a node +/** + * The qse_sll_search() function traverses a list to find a node containing + * the same value as the the data pointer and length. The traversal begins + * from the next node of the positional node. If the positional node is + * QSE_NULL, the traversal begins from the head node. * - * DESCRIPTION - * The qse_sll_search() function traverses a list to find a node containing - * the same value as the the data pointer and length. The traversal begins - * from the next node of the positional node. If the positional node is - * QSE_NULL, the traversal begins from the head node. + * Note that no reverse search is provided because a reverse traversal can not be + * achieved efficiently. * - * RETURN - * The pointer to the node found. Otherwise, QSE_NULL. - * - * NOTES - * No reverse search is provided because a reverse traversal can not be - * achieved efficiently. - * - * SYNOPSIS + * @return pointer to the node found. QSE_NULL if no match is found */ qse_sll_node_t* qse_sll_search ( - qse_sll_t* sll /* a singly linked list */, - qse_sll_node_t* pos /* a positional node */, - const void* dptr /* a data pointer */, - qse_size_t dlen /* a data length */ + qse_sll_t* sll, /**< singly linked list */ + qse_sll_node_t* pos, /**< positional node */ + const void* dptr, /**< data pointer */ + qse_size_t dlen /**< data length */ ); -/******/ -/****f* Common/qse_sll_insert - * NAME - * qse_sll_insert - insert data to a new node - * - * DESCRIPTION - * There is performance penalty unless the positional node is neither - * the head node nor QSE_NULL. You should consider a different data - * structure such as a doubly linked list if you need to insert data - * into a random position. - * - * RETURN - * The pointer to a new node on success and QSE_NULL on failure:w - * - * SYNOPSIS +/** + * The qse_sll_insert() function inserts data to the list @a sll. + * There is performance penalty unless the positional node is neither + * the head node nor QSE_NULL. You should consider a different data + * structure such as a doubly linked list if you need to insert data + * into a random position. + * @return pointer to a new node on success, QSE_NULL on failure */ qse_sll_node_t* qse_sll_insert ( - qse_sll_t* sll /* a singly linked list */, - qse_sll_node_t* pos /* a node before which a new node is inserted */, - void* dptr /* the pointer to the data */, - qse_size_t dlen /* the length of the data */ + qse_sll_t* sll, /**< singly linked list */ + qse_sll_node_t* pos, /**< node before which a new node is inserted */ + void* dptr, /**< the pointer to the data */ + qse_size_t dlen /**< the length of the data */ ); -/******/ -/****f* Common/qse_sll_delete - * NAME - * qse_sll_delete - delete a node - * - * DESCRIPTION - * The qse_sll_delete() function deletes a node. - * - * SYNOPSIS +/** + * The qse_sll_delete() function deletes a node. */ void qse_sll_delete ( - qse_sll_t* sll /* a singly linked list */, - qse_sll_node_t* pos /* a node to delete */ + qse_sll_t* sll, /**< singly linked list */ + qse_sll_node_t* pos /**< node to delete */ ); -/******/ -/****f* Common/qse_sll_clear - * NAME - * qse_sll_clear - delete all nodes - * - * DESCRIPTION - * The qse_sll_clear() function empties a singly linked list by deletinng - * all the nodes. - * - * SYNOPSIS +/** + * The qse_sll_clear() function empties a singly linked list by deletinng + * all the nodes. */ void qse_sll_clear ( - qse_sll_t* sll /* a singly linked list */ + qse_sll_t* sll /**< singly linked list */ ); -/******/ qse_sll_node_t* qse_sll_pushhead ( - qse_sll_t* sll /* a singly linked list */, + qse_sll_t* sll /**< singly linked list */, void* dptr, qse_size_t dlen ); qse_sll_node_t* qse_sll_pushtail ( - qse_sll_t* sll /* a singly linked list */, + qse_sll_t* sll /**< singly linked list */, void* dptr, qse_size_t dlen ); @@ -482,12 +451,7 @@ void qse_sll_poptail ( qse_sll_t* sll ); -/****f* Common/qse_sll_walk - * NAME - * qse_sll_walk - traverse s singly linked list - * - * DESCRIPTION - * A singly linked list allows uni-directional in-order traversal. +/** * The qse_sll_walk() function traverses a singly linkked list from its * head node down to its tail node as long as the walker function returns * QSE_SLL_WALK_FORWARD. A walker can return QSE_SLL_WALK_STOP to cause @@ -497,15 +461,12 @@ void qse_sll_poptail ( * parameters: the singly linked list, the visiting node, and the * user-defined data passed as the third parameter in a call to the * qse_sll_walk() function. - * - * SYNOPSIS */ void qse_sll_walk ( - qse_sll_t* sll /* a singly linked list */, - qse_sll_walker_t walker /* a user-defined walker function */, - void* arg /* the pointer to user-defined data */ + qse_sll_t* sll, /**< singly linked list */ + qse_sll_walker_t walker, /**< user-defined walker function */ + void* ctx /**< the pointer to user-defined data */ ); -/******/ #ifdef __cplusplus } diff --git a/qse/include/qse/sed/sed.h b/qse/include/qse/sed/sed.h index 20b29722..4a92376e 100644 --- a/qse/include/qse/sed/sed.h +++ b/qse/include/qse/sed/sed.h @@ -1,5 +1,5 @@ /* - * $Id: sed.h 296 2009-10-07 12:39:18Z hyunghwan.chung $ + * $Id: sed.h 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -23,9 +23,6 @@ #include #include -#include -#include -#include /** @file * A stream editor performs text transformation on a text stream. @@ -181,8 +178,8 @@ typedef struct qse_sed_io_arg_t qse_sed_io_arg_t; * qse_sed_exec(). */ typedef qse_ssize_t (*qse_sed_io_fun_t) ( - qse_sed_t* sed, - qse_sed_io_cmd_t cmd, + qse_sed_t* sed, + qse_sed_io_cmd_t cmd, qse_sed_io_arg_t* arg, qse_char_t* data, qse_size_t count @@ -339,7 +336,7 @@ void qse_sed_geterror ( * location. */ void qse_sed_seterrnum ( - qse_sed_t* sed, /**< stream editor */ + qse_sed_t* sed, /**< stream editor */ qse_sed_errnum_t errnum, /**< error number */ const qse_cstr_t* errarg /**< argument for formatting error message */ ); @@ -349,9 +346,9 @@ void qse_sed_seterrnum ( * message for a given error number. */ void qse_sed_seterrmsg ( - qse_sed_t* sed, /**< stream editor */ + qse_sed_t* sed, /**< stream editor */ qse_sed_errnum_t errnum, /**< error number */ - const qse_char_t* errmsg, /**< error message */ + const qse_char_t* errmsg, /**< error message */ const qse_sed_loc_t* errloc /**< error location */ ); diff --git a/qse/lib/awk/Awk.cpp b/qse/lib/awk/Awk.cpp index 22859714..2f6cad8a 100644 --- a/qse/lib/awk/Awk.cpp +++ b/qse/lib/awk/Awk.cpp @@ -1,5 +1,5 @@ /* - * $Id: Awk.cpp 318 2009-12-18 12:34:42Z hyunghwan.chung $ + * $Id: Awk.cpp 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -605,7 +605,7 @@ int Awk::Value::setIndexedVal (Run* r, const Index& idx, val_t* v) qse_awk_rtx_refupval (r->rtx, v); /* update the map with a given value */ - pair_t* pair = qse_map_upsert ( + pair_t* pair = qse_htb_upsert ( ((qse_awk_val_map_t*)map)->map, (char_t*)idx.ptr, idx.len, v, 0); if (pair == QSE_NULL) @@ -640,7 +640,7 @@ int Awk::Value::setIndexedVal (Run* r, const Index& idx, val_t* v) qse_awk_rtx_refupval (r->rtx, v); - pair_t* pair = qse_map_upsert ( + pair_t* pair = qse_htb_upsert ( ((qse_awk_val_map_t*)val)->map, (char_t*)idx.ptr, idx.len, v, 0); if (pair == QSE_NULL) @@ -768,7 +768,7 @@ int Awk::Value::getIndexed (const Index& idx, Value* v) const // get the value from the map. qse_awk_val_map_t* m = (qse_awk_val_map_t*)val; - pair_t* pair = qse_map_search (m->map, idx.ptr, idx.len); + pair_t* pair = qse_htb_search (m->map, idx.ptr, idx.len); // the key is not found. it is not an error. v is just nil if (pair == QSE_NULL) @@ -778,7 +778,7 @@ int Awk::Value::getIndexed (const Index& idx, Value* v) const } // if v.set fails, it should return an error - return v->setVal (run, (val_t*)QSE_MAP_VPTR(pair)); + return v->setVal (run, (val_t*)QSE_HTB_VPTR(pair)); } Awk::Value::IndexIterator Awk::Value::getFirstIndex (Index* idx) const @@ -789,11 +789,11 @@ Awk::Value::IndexIterator Awk::Value::getFirstIndex (Index* idx) const size_t buckno; qse_awk_val_map_t* m = (qse_awk_val_map_t*)val; - pair_t* pair = qse_map_getfirstpair (m->map, &buckno); + pair_t* pair = qse_htb_getfirstpair (m->map, &buckno); if (pair == QSE_NULL) return IndexIterator::END; // no more key - idx->ptr = (const char_t*)QSE_MAP_KPTR(pair); - idx->len = QSE_MAP_KLEN(pair); + idx->ptr = (const char_t*)QSE_HTB_KPTR(pair); + idx->len = QSE_HTB_KLEN(pair); return IndexIterator (pair, buckno); } @@ -810,11 +810,11 @@ Awk::Value::IndexIterator Awk::Value::getNextIndex ( pair_t* pair = (pair_t*)iter.pair; size_t buckno = iter.buckno; - pair = qse_map_getnextpair (m->map, pair, &buckno); + pair = qse_htb_getnextpair (m->map, pair, &buckno); if (pair == QSE_NULL) return IndexIterator::END; - idx->ptr = (const char_t*)QSE_MAP_KPTR(pair); - idx->len = QSE_MAP_KLEN(pair); + idx->ptr = (const char_t*)QSE_HTB_KPTR(pair); + idx->len = QSE_HTB_KLEN(pair); return IndexIterator (pair, buckno); } @@ -829,12 +829,12 @@ int Awk::Argument::getFirstIndex (Awk::Argument& val) const qse_size_t buckno; qse_awk_val_map_t* m = (qse_awk_val_map_t*)this->val; - pair_t* pair = qse_map_getfirstpair (m->map, &buckno); + pair_t* pair = qse_htb_getfirstpair (m->map, &buckno); if (pair == QSE_NULL) return 0; // no more key if (val.init ( - (qse_char_t*)QSE_MAP_KPTR(pair), - QSE_MAP_KLEN(pair)) == -1) return -1; + (qse_char_t*)QSE_HTB_KPTR(pair), + QSE_HTB_KLEN(pair)) == -1) return -1; // reuse the string field as an interator. this->str.ptr = (char_t*)pair; @@ -855,12 +855,12 @@ int Awk::Argument::getNextIndex (Awk::Argument& val) const pair_t* pair = (pair_t*)this->str.ptr; qse_size_t buckno = this->str.len; - pair = qse_map_getnextpair (m->map, pair, &buckno); + pair = qse_htb_getnextpair (m->map, pair, &buckno); if (pair == QSE_NULL) return 0; if (val.init ( - (qse_char_t*)QSE_MAP_KPTR(pair), - QSE_MAP_KLEN(pair)) == -1) return -1; + (qse_char_t*)QSE_HTB_KPTR(pair), + QSE_HTB_KLEN(pair)) == -1) return -1; // reuse the string field as an interator. this->str.ptr = (char_t*)pair; @@ -1099,7 +1099,7 @@ void Awk::retrieveError (Run* run) } static void free_function_map_value ( - Awk::map_t* map, void* dptr, Awk::size_t dlen) + Awk::htb_t* map, void* dptr, Awk::size_t dlen) { Awk* awk = *(Awk**) QSE_XTN (map); qse_awk_free ((Awk::awk_t*)*awk, dptr); @@ -1127,7 +1127,7 @@ int Awk::open () dflerrstr = qse_awk_geterrstr (awk); qse_awk_seterrstr (awk, xerrstr); - functionMap = qse_map_open ( + functionMap = qse_htb_open ( qse_awk_getmmgr(awk), QSE_SIZEOF(this), 512, 70); if (functionMap == QSE_NULL) { @@ -1139,9 +1139,9 @@ int Awk::open () } *(Awk**)QSE_XTN(functionMap) = this; - qse_map_setcopier (functionMap, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setfreeer (functionMap, QSE_MAP_VAL, free_function_map_value); - qse_map_setscale (functionMap, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier (functionMap, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setfreeer (functionMap, QSE_HTB_VAL, free_function_map_value); + qse_htb_setscale (functionMap, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); return 0; } @@ -1153,7 +1153,7 @@ void Awk::close () if (functionMap != QSE_NULL) { - qse_map_close (functionMap); + qse_htb_close (functionMap); functionMap = QSE_NULL; } @@ -1327,7 +1327,7 @@ int Awk::dispatch_function (Run* run, const cstr_t* name) { pair_t* pair; - pair = qse_map_search (functionMap, name->ptr, name->len); + pair = qse_htb_search (functionMap, name->ptr, name->len); if (pair == QSE_NULL) { run->setError (QSE_AWK_EFUNNF, name); @@ -1335,7 +1335,7 @@ int Awk::dispatch_function (Run* run, const cstr_t* name) } FunctionHandler handler; - handler = *(FunctionHandler*)QSE_MAP_VPTR(pair); + handler = *(FunctionHandler*)QSE_HTB_VPTR(pair); size_t i, nargs = qse_awk_rtx_getnargs(run->rtx); @@ -1491,6 +1491,14 @@ int Awk::deleteGlobal (const char_t* name) return n; } +int Awk::findGlobal (const char_t* name) +{ + QSE_ASSERT (awk != QSE_NULL); + int n = qse_awk_findgbl (awk, name, qse_strlen(name)); + if (n <= -1) retrieveError (); + return n; +} + int Awk::setGlobal (int id, const Value& v) { QSE_ASSERT (awk != QSE_NULL); @@ -1552,7 +1560,7 @@ int Awk::addFunction ( return -1; } - pair_t* pair = qse_map_upsert ( + pair_t* pair = qse_htb_upsert ( functionMap, (char_t*)name, nameLen, tmp, 0); if (pair == QSE_NULL) { @@ -1573,7 +1581,7 @@ int Awk::deleteFunction (const char_t* name) size_t nameLen = qse_strlen(name); int n = qse_awk_delfnc (awk, name, nameLen); - if (n == 0) qse_map_delete (functionMap, name, nameLen); + if (n == 0) qse_htb_delete (functionMap, name, nameLen); else retrieveError (); return n; diff --git a/qse/lib/awk/StdAwk.cpp b/qse/lib/awk/StdAwk.cpp index 5d193c37..e1f7a4fb 100644 --- a/qse/lib/awk/StdAwk.cpp +++ b/qse/lib/awk/StdAwk.cpp @@ -1,5 +1,5 @@ /* - * $Id: StdAwk.cpp 318 2009-12-18 12:34:42Z hyunghwan.chung $ + * $Id: StdAwk.cpp 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -450,8 +450,8 @@ int StdAwk::open_console_in (Console& io) qse_sio_t* sio; const qse_char_t* file; qse_awk_val_t* argv; - qse_map_t* map; - qse_map_pair_t* pair; + qse_htb_t* map; + qse_htb_pair_t* pair; qse_char_t ibuf[128]; qse_size_t ibuflen; qse_awk_val_t* v; @@ -512,10 +512,10 @@ int StdAwk::open_console_in (Console& io) ibuf, QSE_COUNTOF(ibuf) ); - pair = qse_map_search (map, ibuf, ibuflen); + pair = qse_htb_search (map, ibuf, ibuflen); QSE_ASSERT (pair != QSE_NULL); - v = (qse_awk_val_t*)QSE_MAP_VPTR(pair); + v = (qse_awk_val_t*)QSE_HTB_VPTR(pair); QSE_ASSERT (v != QSE_NULL); out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP; diff --git a/qse/lib/awk/awk.c b/qse/lib/awk/awk.c index 90b65f91..7939a1ce 100644 --- a/qse/lib/awk/awk.c +++ b/qse/lib/awk/awk.c @@ -1,5 +1,5 @@ /* - * $Id: awk.c 287 2009-09-15 10:01:02Z hyunghwan.chung $ + * $Id: awk.c 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -22,7 +22,7 @@ QSE_IMPLEMENT_COMMON_FUNCTIONS (awk) -static void free_fun (qse_map_t* map, void* vptr, qse_size_t vlen) +static void free_fun (qse_htb_t* map, void* vptr, qse_size_t vlen) { qse_awk_t* awk = *(qse_awk_t**)QSE_XTN(map); qse_awk_fun_t* f = (qse_awk_fun_t*)vptr; @@ -34,7 +34,7 @@ static void free_fun (qse_map_t* map, void* vptr, qse_size_t vlen) QSE_AWK_FREE (awk, f); } -static void free_fnc (qse_map_t* map, void* vptr, qse_size_t vlen) +static void free_fnc (qse_htb_t* map, void* vptr, qse_size_t vlen) { qse_awk_t* awk = *(qse_awk_t**)QSE_XTN(map); qse_awk_fnc_t* f = (qse_awk_fnc_t*)vptr; @@ -113,50 +113,50 @@ qse_awk_t* qse_awk_open (qse_mmgr_t* mmgr, qse_size_t xtn, qse_awk_prm_t* prm) if (init_token (mmgr, &awk->tok) == -1) goto oops; if (init_token (mmgr, &awk->ntok) == -1) goto oops; - awk->wtab = qse_map_open (mmgr, QSE_SIZEOF(awk), 512, 70); + awk->wtab = qse_htb_open (mmgr, QSE_SIZEOF(awk), 512, 70); if (awk->wtab == QSE_NULL) goto oops; *(qse_awk_t**)QSE_XTN(awk->wtab) = awk; - qse_map_setcopier (awk->wtab, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setcopier (awk->wtab, QSE_MAP_VAL, QSE_MAP_COPIER_INLINE); - qse_map_setscale (awk->wtab, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); - qse_map_setscale (awk->wtab, QSE_MAP_VAL, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier (awk->wtab, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setcopier (awk->wtab, QSE_HTB_VAL, QSE_HTB_COPIER_INLINE); + qse_htb_setscale (awk->wtab, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setscale (awk->wtab, QSE_HTB_VAL, QSE_SIZEOF(qse_char_t)); - awk->rwtab = qse_map_open (mmgr, QSE_SIZEOF(awk), 512, 70); + awk->rwtab = qse_htb_open (mmgr, QSE_SIZEOF(awk), 512, 70); if (awk->rwtab == QSE_NULL) goto oops; *(qse_awk_t**)QSE_XTN(awk->rwtab) = awk; - qse_map_setcopier (awk->rwtab, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setcopier (awk->rwtab, QSE_MAP_VAL, QSE_MAP_COPIER_INLINE); - qse_map_setscale (awk->rwtab, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); - qse_map_setscale (awk->rwtab, QSE_MAP_VAL, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier (awk->rwtab, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setcopier (awk->rwtab, QSE_HTB_VAL, QSE_HTB_COPIER_INLINE); + qse_htb_setscale (awk->rwtab, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setscale (awk->rwtab, QSE_HTB_VAL, QSE_SIZEOF(qse_char_t)); - awk->sio.names = qse_map_open (mmgr, QSE_SIZEOF(awk), 128, 70); + awk->sio.names = qse_htb_open (mmgr, QSE_SIZEOF(awk), 128, 70); if (awk->sio.names == QSE_NULL) goto oops; *(qse_awk_t**)QSE_XTN(awk->sio.names) = awk; - qse_map_setcopier (awk->sio.names, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setscale (awk->sio.names, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier (awk->sio.names, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setscale (awk->sio.names, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); awk->sio.inp = &awk->sio.arg; /* TODO: initial map size?? */ - awk->tree.funs = qse_map_open (mmgr, QSE_SIZEOF(awk), 512, 70); + awk->tree.funs = qse_htb_open (mmgr, QSE_SIZEOF(awk), 512, 70); if (awk->tree.funs == QSE_NULL) goto oops; *(qse_awk_t**)QSE_XTN(awk->tree.funs) = awk; - qse_map_setcopier (awk->tree.funs, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setfreeer (awk->tree.funs, QSE_MAP_VAL, free_fun); - qse_map_setscale (awk->tree.funs, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier (awk->tree.funs, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setfreeer (awk->tree.funs, QSE_HTB_VAL, free_fun); + qse_htb_setscale (awk->tree.funs, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); - awk->parse.funs = qse_map_open (mmgr, QSE_SIZEOF(awk), 256, 70); + awk->parse.funs = qse_htb_open (mmgr, QSE_SIZEOF(awk), 256, 70); if (awk->parse.funs == QSE_NULL) goto oops; *(qse_awk_t**)QSE_XTN(awk->parse.funs) = awk; - qse_map_setcopier (awk->parse.funs, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setscale (awk->parse.funs, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier (awk->parse.funs, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setscale (awk->parse.funs, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); - awk->parse.named = qse_map_open (mmgr, QSE_SIZEOF(awk), 256, 70); + awk->parse.named = qse_htb_open (mmgr, QSE_SIZEOF(awk), 256, 70); if (awk->parse.named == QSE_NULL) goto oops; *(qse_awk_t**)QSE_XTN(awk->parse.named) = awk; - qse_map_setcopier ( - awk->parse.named, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setscale ( - awk->parse.named, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier ( + awk->parse.named, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setscale ( + awk->parse.named, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); awk->parse.gbls = qse_lda_open (mmgr, QSE_SIZEOF(awk), 128); awk->parse.lcls = qse_lda_open (mmgr, QSE_SIZEOF(awk), 64); @@ -197,28 +197,28 @@ qse_awk_t* qse_awk_open (qse_mmgr_t* mmgr, qse_size_t xtn, qse_awk_prm_t* prm) awk->tree.chain_size = 0; awk->fnc.sys = QSE_NULL; - awk->fnc.user = qse_map_open (mmgr, QSE_SIZEOF(awk), 512, 70); + awk->fnc.user = qse_htb_open (mmgr, QSE_SIZEOF(awk), 512, 70); if (awk->fnc.user == QSE_NULL) goto oops; *(qse_awk_t**)QSE_XTN(awk->fnc.user) = awk; - qse_map_setcopier (awk->fnc.user, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setfreeer (awk->fnc.user, QSE_MAP_VAL, free_fnc); - qse_map_setscale (awk->fnc.user, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier (awk->fnc.user, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setfreeer (awk->fnc.user, QSE_HTB_VAL, free_fnc); + qse_htb_setscale (awk->fnc.user, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); if (qse_awk_initgbls (awk) <= -1) goto oops; return awk; oops: - if (awk->fnc.user) qse_map_close (awk->fnc.user); + if (awk->fnc.user) qse_htb_close (awk->fnc.user); if (awk->parse.params) qse_lda_close (awk->parse.params); if (awk->parse.lcls) qse_lda_close (awk->parse.lcls); if (awk->parse.gbls) qse_lda_close (awk->parse.gbls); - if (awk->parse.named) qse_map_close (awk->parse.named); - if (awk->parse.funs) qse_map_close (awk->parse.funs); - if (awk->tree.funs) qse_map_close (awk->tree.funs); - if (awk->sio.names) qse_map_close (awk->sio.names); - if (awk->rwtab) qse_map_close (awk->rwtab); - if (awk->wtab) qse_map_close (awk->wtab); + if (awk->parse.named) qse_htb_close (awk->parse.named); + if (awk->parse.funs) qse_htb_close (awk->parse.funs); + if (awk->tree.funs) qse_htb_close (awk->tree.funs); + if (awk->sio.names) qse_htb_close (awk->sio.names); + if (awk->rwtab) qse_htb_close (awk->rwtab); + if (awk->wtab) qse_htb_close (awk->wtab); fini_token (&awk->ntok); fini_token (&awk->tok); fini_token (&awk->ptok); @@ -231,19 +231,19 @@ int qse_awk_close (qse_awk_t* awk) { if (qse_awk_clear (awk) <= -1) return -1; /*qse_awk_clrfnc (awk);*/ - qse_map_close (awk->fnc.user); + qse_htb_close (awk->fnc.user); qse_lda_close (awk->parse.params); qse_lda_close (awk->parse.lcls); qse_lda_close (awk->parse.gbls); - qse_map_close (awk->parse.named); - qse_map_close (awk->parse.funs); + qse_htb_close (awk->parse.named); + qse_htb_close (awk->parse.funs); - qse_map_close (awk->tree.funs); - qse_map_close (awk->sio.names); + qse_htb_close (awk->tree.funs); + qse_htb_close (awk->sio.names); - qse_map_close (awk->rwtab); - qse_map_close (awk->wtab); + qse_htb_close (awk->rwtab); + qse_htb_close (awk->wtab); fini_token (&awk->ntok); fini_token (&awk->tok); @@ -271,8 +271,8 @@ int qse_awk_clear (qse_awk_t* awk) qse_lda_clear (awk->parse.lcls); qse_lda_clear (awk->parse.params); - qse_map_clear (awk->parse.named); - qse_map_clear (awk->parse.funs); + qse_htb_clear (awk->parse.named); + qse_htb_clear (awk->parse.funs); awk->parse.nlcls_max = 0; awk->parse.depth.cur.block = 0; @@ -287,7 +287,7 @@ int qse_awk_clear (qse_awk_t* awk) awk->tree.cur_fun.ptr = QSE_NULL; awk->tree.cur_fun.len = 0; - qse_map_clear (awk->tree.funs); + qse_htb_clear (awk->tree.funs); if (awk->tree.begin != QSE_NULL) { @@ -324,7 +324,7 @@ int qse_awk_clear (qse_awk_t* awk) /* this table must not be cleared here as there can be a reference * to an entry of this table from errinf.fil when qse_awk_parse() * failed. this table is cleared in qse_awk_parse(). - * qse_map_clear (awk->sio.names); + * qse_htb_clear (awk->sio.names); */ awk->sio.last.c = QSE_CHAR_EOF; @@ -363,9 +363,9 @@ void qse_awk_stopall (qse_awk_t* awk) int qse_awk_getword (qse_awk_t* awk, const qse_cstr_t* okw, qse_cstr_t* nkw) { - qse_map_pair_t* p; + qse_htb_pair_t* p; - p = qse_map_search (awk->wtab, okw->ptr, okw->len); + p = qse_htb_search (awk->wtab, okw->ptr, okw->len); if (p == QSE_NULL) return -1; nkw->ptr = ((qse_cstr_t*)p->vptr)->ptr; @@ -376,26 +376,26 @@ int qse_awk_getword (qse_awk_t* awk, const qse_cstr_t* okw, qse_cstr_t* nkw) int qse_awk_unsetword (qse_awk_t* awk, const qse_cstr_t* kw) { - qse_map_pair_t* p; + qse_htb_pair_t* p; QSE_ASSERT (kw->ptr != QSE_NULL); - p = qse_map_search (awk->wtab, kw->ptr, kw->len); + p = qse_htb_search (awk->wtab, kw->ptr, kw->len); if (p == QSE_NULL) { qse_awk_seterrnum (awk, QSE_AWK_ENOENT, kw); return -1; } - qse_map_delete (awk->rwtab, QSE_MAP_VPTR(p), QSE_MAP_VLEN(p)); - qse_map_delete (awk->wtab, kw->ptr, kw->len); + qse_htb_delete (awk->rwtab, QSE_HTB_VPTR(p), QSE_HTB_VLEN(p)); + qse_htb_delete (awk->wtab, kw->ptr, kw->len); return 0; } void qse_awk_unsetallwords (qse_awk_t* awk) { - qse_map_clear (awk->wtab); - qse_map_clear (awk->rwtab); + qse_htb_clear (awk->wtab); + qse_htb_clear (awk->rwtab); } int qse_awk_setword ( @@ -422,7 +422,7 @@ int qse_awk_setword ( QSE_ASSERT (nkw->ptr != QSE_NULL); /* set the word */ - if (qse_map_upsert ( + if (qse_htb_upsert ( awk->wtab, (qse_char_t*)okw->ptr, okw->len, (qse_char_t*)nkw->ptr, nkw->len) == QSE_NULL) @@ -431,12 +431,12 @@ int qse_awk_setword ( return -1; } - if (qse_map_upsert ( + if (qse_htb_upsert ( awk->rwtab, (qse_char_t*)nkw->ptr, nkw->len, (qse_char_t*)okw->ptr, okw->len) == QSE_NULL) { - qse_map_delete (awk->wtab, okw->ptr, okw->len); + qse_htb_delete (awk->wtab, okw->ptr, okw->len); qse_awk_seterrnum (awk, QSE_AWK_ENOMEM, QSE_NULL); return -1; } diff --git a/qse/lib/awk/awk.h b/qse/lib/awk/awk.h index 7ae7b738..9385a242 100644 --- a/qse/lib/awk/awk.h +++ b/qse/lib/awk/awk.h @@ -1,5 +1,5 @@ /* - * $Id: awk.h 312 2009-12-10 13:03:54Z hyunghwan.chung $ + * $Id: awk.h 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -25,7 +25,7 @@ #include "../cmn/mem.h" #include #include -#include +#include #include #include @@ -89,7 +89,7 @@ struct qse_awk_tree_t qse_size_t ngbls; /* total number of globals */ qse_size_t ngbls_base; /* number of intrinsic globals */ qse_cstr_t cur_fun; - qse_map_t* funs; /* awk function map */ + qse_htb_t* funs; /* awk function map */ qse_awk_nde_t* begin; qse_awk_nde_t* begin_tail; @@ -123,9 +123,9 @@ struct qse_awk_t int option; /* word table */ - qse_map_t* wtab; + qse_htb_t* wtab; /* reverse word table */ - qse_map_t* rwtab; + qse_htb_t* rwtab; /* parse tree */ qse_awk_tree_t tree; @@ -159,10 +159,10 @@ struct qse_awk_t } depth; /* function calls */ - qse_map_t* funs; + qse_htb_t* funs; /* named variables */ - qse_map_t* named; + qse_htb_t* named; /* global variables */ qse_lda_t* gbls; @@ -190,7 +190,7 @@ struct qse_awk_t qse_awk_sio_arg_t arg; /* for the top level source */ qse_awk_sio_arg_t* inp; /* current input */ - qse_map_t* names; + qse_htb_t* names; } sio; /* previous token */ @@ -204,7 +204,7 @@ struct qse_awk_t struct { qse_awk_fnc_t* sys; - qse_map_t* user; + qse_htb_t* user; } fnc; struct @@ -253,7 +253,7 @@ struct qse_awk_chain_t struct qse_awk_rtx_t { int id; - qse_map_t* named; + qse_htb_t* named; void** stack; qse_size_t stack_top; diff --git a/qse/lib/awk/fnc.c b/qse/lib/awk/fnc.c index dbc1bbbd..b31ba7b7 100644 --- a/qse/lib/awk/fnc.c +++ b/qse/lib/awk/fnc.c @@ -1,5 +1,5 @@ /* - * $Id: fnc.c 312 2009-12-10 13:03:54Z hyunghwan.chung $ + * $Id: fnc.c 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -20,8 +20,6 @@ #include "awk.h" -#include - static int fnc_close (qse_awk_rtx_t*, const qse_cstr_t*); static int fnc_fflush (qse_awk_rtx_t*, const qse_cstr_t*); static int fnc_index (qse_awk_rtx_t*, const qse_cstr_t*); @@ -129,7 +127,7 @@ void* qse_awk_addfnc ( fnc->handler = handler; - if (qse_map_insert (awk->fnc.user, + if (qse_htb_insert (awk->fnc.user, (qse_char_t*)name, name_len, fnc, 0) == QSE_NULL) { QSE_AWK_FREE (awk, fnc); @@ -143,7 +141,7 @@ void* qse_awk_addfnc ( int qse_awk_delfnc ( qse_awk_t* awk, const qse_char_t* name, qse_size_t name_len) { - if (qse_map_delete (awk->fnc.user, name, name_len) == -1) + if (qse_htb_delete (awk->fnc.user, name, name_len) == -1) { qse_cstr_t errarg; @@ -159,14 +157,14 @@ int qse_awk_delfnc ( void qse_awk_clrfnc (qse_awk_t* awk) { - qse_map_clear (awk->fnc.user); + qse_htb_clear (awk->fnc.user); } qse_awk_fnc_t* qse_awk_getfnc ( qse_awk_t* awk, const qse_char_t* name, qse_size_t len) { qse_awk_fnc_t* fnc; - qse_map_pair_t* pair; + qse_htb_pair_t* pair; const qse_char_t* k; qse_size_t l; @@ -176,13 +174,13 @@ qse_awk_fnc_t* qse_awk_getfnc ( if (fnc->valid != 0 && (awk->option & fnc->valid) != fnc->valid) continue; - pair = qse_map_search ( + pair = qse_htb_search ( awk->wtab, fnc->name.ptr, fnc->name.len); if (pair != QSE_NULL) { /* found in the customized word table */ - k = QSE_MAP_VPTR(pair); - l = QSE_MAP_VLEN(pair); + k = QSE_HTB_VPTR(pair); + l = QSE_HTB_VLEN(pair); } else { @@ -197,21 +195,21 @@ qse_awk_fnc_t* qse_awk_getfnc ( * because I'm trying to support qse_awk_setword in * a very flimsy way here. Would it be better to drop * qse_awk_setword totally? */ - pair = qse_map_search (awk->rwtab, name, len); + pair = qse_htb_search (awk->rwtab, name, len); if (pair != QSE_NULL) { /* the current name is a target name for * one of the original word. */ - k = QSE_MAP_VPTR(pair); - l = QSE_MAP_VLEN(pair); + k = QSE_HTB_VPTR(pair); + l = QSE_HTB_VLEN(pair); } else { - pair = qse_map_search (awk->wtab, name, len); + pair = qse_htb_search (awk->wtab, name, len); if (pair != QSE_NULL) { - k = QSE_MAP_VPTR(pair); - l = QSE_MAP_VLEN(pair); + k = QSE_HTB_VPTR(pair); + l = QSE_HTB_VLEN(pair); if (qse_strxncmp (name, len, k, l) != 0) { @@ -235,10 +233,10 @@ qse_awk_fnc_t* qse_awk_getfnc ( } /* END NOTE */ - pair = qse_map_search (awk->fnc.user, k, l); + pair = qse_htb_search (awk->fnc.user, k, l); if (pair == QSE_NULL) return QSE_NULL; - fnc = (qse_awk_fnc_t*)QSE_MAP_VPTR(pair); + fnc = (qse_awk_fnc_t*)QSE_HTB_VPTR(pair); if (fnc->valid != 0 && (awk->option & fnc->valid) == 0) return QSE_NULL; return fnc; @@ -856,7 +854,7 @@ static int fnc_split (qse_awk_rtx_t* run, const qse_cstr_t* fnm) * it is decremented if the assignement fails. */ qse_awk_rtx_refupval (run, t2); - if (qse_map_insert ( + if (qse_htb_insert ( ((qse_awk_val_map_t*)t1)->map, key, key_len, t2, 0) == QSE_NULL) { @@ -870,7 +868,7 @@ static int fnc_split (qse_awk_rtx_t* run, const qse_cstr_t* fnm) if (fs_rex_free != QSE_NULL) QSE_AWK_FREEREX (run->awk, fs_rex_free); - /* qse_map_insert() fails if the key exists. + /* qse_htb_insert() fails if the key exists. * that can't happen here. so set the error code * to ENOMEM */ qse_awk_rtx_seterrnum (run, QSE_AWK_ENOMEM, QSE_NULL); diff --git a/qse/lib/awk/parse.c b/qse/lib/awk/parse.c index 6dbc52ad..09053cd8 100644 --- a/qse/lib/awk/parse.c +++ b/qse/lib/awk/parse.c @@ -1,5 +1,5 @@ /* - * $Id: parse.c 323 2010-04-05 12:50:01Z hyunghwan.chung $ + * $Id: parse.c 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -228,8 +228,8 @@ static int classify_ident ( qse_awk_t* awk, const qse_char_t* name, qse_size_t len); static int deparse (qse_awk_t* awk); -static qse_map_walk_t deparse_func ( - qse_map_t* map, qse_map_pair_t* pair, void* arg); +static qse_htb_walk_t deparse_func ( + qse_htb_t* map, qse_htb_pair_t* pair, void* arg); static int put_char (qse_awk_t* awk, qse_char_t c); static int flush_out (qse_awk_t* awk); @@ -495,16 +495,16 @@ const qse_char_t* qse_awk_getgblname ( qse_cstr_t* qse_awk_getkw (qse_awk_t* awk, int id, qse_cstr_t* s) { - qse_map_pair_t* p; + qse_htb_pair_t* p; s->ptr = kwtab[id].name; s->len = kwtab[id].namelen; - p = qse_map_search (awk->wtab, s->ptr, s->len); + p = qse_htb_search (awk->wtab, s->ptr, s->len); if (p != QSE_NULL) { - s->ptr = QSE_MAP_VPTR(p); - s->len = QSE_MAP_VLEN(p); + s->ptr = QSE_HTB_VPTR(p); + s->len = QSE_HTB_VLEN(p); } return s; @@ -558,31 +558,31 @@ static int parse (qse_awk_t* awk) /* ensure that all functions called are defined * in the EXPLICIT-only mode */ - qse_map_pair_t* p; + qse_htb_pair_t* p; qse_size_t buckno; - p = qse_map_getfirstpair (awk->parse.funs, &buckno); + p = qse_htb_getfirstpair (awk->parse.funs, &buckno); while (p != QSE_NULL) { - if (qse_map_search (awk->tree.funs, - QSE_MAP_KPTR(p), QSE_MAP_KLEN(p)) == QSE_NULL) + if (qse_htb_search (awk->tree.funs, + QSE_HTB_KPTR(p), QSE_HTB_KLEN(p)) == QSE_NULL) { qse_awk_nde_call_t* call; /* see parse_fncall() for what is * stored into awk->tree.funs */ - call = (qse_awk_nde_call_t*)QSE_MAP_VPTR(p); + call = (qse_awk_nde_call_t*)QSE_HTB_VPTR(p); SETERR_ARG_LOC ( awk, QSE_AWK_EFUNNF, - QSE_MAP_KPTR(p), - QSE_MAP_KLEN(p), + QSE_HTB_KPTR(p), + QSE_HTB_KLEN(p), &call->loc ); goto oops; } - p = qse_map_getnextpair (awk->parse.funs, p, &buckno); + p = qse_htb_getnextpair (awk->parse.funs, p, &buckno); } } } @@ -660,7 +660,7 @@ int qse_awk_parse (qse_awk_t* awk, qse_awk_sio_t* sio) QSE_ASSERT (awk->parse.depth.cur.expr == 0); qse_awk_clear (awk); - qse_map_clear (awk->sio.names); + qse_htb_clear (awk->sio.names); awk->sio.inf = sio->in; awk->sio.outf = sio->out; @@ -677,7 +677,7 @@ static int begin_include (qse_awk_t* awk) { qse_ssize_t op; qse_awk_sio_arg_t* arg = QSE_NULL; - qse_map_pair_t* pair = QSE_NULL; + qse_htb_pair_t* pair = QSE_NULL; if (qse_strlen(awk->tok.name->ptr) != QSE_STR_LEN(awk->tok.name)) { @@ -692,7 +692,7 @@ static int begin_include (qse_awk_t* awk) } /* store the file name to awk->sio.names */ - pair = qse_map_ensert ( + pair = qse_htb_ensert ( awk->sio.names, QSE_STR_PTR(awk->tok.name), QSE_STR_LEN(awk->tok.name) + 1, /* to include '\0' */ @@ -704,8 +704,8 @@ static int begin_include (qse_awk_t* awk) goto oops; } - /*QSE_MAP_VPTR(pair) = QSE_MAP_KPTR(pair); - QSE_MAP_VLEN(pair) = QSE_MAP_KLEN(pair);*/ + /*QSE_HTB_VPTR(pair) = QSE_HTB_KPTR(pair); + QSE_HTB_VLEN(pair) = QSE_HTB_KLEN(pair);*/ arg = (qse_awk_sio_arg_t*) QSE_MMGR_ALLOC (awk->mmgr, QSE_SIZEOF(*arg)); if (arg == QSE_NULL) @@ -715,7 +715,7 @@ static int begin_include (qse_awk_t* awk) } QSE_MEMSET (arg, 0, QSE_SIZEOF(*arg)); - arg->name = QSE_MAP_KPTR(pair); + arg->name = QSE_HTB_KPTR(pair); CLRERR (awk); op = awk->sio.inf (awk, QSE_AWK_SIO_OPEN, arg, QSE_NULL, 0); @@ -1051,7 +1051,7 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) qse_awk_nde_t* body; qse_awk_fun_t* fun; qse_size_t nargs, g; - qse_map_pair_t* pair; + qse_htb_pair_t* pair; /* eat up the keyword 'function' and get the next token */ QSE_ASSERT (MATCH(awk,TOK_FUNCTION)); @@ -1077,7 +1077,7 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) } /* check if it has already been defined as a function */ - if (qse_map_search (awk->tree.funs, name, namelen) != QSE_NULL) + if (qse_htb_search (awk->tree.funs, name, namelen) != QSE_NULL) { /* the function is defined previously */ SETERR_ARG_LOC ( @@ -1086,7 +1086,7 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) } /* check if it conflicts with a named variable */ - if (qse_map_search (awk->parse.named, name, namelen) != QSE_NULL) + if (qse_htb_search (awk->parse.named, name, namelen) != QSE_NULL) { SETERR_ARG_LOC ( awk, QSE_AWK_EVARRED, name, namelen, &awk->tok.loc); @@ -1317,10 +1317,10 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) fun->nargs = nargs; fun->body = body; - pair = qse_map_insert (awk->tree.funs, namedup, namelen, fun, 0); + pair = qse_htb_insert (awk->tree.funs, namedup, namelen, fun, 0); if (pair == QSE_NULL) { - /* if qse_map_insert() fails for other reasons than memory + /* if qse_htb_insert() fails for other reasons than memory * shortage, there should be implementaion errors as duplicate * functions are detected earlier in this function */ QSE_AWK_FREE (awk, namedup); @@ -1332,12 +1332,12 @@ static qse_awk_nde_t* parse_function (qse_awk_t* awk) /* do some trick to save a string. make it back-point at the key part * of the pair */ - fun->name.ptr = QSE_MAP_KPTR(pair); - fun->name.len = QSE_MAP_KLEN(pair); + fun->name.ptr = QSE_HTB_KPTR(pair); + fun->name.len = QSE_HTB_KLEN(pair); QSE_AWK_FREE (awk, namedup); /* remove an undefined function call entry from the parse.fun table */ - qse_map_delete (awk->parse.funs, fun->name.ptr, namelen); + qse_htb_delete (awk->parse.funs, fun->name.ptr, namelen); return body; } @@ -1685,9 +1685,9 @@ static qse_lda_walk_t check_global (qse_lda_t* lda, qse_size_t index, void* arg) if (index < awk->tree.ngbls_base) { - qse_map_pair_t* pair; + qse_htb_pair_t* pair; - pair = qse_map_search (awk->wtab, tmp.ptr, tmp.len); + pair = qse_htb_search (awk->wtab, tmp.ptr, tmp.len); if (pair != QSE_NULL) { tmp.ptr = ((qse_cstr_t*)(pair->vptr))->ptr; @@ -1753,7 +1753,7 @@ static int add_global ( } /* check if it conflicts with a function name */ - if (qse_map_search (awk->tree.funs, name, len) != QSE_NULL) + if (qse_htb_search (awk->tree.funs, name, len) != QSE_NULL) { SETERR_ARG_LOC (awk, QSE_AWK_EFUNRED, name, len, xloc); return -1; @@ -1761,7 +1761,7 @@ static int add_global ( /* check if it conflicts with a function name * caught in the function call table */ - if (qse_map_search (awk->parse.funs, name, len) != QSE_NULL) + if (qse_htb_search (awk->parse.funs, name, len) != QSE_NULL) { SETERR_ARG_LOC (awk, QSE_AWK_EFUNRED, name, len, xloc); return -1; @@ -1781,7 +1781,7 @@ static int add_global ( * global X; * function x() { print X++; } */ - if (qse_map_search (awk->parse.named, name, len) != QSE_NULL) + if (qse_htb_search (awk->parse.named, name, len) != QSE_NULL) { SETERR_ARG_LOC (awk, QSE_AWK_EVARRED, name, len, xloc); return -1; @@ -1842,13 +1842,13 @@ int qse_awk_addgbl (qse_awk_t* awk, const qse_char_t* name, qse_size_t len) return n; } +#define QSE_AWK_NUM_STATIC_GBLS \ + (QSE_AWK_MAX_GBL_ID-QSE_AWK_MIN_GBL_ID+1) + int qse_awk_delgbl ( qse_awk_t* awk, const qse_char_t* name, qse_size_t len) { qse_size_t n; - -#define QSE_AWK_NUM_STATIC_GBLS \ - (QSE_AWK_MAX_GBL_ID-QSE_AWK_MIN_GBL_ID+1) if (awk->tree.ngbls > awk->tree.ngbls_base) { @@ -1880,6 +1880,22 @@ int qse_awk_delgbl ( return 0; } +int qse_awk_findgbl ( + qse_awk_t* awk, const qse_char_t* name, qse_size_t len) +{ + qse_size_t n; + + n = qse_lda_search (awk->parse.gbls, + QSE_AWK_NUM_STATIC_GBLS, name, len); + if (n == QSE_LDA_NIL) + { + SETERR_ARG (awk, QSE_AWK_ENOENT, name, len); + return -1; + } + + return (int)n; +} + static qse_awk_t* collect_globals (qse_awk_t* awk) { if (MATCH(awk,TOK_NEWLINE)) @@ -4413,13 +4429,13 @@ static int isfnname (qse_awk_t* awk, const qse_char_t* name, qse_size_t len) } } - if (qse_map_search (awk->tree.funs, name, len) != QSE_NULL) + if (qse_htb_search (awk->tree.funs, name, len) != QSE_NULL) { /* one of the functions defined previously */ return 2; } - if (qse_map_search (awk->parse.funs, name, len) != QSE_NULL) + if (qse_htb_search (awk->parse.funs, name, len) != QSE_NULL) { /* one of the function calls not resolved so far. */ return 2; @@ -4648,7 +4664,7 @@ static qse_awk_nde_t* parse_primary_ident ( } /* must be a function name */ - QSE_ASSERT (qse_map_search ( + QSE_ASSERT (qse_htb_search ( awk->parse.named, namedup, namelen) == QSE_NULL); nde = parse_fncall ( @@ -4665,7 +4681,7 @@ static qse_awk_nde_t* parse_primary_ident ( qse_awk_nde_t* nde; /* a function call to a yet undefined function */ - if (qse_map_search (awk->parse.named, + if (qse_htb_search (awk->parse.named, namedup, namelen) != QSE_NULL) { /* a function call conflicts with a named variable */ @@ -4705,7 +4721,7 @@ static qse_awk_nde_t* parse_primary_ident ( /* collect unique instances of a named variable * for reference */ - if (qse_map_upsert ( + if (qse_htb_upsert ( awk->parse.named, namedup, namelen, QSE_NULL, 0) == QSE_NULL) { @@ -5018,7 +5034,7 @@ make_node: /* store a non-builtin function call into the awk->parse.funs * table */ - if (qse_map_upsert ( + if (qse_htb_upsert ( awk->parse.funs, name, namelen, call, 0) == QSE_NULL) { QSE_AWK_FREE (awk, call); @@ -5707,7 +5723,7 @@ static int preget_token (qse_awk_t* awk) static int classify_ident ( qse_awk_t* awk, const qse_char_t* name, qse_size_t len) { - if (QSE_MAP_SIZE(awk->wtab) <= 0) + if (QSE_HTB_SIZE(awk->wtab) <= 0) { /* perform binary search if no custom words are specified */ @@ -5746,7 +5762,7 @@ static int classify_ident ( { /* perform linear search if there are any custom words set */ kwent_t* kwp, * end; - qse_map_pair_t* pair; + qse_htb_pair_t* pair; end = kwtab + QSE_COUNTOF(kwtab); for (kwp = kwtab; kwp < end; kwp++) @@ -5757,7 +5773,7 @@ static int classify_ident ( if (kwp->valid != 0 && (awk->option & kwp->valid) != kwp->valid) continue; - pair = qse_map_search (awk->wtab, kwp->name, kwp->namelen); + pair = qse_htb_search (awk->wtab, kwp->name, kwp->namelen); if (pair != QSE_NULL) { k = ((qse_cstr_t*)(pair->vptr))->ptr; @@ -5923,7 +5939,7 @@ static int deparse (qse_awk_t* awk) df.tmp_len = QSE_COUNTOF(tmp); df.ret = 0; - qse_map_walk (awk->tree.funs, deparse_func, &df); + qse_htb_walk (awk->tree.funs, deparse_func, &df); if (df.ret <= -1) { EXIT_DEPARSE (); @@ -6029,29 +6045,29 @@ exit_deparse: return n; } -static qse_map_walk_t deparse_func ( - qse_map_t* map, qse_map_pair_t* pair, void* arg) +static qse_htb_walk_t deparse_func ( + qse_htb_t* map, qse_htb_pair_t* pair, void* arg) { struct deparse_func_t* df = (struct deparse_func_t*)arg; - qse_awk_fun_t* fun = (qse_awk_fun_t*)QSE_MAP_VPTR(pair); + qse_awk_fun_t* fun = (qse_awk_fun_t*)QSE_HTB_VPTR(pair); qse_size_t i, n; qse_cstr_t kw; - QSE_ASSERT (qse_strxncmp (QSE_MAP_KPTR(pair), QSE_MAP_KLEN(pair), fun->name.ptr, fun->name.len) == 0); + QSE_ASSERT (qse_strxncmp (QSE_HTB_KPTR(pair), QSE_HTB_KLEN(pair), fun->name.ptr, fun->name.len) == 0); #define PUT_C(x,c) \ if (put_char(x->awk,c)==-1) { \ - x->ret = -1; return QSE_MAP_WALK_STOP; \ + x->ret = -1; return QSE_HTB_WALK_STOP; \ } #define PUT_S(x,str) \ if (qse_awk_putsrcstr(x->awk,str) <= -1) { \ - x->ret = -1; return QSE_MAP_WALK_STOP; \ + x->ret = -1; return QSE_HTB_WALK_STOP; \ } #define PUT_SX(x,str,len) \ if (qse_awk_putsrcstrx (x->awk, str, len) <= -1) { \ - x->ret = -1; return QSE_MAP_WALK_STOP; \ + x->ret = -1; return QSE_HTB_WALK_STOP; \ } qse_awk_getkw (df->awk, KW_FUNCTION, &kw); @@ -6085,7 +6101,7 @@ static qse_map_walk_t deparse_func ( } PUT_C (df, QSE_T('\n')); - return QSE_MAP_WALK_FORWARD; + return QSE_HTB_WALK_FORWARD; #undef PUT_C #undef PUT_S diff --git a/qse/lib/awk/run.c b/qse/lib/awk/run.c index 3da15fc5..d7a23378 100644 --- a/qse/lib/awk/run.c +++ b/qse/lib/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c 323 2010-04-05 12:50:01Z hyunghwan.chung $ + * $Id: run.c 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -691,7 +691,7 @@ qse_mmgr_t* qse_awk_rtx_getmmgr (qse_awk_rtx_t* rtx) return MMGR(rtx); } -qse_map_t* qse_awk_rtx_getnvmap (qse_awk_rtx_t* rtx) +qse_htb_t* qse_awk_rtx_getnvmap (qse_awk_rtx_t* rtx) { return rtx->named; } @@ -713,7 +713,7 @@ qse_awk_rtx_t* qse_awk_rtx_open ( awk->tree.begin == QSE_NULL && awk->tree.end == QSE_NULL && awk->tree.chain_size == 0 && - qse_map_getsize(awk->tree.funs) == 0) + qse_htb_getsize(awk->tree.funs) == 0) { qse_awk_seterrnum (awk, QSE_AWK_ENOPER, QSE_NULL); return QSE_NULL; @@ -773,13 +773,13 @@ void qse_awk_rtx_setrcb (qse_awk_rtx_t* rtx, qse_awk_rcb_t* rcb) rtx->rcb = *rcb; } -static void free_namedval (qse_map_t* map, void* dptr, qse_size_t dlen) +static void free_namedval (qse_htb_t* map, void* dptr, qse_size_t dlen) { qse_awk_rtx_refdownval ( *(qse_awk_rtx_t**)QSE_XTN(map), dptr); } -static void same_namedval (qse_map_t* map, void* dptr, qse_size_t dlen) +static void same_namedval (qse_htb_t* map, void* dptr, qse_size_t dlen) { qse_awk_rtx_refdownval_nofree ( *(qse_awk_rtx_t**)QSE_XTN(map), dptr); @@ -844,7 +844,7 @@ static int init_rtx (qse_awk_rtx_t* rtx, qse_awk_t* awk, qse_awk_rio_t* rio) return -1; } - rtx->named = qse_map_open ( + rtx->named = qse_htb_open ( MMGR(rtx), QSE_SIZEOF(rtx), 1024, 70); if (rtx->named == QSE_NULL) { @@ -856,16 +856,16 @@ static int init_rtx (qse_awk_rtx_t* rtx, qse_awk_t* awk, qse_awk_rio_t* rio) return -1; } *(qse_awk_rtx_t**)QSE_XTN(rtx->named) = rtx; - qse_map_setcopier (rtx->named, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setfreeer (rtx->named, QSE_MAP_VAL, free_namedval); - qse_map_setkeeper (rtx->named, same_namedval); - qse_map_setscale (rtx->named, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier (rtx->named, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setfreeer (rtx->named, QSE_HTB_VAL, free_namedval); + qse_htb_setkeeper (rtx->named, same_namedval); + qse_htb_setscale (rtx->named, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); rtx->format.tmp.ptr = (qse_char_t*) QSE_AWK_ALLOC (rtx->awk, 4096*QSE_SIZEOF(qse_char_t*)); if (rtx->format.tmp.ptr == QSE_NULL) { - qse_map_close (rtx->named); + qse_htb_close (rtx->named); qse_str_fini (&rtx->format.fmt); qse_str_fini (&rtx->format.out); qse_str_fini (&rtx->inrec.linew); @@ -883,7 +883,7 @@ static int init_rtx (qse_awk_rtx_t* rtx, qse_awk_t* awk, qse_awk_rio_t* rio) if (rtx->pattern_range_state == QSE_NULL) { QSE_AWK_FREE (rtx->awk, rtx->format.tmp.ptr); - qse_map_close (rtx->named); + qse_htb_close (rtx->named); qse_str_fini (&rtx->format.fmt); qse_str_fini (&rtx->format.out); qse_str_fini (&rtx->inrec.linew); @@ -1014,7 +1014,7 @@ static void fini_rtx (qse_awk_rtx_t* rtx, int fini_globals) } /* destroy named variables */ - qse_map_close (rtx->named); + qse_htb_close (rtx->named); /* destroy values in free list */ while (rtx->fcache_count > 0) @@ -1082,7 +1082,7 @@ static int build_runarg ( * it has successfully been assigned into ARGV. */ qse_awk_rtx_refupval (rtx, v_tmp); - if (qse_map_upsert ( + if (qse_htb_upsert ( ((qse_awk_val_map_t*)v_argv)->map, key, key_len, v_tmp, 0) == QSE_NULL) { @@ -1508,7 +1508,7 @@ qse_awk_val_t* qse_awk_rtx_call ( qse_awk_rtx_t* rtx, const qse_char_t* name, qse_awk_val_t** args, qse_size_t nargs) { - qse_map_pair_t* pair; + qse_htb_pair_t* pair; qse_awk_fun_t* fun; struct capture_retval_data_t crdata; qse_awk_val_t* v; @@ -1535,7 +1535,7 @@ qse_awk_val_t* qse_awk_rtx_call ( call.nargs = nargs; /* find the function */ - pair = qse_map_search ( + pair = qse_htb_search ( rtx->awk->tree.funs, call.what.fun.name.ptr, call.what.fun.name.len @@ -1548,7 +1548,7 @@ qse_awk_val_t* qse_awk_rtx_call ( return QSE_NULL; } - fun = (qse_awk_fun_t*)QSE_MAP_VPTR(pair); + fun = (qse_awk_fun_t*)QSE_HTB_VPTR(pair); QSE_ASSERT (fun != QSE_NULL); /* check if the number of arguments given is more than expected */ @@ -2216,19 +2216,19 @@ struct foreach_walker_t int ret; }; -static qse_map_walk_t walk_foreach ( - qse_map_t* map, qse_map_pair_t* pair, void* arg) +static qse_htb_walk_t walk_foreach ( + qse_htb_t* map, qse_htb_pair_t* pair, void* arg) { struct foreach_walker_t* w = (struct foreach_walker_t*)arg; qse_awk_val_t* str; str = (qse_awk_val_t*) qse_awk_rtx_makestrval ( - w->rtx, QSE_MAP_KPTR(pair), QSE_MAP_KLEN(pair)); + w->rtx, QSE_HTB_KPTR(pair), QSE_HTB_KLEN(pair)); if (str == QSE_NULL) { ADJERR_LOC (w->rtx, &w->var->loc); w->ret = -1; - return QSE_MAP_WALK_STOP; + return QSE_HTB_WALK_STOP; } qse_awk_rtx_refupval (w->rtx, str); @@ -2236,14 +2236,14 @@ static qse_map_walk_t walk_foreach ( { qse_awk_rtx_refdownval (w->rtx, str); w->ret = -1; - return QSE_MAP_WALK_STOP; + return QSE_HTB_WALK_STOP; } if (run_statement (w->rtx, w->body) == -1) { qse_awk_rtx_refdownval (w->rtx, str); w->ret = -1; - return QSE_MAP_WALK_STOP; + return QSE_HTB_WALK_STOP; } qse_awk_rtx_refdownval (w->rtx, str); @@ -2251,7 +2251,7 @@ static qse_map_walk_t walk_foreach ( if (w->rtx->exit_level == EXIT_BREAK) { w->rtx->exit_level = EXIT_NONE; - return QSE_MAP_WALK_STOP; + return QSE_HTB_WALK_STOP; } else if (w->rtx->exit_level == EXIT_CONTINUE) { @@ -2259,17 +2259,17 @@ static qse_map_walk_t walk_foreach ( } else if (w->rtx->exit_level != EXIT_NONE) { - return QSE_MAP_WALK_STOP; + return QSE_HTB_WALK_STOP; } - return QSE_MAP_WALK_FORWARD; + return QSE_HTB_WALK_FORWARD; } static int run_foreach (qse_awk_rtx_t* rtx, qse_awk_nde_foreach_t* nde) { qse_awk_nde_exp_t* test; qse_awk_val_t* rv; - qse_map_t* map; + qse_htb_t* map; struct foreach_walker_t walker; test = (qse_awk_nde_exp_t*)nde->test; @@ -2303,7 +2303,7 @@ static int run_foreach (qse_awk_rtx_t* rtx, qse_awk_nde_foreach_t* nde) walker.var = test->left; walker.body = nde->body; walker.ret = 0; - qse_map_walk (map, walk_foreach, &walker); + qse_htb_walk (map, walk_foreach, &walker); qse_awk_rtx_refdownval (rtx, rv); return walker.ret; @@ -2477,7 +2477,7 @@ static int run_nextfile (qse_awk_rtx_t* rtx, qse_awk_nde_nextfile_t* nde) } static int delete_indexed ( - qse_awk_rtx_t* rtx, qse_map_t* map, qse_awk_nde_var_t* var) + qse_awk_rtx_t* rtx, qse_htb_t* map, qse_awk_nde_var_t* var) { qse_awk_val_t* idx; @@ -2492,7 +2492,7 @@ static int delete_indexed ( { /* delete x["abc"] */ - qse_map_delete ( + qse_htb_delete ( map, ((qse_awk_val_str_t*)idx)->ptr, ((qse_awk_val_str_t*)idx)->len @@ -2532,7 +2532,7 @@ static int delete_indexed ( keylen = (out.type == QSE_AWK_RTX_VALTOSTR_CPL)? out.u.cpl.len: out.u.cpldup.len; - qse_map_delete (map, key, keylen); + qse_htb_delete (map, key, keylen); if (key != buf) QSE_AWK_FREE (rtx->awk, key); } @@ -2549,14 +2549,14 @@ static int run_delete (qse_awk_rtx_t* rtx, qse_awk_nde_delete_t* nde) if (var->type == QSE_AWK_NDE_NAMED || var->type == QSE_AWK_NDE_NAMEDIDX) { - qse_map_pair_t* pair; + qse_htb_pair_t* pair; QSE_ASSERTX ( (var->type == QSE_AWK_NDE_NAMED && var->idx == QSE_NULL) || (var->type == QSE_AWK_NDE_NAMEDIDX && var->idx != QSE_NULL), "if a named variable has an index part and a named indexed variable doesn't have an index part, the program is definitely wrong"); - pair = qse_map_search ( + pair = qse_htb_search ( rtx->named, var->id.name.ptr, var->id.name.len); if (pair == QSE_NULL) { @@ -2573,7 +2573,7 @@ static int run_delete (qse_awk_rtx_t* rtx, qse_awk_nde_delete_t* nde) return -1; } - pair = qse_map_upsert (rtx->named, + pair = qse_htb_upsert (rtx->named, var->id.name.ptr, var->id.name.len, tmp, 0); if (pair == QSE_NULL) { @@ -2590,9 +2590,9 @@ static int run_delete (qse_awk_rtx_t* rtx, qse_awk_nde_delete_t* nde) else { qse_awk_val_t* val; - qse_map_t* map; + qse_htb_t* map; - val = (qse_awk_val_t*)QSE_MAP_VPTR(pair); + val = (qse_awk_val_t*)QSE_HTB_VPTR(pair); QSE_ASSERT (val != QSE_NULL); if (val->type != QSE_AWK_VAL_MAP) @@ -2613,7 +2613,7 @@ static int run_delete (qse_awk_rtx_t* rtx, qse_awk_nde_delete_t* nde) } else { - qse_map_clear (map); + qse_htb_clear (map); } } } @@ -2678,7 +2678,7 @@ static int run_delete (qse_awk_rtx_t* rtx, qse_awk_nde_delete_t* nde) } else { - qse_map_t* map; + qse_htb_t* map; if (val->type != QSE_AWK_VAL_MAP) { @@ -2700,7 +2700,7 @@ static int run_delete (qse_awk_rtx_t* rtx, qse_awk_nde_delete_t* nde) } else { - qse_map_clear (map); + qse_htb_clear (map); } } } @@ -2731,7 +2731,7 @@ static int run_reset (qse_awk_rtx_t* rtx, qse_awk_nde_reset_t* nde) /* a named variable can be reset if removed from a internal map to manage it */ - qse_map_delete (rtx->named, var->id.name.ptr, var->id.name.len); + qse_htb_delete (rtx->named, var->id.name.ptr, var->id.name.len); } else if (var->type == QSE_AWK_NDE_GBL || var->type == QSE_AWK_NDE_LCL || @@ -3368,12 +3368,12 @@ static qse_awk_val_t* do_assignment_scalar ( if (var->type == QSE_AWK_NDE_NAMED) { - qse_map_pair_t* pair; + qse_htb_pair_t* pair; - pair = qse_map_search ( + pair = qse_htb_search ( run->named, var->id.name.ptr, var->id.name.len); if (pair != QSE_NULL && - ((qse_awk_val_t*)QSE_MAP_VPTR(pair))->type == QSE_AWK_VAL_MAP) + ((qse_awk_val_t*)QSE_HTB_VPTR(pair))->type == QSE_AWK_VAL_MAP) { /* once a variable becomes a map, * it cannot be changed to a scalar variable */ @@ -3383,7 +3383,7 @@ static qse_awk_val_t* do_assignment_scalar ( return QSE_NULL; } - if (qse_map_upsert (run->named, + if (qse_htb_upsert (run->named, var->id.name.ptr, var->id.name.len, val, 0) == QSE_NULL) { SETERR_LOC (run, QSE_AWK_ENOMEM, &var->loc); @@ -3455,12 +3455,12 @@ static qse_awk_val_t* do_assignment_map ( if (var->type == QSE_AWK_NDE_NAMEDIDX) { - qse_map_pair_t* pair; - pair = qse_map_search ( + qse_htb_pair_t* pair; + pair = qse_htb_search ( run->named, var->id.name.ptr, var->id.name.len); map = (pair == QSE_NULL)? (qse_awk_val_map_t*)qse_awk_val_nil: - (qse_awk_val_map_t*)QSE_MAP_VPTR(pair); + (qse_awk_val_map_t*)QSE_HTB_VPTR(pair); } else { @@ -3487,8 +3487,8 @@ static qse_awk_val_t* do_assignment_map ( { /* doesn't have to decrease the reference count * of the previous value here as it is done by - * qse_map_upsert */ - if (qse_map_upsert ( + * qse_htb_upsert */ + if (qse_htb_upsert ( run->named, var->id.name.ptr, var->id.name.len, @@ -3546,7 +3546,7 @@ static qse_awk_val_t* do_assignment_map ( str, (int)map->ref, (int)map->type); #endif - if (qse_map_upsert (map->map, str, len, val, 0) == QSE_NULL) + if (qse_htb_upsert (map->map, str, len, val, 0) == QSE_NULL) { if (str != idxbuf) QSE_AWK_FREE (run->awk, str); SETERR_LOC (run, QSE_AWK_ENOMEM, &var->loc); @@ -3862,10 +3862,10 @@ static qse_awk_val_t* eval_binop_in ( else if (rv->type == QSE_AWK_VAL_MAP) { qse_awk_val_t* res; - qse_map_t* map; + qse_htb_t* map; map = ((qse_awk_val_map_t*)rv)->map; - res = (qse_map_search (map, str, len) == QSE_NULL)? + res = (qse_htb_search (map, str, len) == QSE_NULL)? qse_awk_val_zero: qse_awk_val_one; if (str != idxbuf) QSE_AWK_FREE (run->awk, str); @@ -5429,9 +5429,9 @@ static qse_awk_val_t* eval_fun_ex ( { qse_awk_nde_call_t* call = (qse_awk_nde_call_t*)nde; qse_awk_fun_t* fun; - qse_map_pair_t* pair; + qse_htb_pair_t* pair; - pair = qse_map_search (rtx->awk->tree.funs, + pair = qse_htb_search (rtx->awk->tree.funs, call->what.fun.name.ptr, call->what.fun.name.len); if (pair == QSE_NULL) { @@ -5441,7 +5441,7 @@ static qse_awk_val_t* eval_fun_ex ( return QSE_NULL; } - fun = (qse_awk_fun_t*)QSE_MAP_VPTR(pair); + fun = (qse_awk_fun_t*)QSE_HTB_VPTR(pair); QSE_ASSERT (fun != QSE_NULL); if (call->nargs > fun->nargs) @@ -5862,16 +5862,16 @@ static int get_reference ( if (nde->type == QSE_AWK_NDE_NAMED) { - qse_map_pair_t* pair; + qse_htb_pair_t* pair; - pair = qse_map_search ( + pair = qse_htb_search ( run->named, tgt->id.name.ptr, tgt->id.name.len); if (pair == QSE_NULL) { /* it is bad that the named variable has to be * created in the function named "__get_refernce". * would there be any better ways to avoid this? */ - pair = qse_map_upsert ( + pair = qse_htb_upsert ( run->named, tgt->id.name.ptr, tgt->id.name.len, qse_awk_val_nil, 0); if (pair == QSE_NULL) @@ -5881,7 +5881,7 @@ static int get_reference ( } } - *ref = (qse_awk_val_t**)&QSE_MAP_VPTR(pair); + *ref = (qse_awk_val_t**)&QSE_HTB_VPTR(pair); return 0; } @@ -5905,13 +5905,13 @@ static int get_reference ( if (nde->type == QSE_AWK_NDE_NAMEDIDX) { - qse_map_pair_t* pair; + qse_htb_pair_t* pair; - pair = qse_map_search ( + pair = qse_htb_search ( run->named, tgt->id.name.ptr, tgt->id.name.len); if (pair == QSE_NULL) { - pair = qse_map_upsert ( + pair = qse_htb_upsert ( run->named, tgt->id.name.ptr, tgt->id.name.len, qse_awk_val_nil, 0); if (pair == QSE_NULL) @@ -5922,7 +5922,7 @@ static int get_reference ( } tmp = get_reference_indexed ( - run, tgt, (qse_awk_val_t**)&QSE_MAP_VPTR(pair)); + run, tgt, (qse_awk_val_t**)&QSE_HTB_VPTR(pair)); if (tmp == QSE_NULL) return -1; *ref = tmp; } @@ -5990,7 +5990,7 @@ static int get_reference ( static qse_awk_val_t** get_reference_indexed ( qse_awk_rtx_t* run, qse_awk_nde_var_t* nde, qse_awk_val_t** val) { - qse_map_pair_t* pair; + qse_htb_pair_t* pair; qse_char_t* str; qse_size_t len; qse_char_t idxbuf[IDXBUFSIZE]; @@ -6024,10 +6024,10 @@ static qse_awk_val_t** get_reference_indexed ( str = idxnde_to_str (run, nde->idx, idxbuf, &len); if (str == QSE_NULL) return QSE_NULL; - pair = qse_map_search ((*(qse_awk_val_map_t**)val)->map, str, len); + pair = qse_htb_search ((*(qse_awk_val_map_t**)val)->map, str, len); if (pair == QSE_NULL) { - pair = qse_map_upsert ( + pair = qse_htb_upsert ( (*(qse_awk_val_map_t**)val)->map, str, len, qse_awk_val_nil, 0); if (pair == QSE_NULL) @@ -6037,11 +6037,11 @@ static qse_awk_val_t** get_reference_indexed ( return QSE_NULL; } - qse_awk_rtx_refupval (run, QSE_MAP_VPTR(pair)); + qse_awk_rtx_refupval (run, QSE_HTB_VPTR(pair)); } if (str != idxbuf) QSE_AWK_FREE (run->awk, str); - return (qse_awk_val_t**)&QSE_MAP_VPTR(pair); + return (qse_awk_val_t**)&QSE_HTB_VPTR(pair); } static qse_awk_val_t* eval_int (qse_awk_rtx_t* run, qse_awk_nde_t* nde) @@ -6109,13 +6109,13 @@ static qse_awk_val_t* eval_rex (qse_awk_rtx_t* run, qse_awk_nde_t* nde) static qse_awk_val_t* eval_named (qse_awk_rtx_t* run, qse_awk_nde_t* nde) { - qse_map_pair_t* pair; + qse_htb_pair_t* pair; - pair = qse_map_search (run->named, + pair = qse_htb_search (run->named, ((qse_awk_nde_var_t*)nde)->id.name.ptr, ((qse_awk_nde_var_t*)nde)->id.name.len); - return (pair == QSE_NULL)? qse_awk_val_nil: QSE_MAP_VPTR(pair); + return (pair == QSE_NULL)? qse_awk_val_nil: QSE_HTB_VPTR(pair); } static qse_awk_val_t* eval_gbl (qse_awk_rtx_t* run, qse_awk_nde_t* nde) @@ -6136,7 +6136,7 @@ static qse_awk_val_t* eval_arg (qse_awk_rtx_t* run, qse_awk_nde_t* nde) static qse_awk_val_t* eval_indexed ( qse_awk_rtx_t* run, qse_awk_nde_var_t* nde, qse_awk_val_t** val) { - qse_map_pair_t* pair; + qse_htb_pair_t* pair; qse_char_t* str; qse_size_t len; qse_char_t idxbuf[IDXBUFSIZE]; @@ -6170,22 +6170,22 @@ static qse_awk_val_t* eval_indexed ( str = idxnde_to_str (run, nde->idx, idxbuf, &len); if (str == QSE_NULL) return QSE_NULL; - pair = qse_map_search ((*(qse_awk_val_map_t**)val)->map, str, len); + pair = qse_htb_search ((*(qse_awk_val_map_t**)val)->map, str, len); if (str != idxbuf) QSE_AWK_FREE (run->awk, str); return (pair == QSE_NULL)? qse_awk_val_nil: - (qse_awk_val_t*)QSE_MAP_VPTR(pair); + (qse_awk_val_t*)QSE_HTB_VPTR(pair); } static qse_awk_val_t* eval_namedidx (qse_awk_rtx_t* run, qse_awk_nde_t* nde) { qse_awk_nde_var_t* tgt = (qse_awk_nde_var_t*)nde; - qse_map_pair_t* pair; + qse_htb_pair_t* pair; - pair = qse_map_search (run->named, tgt->id.name.ptr, tgt->id.name.len); + pair = qse_htb_search (run->named, tgt->id.name.ptr, tgt->id.name.len); if (pair == QSE_NULL) { - pair = qse_map_upsert (run->named, + pair = qse_htb_upsert (run->named, tgt->id.name.ptr, tgt->id.name.len, qse_awk_val_nil, 0); if (pair == QSE_NULL) { @@ -6193,10 +6193,10 @@ static qse_awk_val_t* eval_namedidx (qse_awk_rtx_t* run, qse_awk_nde_t* nde) return QSE_NULL; } - qse_awk_rtx_refupval (run, QSE_MAP_VPTR(pair)); + qse_awk_rtx_refupval (run, QSE_HTB_VPTR(pair)); } - return eval_indexed (run, tgt, (qse_awk_val_t**)&QSE_MAP_VPTR(pair)); + return eval_indexed (run, tgt, (qse_awk_val_t**)&QSE_HTB_VPTR(pair)); } static qse_awk_val_t* eval_gblidx (qse_awk_rtx_t* run, qse_awk_nde_t* nde) diff --git a/qse/lib/awk/std.c b/qse/lib/awk/std.c index be78a25d..d4b1546b 100644 --- a/qse/lib/awk/std.c +++ b/qse/lib/awk/std.c @@ -1,5 +1,5 @@ /* - * $Id: std.c 320 2009-12-21 12:29:52Z hyunghwan.chung $ + * $Id: std.c 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -800,8 +800,8 @@ static int open_rio_console (qse_awk_rtx_t* rtx, qse_awk_rio_arg_t* riod) qse_sio_t* sio; const qse_char_t* file; qse_awk_val_t* argv; - qse_map_t* map; - qse_map_pair_t* pair; + qse_htb_t* map; + qse_htb_pair_t* pair; qse_char_t ibuf[128]; qse_size_t ibuflen; qse_awk_val_t* v; @@ -849,10 +849,10 @@ static int open_rio_console (qse_awk_rtx_t* rtx, qse_awk_rio_arg_t* riod) rtx->awk, rxtn->c.in.index + 1, 10, QSE_NULL, ibuf, QSE_COUNTOF(ibuf)); - pair = qse_map_search (map, ibuf, ibuflen); + pair = qse_htb_search (map, ibuf, ibuflen); QSE_ASSERT (pair != QSE_NULL); - v = QSE_MAP_VPTR(pair); + v = QSE_HTB_VPTR(pair); QSE_ASSERT (v != QSE_NULL); out.type = QSE_AWK_RTX_VALTOSTR_CPLDUP; diff --git a/qse/lib/awk/val.c b/qse/lib/awk/val.c index cfd24ef3..bd2cec19 100644 --- a/qse/lib/awk/val.c +++ b/qse/lib/awk/val.c @@ -1,5 +1,5 @@ /* - * $Id: val.c 312 2009-12-10 13:03:54Z hyunghwan.chung $ + * $Id: val.c 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -362,7 +362,7 @@ qse_awk_val_t* qse_awk_rtx_makerexval ( return (qse_awk_val_t*)val; } -static void free_mapval (qse_map_t* map, void* dptr, qse_size_t dlen) +static void free_mapval (qse_htb_t* map, void* dptr, qse_size_t dlen) { qse_awk_rtx_t* rtx = *(qse_awk_rtx_t**)QSE_XTN(map); @@ -375,7 +375,7 @@ static void free_mapval (qse_map_t* map, void* dptr, qse_size_t dlen) qse_awk_rtx_refdownval (rtx, dptr); } -static void same_mapval (qse_map_t* map, void* dptr, qse_size_t dlen) +static void same_mapval (qse_htb_t* map, void* dptr, qse_size_t dlen) { qse_awk_rtx_t* run = *(qse_awk_rtx_t**)QSE_XTN(map); #ifdef DEBUG_VAL @@ -403,7 +403,7 @@ qse_awk_val_t* qse_awk_rtx_makemapval (qse_awk_rtx_t* rtx) val->type = QSE_AWK_VAL_MAP; val->ref = 0; val->nstr = 0; - val->map = qse_map_open ( + val->map = qse_htb_open ( run, 256, 70, free_mapval, same_mapval, run->awk->mmgr); if (val->map == QSE_NULL) { @@ -416,7 +416,7 @@ qse_awk_val_t* qse_awk_rtx_makemapval (qse_awk_rtx_t* rtx) val = (qse_awk_val_map_t*) QSE_AWK_ALLOC ( rtx->awk, QSE_SIZEOF(qse_awk_val_map_t) + - QSE_SIZEOF(qse_map_t) + + QSE_SIZEOF(qse_htb_t) + QSE_SIZEOF(rtx)); if (val == QSE_NULL) { @@ -427,9 +427,9 @@ qse_awk_val_t* qse_awk_rtx_makemapval (qse_awk_rtx_t* rtx) val->type = QSE_AWK_VAL_MAP; val->ref = 0; val->nstr = 0; - val->map = (qse_map_t*)(val + 1); + val->map = (qse_htb_t*)(val + 1); - val->map = qse_map_init (val->map, rtx->awk->mmgr, 256, 70); + val->map = qse_htb_init (val->map, rtx->awk->mmgr, 256, 70); if (val->map == QSE_NULL) { QSE_AWK_FREE (rtx->awk, val); @@ -440,14 +440,14 @@ qse_awk_val_t* qse_awk_rtx_makemapval (qse_awk_rtx_t* rtx) /* the key is copied inline into a pair and is freed when the pair * is destroyed */ - qse_map_setcopier (val->map, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setscale (val->map, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier (val->map, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setscale (val->map, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); /* not setting copier for a value means that the pointer to the data * allocated somewhere else is remembered in a pair. but the freeing * the actual value is handled by free_mapval and same_mapval */ - qse_map_setfreeer (val->map, QSE_MAP_VAL, free_mapval); - qse_map_setkeeper (val->map, same_mapval); + qse_htb_setfreeer (val->map, QSE_HTB_VAL, free_mapval); + qse_htb_setkeeper (val->map, same_mapval); /* END CHECK */ return (qse_awk_val_t*)val; @@ -559,7 +559,7 @@ void qse_awk_rtx_freeval ( } else if (val->type == QSE_AWK_VAL_MAP) { - qse_map_fini (((qse_awk_val_map_t*)val)->map); + qse_htb_fini (((qse_awk_val_map_t*)val)->map); QSE_AWK_FREE (rtx->awk, val); } else if (val->type == QSE_AWK_VAL_REF) @@ -1131,19 +1131,19 @@ int qse_awk_rtx_strtonum ( #define DPRINTF run->awk->prmfns->dprintf #define DCUSTOM run->awk->prmfns->data -static qse_map_walk_t print_pair ( - qse_map_t* map, qse_map_pair_t* pair, void* arg) +static qse_htb_walk_t print_pair ( + qse_htb_t* map, qse_htb_pair_t* pair, void* arg) { qse_awk_rtx_t* run = (qse_awk_rtx_t*)arg; QSE_ASSERT (run == *(qse_awk_rtx_t**)QSE_XTN(map)); DPRINTF (DCUSTOM, QSE_T(" %.*s=>"), - (int)QSE_MAP_KLEN(pair), QSE_MAP_KPTR(pair)); - qse_awk_dprintval ((qse_awk_rtx_t*)arg, QSE_MAP_VPTR(pair)); + (int)QSE_HTB_KLEN(pair), QSE_HTB_KPTR(pair)); + qse_awk_dprintval ((qse_awk_rtx_t*)arg, QSE_HTB_VPTR(pair)); DPRINTF (DCUSTOM, QSE_T(" ")); - return QSE_MAP_WALK_FORWARD; + return QSE_HTB_WALK_FORWARD; } void qse_awk_dprintval (qse_awk_rtx_t* run, qse_awk_val_t* val) @@ -1194,7 +1194,7 @@ void qse_awk_dprintval (qse_awk_rtx_t* run, qse_awk_val_t* val) case QSE_AWK_VAL_MAP: DPRINTF (DCUSTOM, QSE_T("MAP[")); - qse_map_walk (((qse_awk_val_map_t*)val)->map, print_pair, run); + qse_htb_walk (((qse_awk_val_map_t*)val)->map, print_pair, run); DPRINTF (DCUSTOM, QSE_T("]")); break; diff --git a/qse/lib/cmn/Makefile.am b/qse/lib/cmn/Makefile.am index 18acce60..7f8641a8 100644 --- a/qse/lib/cmn/Makefile.am +++ b/qse/lib/cmn/Makefile.am @@ -7,7 +7,7 @@ libqsecmn_la_SOURCES = \ syscall.h mem.h \ mem.c chr.c chr_cnv.c rex.c \ str_bas.c str_cnv.c str_dyn.c str_utl.c \ - lda.c map.c sll.c dll.c opt.c \ + lda.c htb.c rbt.c sll.c dll.c opt.c \ tio.c tio_get.c tio_put.c \ fio.c pio.c sio.c \ time.c \ diff --git a/qse/lib/cmn/Makefile.in b/qse/lib/cmn/Makefile.in index 8d6a596f..0bf7cd8b 100644 --- a/qse/lib/cmn/Makefile.in +++ b/qse/lib/cmn/Makefile.in @@ -74,9 +74,9 @@ am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) libqsecmn_la_DEPENDENCIES = am_libqsecmn_la_OBJECTS = mem.lo chr.lo chr_cnv.lo rex.lo str_bas.lo \ - str_cnv.lo str_dyn.lo str_utl.lo lda.lo map.lo sll.lo dll.lo \ - opt.lo tio.lo tio_get.lo tio_put.lo fio.lo pio.lo sio.lo \ - time.lo misc.lo assert.lo main.lo stdio.lo + str_cnv.lo str_dyn.lo str_utl.lo lda.lo htb.lo rbt.lo sll.lo \ + dll.lo opt.lo tio.lo tio_get.lo tio_put.lo fio.lo pio.lo \ + sio.lo time.lo misc.lo assert.lo main.lo stdio.lo libqsecmn_la_OBJECTS = $(am_libqsecmn_la_OBJECTS) libqsecmn_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ @@ -263,7 +263,7 @@ libqsecmn_la_SOURCES = \ syscall.h mem.h \ mem.c chr.c chr_cnv.c rex.c \ str_bas.c str_cnv.c str_dyn.c str_utl.c \ - lda.c map.c sll.c dll.c opt.c \ + lda.c htb.c rbt.c sll.c dll.c opt.c \ tio.c tio_get.c tio_put.c \ fio.c pio.c sio.c \ time.c \ @@ -361,13 +361,14 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chr_cnv.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dll.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lda.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mem.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pio.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rbt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sll.Plo@am__quote@ diff --git a/qse/lib/cmn/htb.c b/qse/lib/cmn/htb.c new file mode 100644 index 00000000..ffcbcbd3 --- /dev/null +++ b/qse/lib/cmn/htb.c @@ -0,0 +1,696 @@ +/* + * $Id: htb.c 328 2010-07-08 06:58:44Z hyunghwan.chung $ + * + Copyright 2006-2009 Chung, Hyung-Hwan. + This file is part of QSE. + + QSE is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + QSE is distributed in the hope 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 QSE. If not, see . + */ + +#include +#include "mem.h" + +QSE_IMPLEMENT_COMMON_FUNCTIONS (htb) + +#define htb_t qse_htb_t +#define pair_t qse_htb_pair_t +#define copier_t qse_htb_copier_t +#define freeer_t qse_htb_freeer_t +#define hasher_t qse_htb_hasher_t +#define comper_t qse_htb_comper_t +#define keeper_t qse_htb_keeper_t +#define sizer_t qse_htb_sizer_t +#define walker_t qse_htb_walker_t + +#define KPTR(p) QSE_HTB_KPTR(p) +#define KLEN(p) QSE_HTB_KLEN(p) +#define VPTR(p) QSE_HTB_VPTR(p) +#define VLEN(p) QSE_HTB_VLEN(p) +#define NEXT(p) QSE_HTB_NEXT(p) + +#define SIZEOF(x) QSE_SIZEOF(x) +#define size_t qse_size_t +#define byte_t qse_byte_t +#define uint_t qse_uint_t +#define mmgr_t qse_mmgr_t + +#define KTOB(htb,len) ((len)*(htb)->scale[QSE_HTB_KEY]) +#define VTOB(htb,len) ((len)*(htb)->scale[QSE_HTB_VAL]) + +#define UPSERT 1 +#define UPDATE 2 +#define ENSERT 3 +#define INSERT 4 + +static int reorganize (htb_t* htb); + +static size_t hash_key (htb_t* htb, const void* kptr, size_t klen) +{ + /*size_t h = 2166136261;*/ + /*size_t h = 0;*/ + size_t h = 5381; + const byte_t* p = (const byte_t*)kptr; + const byte_t* bound = p + klen; + + while (p < bound) + { + /*h = (h * 16777619) ^ *p++;*/ + /*h = h * 31 + *p++;*/ + h = ((h << 5) + h) + *p++; + } + + return h ; +} + +static int comp_key (htb_t* htb, + const void* kptr1, size_t klen1, + const void* kptr2, size_t klen2) +{ + if (klen1 == klen2) return QSE_MEMCMP (kptr1, kptr2, KTOB(htb,klen1)); + /* it just returns 1 to indicate that they are different. */ + return 1; +} + +static pair_t* alloc_pair (htb_t* htb, + void* kptr, size_t klen, void* vptr, size_t vlen) +{ + pair_t* n; + copier_t kcop = htb->copier[QSE_HTB_KEY]; + copier_t vcop = htb->copier[QSE_HTB_VAL]; + + size_t as = SIZEOF(pair_t); + if (kcop == QSE_HTB_COPIER_INLINE) as += KTOB(htb,klen); + if (vcop == QSE_HTB_COPIER_INLINE) as += VTOB(htb,vlen); + + n = (pair_t*) QSE_MMGR_ALLOC (htb->mmgr, as); + if (n == QSE_NULL) return QSE_NULL; + + NEXT(n) = QSE_NULL; + + KLEN(n) = klen; + if (kcop == QSE_HTB_COPIER_SIMPLE) + { + KPTR(n) = kptr; + } + else if (kcop == QSE_HTB_COPIER_INLINE) + { + KPTR(n) = n + 1; + QSE_MEMCPY (KPTR(n), kptr, KTOB(htb,klen)); + } + else + { + KPTR(n) = kcop (htb, kptr, klen); + if (KPTR(n) == QSE_NULL) + { + QSE_MMGR_FREE (htb->mmgr, n); + return QSE_NULL; + } + } + + VLEN(n) = vlen; + if (vcop == QSE_HTB_COPIER_SIMPLE) + { + VPTR(n) = vptr; + } + else if (vcop == QSE_HTB_COPIER_INLINE) + { + VPTR(n) = n + 1; + if (kcop == QSE_HTB_COPIER_INLINE) + VPTR(n) = (byte_t*)VPTR(n) + KTOB(htb,klen); + QSE_MEMCPY (VPTR(n), vptr, VTOB(htb,vlen)); + } + else + { + VPTR(n) = vcop (htb, vptr, vlen); + if (VPTR(n) != QSE_NULL) + { + if (htb->freeer[QSE_HTB_KEY] != QSE_NULL) + htb->freeer[QSE_HTB_KEY] (htb, KPTR(n), KLEN(n)); + QSE_MMGR_FREE (htb->mmgr, n); + return QSE_NULL; + } + } + + return n; +} + +static void free_pair (htb_t* htb, pair_t* pair) +{ + if (htb->freeer[QSE_HTB_KEY] != QSE_NULL) + htb->freeer[QSE_HTB_KEY] (htb, KPTR(pair), KLEN(pair)); + if (htb->freeer[QSE_HTB_VAL] != QSE_NULL) + htb->freeer[QSE_HTB_VAL] (htb, VPTR(pair), VLEN(pair)); + QSE_MMGR_FREE (htb->mmgr, pair); +} + +static pair_t* change_pair_val ( + htb_t* htb, pair_t* pair, void* vptr, size_t vlen) +{ + if (VPTR(pair) == vptr && VLEN(pair) == vlen) + { + /* if the old value and the new value are the same, + * it just calls the handler for this condition. + * No value replacement occurs. */ + if (htb->keeper != QSE_NULL) + { + htb->keeper (htb, vptr, vlen); + } + } + else + { + copier_t vcop = htb->copier[QSE_HTB_VAL]; + void* ovptr = VPTR(pair); + size_t ovlen = VLEN(pair); + + /* place the new value according to the copier */ + if (vcop == QSE_HTB_COPIER_SIMPLE) + { + VPTR(pair) = vptr; + VLEN(pair) = vlen; + } + else if (vcop == QSE_HTB_COPIER_INLINE) + { + if (ovlen == vlen) + { + QSE_MEMCPY (VPTR(pair), vptr, VTOB(htb,vlen)); + } + else + { + /* need to reconstruct the pair */ + pair_t* p = alloc_pair (htb, + KPTR(pair), KLEN(pair), + vptr, vlen); + if (p == QSE_NULL) return QSE_NULL; + free_pair (htb, pair); + return p; + } + } + else + { + void* nvptr = vcop (htb, vptr, vlen); + if (nvptr == QSE_NULL) return QSE_NULL; + VPTR(pair) = nvptr; + VLEN(pair) = vlen; + } + + /* free up the old value */ + if (htb->freeer[QSE_HTB_VAL] != QSE_NULL) + { + htb->freeer[QSE_HTB_VAL] (htb, ovptr, ovlen); + } + } + + + return pair; +} + +htb_t* qse_htb_open (mmgr_t* mmgr, size_t ext, size_t capa, int factor) +{ + htb_t* htb; + + if (mmgr == QSE_NULL) + { + mmgr = QSE_MMGR_GETDFL(); + + QSE_ASSERTX (mmgr != QSE_NULL, + "Set the memory manager with QSE_MMGR_SETDFL()"); + + if (mmgr == QSE_NULL) return QSE_NULL; + } + + htb = (htb_t*) QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(htb_t) + ext); + if (htb == QSE_NULL) return QSE_NULL; + + if (qse_htb_init (htb, mmgr, capa, factor) == QSE_NULL) + { + QSE_MMGR_FREE (mmgr, htb); + return QSE_NULL; + } + + return htb; +} + +void qse_htb_close (htb_t* htb) +{ + qse_htb_fini (htb); + QSE_MMGR_FREE (htb->mmgr, htb); +} + +htb_t* qse_htb_init (htb_t* htb, mmgr_t* mmgr, size_t capa, int factor) +{ + QSE_ASSERTX (capa > 0, + "The initial capacity should be greater than 0. Otherwise, it is adjusted to 1 in the release mode"); + QSE_ASSERTX (factor >= 0 && factor <= 100, + "The load factor should be between 0 and 100 inclusive. In the release mode, a value out of the range is adjusted to 100"); + + /* some initial adjustment */ + if (capa <= 0) capa = 1; + if (factor > 100) factor = 100; + + /* do not zero out the extension */ + QSE_MEMSET (htb, 0, SIZEOF(*htb)); + htb->mmgr = mmgr; + + htb->bucket = QSE_MMGR_ALLOC (mmgr, capa*SIZEOF(pair_t*)); + if (htb->bucket == QSE_NULL) return QSE_NULL; + + /*for (i = 0; i < capa; i++) htb->bucket[i] = QSE_NULL;*/ + QSE_MEMSET (htb->bucket, 0, capa*SIZEOF(pair_t*)); + + htb->scale[QSE_HTB_KEY] = 1; + htb->scale[QSE_HTB_VAL] = 1; + htb->factor = factor; + + htb->size = 0; + htb->capa = capa; + htb->threshold = htb->capa * htb->factor / 100; + if (htb->capa > 0 && htb->threshold <= 0) htb->threshold = 1; + + htb->hasher = hash_key; + htb->comper = comp_key; + htb->copier[QSE_HTB_KEY] = QSE_HTB_COPIER_SIMPLE; + htb->copier[QSE_HTB_VAL] = QSE_HTB_COPIER_SIMPLE; + + /* + htb->freeer[QSE_HTB_KEY] = QSE_NULL; + htb->freeer[QSE_HTB_VAL] = QSE_NULL; + htb->keeper = QSE_NULL; + htb->sizer = QSE_NULL; + */ + + return htb; +} + +void qse_htb_fini (htb_t* htb) +{ + qse_htb_clear (htb); + QSE_MMGR_FREE (htb->mmgr, htb->bucket); +} + +int qse_htb_getscale (htb_t* htb, qse_htb_id_t id) +{ + QSE_ASSERTX (id == QSE_HTB_KEY || id == QSE_HTB_VAL, + "The ID should be either QSE_HTB_KEY or QSE_HTB_VAL"); + return htb->scale[id]; +} + +void qse_htb_setscale (htb_t* htb, qse_htb_id_t id, int scale) +{ + QSE_ASSERTX (id == QSE_HTB_KEY || id == QSE_HTB_VAL, + "The ID should be either QSE_HTB_KEY or QSE_HTB_VAL"); + + QSE_ASSERTX (scale > 0 && scale <= QSE_TYPE_MAX(qse_byte_t), + "The scale should be larger than 0 and less than or equal to the maximum value that the qse_byte_t type can hold"); + + if (scale <= 0) scale = 1; + if (scale > QSE_TYPE_MAX(qse_byte_t)) scale = QSE_TYPE_MAX(qse_byte_t); + + htb->scale[id] = scale; +} + +copier_t qse_htb_getcopier (htb_t* htb, qse_htb_id_t id) +{ + QSE_ASSERTX (id == QSE_HTB_KEY || id == QSE_HTB_VAL, + "The ID should be either QSE_HTB_KEY or QSE_HTB_VAL"); + return htb->copier[id]; +} + +void qse_htb_setcopier (htb_t* htb, qse_htb_id_t id, copier_t copier) +{ + QSE_ASSERTX (id == QSE_HTB_KEY || id == QSE_HTB_VAL, + "The ID should be either QSE_HTB_KEY or QSE_HTB_VAL"); + if (copier == QSE_NULL) copier = QSE_HTB_COPIER_SIMPLE; + htb->copier[id] = copier; +} + +freeer_t qse_htb_getfreeer (htb_t* htb, qse_htb_id_t id) +{ + QSE_ASSERTX (id == QSE_HTB_KEY || id == QSE_HTB_VAL, + "The ID should be either QSE_HTB_KEY or QSE_HTB_VAL"); + return htb->freeer[id]; +} + +void qse_htb_setfreeer (htb_t* htb, qse_htb_id_t id, freeer_t freeer) +{ + QSE_ASSERTX (id == QSE_HTB_KEY || id == QSE_HTB_VAL, + "The ID should be either QSE_HTB_KEY or QSE_HTB_VAL"); + htb->freeer[id] = freeer; +} + +hasher_t qse_htb_gethasher (htb_t* htb) +{ + return htb->hasher; +} + +void qse_htb_sethasher (htb_t* htb, hasher_t hasher) +{ + if (hasher == QSE_NULL) hasher = hash_key; + htb->hasher = hasher; +} + +comper_t qse_htb_getcomper (htb_t* htb) +{ + return htb->comper; +} + +void qse_htb_setcomper (htb_t* htb, comper_t comper) +{ + if (comper == QSE_NULL) comper = comp_key; + htb->comper = comper; +} + +keeper_t qse_htb_getkeeper (htb_t* htb) +{ + return htb->keeper; +} + +void qse_htb_setkeeper (htb_t* htb, keeper_t keeper) +{ + htb->keeper = keeper; +} + +sizer_t qse_htb_getsizer (htb_t* htb) +{ + return htb->sizer; +} + +void qse_htb_setsizer (htb_t* htb, sizer_t sizer) +{ + htb->sizer = sizer; +} + +size_t qse_htb_getsize (htb_t* htb) +{ + return htb->size; +} + +size_t qse_htb_getcapa (htb_t* htb) +{ + return htb->capa; +} + +pair_t* qse_htb_search (htb_t* htb, const void* kptr, size_t klen) +{ + pair_t* pair; + size_t hc; + + hc = htb->hasher(htb,kptr,klen) % htb->capa; + pair = htb->bucket[hc]; + + while (pair != QSE_NULL) + { + if (htb->comper (htb, KPTR(pair), KLEN(pair), kptr, klen) == 0) + { + return pair; + } + + pair = NEXT(pair); + } + + return QSE_NULL; +} + +static pair_t* insert ( + htb_t* htb, void* kptr, size_t klen, void* vptr, size_t vlen, int opt) +{ + pair_t* pair, * p, * prev, * next; + size_t hc; + + hc = htb->hasher(htb,kptr,klen) % htb->capa; + pair = htb->bucket[hc]; + prev = QSE_NULL; + + while (pair != QSE_NULL) + { + next = NEXT(pair); + + if (htb->comper (htb, KPTR(pair), KLEN(pair), kptr, klen) == 0) + { + /* found a pair with a matching key */ + switch (opt) + { + case UPSERT: + case UPDATE: + p = change_pair_val (htb, pair, vptr, vlen); + if (p == QSE_NULL) + { + /* error in change the value */ + return QSE_NULL; + } + if (p != pair) + { + /* pair reallocated. + * relink it */ + if (prev == QSE_NULL) + htb->bucket[hc] = p; + else NEXT(prev) = p; + NEXT(p) = next; + } + return p; + + case ENSERT: + /* return existing pair */ + return pair; + + case INSERT: + /* return failure */ + return QSE_NULL; + } + } + + prev = pair; + pair = next; + } + + if (opt == UPDATE) return QSE_NULL; + + if (htb->threshold > 0 && htb->size >= htb->threshold) + { + if (reorganize(htb) == 0) /* ignore the error */ + { + hc = htb->hasher(htb,kptr,klen) % htb->capa; + } + } + + QSE_ASSERT (pair == QSE_NULL); + + pair = alloc_pair (htb, kptr, klen, vptr, vlen); + if (pair == QSE_NULL) return QSE_NULL; /* error */ + + NEXT(pair) = htb->bucket[hc]; + htb->bucket[hc] = pair; + htb->size++; + + return pair; /* new key added */ +} + +pair_t* qse_htb_upsert ( + htb_t* htb, void* kptr, size_t klen, void* vptr, size_t vlen) +{ + return insert (htb, kptr, klen, vptr, vlen, UPSERT); +} + +pair_t* qse_htb_ensert ( + htb_t* htb, void* kptr, size_t klen, void* vptr, size_t vlen) +{ + return insert (htb, kptr, klen, vptr, vlen, ENSERT); +} + +pair_t* qse_htb_insert ( + htb_t* htb, void* kptr, size_t klen, void* vptr, size_t vlen) +{ + return insert (htb, kptr, klen, vptr, vlen, INSERT); +} + + +pair_t* qse_htb_update ( + htb_t* htb, void* kptr, size_t klen, void* vptr, size_t vlen) +{ + return insert (htb, kptr, klen, vptr, vlen, UPDATE); +} + +int qse_htb_delete (htb_t* htb, const void* kptr, size_t klen) +{ + pair_t* pair, * prev; + size_t hc; + + hc = htb->hasher(htb,kptr,klen) % htb->capa; + pair = htb->bucket[hc]; + prev = QSE_NULL; + + while (pair != QSE_NULL) + { + if (htb->comper (htb, KPTR(pair), KLEN(pair), kptr, klen) == 0) + { + if (prev == QSE_NULL) + htb->bucket[hc] = NEXT(pair); + else NEXT(prev) = NEXT(pair); + + free_pair (htb, pair); + htb->size--; + + return 0; + } + + prev = pair; + pair = NEXT(pair); + } + + return -1; +} + +void qse_htb_clear (htb_t* htb) +{ + size_t i; + pair_t* pair, * next; + + for (i = 0; i < htb->capa; i++) + { + pair = htb->bucket[i]; + + while (pair != QSE_NULL) + { + next = NEXT(pair); + free_pair (htb, pair); + htb->size--; + pair = next; + } + + htb->bucket[i] = QSE_NULL; + } +} + + +void qse_htb_walk (htb_t* htb, walker_t walker, void* ctx) +{ + size_t i; + pair_t* pair, * next; + + for (i = 0; i < htb->capa; i++) + { + pair = htb->bucket[i]; + + while (pair != QSE_NULL) + { + next = NEXT(pair); + if (walker(htb, pair, ctx) == QSE_HTB_WALK_STOP) return; + pair = next; + } + } +} + +pair_t* qse_htb_getfirstpair (htb_t* htb, size_t* buckno) +{ + size_t i; + pair_t* pair; + + for (i = 0; i < htb->capa; i++) + { + pair = htb->bucket[i]; + if (pair != QSE_NULL) + { + *buckno = i; + return pair; + } + } + + return QSE_NULL; +} + +pair_t* qse_htb_getnextpair (htb_t* htb, pair_t* pair, size_t* buckno) +{ + size_t i; + pair_t* next; + + next = NEXT(pair); + if (next != QSE_NULL) + { + /* no change in bucket number */ + return next; + } + + for (i = (*buckno)+1; i < htb->capa; i++) + { + pair = htb->bucket[i]; + if (pair != QSE_NULL) + { + *buckno = i; + return pair; + } + } + + return QSE_NULL; +} + +static int reorganize (htb_t* htb) +{ + size_t i, hc, new_capa; + pair_t** new_buck; + + if (htb->sizer) + { + new_capa = htb->sizer (htb, htb->capa + 1); + + /* if no change in capacity, return success + * without reorganization */ + if (new_capa == htb->capa) return 0; + + /* adjust to 1 if the new capacity is not reasonable */ + if (new_capa <= 0) new_capa = 1; + } + else + { + /* the bucket is doubled until it grows up to 65536 slots. + * once it has reached it, it grows by 65536 slots */ + new_capa = (htb->capa >= 65536)? (htb->capa + 65536): (htb->capa << 1); + } + + new_buck = (pair_t**) QSE_MMGR_ALLOC ( + htb->mmgr, new_capa*SIZEOF(pair_t*)); + if (new_buck == QSE_NULL) + { + /* reorganization is disabled once it fails */ + htb->threshold = 0; + return -1; + } + + /*for (i = 0; i < new_capa; i++) new_buck[i] = QSE_NULL;*/ + QSE_MEMSET (new_buck, 0, new_capa*SIZEOF(pair_t*)); + + for (i = 0; i < htb->capa; i++) + { + pair_t* pair = htb->bucket[i]; + + while (pair != QSE_NULL) + { + pair_t* next = NEXT(pair); + + hc = htb->hasher (htb, + KPTR(pair), + KLEN(pair)) % new_capa; + + NEXT(pair) = new_buck[hc]; + new_buck[hc] = pair; + + pair = next; + } + } + + QSE_MMGR_FREE (htb->mmgr, htb->bucket); + htb->bucket = new_buck; + htb->capa = new_capa; + htb->threshold = htb->capa * htb->factor / 100; + + return 0; +} diff --git a/qse/lib/cmn/map.c b/qse/lib/cmn/map.c deleted file mode 100644 index fc113bc1..00000000 --- a/qse/lib/cmn/map.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * $Id: map.c 327 2010-05-10 13:15:55Z hyunghwan.chung $ - * - Copyright 2006-2009 Chung, Hyung-Hwan. - This file is part of QSE. - - QSE is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation, either version 3 of - the License, or (at your option) any later version. - - QSE is distributed in the hope 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 QSE. If not, see . - */ - -#include -#include "mem.h" - -QSE_IMPLEMENT_COMMON_FUNCTIONS (map) - -#define map_t qse_map_t -#define pair_t qse_map_pair_t -#define copier_t qse_map_copier_t -#define freeer_t qse_map_freeer_t -#define hasher_t qse_map_hasher_t -#define comper_t qse_map_comper_t -#define keeper_t qse_map_keeper_t -#define sizer_t qse_map_sizer_t -#define walker_t qse_map_walker_t - -#define KPTR(p) QSE_MAP_KPTR(p) -#define KLEN(p) QSE_MAP_KLEN(p) -#define VPTR(p) QSE_MAP_VPTR(p) -#define VLEN(p) QSE_MAP_VLEN(p) -#define NEXT(p) QSE_MAP_NEXT(p) - -#define SIZEOF(x) QSE_SIZEOF(x) -#define size_t qse_size_t -#define byte_t qse_byte_t -#define uint_t qse_uint_t -#define mmgr_t qse_mmgr_t - -#define KTOB(map,len) ((len)*(map)->scale[QSE_MAP_KEY]) -#define VTOB(map,len) ((len)*(map)->scale[QSE_MAP_VAL]) - -#define UPSERT 1 -#define UPDATE 2 -#define ENSERT 3 -#define INSERT 4 - -static int reorganize (map_t* map); - -static size_t hash_key (map_t* map, const void* kptr, size_t klen) -{ - /*size_t h = 2166136261;*/ - /*size_t h = 0;*/ - size_t h = 5381; - const byte_t* p = (const byte_t*)kptr; - const byte_t* bound = p + klen; - - while (p < bound) - { - /*h = (h * 16777619) ^ *p++;*/ - /*h = h * 31 + *p++;*/ - h = ((h << 5) + h) + *p++; - } - - return h ; -} - -static int comp_key (map_t* map, - const void* kptr1, size_t klen1, - const void* kptr2, size_t klen2) -{ - if (klen1 == klen2) return QSE_MEMCMP (kptr1, kptr2, KTOB(map,klen1)); - /* it just returns 1 to indicate that they are different. */ - return 1; -} - -static pair_t* alloc_pair (map_t* map, - void* kptr, size_t klen, void* vptr, size_t vlen) -{ - pair_t* n; - copier_t kcop = map->copier[QSE_MAP_KEY]; - copier_t vcop = map->copier[QSE_MAP_VAL]; - - size_t as = SIZEOF(pair_t); - if (kcop == QSE_MAP_COPIER_INLINE) as += KTOB(map,klen); - if (vcop == QSE_MAP_COPIER_INLINE) as += VTOB(map,vlen); - - n = (pair_t*) QSE_MMGR_ALLOC (map->mmgr, as); - if (n == QSE_NULL) return QSE_NULL; - - NEXT(n) = QSE_NULL; - - KLEN(n) = klen; - if (kcop == QSE_MAP_COPIER_SIMPLE) - { - KPTR(n) = kptr; - } - else if (kcop == QSE_MAP_COPIER_INLINE) - { - KPTR(n) = n + 1; - QSE_MEMCPY (KPTR(n), kptr, KTOB(map,klen)); - } - else - { - KPTR(n) = kcop (map, kptr, klen); - if (KPTR(n) == QSE_NULL) - { - QSE_MMGR_FREE (map->mmgr, n); - return QSE_NULL; - } - } - - VLEN(n) = vlen; - if (vcop == QSE_MAP_COPIER_SIMPLE) - { - VPTR(n) = vptr; - } - else if (vcop == QSE_MAP_COPIER_INLINE) - { - VPTR(n) = n + 1; - if (kcop == QSE_MAP_COPIER_INLINE) - VPTR(n) = (byte_t*)VPTR(n) + KTOB(map,klen); - QSE_MEMCPY (VPTR(n), vptr, VTOB(map,vlen)); - } - else - { - VPTR(n) = vcop (map, vptr, vlen); - if (VPTR(n) != QSE_NULL) - { - if (map->freeer[QSE_MAP_KEY] != QSE_NULL) - map->freeer[QSE_MAP_KEY] (map, KPTR(n), KLEN(n)); - QSE_MMGR_FREE (map->mmgr, n); - return QSE_NULL; - } - } - - return n; -} - -static void free_pair (map_t* map, pair_t* pair) -{ - if (map->freeer[QSE_MAP_KEY] != QSE_NULL) - map->freeer[QSE_MAP_KEY] (map, KPTR(pair), KLEN(pair)); - if (map->freeer[QSE_MAP_VAL] != QSE_NULL) - map->freeer[QSE_MAP_VAL] (map, VPTR(pair), VLEN(pair)); - QSE_MMGR_FREE (map->mmgr, pair); -} - -static pair_t* change_pair_val ( - map_t* map, pair_t* pair, void* vptr, size_t vlen) -{ - if (VPTR(pair) == vptr && VLEN(pair) == vlen) - { - /* if the old value and the new value are the same, - * it just calls the handler for this condition. - * No value replacement occurs. */ - if (map->keeper != QSE_NULL) - { - map->keeper (map, vptr, vlen); - } - } - else - { - copier_t vcop = map->copier[QSE_MAP_VAL]; - void* ovptr = VPTR(pair); - size_t ovlen = VLEN(pair); - - /* place the new value according to the copier */ - if (vcop == QSE_MAP_COPIER_SIMPLE) - { - VPTR(pair) = vptr; - VLEN(pair) = vlen; - } - else if (vcop == QSE_MAP_COPIER_INLINE) - { - if (ovlen == vlen) - { - QSE_MEMCPY (VPTR(pair), vptr, VTOB(map,vlen)); - } - else - { - /* need to reconstruct the pair */ - pair_t* p = alloc_pair (map, - KPTR(pair), KLEN(pair), - vptr, vlen); - if (p == QSE_NULL) return QSE_NULL; - free_pair (map, pair); - return p; - } - } - else - { - void* nvptr = vcop (map, vptr, vlen); - if (nvptr == QSE_NULL) return QSE_NULL; - VPTR(pair) = nvptr; - VLEN(pair) = vlen; - } - - /* free up the old value */ - if (map->freeer[QSE_MAP_VAL] != QSE_NULL) - { - map->freeer[QSE_MAP_VAL] (map, ovptr, ovlen); - } - } - - - return pair; -} - -map_t* qse_map_open (mmgr_t* mmgr, size_t ext, size_t capa, int factor) -{ - map_t* map; - - if (mmgr == QSE_NULL) - { - mmgr = QSE_MMGR_GETDFL(); - - QSE_ASSERTX (mmgr != QSE_NULL, - "Set the memory manager with QSE_MMGR_SETDFL()"); - - if (mmgr == QSE_NULL) return QSE_NULL; - } - - map = (map_t*) QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(map_t) + ext); - if (map == QSE_NULL) return QSE_NULL; - - if (qse_map_init (map, mmgr, capa, factor) == QSE_NULL) - { - QSE_MMGR_FREE (mmgr, map); - return QSE_NULL; - } - - return map; -} - -void qse_map_close (map_t* map) -{ - qse_map_fini (map); - QSE_MMGR_FREE (map->mmgr, map); -} - -map_t* qse_map_init (map_t* map, mmgr_t* mmgr, size_t capa, int factor) -{ - QSE_ASSERTX (capa > 0, - "The initial capacity should be greater than 0. Otherwise, it is adjusted to 1 in the release mode"); - QSE_ASSERTX (factor >= 0 && factor <= 100, - "The load factor should be between 0 and 100 inclusive. In the release mode, a value out of the range is adjusted to 100"); - - /* some initial adjustment */ - if (capa <= 0) capa = 1; - if (factor > 100) factor = 100; - - /* do not zero out the extension */ - QSE_MEMSET (map, 0, SIZEOF(*map)); - map->mmgr = mmgr; - - map->bucket = QSE_MMGR_ALLOC (mmgr, capa*SIZEOF(pair_t*)); - if (map->bucket == QSE_NULL) return QSE_NULL; - - /*for (i = 0; i < capa; i++) map->bucket[i] = QSE_NULL;*/ - QSE_MEMSET (map->bucket, 0, capa*SIZEOF(pair_t*)); - - map->scale[QSE_MAP_KEY] = 1; - map->scale[QSE_MAP_VAL] = 1; - map->factor = factor; - - map->size = 0; - map->capa = capa; - map->threshold = map->capa * map->factor / 100; - if (map->capa > 0 && map->threshold <= 0) map->threshold = 1; - - map->hasher = hash_key; - map->comper = comp_key; - map->copier[QSE_MAP_KEY] = QSE_MAP_COPIER_SIMPLE; - map->copier[QSE_MAP_VAL] = QSE_MAP_COPIER_SIMPLE; - - /* - map->freeer[QSE_MAP_KEY] = QSE_NULL; - map->freeer[QSE_MAP_VAL] = QSE_NULL; - map->keeper = QSE_NULL; - map->sizer = QSE_NULL; - */ - - return map; -} - -void qse_map_fini (map_t* map) -{ - qse_map_clear (map); - QSE_MMGR_FREE (map->mmgr, map->bucket); -} - -int qse_map_getscale (map_t* map, qse_map_id_t id) -{ - QSE_ASSERTX (id == QSE_MAP_KEY || id == QSE_MAP_VAL, - "The ID should be either QSE_MAP_KEY or QSE_MAP_VAL"); - return map->scale[id]; -} - -void qse_map_setscale (map_t* map, qse_map_id_t id, int scale) -{ - QSE_ASSERTX (id == QSE_MAP_KEY || id == QSE_MAP_VAL, - "The ID should be either QSE_MAP_KEY or QSE_MAP_VAL"); - - QSE_ASSERTX (scale > 0 && scale <= QSE_TYPE_MAX(qse_byte_t), - "The scale should be larger than 0 and less than or equal to the maximum value that the qse_byte_t type can hold"); - - if (scale <= 0) scale = 1; - if (scale > QSE_TYPE_MAX(qse_byte_t)) scale = QSE_TYPE_MAX(qse_byte_t); - - map->scale[id] = scale; -} - -copier_t qse_map_getcopier (map_t* map, qse_map_id_t id) -{ - QSE_ASSERTX (id == QSE_MAP_KEY || id == QSE_MAP_VAL, - "The ID should be either QSE_MAP_KEY or QSE_MAP_VAL"); - return map->copier[id]; -} - -void qse_map_setcopier (map_t* map, qse_map_id_t id, copier_t copier) -{ - QSE_ASSERTX (id == QSE_MAP_KEY || id == QSE_MAP_VAL, - "The ID should be either QSE_MAP_KEY or QSE_MAP_VAL"); - if (copier == QSE_NULL) copier = QSE_MAP_COPIER_SIMPLE; - map->copier[id] = copier; -} - -freeer_t qse_map_getfreeer (map_t* map, qse_map_id_t id) -{ - QSE_ASSERTX (id == QSE_MAP_KEY || id == QSE_MAP_VAL, - "The ID should be either QSE_MAP_KEY or QSE_MAP_VAL"); - return map->freeer[id]; -} - -void qse_map_setfreeer (map_t* map, qse_map_id_t id, freeer_t freeer) -{ - QSE_ASSERTX (id == QSE_MAP_KEY || id == QSE_MAP_VAL, - "The ID should be either QSE_MAP_KEY or QSE_MAP_VAL"); - map->freeer[id] = freeer; -} - -hasher_t qse_map_gethasher (map_t* map) -{ - return map->hasher; -} - -void qse_map_sethasher (map_t* map, hasher_t hasher) -{ - if (hasher == QSE_NULL) hasher = hash_key; - map->hasher = hasher; -} - -comper_t qse_map_getcomper (map_t* map) -{ - return map->comper; -} - -void qse_map_setcomper (map_t* map, comper_t comper) -{ - if (comper == QSE_NULL) comper = comp_key; - map->comper = comper; -} - -keeper_t qse_map_getkeeper (map_t* map) -{ - return map->keeper; -} - -void qse_map_setkeeper (map_t* map, keeper_t keeper) -{ - map->keeper = keeper; -} - -sizer_t qse_map_getsizer (map_t* map) -{ - return map->sizer; -} - -void qse_map_setsizer (map_t* map, sizer_t sizer) -{ - map->sizer = sizer; -} - -size_t qse_map_getsize (map_t* map) -{ - return map->size; -} - -size_t qse_map_getcapa (map_t* map) -{ - return map->capa; -} - -pair_t* qse_map_search (map_t* map, const void* kptr, size_t klen) -{ - pair_t* pair; - size_t hc; - - hc = map->hasher(map,kptr,klen) % map->capa; - pair = map->bucket[hc]; - - while (pair != QSE_NULL) - { - if (map->comper (map, KPTR(pair), KLEN(pair), kptr, klen) == 0) - { - return pair; - } - - pair = NEXT(pair); - } - - return QSE_NULL; -} - -static pair_t* insert ( - map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen, int opt) -{ - pair_t* pair, * p, * prev, * next; - size_t hc; - - hc = map->hasher(map,kptr,klen) % map->capa; - pair = map->bucket[hc]; - prev = QSE_NULL; - - while (pair != QSE_NULL) - { - next = NEXT(pair); - - if (map->comper (map, KPTR(pair), KLEN(pair), kptr, klen) == 0) - { - /* found a pair with a matching key */ - switch (opt) - { - case UPSERT: - case UPDATE: - p = change_pair_val (map, pair, vptr, vlen); - if (p == QSE_NULL) - { - /* error in change the value */ - return QSE_NULL; - } - if (p != pair) - { - /* pair reallocated. - * relink it */ - if (prev == QSE_NULL) - map->bucket[hc] = p; - else NEXT(prev) = p; - NEXT(p) = next; - } - return p; - - case ENSERT: - /* return existing pair */ - return pair; - - case INSERT: - /* return failure */ - return QSE_NULL; - } - } - - prev = pair; - pair = next; - } - - if (opt == UPDATE) return QSE_NULL; - - if (map->threshold > 0 && map->size >= map->threshold) - { - if (reorganize(map) == 0) /* ignore the error */ - { - hc = map->hasher(map,kptr,klen) % map->capa; - } - } - - QSE_ASSERT (pair == QSE_NULL); - - pair = alloc_pair (map, kptr, klen, vptr, vlen); - if (pair == QSE_NULL) return QSE_NULL; /* error */ - - NEXT(pair) = map->bucket[hc]; - map->bucket[hc] = pair; - map->size++; - - return pair; /* new key added */ -} - -pair_t* qse_map_upsert ( - map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen) -{ - return insert (map, kptr, klen, vptr, vlen, UPSERT); -} - -pair_t* qse_map_ensert ( - map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen) -{ - return insert (map, kptr, klen, vptr, vlen, ENSERT); -} - -pair_t* qse_map_insert ( - map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen) -{ - return insert (map, kptr, klen, vptr, vlen, INSERT); -} - - -pair_t* qse_map_update ( - map_t* map, void* kptr, size_t klen, void* vptr, size_t vlen) -{ - return insert (map, kptr, klen, vptr, vlen, UPDATE); -} - -int qse_map_delete (map_t* map, const void* kptr, size_t klen) -{ - pair_t* pair, * prev; - size_t hc; - - hc = map->hasher(map,kptr,klen) % map->capa; - pair = map->bucket[hc]; - prev = QSE_NULL; - - while (pair != QSE_NULL) - { - if (map->comper (map, KPTR(pair), KLEN(pair), kptr, klen) == 0) - { - if (prev == QSE_NULL) - map->bucket[hc] = NEXT(pair); - else NEXT(prev) = NEXT(pair); - - free_pair (map, pair); - map->size--; - - return 0; - } - - prev = pair; - pair = NEXT(pair); - } - - return -1; -} - -void qse_map_clear (map_t* map) -{ - size_t i; - pair_t* pair, * next; - - for (i = 0; i < map->capa; i++) - { - pair = map->bucket[i]; - - while (pair != QSE_NULL) - { - next = NEXT(pair); - free_pair (map, pair); - map->size--; - pair = next; - } - - map->bucket[i] = QSE_NULL; - } -} - - -size_t qse_map_walk (map_t* map, walker_t walker, void* arg) -{ - size_t i, nwalks = 0; - pair_t* pair, * next; - - for (i = 0; i < map->capa; i++) - { - pair = map->bucket[i]; - - while (pair != QSE_NULL) - { - next = NEXT(pair); - if (walker(map, pair, arg) == QSE_MAP_WALK_STOP) - return nwalks; - nwalks++; - pair = next; - } - } - - return nwalks; -} - -pair_t* qse_map_getfirstpair (map_t* map, size_t* buckno) -{ - size_t i; - pair_t* pair; - - for (i = 0; i < map->capa; i++) - { - pair = map->bucket[i]; - if (pair != QSE_NULL) - { - *buckno = i; - return pair; - } - } - - return QSE_NULL; -} - -pair_t* qse_map_getnextpair (map_t* map, pair_t* pair, size_t* buckno) -{ - size_t i; - pair_t* next; - - next = NEXT(pair); - if (next != QSE_NULL) - { - /* no change in bucket number */ - return next; - } - - for (i = (*buckno)+1; i < map->capa; i++) - { - pair = map->bucket[i]; - if (pair != QSE_NULL) - { - *buckno = i; - return pair; - } - } - - return QSE_NULL; -} - -static int reorganize (map_t* map) -{ - size_t i, hc, new_capa; - pair_t** new_buck; - - if (map->sizer) - { - new_capa = map->sizer (map, map->capa + 1); - - /* if no change in capacity, return success - * without reorganization */ - if (new_capa == map->capa) return 0; - - /* adjust to 1 if the new capacity is not reasonable */ - if (new_capa <= 0) new_capa = 1; - } - else - { - /* the bucket is doubled until it grows up to 65536 slots. - * once it has reached it, it grows by 65536 slots */ - new_capa = (map->capa >= 65536)? (map->capa + 65536): (map->capa << 1); - } - - new_buck = (pair_t**) QSE_MMGR_ALLOC ( - map->mmgr, new_capa*SIZEOF(pair_t*)); - if (new_buck == QSE_NULL) - { - /* reorganization is disabled once it fails */ - map->threshold = 0; - return -1; - } - - /*for (i = 0; i < new_capa; i++) new_buck[i] = QSE_NULL;*/ - QSE_MEMSET (new_buck, 0, new_capa*SIZEOF(pair_t*)); - - for (i = 0; i < map->capa; i++) - { - pair_t* pair = map->bucket[i]; - - while (pair != QSE_NULL) - { - pair_t* next = NEXT(pair); - - hc = map->hasher (map, - KPTR(pair), - KLEN(pair)) % new_capa; - - NEXT(pair) = new_buck[hc]; - new_buck[hc] = pair; - - pair = next; - } - } - - QSE_MMGR_FREE (map->mmgr, map->bucket); - map->bucket = new_buck; - map->capa = new_capa; - map->threshold = map->capa * map->factor / 100; - - return 0; -} diff --git a/qse/lib/cmn/rbt.c b/qse/lib/cmn/rbt.c new file mode 100644 index 00000000..ce0f8767 --- /dev/null +++ b/qse/lib/cmn/rbt.c @@ -0,0 +1,691 @@ +/* + * $Id$ + * + Copyright 2006-2009 Chung, Hyung-Hwan. + This file is part of QSE. + + QSE is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. + + QSE is distributed in the hope 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 QSE. If not, see . + */ + +#include +#include "mem.h" + +#define IS_NIL(rbt,x) ((x) == &((rbt)->nil)) + +#define KTOB(htb,len) ((len)*(htb)->scale[QSE_RBT_KEY]) + +#define LEFT 0 +#define RIGHT 1 + +#define left child[LEFT] +#define right child[RIGHT] + +#define rotate_left(rbt,pivot) rotate(rbt,pivot,1); +#define rotate_right(rbt,pivot) rotate(rbt,pivot,0); + +QSE_IMPLEMENT_COMMON_FUNCTIONS (rbt) + +static QSE_INLINE void init_node ( + qse_rbt_t* rbt, qse_rbt_node_t* node, int color, + int key, int value) +{ + QSE_MEMSET (node, 0, QSE_SIZEOF(*node)); + + node->color = color; + node->right = &rbt->nil; + node->left = &rbt->nil; + + node->key = key; + node->value = value; +} + +static QSE_INLINE int comp_key ( + qse_rbt_t* rbt, + const void* kptr1, qse_size_t klen1, + const void* kptr2, qse_size_t klen2) +{ + qse_size_t min; + int n, nn; + + if (klen1 < klen2) + { + min = klen1; + nn = -1; + } + else + { + min = klen2; + nn = (klen1 == klen2)? 0: 1; + } + + n = QSE_MEMCMP (kptr1, kptr2, KTOB(rbt,min)); + if (n == 0) n = nn; + return n; +} + +qse_rbt_t* qse_rbt_open (qse_mmgr_t* mmgr, qse_size_t ext) +{ + qse_rbt_t* rbt; + + if (mmgr == QSE_NULL) + { + mmgr = QSE_MMGR_GETDFL(); + + QSE_ASSERTX (mmgr != QSE_NULL, + "Set the memory manager with QSE_MMGR_SETDFL()"); + + if (mmgr == QSE_NULL) return QSE_NULL; + } + + rbt = QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(qse_rbt_t) + ext); + if (rbt == QSE_NULL) return QSE_NULL; + + if (qse_rbt_init (rbt, mmgr) == QSE_NULL) + { + QSE_MMGR_FREE (mmgr, rbt); + return QSE_NULL; + } + + return rbt; +} + +void qse_rbt_close (qse_rbt_t* rbt) +{ + qse_rbt_fini (rbt); + QSE_MMGR_FREE (rbt->mmgr, rbt); +} + +qse_rbt_t* qse_rbt_init (qse_rbt_t* rbt, qse_mmgr_t* mmgr) +{ + /* do not zero out the extension */ + QSE_MEMSET (rbt, 0, QSE_SIZEOF(*rbt)); + + rbt->mmgr = mmgr; + rbt->size = 0; + + rbt->scale[QSE_RBT_KEY] = 1; + rbt->scale[QSE_RBT_VAL] = 1; + + rbt->comper = comp_key; + rbt->copier[QSE_RBT_KEY] = QSE_RBT_COPIER_SIMPLE; + rbt->copier[QSE_RBT_VAL] = QSE_RBT_COPIER_SIMPLE; + + init_node (rbt, &rbt->nil, QSE_RBT_BLACK, 0, 0); + rbt->root = &rbt->nil; + return rbt; +} + +void qse_rbt_fini (qse_rbt_t* rbt) +{ + qse_rbt_clear (rbt); +} + +qse_rbt_node_t* qse_rbt_search (qse_rbt_t* rbt, int key) +{ + /* TODO: enhance this. ues comper... etc */ + + qse_rbt_node_t* node = rbt->root; + + while (!IS_NIL(rbt,node)) + { +#if 0 + int n = rbt->comper (rbt, kptr, klen, node->kptr, node->klen); + if (n == 0) return node; + + if (n > 0) node = node->right; + else /* if (n < 0) */ node = node->left; +#endif + if (key == node->key) return node; + + if (key > node->key) node = node->right; + else /* if (key < node->key) */ node = node->left; + } + + return QSE_NULL; +} + +#if 0 +static void rotate_left (qse_rbt_t* rbt, qse_rbt_node_t* pivot) +{ + /* move the pivot node down to the poistion of the pivot's original + * left child(x). move the pivot's right child(y) to the pivot's original + * position. as 'c1' is between 'y' and 'pivot', move it to the right + * of the new pivot position. + * + * parent parent + * | | (left or right?) | | + * pivot y + * / \ / \ + * x y =====> pivot c2 + * / \ / \ + * c1 c2 x c1 + * + * the actual implementation here resolves the pivot's relationship to + * its parent by comparaing pointers as it is not known if the pivot node + * is the left child or the right child of its parent, + */ + + qse_rbt_node_t* parent, * y, * c1; + + QSE_ASSERT (pivot != QSE_NULL && pivot->right != QSE_NULL); + + parent = pivot->parent; + y = pivot->right; + c1 = y->left; + + y->parent = parent; + if (parent) + { + if (parent->left == pivot) + { + parent->left = y; + } + else + { + QSE_ASSERT (parent->right == pivot); + parent->right = y; + } + } + else + { + QSE_ASSERT (rbt->root == pivot); + rbt->root = y; + } + + y->left = pivot; + if (!IS_NIL(rbt,pivot)) pivot->parent = y; + + pivot->right = c1; + if (!IS_NIL(rbt,c1)) c1->parent = pivot; +} + +static void rotate_right (qse_rbt_t* rbt, qse_rbt_node_t* pivot) +{ + /* move the pivot node down to the poistion of the pivot's original + * right child(y). move the pivot's left child(x) to the pivot's original + * position. as 'c2' is between 'x' and 'pivot', move it to the left + * of the new pivot position. + * + * parent parent + * | | (left or right?) | | + * pivot x + * / \ / \ + * x y =====> c1 pivot + * / \ / \ + * c1 c2 c2 y + * + * the actual implementation here resolves the pivot's relationship to + * its parent by comparaing pointers as it is not known if the pivot node + * is the left child or the right child of its parent, + */ + + qse_rbt_node_t* parent, * x, * c2; + + QSE_ASSERT (pivot != QSE_NULL); + + parent = pivot->parent; + x = pivot->left; + c2 = x->right; + + x->parent = parent; + if (parent) + { + if (parent->left == pivot) + { + /* pivot is the left child of its parent */ + parent->left = x; + } + else + { + /* pivot is the right child of its parent */ + QSE_ASSERT (parent->right == pivot); + parent->right = x; + } + } + else + { + /* pivot is the root node */ + QSE_ASSERT (rbt->root == pivot); + rbt->root = x; + } + + x->right = pivot; + if (!IS_NIL(rbt,pivot)) pivot->parent = x; + + pivot->left = c2; + if (!IS_NIL(rbt,c2)) c2->parent = pivot; +} +#endif + +static void rotate (qse_rbt_t* rbt, qse_rbt_node_t* pivot, int leftwise) +{ + /* + * == leftwise rotation + * move the pivot node down to the poistion of the pivot's original + * left child(x). move the pivot's right child(y) to the pivot's original + * position. as 'c1' is between 'y' and 'pivot', move it to the right + * of the new pivot position. + * parent parent + * | | (left or right?) | | + * pivot y + * / \ / \ + * x y =====> pivot c2 + * / \ / \ + * c1 c2 x c1 + * + * == rightwise rotation + * move the pivot node down to the poistion of the pivot's original + * right child(y). move the pivot's left child(x) to the pivot's original + * position. as 'c2' is between 'x' and 'pivot', move it to the left + * of the new pivot position. + * + * parent parent + * | | (left or right?) | | + * pivot x + * / \ / \ + * x y =====> c1 pivot + * / \ / \ + * c1 c2 c2 y + * + * + * the actual implementation here resolves the pivot's relationship to + * its parent by comparaing pointers as it is not known if the pivot node + * is the left child or the right child of its parent, + */ + + qse_rbt_node_t* parent, * z, * c; + int cid1, cid2; + + QSE_ASSERT (pivot != QSE_NULL); + + if (leftwise) + { + cid1 = RIGHT; + cid2 = LEFT; + } + else + { + cid1 = LEFT; + cid2 = RIGHT; + } + + parent = pivot->parent; + /* y for leftwise rotation, x for rightwise rotation */ + z = pivot->child[cid1]; + /* c1 for leftwise rotation, c1 for rightwise rotation */ + c = z->child[cid2]; + + z->parent = parent; + if (parent) + { + if (parent->left == pivot) + { + parent->left = z; + } + else + { + QSE_ASSERT (parent->right == pivot); + parent->right = z; + } + } + else + { + QSE_ASSERT (rbt->root == pivot); + rbt->root = z; + } + + z->child[cid2] = pivot; + if (!IS_NIL(rbt,pivot)) pivot->parent = z; + + pivot->child[cid1] = c; + if (!IS_NIL(rbt,c)) c->parent = pivot; +} + +static void adjust (qse_rbt_t* rbt, qse_rbt_node_t* node) +{ + while (node != rbt->root) + { + qse_rbt_node_t* tmp, * tmp2; + int leftwise; + + qse_rbt_node_t* xpar = node->parent; + if (xpar->color == QSE_RBT_BLACK) break; + + QSE_ASSERT (xpar->parent != QSE_NULL); + + if (xpar == xpar->parent->child[LEFT]) + { + tmp = xpar->parent->child[RIGHT]; + tmp2 = xpar->child[RIGHT]; + leftwise = 1; + } + else + { + tmp = xpar->parent->child[LEFT]; + tmp2 = xpar->child[LEFT]; + leftwise = 0; + } + + if (tmp->color == QSE_RBT_RED) + { + xpar->color = QSE_RBT_BLACK; + tmp->color = QSE_RBT_BLACK; + xpar->parent->color = QSE_RBT_RED; + node = xpar->parent; + } + else + { + if (node == tmp2) + { + node = xpar; + rotate (rbt, node, leftwise); + xpar = node->parent; + } + + xpar->color = QSE_RBT_BLACK; + xpar->parent->color = QSE_RBT_RED; + rotate (rbt, xpar->parent, !leftwise); + } + } +} + +static qse_rbt_node_t* new_node (qse_rbt_t* rbt, int key, int value) +{ + qse_rbt_node_t* node; + + node = QSE_MMGR_ALLOC (rbt->mmgr, QSE_SIZEOF(*node)); + if (node == QSE_NULL) return QSE_NULL; + + init_node (rbt, node, QSE_RBT_RED, key, value); + return node; +} + +static void free_node (qse_rbt_t* rbt, qse_rbt_node_t* node) +{ + /* TODO: call destructor... */ + QSE_MMGR_FREE (rbt->mmgr, node); +} + +qse_rbt_node_t* qse_rbt_insert (qse_rbt_t* rbt, int key, int value) +{ + /* TODO: enhance this. ues comper... etc */ + + qse_rbt_node_t* xcur = rbt->root; + qse_rbt_node_t* xpar = QSE_NULL; + qse_rbt_node_t* xnew; + + while (!IS_NIL(rbt,xcur)) + { + if (key == xcur->key) + { + /* TODO: handle various cases depending on insert types. + * return error. update value. */ + xcur->value = value; + return xcur; + } + + xpar = xcur; + + if (key > xcur->key) xcur = xcur->right; + else /* if (key < xcur->key) */ xcur = xcur->left; + } + + xnew = new_node (rbt, key, value); + if (xnew == QSE_NULL) return QSE_NULL; + + if (xpar == QSE_NULL) + { + /* the tree contains no node */ + QSE_ASSERT (rbt->root == &rbt->nil); + rbt->root = xnew; + } + else + { + /* perform normal binary insert */ + if (key > xpar->key) + { + QSE_ASSERT (xpar->right == &rbt->nil); + xpar->right = xnew; + } + else + { + QSE_ASSERT (xpar->left == &rbt->nil); + xpar->left = xnew; + } + + xnew->parent = xpar; + adjust (rbt, xnew); + } + + rbt->root->color = QSE_RBT_BLACK; + return xnew; +} + +static void adjust_for_delete ( + qse_rbt_t* rbt, qse_rbt_node_t* node, qse_rbt_node_t* par) +{ + while (node != rbt->root && node->color == QSE_RBT_BLACK) + { + qse_rbt_node_t* tmp; + + if (node == par->left) + { + tmp = par->right; + if (tmp->color == QSE_RBT_RED) + { + tmp->color = QSE_RBT_BLACK; + par->color = QSE_RBT_RED; + rotate_left (rbt, par); + tmp = par->right; + } + + if (tmp->left->color == QSE_RBT_BLACK && + tmp->right->color == QSE_RBT_BLACK) + { + if (!IS_NIL(rbt,tmp)) tmp->color = QSE_RBT_RED; + node = par; + par = node->parent; + } + else + { + if (tmp->right->color == QSE_RBT_BLACK) + { + if (!IS_NIL(rbt,tmp->left)) + tmp->left->color = QSE_RBT_BLACK; + tmp->color = QSE_RBT_RED; + rotate_right (rbt, tmp); + tmp = par->right; + } + + tmp->color = par->color; + if (!IS_NIL(rbt,par)) par->color = QSE_RBT_BLACK; + if (tmp->right->color == QSE_RBT_RED) + tmp->right->color = QSE_RBT_BLACK; + + rotate_left (rbt, par); + node = rbt->root; + } + } + else + { + QSE_ASSERT (node == par->right); + tmp = par->left; + if (tmp->color == QSE_RBT_RED) + { + tmp->color = QSE_RBT_BLACK; + par->color = QSE_RBT_RED; + rotate_right (rbt, par); + tmp = par->left; + } + + if (tmp->left->color == QSE_RBT_BLACK && + tmp->right->color == QSE_RBT_BLACK) + { + if (!IS_NIL(rbt,tmp)) tmp->color = QSE_RBT_RED; + node = par; + par = node->parent; + } + else + { + if (tmp->left->color == QSE_RBT_BLACK) + { + if (!IS_NIL(rbt,tmp->right)) + tmp->right->color = QSE_RBT_BLACK; + tmp->color = QSE_RBT_RED; + rotate_left (rbt, tmp); + tmp = par->left; + } + tmp->color = par->color; + if (!IS_NIL(rbt,par)) par->color = QSE_RBT_BLACK; + if (tmp->left->color == QSE_RBT_RED) + tmp->left->color = QSE_RBT_BLACK; + + rotate_right (rbt, par); + node = rbt->root; + } + } + } + + node->color = QSE_RBT_BLACK; +} + +static void delete_node (qse_rbt_t* rbt, qse_rbt_node_t* node) +{ + qse_rbt_node_t* x, * y, * par; + + QSE_ASSERT (node && !IS_NIL(rbt,node)); + + if (IS_NIL(rbt,node->left) || IS_NIL(rbt,node->right)) + { + y = node; + } + else + { + /* find a successor with NIL as a child */ + y = node->right; + while (!IS_NIL(rbt,y->left)) y = y->left; + } + + x = IS_NIL(rbt,y->left)? y->right: y->left; + + par = y->parent; + if (!IS_NIL(rbt,x)) x->parent = par; + + if (par) + { + if (y == par->left) + par->left = x; + else + par->right = x; + } + else + { + rbt->root = x; + } + + if (y == node) + { + if (y->color == QSE_RBT_BLACK && !IS_NIL(rbt,x)) + adjust_for_delete (rbt, x, par); + + free_node (rbt, y); + } + else + { + if (y->color == QSE_RBT_BLACK && !IS_NIL(rbt,x)) + adjust_for_delete (rbt, x, par); + +#if 1 + if (node->parent) + { + if (node->parent->left == node) node->parent->left = y; + if (node->parent->right == node) node->parent->right = y; + } + else + { + rbt->root = y; + } + + y->parent = node->parent; + y->left = node->left; + y->right = node->right; + y->color = node->color; + + if (node->left->parent == node) node->left->parent = y; + if (node->right->parent == node) node->right->parent = y; +#else + *y = *node; + if (y->parent) + { + if (y->parent->left == node) y->parent->left = y; + if (y->parent->right == node) y->parent->right = y; + } + else + { + rbt->root = y; + } + + if (y->left->parent == node) y->left->parent = y; + if (y->right->parent == node) y->right->parent = y; +#endif + + free_node (rbt, node); + } + + /* TODO: update tally */ +} + +int qse_rbt_delete (qse_rbt_t* rbt, int key) +{ + qse_rbt_node_t* node; + + node = qse_rbt_search (rbt, key); + if (node == QSE_NULL) return -1; + + delete_node (rbt, node); + return 0; +} + +void qse_rbt_clear (qse_rbt_t* rbt) +{ + /* TODO: improve this */ + while (!IS_NIL(rbt,rbt->root)) delete_node (rbt, rbt->root); +} + +static qse_rbt_walk_t walk ( + qse_rbt_t* rbt, qse_rbt_walker_t walker, + void* ctx, qse_rbt_node_t* node) +{ + if (!IS_NIL(rbt,node->left)) + { + if (walk (rbt, walker, ctx, node->left) == QSE_RBT_WALK_STOP) + return QSE_RBT_WALK_STOP; + } + + if (walker (rbt, node, ctx) == QSE_RBT_WALK_STOP) + return QSE_RBT_WALK_STOP; + + if (!IS_NIL(rbt,node->right)) + { + if (walk (rbt, walker, ctx, node->right) == QSE_RBT_WALK_STOP) + return QSE_RBT_WALK_STOP; + } + + return QSE_RBT_WALK_FORWARD; +} + +void qse_rbt_walk (qse_rbt_t* rbt, qse_rbt_walker_t walker, void* ctx) +{ + walk (rbt, walker, ctx, rbt->root); +} diff --git a/qse/lib/cmn/rex.c b/qse/lib/cmn/rex.c index 810483f4..ce8a26f5 100644 --- a/qse/lib/cmn/rex.c +++ b/qse/lib/cmn/rex.c @@ -1,5 +1,5 @@ /* - * $Id: rex.c 327 2010-05-10 13:15:55Z hyunghwan.chung $ + * $Id: rex.c 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -375,6 +375,9 @@ static int getc (comp_t* com, int noesc) else if (c == QSE_T('b')) c = QSE_T('\b'); else if (c == QSE_T('v')) c = QSE_T('\v'); else if (c == QSE_T('a')) c = QSE_T('\a'); + +#if 0 + /* backrefernce conflicts with octal notation */ else if (c >= QSE_T('0') && c <= QSE_T('7')) { qse_char_t cx; @@ -395,6 +398,8 @@ static int getc (comp_t* com, int noesc) } } } +#endif + else if (c == QSE_T('x')) { qse_char_t cx; @@ -505,6 +510,11 @@ static int cc_isupper (exec_t* e, qse_char_t c) static int cc_isxdigit (exec_t* e, qse_char_t c) { return QSE_ISXDIGIT (c); } +static int cc_isword (exec_t* e, qse_char_t c) +{ + return QSE_ISALNUM (c) || c == QSE_T('_'); +} + static struct ccinfo_t ccinfo[] = { { { QSE_T("alnum"), 5 }, cc_isalnum }, @@ -519,6 +529,7 @@ static struct ccinfo_t ccinfo[] = { { QSE_T("space"), 5 }, cc_isspace }, { { QSE_T("upper"), 5 }, cc_isupper }, { { QSE_T("xdigit"), 6 }, cc_isxdigit }, + { { QSE_T("word"), 4 }, cc_isword }, /* { { QSE_T("arabic"), 6 }, cc_isarabic }, diff --git a/qse/lib/cmn/sll.c b/qse/lib/cmn/sll.c index d438b61a..0bf6685f 100644 --- a/qse/lib/cmn/sll.c +++ b/qse/lib/cmn/sll.c @@ -1,5 +1,5 @@ /* - * $Id: sll.c 287 2009-09-15 10:01:02Z hyunghwan.chung $ + * $Id: sll.c 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -319,13 +319,13 @@ void qse_sll_poptail (sll_t* sll) qse_sll_delete (sll, TAIL(sll)); } -void qse_sll_walk (sll_t* sll, walker_t walker, void* arg) +void qse_sll_walk (sll_t* sll, walker_t walker, void* ctx) { node_t* n = HEAD(sll); while (n != QSE_NULL) { - if (walker(sll,n,arg) == QSE_SLL_WALK_STOP) return; + if (walker(sll,n,ctx) == QSE_SLL_WALK_STOP) return; n = NEXT(n); } } diff --git a/qse/lib/sed/sed.c b/qse/lib/sed/sed.c index 03b1923a..c79f362f 100644 --- a/qse/lib/sed/sed.c +++ b/qse/lib/sed/sed.c @@ -1,5 +1,5 @@ /* - * $Id: sed.c 312 2009-12-10 13:03:54Z hyunghwan.chung $ + * $Id: sed.c 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -92,19 +92,19 @@ static qse_sed_t* qse_sed_init (qse_sed_t* sed, qse_mmgr_t* mmgr) return QSE_NULL; } - if (qse_map_init (&sed->tmp.labs, mmgr, 128, 70) == QSE_NULL) + if (qse_htb_init (&sed->tmp.labs, mmgr, 128, 70) == QSE_NULL) { qse_str_fini (&sed->tmp.lab); qse_str_fini (&sed->tmp.rex); SETERR0 (sed, QSE_SED_ENOMEM, QSE_NULL); return QSE_NULL; } - qse_map_setcopier (&sed->tmp.labs, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setscale (&sed->tmp.labs, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier (&sed->tmp.labs, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setscale (&sed->tmp.labs, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); if (qse_lda_init (&sed->e.txt.appended, mmgr, 32) == QSE_NULL) { - qse_map_fini (&sed->tmp.labs); + qse_htb_fini (&sed->tmp.labs); qse_str_fini (&sed->tmp.lab); qse_str_fini (&sed->tmp.rex); return QSE_NULL; @@ -113,7 +113,7 @@ static qse_sed_t* qse_sed_init (qse_sed_t* sed, qse_mmgr_t* mmgr) if (qse_str_init (&sed->e.txt.read, mmgr, 256) == QSE_NULL) { qse_lda_fini (&sed->e.txt.appended); - qse_map_fini (&sed->tmp.labs); + qse_htb_fini (&sed->tmp.labs); qse_str_fini (&sed->tmp.lab); qse_str_fini (&sed->tmp.rex); return QSE_NULL; @@ -123,7 +123,7 @@ static qse_sed_t* qse_sed_init (qse_sed_t* sed, qse_mmgr_t* mmgr) { qse_str_fini (&sed->e.txt.read); qse_lda_fini (&sed->e.txt.appended); - qse_map_fini (&sed->tmp.labs); + qse_htb_fini (&sed->tmp.labs); qse_str_fini (&sed->tmp.lab); qse_str_fini (&sed->tmp.rex); return QSE_NULL; @@ -134,7 +134,7 @@ static qse_sed_t* qse_sed_init (qse_sed_t* sed, qse_mmgr_t* mmgr) qse_str_fini (&sed->e.txt.held); qse_str_fini (&sed->e.txt.read); qse_lda_fini (&sed->e.txt.appended); - qse_map_fini (&sed->tmp.labs); + qse_htb_fini (&sed->tmp.labs); qse_str_fini (&sed->tmp.lab); qse_str_fini (&sed->tmp.rex); return QSE_NULL; @@ -158,7 +158,7 @@ static void qse_sed_fini (qse_sed_t* sed) qse_str_fini (&sed->e.txt.read); qse_lda_fini (&sed->e.txt.appended); - qse_map_fini (&sed->tmp.labs); + qse_htb_fini (&sed->tmp.labs); qse_str_fini (&sed->tmp.lab); qse_str_fini (&sed->tmp.rex); } @@ -196,7 +196,7 @@ void qse_sed_setmaxdepth (qse_sed_t* sed, int ids, qse_size_t depth) c == QSE_T(';') || IS_LINTERM(c) || \ c == QSE_T('{') || c == QSE_T('}')) /* check if c can compose a label */ -#define IS_LABC(c) \ +#define IS_LABCHAR(c) \ (QSE_ISALNUM(c) || c == QSE_T('.') || \ c == QSE_T('-') || c == QSE_T('_')) @@ -406,13 +406,6 @@ static qse_sed_adr_t* get_address (qse_sed_t* sed, qse_sed_adr_t* a) a->type = QSE_SED_ADR_DOL; NXTSC (sed); } - else if (c == QSE_T('/')) - { - a->u.rex = compile_rex (sed, c); - if (a->u.rex == QSE_NULL) return QSE_NULL; - a->type = QSE_SED_ADR_REX; - NXTSC (sed); - } else if (c >= QSE_T('0') && c <= QSE_T('9')) { qse_size_t lno = 0; @@ -429,10 +422,19 @@ static qse_sed_adr_t* get_address (qse_sed_t* sed, qse_sed_adr_t* a) a->type = QSE_SED_ADR_LINE; a->u.lno = lno; } + else if (c == QSE_T('/')) + { + /* /REGEX/ */ + a->u.rex = compile_rex (sed, c); + if (a->u.rex == QSE_NULL) return QSE_NULL; + a->type = QSE_SED_ADR_REX; + NXTSC (sed); + } else if (c == QSE_T('\\')) { + /* \cREGEXc */ c = NXTSC (sed); - if (c == QSE_CHAR_EOF || c == QSE_T('\n')) + if (c == QSE_CHAR_EOF || IS_LINTERM(c)) { SETERR1 (sed, QSE_SED_EREXIC, QSE_T(""), 0, &sed->src.loc); @@ -543,7 +545,7 @@ static int get_label (qse_sed_t* sed, qse_sed_cmd_t* cmd) c = CURSC (sed); while (IS_SPACE(c)) c = NXTSC (sed); - if (!IS_LABC(c)) + if (!IS_LABCHAR(c)) { /* label name is empty */ SETERR0 (sed, QSE_SED_ELABEM, &sed->src.loc); @@ -561,9 +563,9 @@ static int get_label (qse_sed_t* sed, qse_sed_cmd_t* cmd) } c = NXTSC (sed); } - while (IS_LABC(c)); + while (IS_LABCHAR(c)); - if (qse_map_search ( + if (qse_htb_search ( &sed->tmp.labs, QSE_STR_PTR(&sed->tmp.lab), QSE_STR_LEN(&sed->tmp.lab)) != QSE_NULL) @@ -577,7 +579,7 @@ static int get_label (qse_sed_t* sed, qse_sed_cmd_t* cmd) return -1; } - if (qse_map_insert ( + if (qse_htb_insert ( &sed->tmp.labs, QSE_STR_PTR(&sed->tmp.lab), QSE_STR_LEN(&sed->tmp.lab), cmd, 0) == QSE_NULL) @@ -611,7 +613,7 @@ static int terminate_command (qse_sed_t* sed) } /* if the target is terminated by #, it should let the caller - * to skip the comment e.txt. so don't read in the next character. + * to skip the comment text. so don't read in the next character. * the same goes for brackets. */ if (c != QSE_T('#') && c != QSE_T('{') && @@ -624,7 +626,7 @@ static int get_branch_target (qse_sed_t* sed, qse_sed_cmd_t* cmd) { qse_cint_t c; qse_str_t* t = QSE_NULL; - qse_map_pair_t* pair; + qse_htb_pair_t* pair; /* skip white spaces */ c = CURSC(sed); @@ -649,7 +651,7 @@ static int get_branch_target (qse_sed_t* sed, qse_sed_cmd_t* cmd) goto oops; } - while (IS_LABC(c)) + while (IS_LABCHAR(c)) { if (qse_str_ccat (t, c) == (qse_size_t)-1) { @@ -662,7 +664,7 @@ static int get_branch_target (qse_sed_t* sed, qse_sed_cmd_t* cmd) if (terminate_command (sed) <= -1) goto oops; - pair = qse_map_search (&sed->tmp.labs, QSE_STR_PTR(t), QSE_STR_LEN(t)); + pair = qse_htb_search (&sed->tmp.labs, QSE_STR_PTR(t), QSE_STR_LEN(t)); if (pair == QSE_NULL) { /* label not resolved yet */ @@ -673,7 +675,7 @@ static int get_branch_target (qse_sed_t* sed, qse_sed_cmd_t* cmd) { cmd->u.branch.label.ptr = QSE_NULL; cmd->u.branch.label.len = 0; - cmd->u.branch.target = QSE_MAP_VPTR(pair); + cmd->u.branch.target = QSE_HTB_VPTR(pair); } qse_str_close (t); @@ -1245,7 +1247,7 @@ int qse_sed_comp (qse_sed_t* sed, const qse_char_t* sptr, qse_size_t slen) QSE_ASSERT (sed->cmd.lb == &sed->cmd.fb && sed->cmd.lb->len == 0); /* clear the label table */ - qse_map_clear (&sed->tmp.labs); + qse_htb_clear (&sed->tmp.labs); /* clear temporary data */ sed->tmp.grp.level = 0; @@ -1255,8 +1257,13 @@ int qse_sed_comp (qse_sed_t* sed, const qse_char_t* sptr, qse_size_t slen) { int n; - /* skip white spaces and comments*/ + /* skip spaces including newlines */ while (IS_WSPACE(c)) c = NXTSC (sed); + + /* check if the end has been reached */ + if (c == QSE_CHAR_EOF) break; + + /* check if the line is commented out */ if (c == QSE_T('#')) { do c = NXTSC (sed); @@ -1265,9 +1272,6 @@ int qse_sed_comp (qse_sed_t* sed, const qse_char_t* sptr, qse_size_t slen) continue; } - /* check if it has reached the end or is commented */ - if (c == QSE_CHAR_EOF) break; - if (c == QSE_T(';')) { /* semicolon without a address-command pair */ @@ -1746,16 +1750,16 @@ static int write_str_to_file ( const qse_char_t* path, qse_size_t plen) { qse_ssize_t n; - qse_map_pair_t* pair; + qse_htb_pair_t* pair; qse_sed_io_arg_t* ap; - pair = qse_map_search (&sed->e.out.files, path, plen); + pair = qse_htb_search (&sed->e.out.files, path, plen); if (pair == QSE_NULL) { qse_sed_io_arg_t arg; QSE_MEMSET (&arg, 0, QSE_SIZEOF(arg)); - pair = qse_map_insert (&sed->e.out.files, + pair = qse_htb_insert (&sed->e.out.files, (void*)path, plen, &arg, QSE_SIZEOF(arg)); if (pair == QSE_NULL) { @@ -1764,7 +1768,7 @@ static int write_str_to_file ( } } - ap = QSE_MAP_VPTR(pair); + ap = QSE_HTB_VPTR(pair); if (ap->handle == QSE_NULL) { sed->errnum = QSE_SED_ENOERR; @@ -2500,7 +2504,7 @@ static qse_sed_cmd_t* exec_cmd (qse_sed_t* sed, qse_sed_cmd_t* cmd) return jumpto; } -static void close_outfile (qse_map_t* map, void* dptr, qse_size_t dlen) +static void close_outfile (qse_htb_t* map, void* dptr, qse_size_t dlen) { qse_sed_io_arg_t* arg = dptr; QSE_ASSERT (dlen == QSE_SIZEOF(*arg)); @@ -2546,7 +2550,7 @@ static int init_command_block_for_exec (qse_sed_t* sed, qse_sed_cmd_blk_t* b) c->u.branch.target == QSE_NULL) { /* resolve unresolved branch targets */ - qse_map_pair_t* pair; + qse_htb_pair_t* pair; qse_xstr_t* lab = &c->u.branch.label; if (lab->ptr == QSE_NULL) @@ -2557,7 +2561,7 @@ static int init_command_block_for_exec (qse_sed_t* sed, qse_sed_cmd_blk_t* b) else { /* resolve the target */ - pair = qse_map_search ( + pair = qse_htb_search ( &sed->tmp.labs, lab->ptr, lab->len); if (pair == QSE_NULL) { @@ -2568,7 +2572,7 @@ static int init_command_block_for_exec (qse_sed_t* sed, qse_sed_cmd_blk_t* b) return -1; } - c->u.branch.target = QSE_MAP_VPTR(pair); + c->u.branch.target = QSE_HTB_VPTR(pair); /* free resolved label name */ QSE_MMGR_FREE (sed->mmgr, lab->ptr); @@ -2636,20 +2640,20 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf) sed->e.out.fun = outf; sed->e.out.eof = 0; sed->e.out.len = 0; - if (qse_map_init (&sed->e.out.files, sed->mmgr, 128, 70) == QSE_NULL) + if (qse_htb_init (&sed->e.out.files, sed->mmgr, 128, 70) == QSE_NULL) { SETERR0 (sed, QSE_SED_ENOMEM, QSE_NULL); return -1; } *(qse_sed_t**)QSE_XTN(&sed->e.out.files) = sed; - qse_map_setcopier ( - &sed->e.out.files, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setscale ( - &sed->e.out.files, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); - qse_map_setcopier ( - &sed->e.out.files, QSE_MAP_VAL, QSE_MAP_COPIER_INLINE); - qse_map_setfreeer ( - &sed->e.out.files, QSE_MAP_VAL, close_outfile); + qse_htb_setcopier ( + &sed->e.out.files, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setscale ( + &sed->e.out.files, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier ( + &sed->e.out.files, QSE_HTB_VAL, QSE_HTB_COPIER_INLINE); + qse_htb_setfreeer ( + &sed->e.out.files, QSE_HTB_VAL, close_outfile); sed->e.in.fun = inf; sed->e.in.eof = 0; @@ -2658,7 +2662,7 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf) sed->e.in.num = 0; if (qse_str_init (&sed->e.in.line, QSE_MMGR(sed), 256) == QSE_NULL) { - qse_map_fini (&sed->e.out.files); + qse_htb_fini (&sed->e.out.files); SETERR0 (sed, QSE_SED_ENOMEM, QSE_NULL); return -1; } @@ -2775,13 +2779,13 @@ int qse_sed_exec (qse_sed_t* sed, qse_sed_io_fun_t inf, qse_sed_io_fun_t outf) } done: - qse_map_clear (&sed->e.out.files); + qse_htb_clear (&sed->e.out.files); sed->e.out.fun (sed, QSE_SED_IO_CLOSE, &sed->e.out.arg, QSE_NULL, 0); done2: sed->e.in.fun (sed, QSE_SED_IO_CLOSE, &sed->e.in.arg, QSE_NULL, 0); done3: qse_str_fini (&sed->e.in.line); - qse_map_fini (&sed->e.out.files); + qse_htb_fini (&sed->e.out.files); return ret; } diff --git a/qse/lib/sed/sed.h b/qse/lib/sed/sed.h index 78a3a731..fc5fe7d6 100644 --- a/qse/lib/sed/sed.h +++ b/qse/lib/sed/sed.h @@ -1,5 +1,5 @@ /* - * $Id: sed.h 293 2009-10-04 14:08:27Z hyunghwan.chung $ + * $Id: sed.h 328 2010-07-08 06:58:44Z hyunghwan.chung $ * Copyright 2006-2009 Chung, Hyung-Hwan. This file is part of QSE. @@ -23,6 +23,8 @@ #include #include +#include +#include typedef struct qse_sed_adr_t qse_sed_adr_t; typedef struct qse_sed_cmd_t qse_sed_cmd_t; @@ -186,7 +188,7 @@ struct qse_sed_t } grp; /** a table storing labels seen */ - qse_map_t labs; + qse_htb_t labs; } tmp; /** compiled commands */ @@ -216,7 +218,7 @@ struct qse_sed_t /*****************************************************/ /* the following two fields are very tightly-coupled. * don't make any partial changes */ - qse_map_t files; + qse_htb_t files; qse_sed_t* files_ext; /*****************************************************/ } out; diff --git a/qse/samples/cmn/Makefile.am b/qse/samples/cmn/Makefile.am index 19903341..63801497 100644 --- a/qse/samples/cmn/Makefile.am +++ b/qse/samples/cmn/Makefile.am @@ -1,6 +1,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/include -DNDEBUG -bin_PROGRAMS = chr str sll map lda fio pio sio time main rex01 +bin_PROGRAMS = chr str sll lda htb rbt fio pio sio time main rex01 LDFLAGS = -L../../lib/cmn LDADD = -lqsecmn @@ -8,8 +8,9 @@ LDADD = -lqsecmn chr_SOURCES = chr.c str_SOURCES = str.c sll_SOURCES = sll.c -map_SOURCES = map.c lda_SOURCES = lda.c +htb_SOURCES = htb.c +rbt_SOURCES = rbt.c fio_SOURCES = fio.c pio_SOURCES = pio.c sio_SOURCES = sio.c diff --git a/qse/samples/cmn/Makefile.in b/qse/samples/cmn/Makefile.in index 2f97d3bd..c96a953f 100644 --- a/qse/samples/cmn/Makefile.in +++ b/qse/samples/cmn/Makefile.in @@ -34,9 +34,9 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -bin_PROGRAMS = chr$(EXEEXT) str$(EXEEXT) sll$(EXEEXT) map$(EXEEXT) \ - lda$(EXEEXT) fio$(EXEEXT) pio$(EXEEXT) sio$(EXEEXT) \ - time$(EXEEXT) main$(EXEEXT) rex01$(EXEEXT) +bin_PROGRAMS = chr$(EXEEXT) str$(EXEEXT) sll$(EXEEXT) lda$(EXEEXT) \ + htb$(EXEEXT) rbt$(EXEEXT) fio$(EXEEXT) pio$(EXEEXT) \ + sio$(EXEEXT) time$(EXEEXT) main$(EXEEXT) rex01$(EXEEXT) subdir = samples/cmn DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -61,6 +61,10 @@ am_fio_OBJECTS = fio.$(OBJEXT) fio_OBJECTS = $(am_fio_OBJECTS) fio_LDADD = $(LDADD) fio_DEPENDENCIES = +am_htb_OBJECTS = htb.$(OBJEXT) +htb_OBJECTS = $(am_htb_OBJECTS) +htb_LDADD = $(LDADD) +htb_DEPENDENCIES = am_lda_OBJECTS = lda.$(OBJEXT) lda_OBJECTS = $(am_lda_OBJECTS) lda_LDADD = $(LDADD) @@ -69,14 +73,14 @@ am_main_OBJECTS = main.$(OBJEXT) main_OBJECTS = $(am_main_OBJECTS) main_LDADD = $(LDADD) main_DEPENDENCIES = -am_map_OBJECTS = map.$(OBJEXT) -map_OBJECTS = $(am_map_OBJECTS) -map_LDADD = $(LDADD) -map_DEPENDENCIES = am_pio_OBJECTS = pio.$(OBJEXT) pio_OBJECTS = $(am_pio_OBJECTS) pio_LDADD = $(LDADD) pio_DEPENDENCIES = +am_rbt_OBJECTS = rbt.$(OBJEXT) +rbt_OBJECTS = $(am_rbt_OBJECTS) +rbt_LDADD = $(LDADD) +rbt_DEPENDENCIES = am_rex01_OBJECTS = rex01.$(OBJEXT) rex01_OBJECTS = $(am_rex01_OBJECTS) rex01_LDADD = $(LDADD) @@ -110,12 +114,13 @@ CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ -SOURCES = $(chr_SOURCES) $(fio_SOURCES) $(lda_SOURCES) $(main_SOURCES) \ - $(map_SOURCES) $(pio_SOURCES) $(rex01_SOURCES) $(sio_SOURCES) \ - $(sll_SOURCES) $(str_SOURCES) $(time_SOURCES) -DIST_SOURCES = $(chr_SOURCES) $(fio_SOURCES) $(lda_SOURCES) \ - $(main_SOURCES) $(map_SOURCES) $(pio_SOURCES) $(rex01_SOURCES) \ +SOURCES = $(chr_SOURCES) $(fio_SOURCES) $(htb_SOURCES) $(lda_SOURCES) \ + $(main_SOURCES) $(pio_SOURCES) $(rbt_SOURCES) $(rex01_SOURCES) \ $(sio_SOURCES) $(sll_SOURCES) $(str_SOURCES) $(time_SOURCES) +DIST_SOURCES = $(chr_SOURCES) $(fio_SOURCES) $(htb_SOURCES) \ + $(lda_SOURCES) $(main_SOURCES) $(pio_SOURCES) $(rbt_SOURCES) \ + $(rex01_SOURCES) $(sio_SOURCES) $(sll_SOURCES) $(str_SOURCES) \ + $(time_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -263,8 +268,9 @@ LDADD = -lqsecmn chr_SOURCES = chr.c str_SOURCES = str.c sll_SOURCES = sll.c -map_SOURCES = map.c lda_SOURCES = lda.c +htb_SOURCES = htb.c +rbt_SOURCES = rbt.c fio_SOURCES = fio.c pio_SOURCES = pio.c sio_SOURCES = sio.c @@ -354,18 +360,21 @@ chr$(EXEEXT): $(chr_OBJECTS) $(chr_DEPENDENCIES) fio$(EXEEXT): $(fio_OBJECTS) $(fio_DEPENDENCIES) @rm -f fio$(EXEEXT) $(LINK) $(fio_OBJECTS) $(fio_LDADD) $(LIBS) +htb$(EXEEXT): $(htb_OBJECTS) $(htb_DEPENDENCIES) + @rm -f htb$(EXEEXT) + $(LINK) $(htb_OBJECTS) $(htb_LDADD) $(LIBS) lda$(EXEEXT): $(lda_OBJECTS) $(lda_DEPENDENCIES) @rm -f lda$(EXEEXT) $(LINK) $(lda_OBJECTS) $(lda_LDADD) $(LIBS) main$(EXEEXT): $(main_OBJECTS) $(main_DEPENDENCIES) @rm -f main$(EXEEXT) $(LINK) $(main_OBJECTS) $(main_LDADD) $(LIBS) -map$(EXEEXT): $(map_OBJECTS) $(map_DEPENDENCIES) - @rm -f map$(EXEEXT) - $(LINK) $(map_OBJECTS) $(map_LDADD) $(LIBS) pio$(EXEEXT): $(pio_OBJECTS) $(pio_DEPENDENCIES) @rm -f pio$(EXEEXT) $(LINK) $(pio_OBJECTS) $(pio_LDADD) $(LIBS) +rbt$(EXEEXT): $(rbt_OBJECTS) $(rbt_DEPENDENCIES) + @rm -f rbt$(EXEEXT) + $(LINK) $(rbt_OBJECTS) $(rbt_LDADD) $(LIBS) rex01$(EXEEXT): $(rex01_OBJECTS) $(rex01_DEPENDENCIES) @rm -f rex01$(EXEEXT) $(LINK) $(rex01_OBJECTS) $(rex01_LDADD) $(LIBS) @@ -390,10 +399,11 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lda.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pio.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rbt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rex01.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sio.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sll.Po@am__quote@ diff --git a/qse/samples/cmn/chr.c b/qse/samples/cmn/chr.c index 5dd4d6fe..e1d2f365 100644 --- a/qse/samples/cmn/chr.c +++ b/qse/samples/cmn/chr.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include diff --git a/qse/samples/cmn/map.c b/qse/samples/cmn/htb.c similarity index 60% rename from qse/samples/cmn/map.c rename to qse/samples/cmn/htb.c index 5e9e2d11..40866dae 100644 --- a/qse/samples/cmn/map.c +++ b/qse/samples/cmn/htb.c @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #define R(f) \ @@ -10,7 +10,7 @@ if (f() == -1) return -1; \ } while (0) -static int test1_build (qse_map_t* s1) +static int test1_build (qse_htb_t* s1) { int i; @@ -20,7 +20,7 @@ static int test1_build (qse_map_t* s1) int j = i * 2; qse_printf (QSE_T("inserting a key %d and a value %d: "), i, j); - if (qse_map_insert (s1, &i, sizeof(i), &j, sizeof(j)) == QSE_NULL) + if (qse_htb_insert (s1, &i, sizeof(i), &j, sizeof(j)) == QSE_NULL) { qse_printf (QSE_T("[FAILED]\n")); return -1; @@ -32,7 +32,7 @@ static int test1_build (qse_map_t* s1) return 0; } -static void test1_delete (qse_map_t* s1) +static void test1_delete (qse_htb_t* s1) { int i; int t[] = { 20, 11, 13, 40 }; @@ -41,7 +41,7 @@ static void test1_delete (qse_map_t* s1) for (i = 1; i < 53; i+=2) { qse_printf (QSE_T("deleting a key %d: "), i); - if (qse_map_delete (s1, &i, sizeof(i)) == -1) + if (qse_htb_delete (s1, &i, sizeof(i)) == -1) qse_printf (QSE_T("[FAILED]\n")); else qse_printf (QSE_T("[OK]\n")); @@ -54,7 +54,7 @@ static void test1_delete (qse_map_t* s1) int v = k * 1000; qse_printf (QSE_T("updating a key %d value %d: "), k, v); - if (qse_map_update (s1, &k, sizeof(k), &v, sizeof(v)) == QSE_NULL) + if (qse_htb_update (s1, &k, sizeof(k), &v, sizeof(v)) == QSE_NULL) qse_printf (QSE_T("[FAILED]\n")); else qse_printf (QSE_T("[OK]\n")); @@ -66,7 +66,7 @@ static void test1_delete (qse_map_t* s1) int v = k * 1000; qse_printf (QSE_T("inserting a key %d value %d: "), k, v); - if (qse_map_insert (s1, &k, sizeof(k), &v, sizeof(v)) == QSE_NULL) + if (qse_htb_insert (s1, &k, sizeof(k), &v, sizeof(v)) == QSE_NULL) qse_printf (QSE_T("[FAILED]\n")); else qse_printf (QSE_T("[OK]\n")); @@ -78,21 +78,21 @@ static void test1_delete (qse_map_t* s1) int v = k * 2000; qse_printf (QSE_T("upserting a key %d value %d: "), k, v); - if (qse_map_upsert (s1, &k, sizeof(k), &v, sizeof(v)) == QSE_NULL) + if (qse_htb_upsert (s1, &k, sizeof(k), &v, sizeof(v)) == QSE_NULL) qse_printf (QSE_T("[FAILED]\n")); else qse_printf (QSE_T("[OK]\n")); } } -static void test1_dump (qse_map_t* s1) +static void test1_dump (qse_htb_t* s1) { int i; - qse_printf (QSE_T("map contains %u pairs\n"), (unsigned)QSE_MAP_SIZE(s1)); + qse_printf (QSE_T("map contains %u pairs\n"), (unsigned)QSE_HTB_SIZE(s1)); for (i = 1; i < 50; i++) { - qse_map_pair_t* p = qse_map_search (s1, &i, sizeof(i)); + qse_htb_pair_t* p = qse_htb_search (s1, &i, sizeof(i)); if (p == QSE_NULL) { qse_printf (QSE_T("%d => unknown\n"), i); @@ -100,28 +100,28 @@ static void test1_dump (qse_map_t* s1) else { qse_printf (QSE_T("%d => %d(%d)\n"), - i, *(int*)QSE_MAP_VPTR(p), (int)QSE_MAP_VLEN(p)); + i, *(int*)QSE_HTB_VPTR(p), (int)QSE_HTB_VLEN(p)); } } } static int test1 () { - qse_map_t* s1; + qse_htb_t* s1; - s1 = qse_map_open (QSE_MMGR_GETDFL(), 0, 5, 70); + s1 = qse_htb_open (QSE_MMGR_GETDFL(), 0, 5, 70); if (s1 == QSE_NULL) { qse_printf (QSE_T("cannot open a map\n")); return -1; } - qse_map_setcopier (s1, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setcopier (s1, QSE_MAP_VAL, QSE_MAP_COPIER_INLINE); + qse_htb_setcopier (s1, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setcopier (s1, QSE_HTB_VAL, QSE_HTB_COPIER_INLINE); if (test1_build(s1) == -1) { - qse_map_close (s1); + qse_htb_close (s1); return -1; } test1_dump (s1); @@ -129,22 +129,22 @@ static int test1 () test1_delete (s1); test1_dump (s1); - qse_map_close (s1); + qse_htb_close (s1); return 0; } -qse_map_walk_t print_map_pair (qse_map_t* map, qse_map_pair_t* pair, void* arg) +qse_htb_walk_t print_map_pair (qse_htb_t* map, qse_htb_pair_t* pair, void* arg) { qse_printf (QSE_T("%.*s[%d] => %.*s[%d]\n"), - (int)QSE_MAP_KLEN(pair), QSE_MAP_KPTR(pair), (int)QSE_MAP_KLEN(pair), - (int)QSE_MAP_VLEN(pair), QSE_MAP_VPTR(pair), (int)QSE_MAP_VLEN(pair)); + (int)QSE_HTB_KLEN(pair), QSE_HTB_KPTR(pair), (int)QSE_HTB_KLEN(pair), + (int)QSE_HTB_VLEN(pair), QSE_HTB_VPTR(pair), (int)QSE_HTB_VLEN(pair)); - return QSE_MAP_WALK_FORWARD; + return QSE_HTB_WALK_FORWARD; } static int test2 () { - qse_map_t* s1; + qse_htb_t* s1; int i; qse_char_t* keys[] = { @@ -154,24 +154,24 @@ static int test2 () QSE_T("in a given directory") }; - s1 = qse_map_open (QSE_MMGR_GETDFL(), 0, 1, 70); + s1 = qse_htb_open (QSE_MMGR_GETDFL(), 0, 1, 70); if (s1 == QSE_NULL) { qse_printf (QSE_T("cannot open a map\n")); return -1; } - qse_map_setcopier (s1, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setcopier (s1, QSE_MAP_VAL, QSE_MAP_COPIER_INLINE); - qse_map_setscale (s1, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); - qse_map_setscale (s1, QSE_MAP_VAL, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier (s1, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setcopier (s1, QSE_HTB_VAL, QSE_HTB_COPIER_INLINE); + qse_htb_setscale (s1, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setscale (s1, QSE_HTB_VAL, QSE_SIZEOF(qse_char_t)); for (i = 0; i < QSE_COUNTOF(keys); i++) { int vi = QSE_COUNTOF(keys)-i-1; qse_printf (QSE_T("inserting a key [%s] and a value [%s]: "), keys[i], keys[vi]); - if (qse_map_insert (s1, + if (qse_htb_insert (s1, keys[i], qse_strlen(keys[i]), keys[vi], qse_strlen(keys[vi])) == QSE_NULL) { @@ -183,31 +183,31 @@ static int test2 () } } - qse_map_walk (s1, print_map_pair, QSE_NULL); + qse_htb_walk (s1, print_map_pair, QSE_NULL); - qse_map_close (s1); + qse_htb_close (s1); return 0; } -static int comp_key (qse_map_t* map, +static int comp_key (qse_htb_t* map, const void* kptr1, qse_size_t klen1, const void* kptr2, qse_size_t klen2) { return qse_strxncasecmp (kptr1, klen1, kptr2, klen2); } -qse_map_walk_t print_map_pair_3 (qse_map_t* map, qse_map_pair_t* pair, void* arg) +qse_htb_walk_t print_map_pair_3 (qse_htb_t* map, qse_htb_pair_t* pair, void* arg) { qse_printf (QSE_T("%.*s[%d] => %d\n"), - (int)QSE_MAP_KLEN(pair), QSE_MAP_KPTR(pair), (int)QSE_MAP_KLEN(pair), - *(int*)QSE_MAP_VPTR(pair)); + (int)QSE_HTB_KLEN(pair), QSE_HTB_KPTR(pair), (int)QSE_HTB_KLEN(pair), + *(int*)QSE_HTB_VPTR(pair)); - return QSE_MAP_WALK_FORWARD; + return QSE_HTB_WALK_FORWARD; } static int test3 () { - qse_map_t* s1; + qse_htb_t* s1; int i; qse_char_t* keys[] = { @@ -220,22 +220,22 @@ static int test3 () QSE_T("thRee") }; - s1 = qse_map_open (QSE_MMGR_GETDFL(), 0, 1, 70); + s1 = qse_htb_open (QSE_MMGR_GETDFL(), 0, 1, 70); if (s1 == QSE_NULL) { qse_printf (QSE_T("cannot open a map\n")); return -1; } - qse_map_setcopier (s1, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setcopier (s1, QSE_MAP_VAL, QSE_MAP_COPIER_INLINE); - qse_map_setcomper (s1, comp_key); - qse_map_setscale (s1, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier (s1, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setcopier (s1, QSE_HTB_VAL, QSE_HTB_COPIER_INLINE); + qse_htb_setcomper (s1, comp_key); + qse_htb_setscale (s1, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); for (i = 0; i < QSE_COUNTOF(keys); i++) { qse_printf (QSE_T("inserting a key [%s] and a value %d: "), keys[i], i); - if (qse_map_insert (s1, keys[i], qse_strlen(keys[i]), &i, sizeof(i)) == QSE_NULL) + if (qse_htb_insert (s1, keys[i], qse_strlen(keys[i]), &i, sizeof(i)) == QSE_NULL) { qse_printf (QSE_T("[FAILED]\n")); } @@ -245,15 +245,15 @@ static int test3 () } } - qse_map_walk (s1, print_map_pair_3, QSE_NULL); + qse_htb_walk (s1, print_map_pair_3, QSE_NULL); - qse_map_close (s1); + qse_htb_close (s1); return 0; } static int test4 () { - qse_map_t* s1; + qse_htb_t* s1; int i; qse_char_t* keys[] = { @@ -266,22 +266,22 @@ static int test4 () QSE_T("thRee") }; - s1 = qse_map_open (QSE_MMGR_GETDFL(), 0, 1, 70); + s1 = qse_htb_open (QSE_MMGR_GETDFL(), 0, 1, 70); if (s1 == QSE_NULL) { qse_printf (QSE_T("cannot open a map\n")); return -1; } - qse_map_setcopier (s1, QSE_MAP_KEY, QSE_MAP_COPIER_INLINE); - qse_map_setcopier (s1, QSE_MAP_VAL, QSE_MAP_COPIER_INLINE); - qse_map_setcomper (s1, comp_key); - qse_map_setscale (s1, QSE_MAP_KEY, QSE_SIZEOF(qse_char_t)); + qse_htb_setcopier (s1, QSE_HTB_KEY, QSE_HTB_COPIER_INLINE); + qse_htb_setcopier (s1, QSE_HTB_VAL, QSE_HTB_COPIER_INLINE); + qse_htb_setcomper (s1, comp_key); + qse_htb_setscale (s1, QSE_HTB_KEY, QSE_SIZEOF(qse_char_t)); for (i = 0; i < QSE_COUNTOF(keys); i++) { qse_printf (QSE_T("upserting a key [%s] and a value %d: "), keys[i], i); - if (qse_map_upsert (s1, keys[i], qse_strlen(keys[i]), &i, sizeof(i)) == QSE_NULL) + if (qse_htb_upsert (s1, keys[i], qse_strlen(keys[i]), &i, sizeof(i)) == QSE_NULL) { qse_printf (QSE_T("[FAILED]\n")); } @@ -291,9 +291,9 @@ static int test4 () } } - qse_map_walk (s1, print_map_pair_3, QSE_NULL); + qse_htb_walk (s1, print_map_pair_3, QSE_NULL); - qse_map_close (s1); + qse_htb_close (s1); return 0; } diff --git a/qse/samples/cmn/rbt.c b/qse/samples/cmn/rbt.c new file mode 100644 index 00000000..38bf5a23 --- /dev/null +++ b/qse/samples/cmn/rbt.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include + + +#define R(f) \ + do { \ + qse_printf (QSE_T("== %s ==\n"), QSE_T(#f)); \ + if (f() == -1) return -1; \ + } while (0) + +static qse_rbt_walk_t walk (qse_rbt_t* rbt, qse_rbt_node_t* node, void* ctx) +{ + qse_printf (QSE_T("key = %d, value = %d\n"), node->key, node->value); + return QSE_RBT_WALK_FORWARD; +} + +static int test1 () +{ + qse_rbt_t* s1; + qse_char_t* x[] = + { + QSE_T("this is so good"), + QSE_T("what the fuck"), + QSE_T("do you like it?"), + QSE_T("oopsy!") + }; + int i; + + s1 = qse_rbt_open (QSE_MMGR_GETDFL(), 0); + if (s1 == QSE_NULL) + { + qse_printf (QSE_T("cannot open a string\n")); + return -1; + } + + /* + qse_rbt_setcopier (s1, QSE_LDA_COPIER_INLINE); + qse_rbt_setkeeper (s1, keeper1); + qse_rbt_setscale (s1, QSE_SIZEOF(qse_char_t)); + */ + + for (i = 0; i < 20; i++) + { +qse_printf (QSE_T("inserting at %d\n"), i); + qse_rbt_insert (s1, i, i * 20); + } + + qse_rbt_walk (s1, walk, QSE_NULL); + + for (i = 0; i < 20; i += 2) + { +qse_printf (QSE_T("deleting %d\n"), i); + qse_rbt_delete (s1, i); + } + + qse_rbt_walk (s1, walk, QSE_NULL); + + for (i = 0; i < 20; i++) + { +qse_printf (QSE_T("inserting at %d\n"), i); + qse_rbt_insert (s1, i, i * 20); + } + + qse_rbt_walk (s1, walk, QSE_NULL); + + qse_rbt_clear (s1); + for (i = 20; i > 0; i--) + { +qse_printf (QSE_T("inserting at %d\n"), i); + qse_rbt_insert (s1, i, i * 20); + } + + qse_rbt_walk (s1, walk, QSE_NULL); + + for (i = 0; i < 20; i += 3) + { +qse_printf (QSE_T("deleting %d\n"), i); + qse_rbt_delete (s1, i); + } + + qse_rbt_walk (s1, walk, QSE_NULL); + + qse_rbt_close (s1); + return 0; +} + +int main () +{ + R (test1); + return 0; +}