added qse_awk_rtx_getrefvaltype()/qse_awk_rtx_getrefval()
finished asort() in awk added qse_sortx()
This commit is contained in:
parent
c3e30eaae4
commit
2ac2ad8200
@ -2958,6 +2958,21 @@ QSE_EXPORT qse_awk_int_t qse_awk_rtx_hashval (
|
|||||||
qse_awk_val_t* v
|
qse_awk_val_t* v
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_awk_rtx_getrefvaltype() function returns the type of the value
|
||||||
|
* that the given reference points to.
|
||||||
|
*/
|
||||||
|
QSE_EXPORT qse_awk_val_type_t qse_awk_rtx_getrefvaltype (
|
||||||
|
qse_awk_rtx_t* rtx,
|
||||||
|
qse_awk_val_ref_t* ref
|
||||||
|
);
|
||||||
|
|
||||||
|
QSE_EXPORT qse_awk_val_t* qse_awk_rtx_getrefval (
|
||||||
|
qse_awk_rtx_t* rtx,
|
||||||
|
qse_awk_val_ref_t* ref
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_awk_rtx_setrefval() function changes the value
|
* The qse_awk_rtx_setrefval() function changes the value
|
||||||
* of a variable referenced in \a ref.
|
* of a variable referenced in \a ref.
|
||||||
|
@ -55,10 +55,23 @@ typedef int (*qse_search_comper_t) (
|
|||||||
void* ctx
|
void* ctx
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The qse_search_comperx_t type defines a search callback function.
|
||||||
|
* It should return 0 on success and -1 on failure. the comparsion
|
||||||
|
* result must be put back into the variable pointed to by \a cv.
|
||||||
|
*/
|
||||||
|
typedef int (*qse_search_comperx_t) (
|
||||||
|
const void* ptr1,
|
||||||
|
const void* ptr2,
|
||||||
|
void* ctx,
|
||||||
|
int * cv
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_sort_comper_t type defines a sort callback function.
|
* The qse_sort_comper_t type defines a sort callback function.
|
||||||
*/
|
*/
|
||||||
typedef qse_search_comper_t qse_sort_comper_t;
|
typedef qse_search_comper_t qse_sort_comper_t;
|
||||||
|
typedef qse_search_comperx_t qse_sort_comperx_t;
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -134,6 +147,14 @@ QSE_EXPORT void qse_qsort (
|
|||||||
void* ctx
|
void* ctx
|
||||||
);
|
);
|
||||||
|
|
||||||
|
QSE_EXPORT int qse_qsortx (
|
||||||
|
void* base,
|
||||||
|
qse_size_t nmemb,
|
||||||
|
qse_size_t size,
|
||||||
|
qse_sort_comperx_t comper,
|
||||||
|
void* ctx
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The qse_rand31() function implements Park-Miller's minimal standard
|
* The qse_rand31() function implements Park-Miller's minimal standard
|
||||||
|
@ -45,7 +45,7 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi);
|
|||||||
*
|
*
|
||||||
* - v: value. pass it after normal evaluation.
|
* - v: value. pass it after normal evaluation.
|
||||||
* - r: pass a variable by reference
|
* - r: pass a variable by reference
|
||||||
* - x: regular expression as it it. not evaluated as /rex/ ~ $0.
|
* - x: regular expression as it is. not evaluated as /rex/ ~ $0.
|
||||||
*
|
*
|
||||||
* If the first character of the specifer is 'R', all
|
* If the first character of the specifer is 'R', all
|
||||||
* parameters are passed by reference regarless of the remaining
|
* parameters are passed by reference regarless of the remaining
|
||||||
@ -67,7 +67,7 @@ static qse_awk_fnc_t sysfnctab[] =
|
|||||||
{ {QSE_T("typename"), 8}, 0, { {1, 1, QSE_NULL}, fnc_typename, 0 }, QSE_NULL},
|
{ {QSE_T("typename"), 8}, 0, { {1, 1, QSE_NULL}, fnc_typename, 0 }, QSE_NULL},
|
||||||
|
|
||||||
/* array sort */
|
/* array sort */
|
||||||
{ {QSE_T("asort"), 5}, 0, { {1, 3, QSE_NULL}, fnc_asort, 0 }, QSE_NULL},
|
{ {QSE_T("asort"), 5}, 0, { {1, 3, QSE_T("rrv")}, fnc_asort, 0 }, QSE_NULL},
|
||||||
|
|
||||||
/* string functions */
|
/* string functions */
|
||||||
{ {QSE_T("gsub"), 4}, 0, { {2, 3, QSE_T("xvr")}, qse_awk_fnc_gsub, 0 }, QSE_NULL},
|
{ {QSE_T("gsub"), 4}, 0, { {2, 3, QSE_T("xvr")}, qse_awk_fnc_gsub, 0 }, QSE_NULL},
|
||||||
@ -704,7 +704,6 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
|||||||
a2 = (nargs >= 3)? qse_awk_rtx_getarg (rtx, 2): QSE_NULL;
|
a2 = (nargs >= 3)? qse_awk_rtx_getarg (rtx, 2): QSE_NULL;
|
||||||
|
|
||||||
a1_vtype = QSE_AWK_RTX_GETVALTYPE (rtx, a1);
|
a1_vtype = QSE_AWK_RTX_GETVALTYPE (rtx, a1);
|
||||||
|
|
||||||
QSE_ASSERT (a1_vtype == QSE_AWK_VAL_REF);
|
QSE_ASSERT (a1_vtype == QSE_AWK_VAL_REF);
|
||||||
|
|
||||||
str.ptr = qse_awk_rtx_getvalstr(rtx, a0, &str.len);
|
str.ptr = qse_awk_rtx_getvalstr(rtx, a0, &str.len);
|
||||||
@ -714,7 +713,7 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
|||||||
{
|
{
|
||||||
/* get the value from FS */
|
/* get the value from FS */
|
||||||
t1 = qse_awk_rtx_getgbl(rtx, QSE_AWK_GBL_FS);
|
t1 = qse_awk_rtx_getgbl(rtx, QSE_AWK_GBL_FS);
|
||||||
t1_vtype = QSE_AWK_RTX_GETVALTYPE (rtx, t1);
|
t1_vtype = QSE_AWK_RTX_GETVALTYPE(rtx, t1);
|
||||||
if (t1_vtype == QSE_AWK_VAL_NIL)
|
if (t1_vtype == QSE_AWK_VAL_NIL)
|
||||||
{
|
{
|
||||||
fs.ptr = QSE_T(" ");
|
fs.ptr = QSE_T(" ");
|
||||||
@ -727,7 +726,7 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fs.ptr = qse_awk_rtx_valtostrdup (rtx, t1, &fs.len);
|
fs.ptr = qse_awk_rtx_valtostrdup(rtx, t1, &fs.len);
|
||||||
if (fs.ptr == QSE_NULL) goto oops;
|
if (fs.ptr == QSE_NULL) goto oops;
|
||||||
fs_free = (qse_char_t*)fs.ptr;
|
fs_free = (qse_char_t*)fs.ptr;
|
||||||
}
|
}
|
||||||
@ -801,15 +800,11 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
|||||||
|
|
||||||
if (fs.len <= 1)
|
if (fs.len <= 1)
|
||||||
{
|
{
|
||||||
p = qse_awk_rtx_strxntok (rtx,
|
p = qse_awk_rtx_strxntok(rtx, p, str.len, fs.ptr, fs.len, &tok);
|
||||||
p, str.len, fs.ptr, fs.len, &tok);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
p = qse_awk_rtx_strxntokbyrex (
|
p = qse_awk_rtx_strxntokbyrex(rtx, str.ptr, org_len, p, str.len, fs_rex, &tok, &errnum);
|
||||||
rtx, str.ptr, org_len, p, str.len,
|
|
||||||
fs_rex, &tok, &errnum
|
|
||||||
);
|
|
||||||
if (p == QSE_NULL && errnum != QSE_AWK_ENOERR)
|
if (p == QSE_NULL && errnum != QSE_AWK_ENOERR)
|
||||||
{
|
{
|
||||||
qse_awk_rtx_seterrnum (rtx, errnum, QSE_NULL);
|
qse_awk_rtx_seterrnum (rtx, errnum, QSE_NULL);
|
||||||
@ -848,7 +843,7 @@ int qse_awk_fnc_split (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
|||||||
/*if (str_free) QSE_AWK_FREE (rtx->awk, str_free);*/
|
/*if (str_free) QSE_AWK_FREE (rtx->awk, str_free);*/
|
||||||
qse_awk_rtx_freevalstr (rtx, a0, str.ptr);
|
qse_awk_rtx_freevalstr (rtx, a0, str.ptr);
|
||||||
|
|
||||||
if (fs_free) QSE_AWK_FREE (rtx->awk, fs_free);
|
if (fs_free) qse_awk_rtx_freemem (rtx, fs_free);
|
||||||
|
|
||||||
if (fs_rex_free)
|
if (fs_rex_free)
|
||||||
{
|
{
|
||||||
@ -870,7 +865,7 @@ oops:
|
|||||||
/*if (str_free) QSE_AWK_FREE (rtx->awk, str_free);*/
|
/*if (str_free) QSE_AWK_FREE (rtx->awk, str_free);*/
|
||||||
if (str.ptr) qse_awk_rtx_freevalstr (rtx, a0, str.ptr);
|
if (str.ptr) qse_awk_rtx_freevalstr (rtx, a0, str.ptr);
|
||||||
|
|
||||||
if (fs_free) QSE_AWK_FREE (rtx->awk, fs_free);
|
if (fs_free) qse_awk_rtx_freemem (rtx, fs_free);
|
||||||
|
|
||||||
if (fs_rex_free)
|
if (fs_rex_free)
|
||||||
{
|
{
|
||||||
@ -1531,31 +1526,58 @@ static int fnc_ismap (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QSE_INLINE int asort_compare (const void* x1, const void* x2, void* ctx)
|
static QSE_INLINE int asort_compare (const void* x1, const void* x2, void* ctx, int* cv)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
if (qse_awk_rtx_cmpval((qse_awk_rtx_t*)ctx, (qse_awk_val_t*)x1, (qse_awk_val_t*)x2, &n) <= -1) return -1;
|
if (qse_awk_rtx_cmpval((qse_awk_rtx_t*)ctx, *(qse_awk_val_t**)x1, *(qse_awk_val_t**)x2, &n) <= -1) return -1;
|
||||||
return n;
|
*cv = n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cud_t
|
||||||
|
{
|
||||||
|
qse_awk_rtx_t* rtx;
|
||||||
|
qse_awk_fun_t* fun;
|
||||||
|
};
|
||||||
|
|
||||||
|
static QSE_INLINE int asort_compare_ud (const void* x1, const void* x2, void* ctx, int* cv)
|
||||||
|
{
|
||||||
|
struct cud_t* cud = (struct cud_t*)ctx;
|
||||||
|
qse_awk_val_t* r, * args[2];
|
||||||
|
qse_awk_int_t rv;
|
||||||
|
|
||||||
|
args[0] = *(qse_awk_val_t**)x1;
|
||||||
|
args[1] = *(qse_awk_val_t**)x2;
|
||||||
|
r = qse_awk_rtx_callfun(cud->rtx, cud->fun, args, 2);
|
||||||
|
if (!r) return -1;
|
||||||
|
if (qse_awk_rtx_valtoint(cud->rtx, r, &rv) <= -1) return -1;
|
||||||
|
*cv = rv;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
||||||
{
|
{
|
||||||
qse_size_t nargs;
|
qse_size_t nargs;
|
||||||
qse_awk_val_t* a0, * a2;
|
qse_awk_val_t* a0, * a0_val, * a1, * a2;
|
||||||
|
qse_awk_val_type_t a0_type, v_type;
|
||||||
qse_awk_val_t* r, * rmap;
|
qse_awk_val_t* r, * rmap;
|
||||||
qse_awk_int_t rv = 0; /* as if no element in the map */
|
qse_awk_int_t rv = 0; /* as if no element in the map */
|
||||||
qse_awk_val_map_itr_t itr;
|
qse_awk_val_map_itr_t itr;
|
||||||
qse_awk_fun_t* fun;
|
qse_awk_fun_t* fun = QSE_NULL;
|
||||||
qse_size_t msz, i;
|
qse_size_t msz, i;
|
||||||
qse_awk_val_t** va;
|
qse_awk_val_t** va;
|
||||||
|
int x;
|
||||||
|
|
||||||
nargs = qse_awk_rtx_getnargs(rtx);
|
nargs = qse_awk_rtx_getnargs(rtx);
|
||||||
|
|
||||||
a0 = qse_awk_rtx_getarg(rtx, 0);
|
a0 = qse_awk_rtx_getarg(rtx, 0);
|
||||||
|
a0_type = QSE_AWK_RTX_GETVALTYPE(rtx, a0);
|
||||||
|
QSE_ASSERT (a0_type == QSE_AWK_VAL_REF);
|
||||||
|
|
||||||
if (QSE_AWK_RTX_GETVALTYPE(rtx, a0) != QSE_AWK_VAL_MAP)
|
v_type = qse_awk_rtx_getrefvaltype(rtx, (qse_awk_val_ref_t*)a0);
|
||||||
|
if (v_type != QSE_AWK_VAL_MAP)
|
||||||
{
|
{
|
||||||
if (QSE_AWK_RTX_GETVALTYPE(rtx, a0) == QSE_AWK_VAL_NIL)
|
if (v_type == QSE_AWK_VAL_NIL)
|
||||||
{
|
{
|
||||||
/* treat it as an empty value */
|
/* treat it as an empty value */
|
||||||
goto done;
|
goto done;
|
||||||
@ -1565,7 +1587,14 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a0_val = qse_awk_rtx_getrefval(rtx, (qse_awk_val_ref_t*)a0);
|
||||||
|
QSE_ASSERT (QSE_AWK_RTX_GETVALTYPE(rtx, a0_val) == QSE_AWK_VAL_MAP);
|
||||||
|
|
||||||
if (nargs >= 2)
|
if (nargs >= 2)
|
||||||
|
{
|
||||||
|
a1 = qse_awk_rtx_getarg(rtx, 1); /* destination map */
|
||||||
|
|
||||||
|
if (nargs >= 3)
|
||||||
{
|
{
|
||||||
a2 = qse_awk_rtx_getarg(rtx, 2);
|
a2 = qse_awk_rtx_getarg(rtx, 2);
|
||||||
if (QSE_AWK_RTX_GETVALTYPE(rtx, a2) != QSE_AWK_VAL_FUN)
|
if (QSE_AWK_RTX_GETVALTYPE(rtx, a2) != QSE_AWK_VAL_FUN)
|
||||||
@ -1582,13 +1611,19 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a1 = a0; /* let a0 be the destination. a0 is both source and destination */
|
||||||
|
}
|
||||||
|
|
||||||
if (!qse_awk_rtx_getfirstmapvalitr(rtx, a0, &itr)) goto done; /* map empty */
|
|
||||||
|
|
||||||
msz = qse_htb_getsize(((qse_awk_val_map_t*)a0)->map);
|
if (!qse_awk_rtx_getfirstmapvalitr(rtx, a0_val, &itr)) goto done; /* map empty */
|
||||||
|
|
||||||
|
msz = qse_htb_getsize(((qse_awk_val_map_t*)a0_val)->map);
|
||||||
QSE_ASSERT (msz > 0);
|
QSE_ASSERT (msz > 0);
|
||||||
|
|
||||||
va = (qse_awk_val_t**)qse_awk_rtx_allocmem(rtx, msz * QSE_SIZEOF(qse_awk_val_t*));
|
va = (qse_awk_val_t**)qse_awk_rtx_allocmem(rtx, msz * QSE_SIZEOF(*va));
|
||||||
if (!va) return -1;
|
if (!va) return -1;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
@ -1596,9 +1631,25 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
|||||||
{
|
{
|
||||||
va[i++] = (qse_awk_val_t*)QSE_AWK_VAL_MAP_ITR_VAL(&itr);
|
va[i++] = (qse_awk_val_t*)QSE_AWK_VAL_MAP_ITR_VAL(&itr);
|
||||||
}
|
}
|
||||||
while (qse_awk_rtx_getnextmapvalitr(rtx, a0, &itr));
|
while (qse_awk_rtx_getnextmapvalitr(rtx, a0_val, &itr));
|
||||||
|
|
||||||
qse_qsort (va, msz, QSE_SIZEOF(*va), asort_compare, rtx);
|
if (fun)
|
||||||
|
{
|
||||||
|
struct cud_t cud;
|
||||||
|
cud.rtx = rtx;
|
||||||
|
cud.fun = fun;
|
||||||
|
x = qse_qsortx(va, msz, QSE_SIZEOF(*va), asort_compare_ud, &cud);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = qse_qsortx(va, msz, QSE_SIZEOF(*va), asort_compare, rtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x <= -1)
|
||||||
|
{
|
||||||
|
qse_awk_rtx_freemem (rtx, va);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
rmap = qse_awk_rtx_makemapval(rtx);
|
rmap = qse_awk_rtx_makemapval(rtx);
|
||||||
if (!rmap)
|
if (!rmap)
|
||||||
@ -1622,7 +1673,7 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
|||||||
QSE_NULL
|
QSE_NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
if (qse_awk_rtx_setmapvalfld (rtx, rmap, ridx, ridx_len, va[i]) == QSE_NULL)
|
if (qse_awk_rtx_setmapvalfld(rtx, rmap, ridx, ridx_len, va[i]) == QSE_NULL)
|
||||||
{
|
{
|
||||||
qse_awk_rtx_freeval (rtx, rmap, 0);
|
qse_awk_rtx_freeval (rtx, rmap, 0);
|
||||||
qse_awk_rtx_freemem (rtx, va);
|
qse_awk_rtx_freemem (rtx, va);
|
||||||
@ -1630,30 +1681,13 @@ static int fnc_asort (qse_awk_rtx_t* rtx, const qse_awk_fnc_info_t* fi)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
/* TODO: complete this function */
|
|
||||||
r = qse_awk_rtx_callfun(rtx, fun, valargs, nargs);
|
|
||||||
if (qse_awk_rtx_valtoint(rtx, r, &rv) <= -1) return -1;
|
|
||||||
|
|
||||||
if (rv > 0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if (rv < 0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = msz;
|
rv = msz;
|
||||||
qse_awk_rtx_freemem (rtx, va);
|
qse_awk_rtx_freemem (rtx, va);
|
||||||
/* TODO: set the resulting map back to a0.
|
|
||||||
* or to a1 if a1 is given */
|
qse_awk_rtx_refupval (rtx, rmap);
|
||||||
qse_awk_rtx_setretval (rtx, rmap);
|
x = qse_awk_rtx_setrefval (rtx, (qse_awk_val_ref_t*)a1, rmap);
|
||||||
return 0;
|
qse_awk_rtx_refdownval (rtx, rmap);
|
||||||
|
if (x <= -1) return -1;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
r = qse_awk_rtx_makeintval(rtx, rv);
|
r = qse_awk_rtx_makeintval(rtx, rv);
|
||||||
|
@ -1650,7 +1650,7 @@ qse_awk_val_t* qse_awk_rtx_callfun (
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* thr return value captured in termination by exit()
|
/* the return value captured in termination by exit()
|
||||||
* is reference-counted up in capture_retval_on_exit().
|
* is reference-counted up in capture_retval_on_exit().
|
||||||
* let's do the same thing for the return value normally
|
* let's do the same thing for the return value normally
|
||||||
* returned. */
|
* returned. */
|
||||||
@ -5996,7 +5996,7 @@ static qse_awk_val_t* __eval_call (
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* push all arguments onto the stack */
|
/* push all arguments onto the stack */
|
||||||
nargs = argpusher (run, call, apdata);
|
nargs = argpusher(run, call, apdata);
|
||||||
if (nargs == (qse_size_t)-1)
|
if (nargs == (qse_size_t)-1)
|
||||||
{
|
{
|
||||||
UNWIND_RTX_STACK_BASE (run);
|
UNWIND_RTX_STACK_BASE (run);
|
||||||
@ -6049,7 +6049,7 @@ static qse_awk_val_t* __eval_call (
|
|||||||
{
|
{
|
||||||
run->errinf.num = QSE_AWK_ENOERR;
|
run->errinf.num = QSE_AWK_ENOERR;
|
||||||
|
|
||||||
n = call->u.fnc.spec.impl (run, &call->u.fnc.info);
|
n = call->u.fnc.spec.impl(run, &call->u.fnc.info);
|
||||||
|
|
||||||
if (n <= -1)
|
if (n <= -1)
|
||||||
{
|
{
|
||||||
|
@ -1911,6 +1911,69 @@ qse_awk_int_t qse_awk_rtx_hashval (qse_awk_rtx_t* rtx, qse_awk_val_t* v)
|
|||||||
return hv & ~(((qse_awk_uint_t)1) << ((QSE_SIZEOF(qse_awk_uint_t) * 8) - 1));
|
return hv & ~(((qse_awk_uint_t)1) << ((QSE_SIZEOF(qse_awk_uint_t) * 8) - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qse_awk_val_type_t qse_awk_rtx_getrefvaltype (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref)
|
||||||
|
{
|
||||||
|
/* return the type of the value that the reference points to */
|
||||||
|
switch (ref->id)
|
||||||
|
{
|
||||||
|
case QSE_AWK_VAL_REF_POS:
|
||||||
|
{
|
||||||
|
return QSE_AWK_VAL_STR;
|
||||||
|
}
|
||||||
|
case QSE_AWK_VAL_REF_GBL:
|
||||||
|
{
|
||||||
|
qse_size_t idx;
|
||||||
|
qse_awk_val_t* v;
|
||||||
|
idx = (qse_size_t)ref->adr;
|
||||||
|
v = RTX_STACK_GBL(rtx, idx);
|
||||||
|
return QSE_AWK_RTX_GETVALTYPE(rtx, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
qse_awk_val_t** xref = (qse_awk_val_t**)ref->adr;
|
||||||
|
qse_awk_val_t* v;
|
||||||
|
|
||||||
|
/* A reference value is not able to point to another
|
||||||
|
* refernce value for the way values are represented
|
||||||
|
* in QSEAWK */
|
||||||
|
v = *xref;
|
||||||
|
QSE_ASSERT (QSE_AWK_RTX_GETVALTYPE(rtx, v) != QSE_AWK_VAL_REF);
|
||||||
|
return QSE_AWK_RTX_GETVALTYPE(rtx, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qse_awk_val_t* qse_awk_rtx_getrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref)
|
||||||
|
{
|
||||||
|
switch (ref->id)
|
||||||
|
{
|
||||||
|
case QSE_AWK_VAL_REF_POS:
|
||||||
|
{
|
||||||
|
/* a positional doesn't contain a value. you should use qse_awk_rtx_valtoXXX()
|
||||||
|
* like qse_awk_rtx_valtostr(), qse_Awk_rtx_valtoint() */
|
||||||
|
return QSE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
case QSE_AWK_VAL_REF_GBL:
|
||||||
|
{
|
||||||
|
qse_size_t idx;
|
||||||
|
idx = (qse_size_t)ref->adr;
|
||||||
|
return RTX_STACK_GBL(rtx, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
qse_awk_val_t** xref = (qse_awk_val_t**)ref->adr;
|
||||||
|
/* A reference value is not able to point to another
|
||||||
|
* refernce value for the way values are represented
|
||||||
|
* in QSEAWK */
|
||||||
|
QSE_ASSERT (QSE_AWK_RTX_GETVALTYPE (rtx, *xref)!= QSE_AWK_VAL_REF);
|
||||||
|
return *xref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int qse_awk_rtx_setrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref, qse_awk_val_t* val)
|
int qse_awk_rtx_setrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref, qse_awk_val_t* val)
|
||||||
{
|
{
|
||||||
qse_awk_val_type_t vtype = QSE_AWK_RTX_GETVALTYPE (rtx, val);
|
qse_awk_val_type_t vtype = QSE_AWK_RTX_GETVALTYPE (rtx, val);
|
||||||
@ -2001,7 +2064,7 @@ int qse_awk_rtx_setrefval (qse_awk_rtx_t* rtx, qse_awk_val_ref_t* ref, qse_awk_v
|
|||||||
qse_awk_val_type_t rref_vtype;
|
qse_awk_val_type_t rref_vtype;
|
||||||
|
|
||||||
rref = (qse_awk_val_t**)ref->adr; /* old value pointer */
|
rref = (qse_awk_val_t**)ref->adr; /* old value pointer */
|
||||||
rref_vtype = QSE_AWK_RTX_GETVALTYPE (rtx, *rref); /* old value type */
|
rref_vtype = QSE_AWK_RTX_GETVALTYPE(rtx, *rref); /* old value type */
|
||||||
if (vtype == QSE_AWK_VAL_MAP)
|
if (vtype == QSE_AWK_VAL_MAP)
|
||||||
{
|
{
|
||||||
/* new value: map, old value: nil or map => ok */
|
/* new value: map, old value: nil or map => ok */
|
||||||
|
@ -64,8 +64,8 @@
|
|||||||
/*
|
/*
|
||||||
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
|
* Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
|
||||||
*/
|
*/
|
||||||
#define swapcode(TYPE,parmi,parmj,n) { \
|
#define swapcode(TYPE,parmi,parmj,n) do { \
|
||||||
qse_size_t i = (n) / sizeof (TYPE); \
|
qse_size_t i = (n) / QSE_SIZEOF (TYPE); \
|
||||||
register TYPE *pi = (TYPE*)(parmi); \
|
register TYPE *pi = (TYPE*)(parmi); \
|
||||||
register TYPE *pj = (TYPE*)(parmj); \
|
register TYPE *pj = (TYPE*)(parmj); \
|
||||||
do { \
|
do { \
|
||||||
@ -73,29 +73,38 @@
|
|||||||
*pi++ = *pj; \
|
*pi++ = *pj; \
|
||||||
*pj++ = t; \
|
*pj++ = t; \
|
||||||
} while (--i > 0); \
|
} while (--i > 0); \
|
||||||
}
|
} while(0)
|
||||||
|
|
||||||
#define SWAPINIT(a,size) \
|
|
||||||
swaptype = ((qse_byte_t*)a-(qse_byte_t*)0)%sizeof(long) || \
|
|
||||||
size % sizeof(long) ? 2 : size == sizeof(long)? 0 : 1;
|
|
||||||
|
|
||||||
static QSE_INLINE void swapfunc (
|
#define get_swaptype(a, elemsize) (((qse_byte_t*)(a) - (qse_byte_t*)0) % QSE_SIZEOF(long) || elemsize % QSE_SIZEOF(long)? 2 : elemsize == QSE_SIZEOF(long)? 0 : 1)
|
||||||
qse_byte_t* a, qse_byte_t* b, int n, int swaptype)
|
|
||||||
{
|
|
||||||
if (swaptype <= 1)
|
|
||||||
swapcode(long, a, b, n)
|
|
||||||
else
|
|
||||||
swapcode(qse_byte_t, a, b, n)
|
|
||||||
}
|
|
||||||
|
|
||||||
#define swap(a, b) \
|
#define swap(a, b, elemsize) do { \
|
||||||
if (swaptype == 0) { \
|
switch (swaptype) \
|
||||||
|
{ \
|
||||||
|
case 0: \
|
||||||
|
{ \
|
||||||
long t = *(long*)(a); \
|
long t = *(long*)(a); \
|
||||||
*(long*)(a) = *(long*)(b); \
|
*(long*)(a) = *(long*)(b); \
|
||||||
*(long*)(b) = t; \
|
*(long*)(b) = t; \
|
||||||
} else swapfunc(a, b, size, swaptype)
|
break; \
|
||||||
|
} \
|
||||||
|
case 1: \
|
||||||
|
swapcode(long, a, b, elemsize); \
|
||||||
|
break; \
|
||||||
|
default: \
|
||||||
|
swapcode(qse_byte_t, a, b, elemsize); \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
#define vecswap(a,b,n) if ((n) > 0) swapfunc(a, b, n, swaptype)
|
|
||||||
|
#define vecswap(a,b,n) do { \
|
||||||
|
if ((n) > 0) \
|
||||||
|
{ \
|
||||||
|
if (swaptype <= 1) swapcode(long, a, b, n); \
|
||||||
|
else swapcode(qse_byte_t, a, b, n); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
static QSE_INLINE qse_byte_t* med3 (qse_byte_t* a, qse_byte_t* b, qse_byte_t* c, qse_sort_comper_t comper, void* ctx)
|
static QSE_INLINE qse_byte_t* med3 (qse_byte_t* a, qse_byte_t* b, qse_byte_t* c, qse_sort_comper_t comper, void* ctx)
|
||||||
{
|
{
|
||||||
@ -111,26 +120,48 @@ static QSE_INLINE qse_byte_t* med3 (qse_byte_t* a, qse_byte_t* b, qse_byte_t* c,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QSE_INLINE qse_byte_t* med3x (qse_byte_t* a, qse_byte_t* b, qse_byte_t* c, qse_sort_comperx_t comper, void* ctx)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
if (comper(a, b, ctx, &n) <= -1) return QSE_NULL;
|
||||||
|
if (n < 0)
|
||||||
|
{
|
||||||
|
if (comper(b, c, ctx, &n) <= -1) return QSE_NULL;
|
||||||
|
if (n < 0) return b;
|
||||||
|
|
||||||
|
if (comper(a, c, ctx, &n) <= -1) return QSE_NULL;
|
||||||
|
return (n < 0)? c: a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (comper(b, c, ctx, &n) <= -1) return QSE_NULL;
|
||||||
|
if (n > 0) return b;
|
||||||
|
if (comper(a, c, ctx, &n) <= -1) return QSE_NULL;
|
||||||
|
return (n > 0)? c: a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void qse_qsort (void* base, qse_size_t nmemb, qse_size_t size, qse_sort_comper_t comper, void* ctx)
|
void qse_qsort (void* base, qse_size_t nmemb, qse_size_t size, qse_sort_comper_t comper, void* ctx)
|
||||||
{
|
{
|
||||||
qse_byte_t*pa, *pb, *pc, *pd, *pl, *pm, *pn;
|
qse_byte_t* pa, * pb, * pc, * pd, * pl, * pm, * pn;
|
||||||
int swaptype, swap_cnt;
|
int swaptype, swap_cnt;
|
||||||
long r;
|
long r;
|
||||||
qse_size_t d;
|
qse_size_t d;
|
||||||
register qse_byte_t*a = (qse_byte_t*)base;
|
register qse_byte_t* a = (qse_byte_t*)base;
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
SWAPINIT(a, size);
|
swaptype = get_swaptype(a, size);
|
||||||
|
|
||||||
swap_cnt = 0;
|
swap_cnt = 0;
|
||||||
if (nmemb < 7)
|
if (nmemb < 7)
|
||||||
{
|
{
|
||||||
for (pm = (qse_byte_t*)a + size;
|
qse_byte_t* end = (qse_byte_t*)a + (nmemb * size);
|
||||||
pm < (qse_byte_t*) a + nmemb * size; pm += size)
|
for (pm = (qse_byte_t*)a + size; pm < end; pm += size)
|
||||||
{
|
{
|
||||||
for (pl = pm; pl > (qse_byte_t*)a && comper(pl - size, pl, ctx) > 0; pl -= size)
|
for (pl = pm; pl > (qse_byte_t*)a && comper(pl - size, pl, ctx) > 0; pl -= size)
|
||||||
{
|
{
|
||||||
swap(pl, pl - size);
|
swap(pl, pl - size, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -149,7 +180,7 @@ loop:
|
|||||||
}
|
}
|
||||||
pm = med3(pl, pm, pn, comper, ctx);
|
pm = med3(pl, pm, pn, comper, ctx);
|
||||||
}
|
}
|
||||||
swap(a, pm);
|
swap(a, pm, size);
|
||||||
pa = pb = (qse_byte_t*)a + size;
|
pa = pb = (qse_byte_t*)a + size;
|
||||||
|
|
||||||
pc = pd = (qse_byte_t*)a + (nmemb - 1) * size;
|
pc = pd = (qse_byte_t*)a + (nmemb - 1) * size;
|
||||||
@ -160,7 +191,7 @@ loop:
|
|||||||
if (r == 0)
|
if (r == 0)
|
||||||
{
|
{
|
||||||
swap_cnt = 1;
|
swap_cnt = 1;
|
||||||
swap(pa, pb);
|
swap(pa, pb, size);
|
||||||
pa += size;
|
pa += size;
|
||||||
}
|
}
|
||||||
pb += size;
|
pb += size;
|
||||||
@ -170,13 +201,13 @@ loop:
|
|||||||
if (r == 0)
|
if (r == 0)
|
||||||
{
|
{
|
||||||
swap_cnt = 1;
|
swap_cnt = 1;
|
||||||
swap(pc, pd);
|
swap(pc, pd, size);
|
||||||
pd -= size;
|
pd -= size;
|
||||||
}
|
}
|
||||||
pc -= size;
|
pc -= size;
|
||||||
}
|
}
|
||||||
if (pb > pc) break;
|
if (pb > pc) break;
|
||||||
swap (pb, pc);
|
swap (pb, pc, size);
|
||||||
swap_cnt = 1;
|
swap_cnt = 1;
|
||||||
pb += size;
|
pb += size;
|
||||||
pc -= size;
|
pc -= size;
|
||||||
@ -188,10 +219,9 @@ loop:
|
|||||||
for (pm = (qse_byte_t*)a + size;
|
for (pm = (qse_byte_t*)a + size;
|
||||||
pm < (qse_byte_t*)a + nmemb * size; pm += size)
|
pm < (qse_byte_t*)a + nmemb * size; pm += size)
|
||||||
{
|
{
|
||||||
for (pl = pm; pl > (qse_byte_t*)a &&
|
for (pl = pm; pl > (qse_byte_t*)a && comper(pl - size, pl, ctx) > 0; pl -= size)
|
||||||
comper(pl - size, pl, ctx) > 0; pl -= size)
|
|
||||||
{
|
{
|
||||||
swap(pl, pl - size);
|
swap(pl, pl - size, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -215,6 +245,134 @@ loop:
|
|||||||
/* qsort(pn - r, r / size, size, comper);*/
|
/* qsort(pn - r, r / size, size, comper);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qse_qsortx (void* base, qse_size_t nmemb, qse_size_t size, qse_sort_comperx_t comper, void* ctx)
|
||||||
|
{
|
||||||
|
qse_byte_t* pa, * pb, * pc, * pd, * pl, * pm, * pn;
|
||||||
|
int swaptype, swap_cnt;
|
||||||
|
long r;
|
||||||
|
int n;
|
||||||
|
qse_size_t d;
|
||||||
|
register qse_byte_t* a = (qse_byte_t*)base;
|
||||||
|
|
||||||
|
loop:
|
||||||
|
swaptype = get_swaptype(a, size);
|
||||||
|
|
||||||
|
swap_cnt = 0;
|
||||||
|
if (nmemb < 7)
|
||||||
|
{
|
||||||
|
qse_byte_t* end = (qse_byte_t*)a + (nmemb * size);
|
||||||
|
for (pm = (qse_byte_t*)a + size; pm < end; pm += size)
|
||||||
|
{
|
||||||
|
pl = pm;
|
||||||
|
while (pl > (qse_byte_t*)a)
|
||||||
|
{
|
||||||
|
qse_byte_t* pl2 = pl - size;
|
||||||
|
if (comper(pl2, pl, ctx, &n) <= -1) return -1;
|
||||||
|
if (n <= 0) break;
|
||||||
|
swap (pl, pl2, size);
|
||||||
|
pl = pl2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pm = (qse_byte_t*)a + (nmemb / 2) * size;
|
||||||
|
if (nmemb > 7)
|
||||||
|
{
|
||||||
|
pl = (qse_byte_t*)a;
|
||||||
|
pn = (qse_byte_t*)a + (nmemb - 1) * size;
|
||||||
|
if (nmemb > 40)
|
||||||
|
{
|
||||||
|
d = (nmemb / 8) * size;
|
||||||
|
pl = med3x(pl, pl + d, pl + 2 * d, comper, ctx);
|
||||||
|
if (!pl) return -1;
|
||||||
|
pm = med3x(pm - d, pm, pm + d, comper, ctx);
|
||||||
|
if (!pm) return -1;
|
||||||
|
pn = med3x(pn - 2 * d, pn - d, pn, comper, ctx);
|
||||||
|
if (!pn) return -1;
|
||||||
|
}
|
||||||
|
pm = med3x(pl, pm, pn, comper, ctx);
|
||||||
|
if (!pm) return -1;
|
||||||
|
}
|
||||||
|
swap(a, pm, size);
|
||||||
|
pa = pb = (qse_byte_t*)a + size;
|
||||||
|
|
||||||
|
pc = pd = (qse_byte_t*)a + (nmemb - 1) * size;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
while (pb <= pc)
|
||||||
|
{
|
||||||
|
if (comper(pb, a, ctx, &n) <= -1) return -1;
|
||||||
|
if (n > 0) break;
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
swap_cnt = 1;
|
||||||
|
swap(pa, pb, size);
|
||||||
|
pa += size;
|
||||||
|
}
|
||||||
|
pb += size;
|
||||||
|
}
|
||||||
|
while (pb <= pc)
|
||||||
|
{
|
||||||
|
if (comper(pc, a, ctx, &n) <= -1) return -1;
|
||||||
|
if (n < 0) break;
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
swap_cnt = 1;
|
||||||
|
swap(pc, pd, size);
|
||||||
|
pd -= size;
|
||||||
|
}
|
||||||
|
pc -= size;
|
||||||
|
}
|
||||||
|
if (pb > pc) break;
|
||||||
|
swap (pb, pc, size);
|
||||||
|
swap_cnt = 1;
|
||||||
|
pb += size;
|
||||||
|
pc -= size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (swap_cnt == 0)
|
||||||
|
{
|
||||||
|
/* switch to insertion sort */
|
||||||
|
qse_byte_t* end = (qse_byte_t*)a + (nmemb * size);
|
||||||
|
for (pm = (qse_byte_t*)a + size; pm < end; pm += size)
|
||||||
|
{
|
||||||
|
pl = pm;
|
||||||
|
while (pl > (qse_byte_t*)a)
|
||||||
|
{
|
||||||
|
if (comper(pl - size, pl, ctx, &n) <= -1) return -1;
|
||||||
|
if (n <= 0) break;
|
||||||
|
swap(pl, pl - size, size);
|
||||||
|
pl = pl - size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pn = (qse_byte_t*)a + nmemb * size;
|
||||||
|
r = qsort_min(pa - (qse_byte_t*)a, pb - pa);
|
||||||
|
vecswap (a, pb - r, r);
|
||||||
|
r = qsort_min (pd - pc, pn - pd - size);
|
||||||
|
vecswap (pb, pn - r, r);
|
||||||
|
|
||||||
|
if ((r = pb - pa) > size)
|
||||||
|
{
|
||||||
|
if (qse_qsortx(a, r / size, size, comper, ctx) <= -1) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((r = pd - pc) > size)
|
||||||
|
{
|
||||||
|
/* Iterate rather than recurse to save stack space */
|
||||||
|
a = pn - r;
|
||||||
|
nmemb = r / size;
|
||||||
|
goto loop;
|
||||||
|
}
|
||||||
|
/* qsortx(pn - r, r / size, size, comper);*/
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user