enhanced asort() and asorti() to handle an array value.
added hawk_rtx_getarrvalfld() and hawk_rtx_setarrvalfld()
This commit is contained in:
parent
5326953e9b
commit
29bc731ccb
301
hawk/lib/fnc.c
301
hawk/lib/fnc.c
@ -1774,13 +1774,9 @@ static HAWK_INLINE int __fnc_asort (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi,
|
|||||||
hawk_oow_t nargs;
|
hawk_oow_t nargs;
|
||||||
hawk_val_t* a0, * a0_val;
|
hawk_val_t* a0, * a0_val;
|
||||||
hawk_val_type_t a0_type, v_type;
|
hawk_val_type_t a0_type, v_type;
|
||||||
hawk_val_t* r, * rmap = HAWK_NULL;
|
hawk_val_t* r, * rrv = HAWK_NULL;
|
||||||
hawk_int_t rv = 0; /* as if no element in the map */
|
hawk_int_t rv = 0; /* as if no element in the map */
|
||||||
hawk_val_map_itr_t itr;
|
|
||||||
hawk_fun_t* fun = HAWK_NULL;
|
hawk_fun_t* fun = HAWK_NULL;
|
||||||
hawk_oow_t msz, i;
|
|
||||||
hawk_val_t** va;
|
|
||||||
int x;
|
|
||||||
|
|
||||||
nargs = hawk_rtx_getnargs(rtx);
|
nargs = hawk_rtx_getnargs(rtx);
|
||||||
|
|
||||||
@ -1788,23 +1784,6 @@ static HAWK_INLINE int __fnc_asort (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi,
|
|||||||
a0_type = HAWK_RTX_GETVALTYPE(rtx, a0);
|
a0_type = HAWK_RTX_GETVALTYPE(rtx, a0);
|
||||||
HAWK_ASSERT (a0_type == HAWK_VAL_REF);
|
HAWK_ASSERT (a0_type == HAWK_VAL_REF);
|
||||||
|
|
||||||
/* TODO: handle HAWK_VAL_ARR as input */
|
|
||||||
v_type = hawk_rtx_getrefvaltype(rtx, (hawk_val_ref_t*)a0);
|
|
||||||
if (v_type != HAWK_VAL_MAP)
|
|
||||||
{
|
|
||||||
if (v_type == HAWK_VAL_NIL)
|
|
||||||
{
|
|
||||||
/* treat it as an empty value */
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
hawk_rtx_seterrfmt (rtx, HAWK_NULL, HAWK_ENOTMAP, HAWK_T("source not a map"));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
a0_val = hawk_rtx_getrefval(rtx, (hawk_val_ref_t*)a0);
|
|
||||||
HAWK_ASSERT (HAWK_RTX_GETVALTYPE(rtx, a0_val) == HAWK_VAL_MAP);
|
|
||||||
|
|
||||||
if (nargs >= 3)
|
if (nargs >= 3)
|
||||||
{
|
{
|
||||||
fun = hawk_rtx_valtofun(rtx, hawk_rtx_getarg(rtx, 2));
|
fun = hawk_rtx_valtofun(rtx, hawk_rtx_getarg(rtx, 2));
|
||||||
@ -1823,111 +1802,215 @@ static HAWK_INLINE int __fnc_asort (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hawk_rtx_getfirstmapvalitr(rtx, a0_val, &itr)) goto done; /* map empty */
|
v_type = hawk_rtx_getrefvaltype(rtx, (hawk_val_ref_t*)a0);
|
||||||
|
switch (v_type)
|
||||||
msz = hawk_map_getsize(((hawk_val_map_t*)a0_val)->map);
|
|
||||||
HAWK_ASSERT (msz > 0);
|
|
||||||
|
|
||||||
va = (hawk_val_t**)hawk_rtx_allocmem(rtx, msz * HAWK_SIZEOF(*va));
|
|
||||||
if (HAWK_UNLIKELY(!va)) return -1;
|
|
||||||
i = 0;
|
|
||||||
if (sort_keys)
|
|
||||||
{
|
{
|
||||||
do
|
case HAWK_VAL_NIL:
|
||||||
|
goto done; /* treat it as an empty value */
|
||||||
|
|
||||||
|
case HAWK_VAL_MAP:
|
||||||
|
goto val_map;
|
||||||
|
|
||||||
|
case HAWK_VAL_ARR:
|
||||||
|
goto val_arr;
|
||||||
|
|
||||||
|
default:
|
||||||
|
hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ENOTIDXACC);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
val_map:
|
||||||
|
{
|
||||||
|
hawk_val_map_itr_t itr;
|
||||||
|
hawk_oow_t i, msz;
|
||||||
|
hawk_val_t** va;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
a0_val = hawk_rtx_getrefval(rtx, (hawk_val_ref_t*)a0);
|
||||||
|
HAWK_ASSERT (HAWK_RTX_GETVALTYPE(rtx, a0_val) == HAWK_VAL_MAP);
|
||||||
|
|
||||||
|
if (!hawk_rtx_getfirstmapvalitr(rtx, a0_val, &itr)) goto done; /* map empty */
|
||||||
|
|
||||||
|
msz = hawk_map_getsize(((hawk_val_map_t*)a0_val)->map);
|
||||||
|
HAWK_ASSERT (msz > 0);
|
||||||
|
|
||||||
|
va = (hawk_val_t**)hawk_rtx_allocmem(rtx, msz * HAWK_SIZEOF(*va));
|
||||||
|
if (HAWK_UNLIKELY(!va)) return -1;
|
||||||
|
i = 0;
|
||||||
|
if (sort_keys)
|
||||||
{
|
{
|
||||||
const hawk_oocs_t* key = HAWK_VAL_MAP_ITR_KEY(&itr);
|
|
||||||
va[i] = hawk_rtx_makestrvalwithoocs(rtx, key);
|
|
||||||
if (HAWK_UNLIKELY(!va[i]))
|
|
||||||
{
|
|
||||||
while (i > 0)
|
|
||||||
{
|
|
||||||
--i;
|
|
||||||
hawk_rtx_refdownval (rtx, va[i]);
|
|
||||||
}
|
|
||||||
hawk_rtx_freemem (rtx, va);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
hawk_rtx_refupval (rtx, va[i]);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
while (hawk_rtx_getnextmapvalitr(rtx, a0_val, &itr));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
va[i] = (hawk_val_t*)HAWK_VAL_MAP_ITR_VAL(&itr);
|
|
||||||
hawk_rtx_refupval (rtx, va[i]);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
while (hawk_rtx_getnextmapvalitr(rtx, a0_val, &itr));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fun)
|
|
||||||
{
|
|
||||||
struct cud_t cud;
|
|
||||||
cud.rtx = rtx;
|
|
||||||
cud.fun = fun;
|
|
||||||
x = hawk_qsortx(va, msz, HAWK_SIZEOF(*va), asort_compare_ud, &cud);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
x = hawk_qsortx(va, msz, HAWK_SIZEOF(*va), asort_compare, rtx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x <= -1 || !(rmap = hawk_rtx_makemapval(rtx)))
|
|
||||||
{
|
|
||||||
for (i = 0; i < msz; i++) hawk_rtx_refdownval (rtx, va[i]);
|
|
||||||
hawk_rtx_freemem (rtx, va);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < msz; i++)
|
|
||||||
{
|
|
||||||
hawk_ooch_t ridx[128]; /* TODO: make it dynamic? can overflow? */
|
|
||||||
hawk_oow_t ridx_len;
|
|
||||||
|
|
||||||
ridx_len = hawk_fmt_uintmax_to_oocstr(
|
|
||||||
ridx,
|
|
||||||
HAWK_COUNTOF(ridx),
|
|
||||||
i,
|
|
||||||
10 | HAWK_FMT_UINTMAX_NOTRUNC | HAWK_FMT_UINTMAX_NONULL,
|
|
||||||
-1,
|
|
||||||
HAWK_T('\0'),
|
|
||||||
HAWK_NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
if (hawk_rtx_setmapvalfld(rtx, rmap, ridx, ridx_len, va[i]) == HAWK_NULL)
|
|
||||||
{
|
|
||||||
/* decrement the reference count of the values not added to the map */
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
hawk_rtx_refdownval (rtx, va[i]);
|
const hawk_oocs_t* key = HAWK_VAL_MAP_ITR_KEY(&itr);
|
||||||
|
va[i] = hawk_rtx_makestrvalwithoocs(rtx, key);
|
||||||
|
if (HAWK_UNLIKELY(!va[i]))
|
||||||
|
{
|
||||||
|
while (i > 0)
|
||||||
|
{
|
||||||
|
--i;
|
||||||
|
hawk_rtx_refdownval (rtx, va[i]);
|
||||||
|
}
|
||||||
|
hawk_rtx_freemem (rtx, va);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
hawk_rtx_refupval (rtx, va[i]);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
while (i < msz);
|
while (hawk_rtx_getnextmapvalitr(rtx, a0_val, &itr));
|
||||||
hawk_rtx_freeval (rtx, rmap, 0); /* this derefs the elements added. */
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
va[i] = (hawk_val_t*)HAWK_VAL_MAP_ITR_VAL(&itr);
|
||||||
|
hawk_rtx_refupval (rtx, va[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while (hawk_rtx_getnextmapvalitr(rtx, a0_val, &itr));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fun)
|
||||||
|
{
|
||||||
|
struct cud_t cud;
|
||||||
|
cud.rtx = rtx;
|
||||||
|
cud.fun = fun;
|
||||||
|
x = hawk_qsortx(va, msz, HAWK_SIZEOF(*va), asort_compare_ud, &cud);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = hawk_qsortx(va, msz, HAWK_SIZEOF(*va), asort_compare, rtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x <= -1 || !(rrv = hawk_rtx_makemapval(rtx)))
|
||||||
|
{
|
||||||
|
for (i = 0; i < msz; i++) hawk_rtx_refdownval (rtx, va[i]);
|
||||||
hawk_rtx_freemem (rtx, va);
|
hawk_rtx_freemem (rtx, va);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
hawk_rtx_refdownval (rtx, va[i]); /* deref it as it has been added to the map */
|
for (i = 0; i < msz; i++)
|
||||||
|
{
|
||||||
|
hawk_ooch_t ridx[128]; /* TODO: make it dynamic? can overflow? */
|
||||||
|
hawk_oow_t ridx_len;
|
||||||
|
|
||||||
|
ridx_len = hawk_fmt_uintmax_to_oocstr(
|
||||||
|
ridx,
|
||||||
|
HAWK_COUNTOF(ridx),
|
||||||
|
i + 1, /* basically 1-based */
|
||||||
|
10 | HAWK_FMT_UINTMAX_NOTRUNC | HAWK_FMT_UINTMAX_NONULL,
|
||||||
|
-1,
|
||||||
|
HAWK_T('\0'),
|
||||||
|
HAWK_NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hawk_rtx_setmapvalfld(rtx, rrv, ridx, ridx_len, va[i]) == HAWK_NULL)
|
||||||
|
{
|
||||||
|
/* decrement the reference count of the values not added to the map */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
hawk_rtx_refdownval (rtx, va[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while (i < msz);
|
||||||
|
hawk_rtx_freeval (rtx, rrv, 0); /* this derefs the elements added. */
|
||||||
|
hawk_rtx_freemem (rtx, va);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hawk_rtx_refdownval (rtx, va[i]); /* deref it as it has been added to the map */
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = msz;
|
||||||
|
hawk_rtx_freemem (rtx, va);
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = msz;
|
|
||||||
hawk_rtx_freemem (rtx, va);
|
val_arr:
|
||||||
|
{
|
||||||
|
hawk_arr_t* arr;
|
||||||
|
hawk_oow_t i, j, msz, ssz;
|
||||||
|
hawk_val_t** va;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
a0_val = hawk_rtx_getrefval(rtx, (hawk_val_ref_t*)a0);
|
||||||
|
HAWK_ASSERT (HAWK_RTX_GETVALTYPE(rtx, a0_val) == HAWK_VAL_ARR);
|
||||||
|
arr = ((hawk_val_arr_t*)a0_val)->arr;
|
||||||
|
msz = HAWK_ARR_TALLY(arr);
|
||||||
|
if (msz == 0) goto done; /* array empty */
|
||||||
|
|
||||||
|
ssz = HAWK_ARR_SIZE(arr);
|
||||||
|
HAWK_ASSERT (msz <= ssz);
|
||||||
|
HAWK_ASSERT (msz <= HAWK_QUICKINT_MAX);
|
||||||
|
HAWK_ASSERT (ssz <= HAWK_QUICKINT_MAX);
|
||||||
|
|
||||||
|
va = (hawk_val_t**)hawk_rtx_allocmem(rtx, msz * HAWK_SIZEOF(*va));
|
||||||
|
if (HAWK_UNLIKELY(!va)) return -1;
|
||||||
|
for (i = 0, j = 0; j < ssz; j++)
|
||||||
|
{
|
||||||
|
if (HAWK_ARR_SLOT(arr, j))
|
||||||
|
{
|
||||||
|
va[i] = sort_keys? hawk_rtx_makeintval(rtx, j): HAWK_ARR_DPTR(arr, j);
|
||||||
|
hawk_rtx_refupval (rtx, va[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fun)
|
||||||
|
{
|
||||||
|
struct cud_t cud;
|
||||||
|
cud.rtx = rtx;
|
||||||
|
cud.fun = fun;
|
||||||
|
x = hawk_qsortx(va, msz, HAWK_SIZEOF(*va), asort_compare_ud, &cud);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = hawk_qsortx(va, msz, HAWK_SIZEOF(*va), asort_compare, rtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x <= -1 || !(rrv = hawk_rtx_makearrval(rtx, -1)))
|
||||||
|
{
|
||||||
|
for (i = 0; i < msz; i++) hawk_rtx_refdownval (rtx, va[i]);
|
||||||
|
hawk_rtx_freemem (rtx, va);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < msz; i++)
|
||||||
|
{
|
||||||
|
if (hawk_rtx_setarrvalfld(rtx, rrv, i + 1, va[i]) == HAWK_NULL) /* i + 1 for 1-based indexing*/
|
||||||
|
{
|
||||||
|
/* decrement the reference count of the values not added to the map */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
hawk_rtx_refdownval (rtx, va[i]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while (i < msz);
|
||||||
|
hawk_rtx_freeval (rtx, rrv, 0); /* this derefs the elements added. */
|
||||||
|
hawk_rtx_freemem (rtx, va);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hawk_rtx_refdownval (rtx, va[i]); /* deref it as it has been added to the map */
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = msz;
|
||||||
|
hawk_rtx_freemem (rtx, va);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
r = hawk_rtx_makeintval(rtx, rv);
|
r = hawk_rtx_makeintval(rtx, rv);
|
||||||
if (!r) return -1;
|
if (HAWK_UNLIKELY(!r)) return -1;
|
||||||
|
|
||||||
if (rmap)
|
if (rrv)
|
||||||
{
|
{
|
||||||
/* rmap can be NULL when a jump has been made for an empty source
|
int x;
|
||||||
|
/* rrv can be NULL when a jump has been made for an empty source
|
||||||
* at the beginning of this fucntion */
|
* at the beginning of this fucntion */
|
||||||
hawk_rtx_refupval (rtx, rmap);
|
hawk_rtx_refupval (rtx, rrv);
|
||||||
x = hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, (nargs >= 2)), rmap);
|
x = hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, (nargs >= 2)), rrv);
|
||||||
hawk_rtx_refdownval (rtx, rmap);
|
hawk_rtx_refdownval (rtx, rrv);
|
||||||
if (x <= -1)
|
if (x <= -1)
|
||||||
{
|
{
|
||||||
hawk_rtx_freeval (rtx, r, 0);
|
hawk_rtx_freeval (rtx, r, 0);
|
||||||
|
@ -2962,6 +2962,20 @@ HAWK_EXPORT hawk_val_map_itr_t* hawk_rtx_getnextmapvalitr (
|
|||||||
hawk_val_map_itr_t* itr
|
hawk_val_map_itr_t* itr
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
HAWK_EXPORT hawk_val_t* hawk_rtx_setarrvalfld (
|
||||||
|
hawk_rtx_t* rtx,
|
||||||
|
hawk_val_t* arr,
|
||||||
|
hawk_ooi_t index,
|
||||||
|
hawk_val_t* v
|
||||||
|
);
|
||||||
|
|
||||||
|
HAWK_EXPORT hawk_val_t* hawk_rtx_getarrvalfld (
|
||||||
|
hawk_rtx_t* rtx,
|
||||||
|
hawk_val_t* arr,
|
||||||
|
hawk_ooi_t index
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The hawk_rtx_makerefval() function creates a reference value.
|
* The hawk_rtx_makerefval() function creates a reference value.
|
||||||
* \return value on success, #HAWK_NULL on failure
|
* \return value on success, #HAWK_NULL on failure
|
||||||
|
@ -1287,6 +1287,30 @@ hawk_val_map_itr_t* hawk_rtx_getnextmapvalitr (hawk_rtx_t* rtx, hawk_val_t* map,
|
|||||||
return itr->pair? itr: HAWK_NULL;
|
return itr->pair? itr: HAWK_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hawk_val_t* hawk_rtx_setarrvalfld (hawk_rtx_t* rtx, hawk_val_t* arr, hawk_ooi_t index, hawk_val_t* v)
|
||||||
|
{
|
||||||
|
HAWK_ASSERT (HAWK_RTX_GETVALTYPE(rtx, arr) == HAWK_VAL_ARR);
|
||||||
|
|
||||||
|
if (hawk_arr_upsert(((hawk_val_arr_t*)arr)->arr, index, v, 0) == HAWK_ARR_NIL) return HAWK_NULL;
|
||||||
|
|
||||||
|
/* the value is passed in by an external party. we can't refup()
|
||||||
|
* and refdown() the value if htb_upsert() fails. that way, the value
|
||||||
|
* can be destroyed if it was passed with the reference count of 0.
|
||||||
|
* so we increment the reference count when htb_upsert() is complete */
|
||||||
|
hawk_rtx_refupval (rtx, v);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
hawk_val_t* hawk_rtx_getarrvalfld (hawk_rtx_t* rtx, hawk_val_t* arr, hawk_ooi_t index)
|
||||||
|
{
|
||||||
|
hawk_arr_t* _arr;
|
||||||
|
HAWK_ASSERT (HAWK_RTX_GETVALTYPE(rtx, arr) == HAWK_VAL_ARR);
|
||||||
|
_arr = ((hawk_val_arr_t*)arr)->arr;
|
||||||
|
if (index < 0 || index >= HAWK_ARR_SIZE(_arr) || !HAWK_ARR_SLOT(_arr, index)) return HAWK_NULL;
|
||||||
|
return HAWK_ARR_DPTR(_arr, index);
|
||||||
|
}
|
||||||
|
|
||||||
hawk_val_t* hawk_rtx_makerefval (hawk_rtx_t* rtx, int id, hawk_val_t** adr)
|
hawk_val_t* hawk_rtx_makerefval (hawk_rtx_t* rtx, int id, hawk_val_t** adr)
|
||||||
{
|
{
|
||||||
hawk_val_ref_t* val;
|
hawk_val_ref_t* val;
|
||||||
|
Loading…
Reference in New Issue
Block a user