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
147
hawk/lib/fnc.c
147
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_val_t* a0, * a0_val;
|
||||
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_val_map_itr_t itr;
|
||||
hawk_fun_t* fun = HAWK_NULL;
|
||||
hawk_oow_t msz, i;
|
||||
hawk_val_t** va;
|
||||
int x;
|
||||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
fun = hawk_rtx_valtofun(rtx, hawk_rtx_getarg(rtx, 2));
|
||||
@ -1823,6 +1802,33 @@ static HAWK_INLINE int __fnc_asort (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi,
|
||||
}
|
||||
}
|
||||
|
||||
v_type = hawk_rtx_getrefvaltype(rtx, (hawk_val_ref_t*)a0);
|
||||
switch (v_type)
|
||||
{
|
||||
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);
|
||||
@ -1875,7 +1881,7 @@ static HAWK_INLINE int __fnc_asort (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi,
|
||||
x = hawk_qsortx(va, msz, HAWK_SIZEOF(*va), asort_compare, rtx);
|
||||
}
|
||||
|
||||
if (x <= -1 || !(rmap = hawk_rtx_makemapval(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);
|
||||
@ -1890,14 +1896,14 @@ static HAWK_INLINE int __fnc_asort (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi,
|
||||
ridx_len = hawk_fmt_uintmax_to_oocstr(
|
||||
ridx,
|
||||
HAWK_COUNTOF(ridx),
|
||||
i,
|
||||
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, rmap, ridx, ridx_len, va[i]) == 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
|
||||
@ -1906,7 +1912,7 @@ static HAWK_INLINE int __fnc_asort (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi,
|
||||
i++;
|
||||
}
|
||||
while (i < msz);
|
||||
hawk_rtx_freeval (rtx, rmap, 0); /* this derefs the elements added. */
|
||||
hawk_rtx_freeval (rtx, rrv, 0); /* this derefs the elements added. */
|
||||
hawk_rtx_freemem (rtx, va);
|
||||
return -1;
|
||||
}
|
||||
@ -1916,18 +1922,95 @@ static HAWK_INLINE int __fnc_asort (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi,
|
||||
|
||||
rv = msz;
|
||||
hawk_rtx_freemem (rtx, va);
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
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:
|
||||
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 */
|
||||
hawk_rtx_refupval (rtx, rmap);
|
||||
x = hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, (nargs >= 2)), rmap);
|
||||
hawk_rtx_refdownval (rtx, rmap);
|
||||
hawk_rtx_refupval (rtx, rrv);
|
||||
x = hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, (nargs >= 2)), rrv);
|
||||
hawk_rtx_refdownval (rtx, rrv);
|
||||
if (x <= -1)
|
||||
{
|
||||
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_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.
|
||||
* \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;
|
||||
}
|
||||
|
||||
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_ref_t* val;
|
||||
|
Loading…
Reference in New Issue
Block a user