* renamed map to htb
* added qse_awk_findgbl() * added Awk::findGlobal() * began working on red-black tree
This commit is contained in:
parent
57c56594a5
commit
99c72b1755
@ -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);
|
||||
|
@ -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 <qse/awk/awk.h>
|
||||
#include <qse/cmn/map.h>
|
||||
#include <qse/cmn/htb.h>
|
||||
#include <qse/cmn/chr.h>
|
||||
#include <qse/cmn/Mmged.hpp>
|
||||
#include <stdarg.h>
|
||||
@ -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;
|
||||
|
@ -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 <qse/types.h>
|
||||
#include <qse/macros.h>
|
||||
#include <qse/cmn/map.h>
|
||||
#include <qse/cmn/htb.h>
|
||||
#include <qse/cmn/str.h>
|
||||
|
||||
/** @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 */
|
||||
);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
486
qse/include/qse/cmn/htb.h
Normal file
486
qse/include/qse/cmn/htb.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _QSE_CMN_HTB_H_
|
||||
#define _QSE_CMN_HTB_H_
|
||||
|
||||
#include <qse/types.h>
|
||||
#include <qse/macros.h>
|
||||
|
||||
/**@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
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _QSE_CMN_MAP_H_
|
||||
#define _QSE_CMN_MAP_H_
|
||||
|
||||
#include <qse/types.h>
|
||||
#include <qse/macros.h>
|
||||
|
||||
/**@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
|
140
qse/include/qse/cmn/rbt.h
Normal file
140
qse/include/qse/cmn/rbt.h
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _QSE_CMN_RBT_H_
|
||||
#define _QSE_CMN_RBT_H_
|
||||
|
||||
#include <qse/types.h>
|
||||
#include <qse/macros.h>
|
||||
|
||||
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
|
@ -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 (
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 <qse/types.h>
|
||||
#include <qse/macros.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/lda.h>
|
||||
#include <qse/cmn/map.h>
|
||||
|
||||
/** @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 */
|
||||
);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 <qse/cmn/chr.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/map.h>
|
||||
#include <qse/cmn/htb.h>
|
||||
#include <qse/cmn/lda.h>
|
||||
#include <qse/cmn/rex.h>
|
||||
|
||||
@ -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;
|
||||
|
@ -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 <qse/cmn/stdio.h>
|
||||
|
||||
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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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@
|
||||
|
696
qse/lib/cmn/htb.c
Normal file
696
qse/lib/cmn/htb.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <qse/cmn/htb.h>
|
||||
#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;
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <qse/cmn/map.h>
|
||||
#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;
|
||||
}
|
691
qse/lib/cmn/rbt.c
Normal file
691
qse/lib/cmn/rbt.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <qse/cmn/rbt.h>
|
||||
#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);
|
||||
}
|
@ -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 },
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 <qse/sed/sed.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/htb.h>
|
||||
#include <qse/cmn/lda.h>
|
||||
|
||||
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;
|
||||
|
@ -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
|
||||
|
@ -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@
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <qse/cmn/mem.h>
|
||||
#include <qse/cmn/chr.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/map.h>
|
||||
#include <qse/cmn/stdio.h>
|
||||
|
||||
#include <string.h>
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <qse/cmn/mem.h>
|
||||
#include <qse/cmn/chr.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/map.h>
|
||||
#include <qse/cmn/htb.h>
|
||||
#include <qse/cmn/stdio.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
94
qse/samples/cmn/rbt.c
Normal file
94
qse/samples/cmn/rbt.c
Normal file
@ -0,0 +1,94 @@
|
||||
#include <qse/cmn/mem.h>
|
||||
#include <qse/cmn/str.h>
|
||||
#include <qse/cmn/rbt.h>
|
||||
#include <qse/cmn/stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user