* renamed map to htb

* added qse_awk_findgbl()
* added Awk::findGlobal()
* began working on red-black tree
This commit is contained in:
hyung-hwan 2010-07-09 00:58:44 +00:00
parent 57c56594a5
commit 99c72b1755
34 changed files with 2709 additions and 1777 deletions

View File

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

View File

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

View File

@ -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 */
);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 */
);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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
View 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);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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