added some code for sys::unpack()

This commit is contained in:
hyung-hwan 2020-12-13 16:54:39 +00:00
parent 40c750ef3b
commit 55e1003715

View File

@ -4971,10 +4971,7 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk
break; break;
case '>': /* big-endian */ case '>': /* big-endian */
endian = ENDIAN_BIG; case '!': /* network */
break;
case '!': /* network (= big-endian) */
endian = ENDIAN_BIG; endian = ENDIAN_BIG;
break; break;
@ -5148,49 +5145,293 @@ oops_internal:
return copy_error_to_sys_list (rtx, &rdp->sys_list); return copy_error_to_sys_list (rtx, &rdp->sys_list);
} }
static hawk_uint16_t unpack_uint16 (const hawk_uint8_t* binp, int endian)
{
hawk_uint16_t v;
if (endian == ENDIAN_NATIVE)
{
v = *binp++;
v |= (hawk_uint16_t)(*binp++) << 8;
}
else
{
v = (hawk_uint16_t)(*binp++) << 8;
v |= *binp++;
}
return v;
}
static hawk_int16_t unpack_int16 (const hawk_uint8_t* binp, int endian)
{
hawk_uint16_t v = unpack_uint16 (binp, endian);
return (v <= HAWK_TYPE_MAX(hawk_int16_t))? (hawk_int16_t)v: ((hawk_int16_t)-1 - (hawk_int16_t)(HAWK_TYPE_MAX(hawk_uint16_t) - v));
}
static hawk_uint32_t unpack_uint32 (const hawk_uint8_t* binp, int endian)
{
hawk_uint32_t v;
if (endian == ENDIAN_NATIVE)
{
v = *binp++;
v |= (hawk_uint32_t)(*binp++) << 8;
v |= (hawk_uint32_t)(*binp++) << 16;
v |= (hawk_uint32_t)(*binp++) << 24;
}
else
{
v = (hawk_uint32_t)(*binp++) << 24;
v |= (hawk_uint32_t)(*binp++) << 16;
v |= (hawk_uint32_t)(*binp++) << 8;
v |= *binp++;
}
return v;
}
static hawk_int32_t unpack_int32 (const hawk_uint8_t* binp, int endian)
{
hawk_uint32_t v = unpack_uint32 (binp, endian);
return (v <= HAWK_TYPE_MAX(hawk_int32_t))? (hawk_int32_t)v: ((hawk_int32_t)-1 - (hawk_int32_t)(HAWK_TYPE_MAX(hawk_uint32_t) - v));
}
static hawk_uint64_t unpack_uint64 (const hawk_uint8_t* binp, int endian)
{
hawk_uint64_t v;
if (endian == ENDIAN_NATIVE)
{
v = *binp++;
v |= (hawk_uint64_t)(*binp++) << 8;
v |= (hawk_uint64_t)(*binp++) << 16;
v |= (hawk_uint64_t)(*binp++) << 24;
v |= (hawk_uint64_t)(*binp++) << 32;
v |= (hawk_uint64_t)(*binp++) << 40;
v |= (hawk_uint64_t)(*binp++) << 48;
v |= (hawk_uint64_t)(*binp++) << 56;
}
else
{
v = (hawk_uint64_t)(*binp++) << 56;
v |= (hawk_uint64_t)(*binp++) << 48;
v |= (hawk_uint64_t)(*binp++) << 40;
v |= (hawk_uint64_t)(*binp++) << 32;
v |= (hawk_uint64_t)(*binp++) << 24;
v |= (hawk_uint64_t)(*binp++) << 16;
v |= (hawk_uint64_t)(*binp++) << 8;
v |= *binp++;
}
return v;
}
static hawk_int64_t unpack_int64 (const hawk_uint8_t* binp, int endian)
{
hawk_uint64_t v = unpack_uint64 (binp, endian);
return (v <= HAWK_TYPE_MAX(hawk_int64_t))? (hawk_int64_t)v: ((hawk_int64_t)-1 - (hawk_int64_t)(HAWK_TYPE_MAX(hawk_uint64_t) - v));
}
static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const hawk_oocs_t* fmt, const hawk_fnc_info_t* fi, rtx_data_t* rdp) static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const hawk_oocs_t* fmt, const hawk_fnc_info_t* fi, rtx_data_t* rdp)
{ {
const hawk_ooch_t* fmtp, * fmte; const hawk_ooch_t* fmtp, * fmte;
const hawk_bch_t* binp, * bine; const hawk_uint8_t* binp, * bine;
hawk_oow_t rep_cnt, rep_set, rc;
hawk_oow_t arg_idx, arg_cnt; hawk_oow_t arg_idx, arg_cnt;
int endian = ENDIAN_NATIVE;
hawk_val_t* v; hawk_val_t* v;
#define UNPACK_CHECK_ARG_AND_DATA(reqarg, reqsz) do { \
if (arg_cnt - arg_idx < reqarg) return set_error_on_sys_list (rtx, &rdp->sys_list, HAWK_EARGTF, HAWK_NULL); \
if (bine - binp < reqsz) goto oops_internal; \
} while(0)
/* TODO: */ /* TODO: */
arg_idx = 2; /* set past the format specifier */ arg_idx = 2; /* set past the format specifier */
arg_cnt = hawk_rtx_getnargs(rtx); arg_cnt = hawk_rtx_getnargs(rtx);
binp = bin->ptr; rep_cnt = 1;
bine = bin->ptr + bin->len; rep_set = 0;
binp = (hawk_uint8_t*)bin->ptr;
bine = (hawk_uint8_t*)bin->ptr + bin->len;
fmte = fmt->ptr + fmt->len; fmte = fmt->ptr + fmt->len;
#if 0
for (fmtp = fmt->ptr; fmtp < fmte; fmtp++) for (fmtp = fmt->ptr; fmtp < fmte; fmtp++)
{ {
switch (*fmtp) switch (*fmtp)
{ {
case '=': /* native */
endian = ENDIAN_NATIVE;
break;
case '<': /* little-endian */
endian = ENDIAN_LITTLE;
break;
case '>': /* big-endian */
case '!': /* network */
endian = ENDIAN_BIG;
break;
case 'b': case 'b':
{ {
v = hawk_rtx_makeintval(rtx, *binp++); UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int8_t));
if (HAWK_UNLIKELY(!v)) goto oops_internal; for (rc = 0; rc < rep_cnt; rc++)
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx), v) <= -1) goto oops_internal; {
v = hawk_rtx_makeintval(rtx, (hawk_int8_t)*binp++);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
}
break;
}
case 'B':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int8_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval(rtx, *binp++);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
}
break;
} }
case 'h': case 'h':
{ {
v = hawk_rtx_makeintval(rtx, *binp++); UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int16_t));
if (HAWK_UNLIKELY(!v)) goto oops_internal; for (rc = 0; rc < rep_cnt; rc++)
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx), v) <= -1) goto oops_internal; {
v = hawk_rtx_makeintval(rtx, unpack_int16(binp, endian));
binp += HAWK_SIZEOF(hawk_int16_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
}
break;
} }
case 'H':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint16_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval(rtx, unpack_uint16(binp, endian));
binp += HAWK_SIZEOF(hawk_uint16_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
}
break;
}
case 'i':
case 'l':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int32_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval(rtx, unpack_int32(binp, endian));
binp += HAWK_SIZEOF(hawk_int32_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
}
break;
}
case 'I':
case 'L':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint32_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval(rtx, unpack_uint32(binp, endian));
binp += HAWK_SIZEOF(hawk_uint32_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
}
break;
}
case 'q':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int64_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval(rtx, unpack_int64(binp, endian));
binp += HAWK_SIZEOF(hawk_int64_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
}
break;
}
case 'Q':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint64_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval(rtx, unpack_uint64(binp, endian));
binp += HAWK_SIZEOF(hawk_uint64_t);
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
}
break;
}
#if 0
case 'f':
case 'd':
#endif
case 's':
case 'p':
{
UNPACK_CHECK_ARG_AND_DATA (1, rep_cnt);
v = hawk_rtx_makembsvalwithbchars(rtx, binp, rep_cnt);
binp += rep_cnt;
if (HAWK_UNLIKELY(!v)) goto oops_internal;
if (hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, arg_idx++), v) <= -1) goto oops_internal;
break;
}
case 'x':
binp += rep_cnt;
break;
default:
/* handle below outside 'switch' */
if (hawk_is_ooch_digit(*fmtp))
{
if (!rep_set)
{
rep_cnt = 0;
rep_set = 1;
}
rep_cnt = rep_cnt * 10 + (*fmtp - '0');
}
else if (!hawk_is_ooch_space(*fmtp))
{
return set_error_on_sys_list (rtx, &rdp->sys_list, HAWK_EINVAL, HAWK_T("invalid specifier - %jc"), *fmtp);
}
break;
}
if (!hawk_is_ooch_digit(*fmtp) && !hawk_is_ooch_space(*fmtp))
{
rep_cnt = 1;
rep_set = 0;
} }
} }
#endif
return 0; return 0;
oops_internal: oops_internal:
return copy_error_to_sys_list (rtx, &rdp->sys_list); return copy_error_to_sys_list (rtx, &rdp->sys_list);
} }
/*
sys::pack(bin, "i 5s h", 10, "hello", -20);
printf ("%W\n", bin);
*/
static int fnc_pack (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) static int fnc_pack (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{ {
rtx_data_t* rdp = rtx_to_data(rtx, fi); rtx_data_t* rdp = rtx_to_data(rtx, fi);
@ -5229,6 +5470,9 @@ static int fnc_pack (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
return 0; return 0;
} }
/* sys::unpack(@b"\x00\x11\x12\x13\x14\x15", "h h h", a, b, c);
* print a, b, c;
*/
static int fnc_unpack (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi) static int fnc_unpack (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{ {
rtx_data_t* rdp = rtx_to_data(rtx, fi); rtx_data_t* rdp = rtx_to_data(rtx, fi);
@ -5241,34 +5485,19 @@ static int fnc_unpack (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
bin.ptr = HAWK_NULL; bin.ptr = HAWK_NULL;
a0 = hawk_rtx_getarg(rtx, 0); a0 = hawk_rtx_getarg(rtx, 0);
a1 = hawk_rtx_getarg(rtx, 1);
bin.ptr = hawk_rtx_getvalbcstr(rtx, a0, &bin.len); bin.ptr = hawk_rtx_getvalbcstr(rtx, a0, &bin.len);
if (HAWK_UNLIKELY(!bin.ptr)) goto fail; if (HAWK_UNLIKELY(!bin.ptr)) goto fail;
a1 = hawk_rtx_getarg(rtx, 1);
fmt.ptr = hawk_rtx_getvaloocstr(rtx, a1, &fmt.len); fmt.ptr = hawk_rtx_getvaloocstr(rtx, a1, &fmt.len);
if (HAWK_UNLIKELY(!fmt.ptr)) goto fail; if (HAWK_UNLIKELY(!fmt.ptr)) goto fail;
/* sys::unpack(@b"\x00\x11\x12\x13\x14\x15", "h h h", a, b, c); */
rx = unpack_data(rtx, &bin, &fmt, fi, rdp); rx = unpack_data(rtx, &bin, &fmt, fi, rdp);
hawk_rtx_freevaloocstr (rtx, a1, fmt.ptr); fmt.ptr = HAWK_NULL; hawk_rtx_freevaloocstr (rtx, a1, fmt.ptr); fmt.ptr = HAWK_NULL;
hawk_rtx_freevalbcstr (rtx, a0, bin.ptr); bin.ptr = HAWK_NULL; hawk_rtx_freevalbcstr (rtx, a0, bin.ptr); bin.ptr = HAWK_NULL;
if (rx >= 0)
{
hawk_val_t* tmp;
int x;
tmp = hawk_rtx_makembsvalwithbchars(rtx, rdp->pack.ptr, rdp->pack.len);
if (HAWK_UNLIKELY(!tmp)) goto fail;
hawk_rtx_refupval (rtx, tmp);
x = hawk_rtx_setrefval(rtx, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, 0), tmp);
hawk_rtx_refdownval (rtx, tmp);
if (x <= -1) goto fail;
}
done: done:
hawk_rtx_setretval (rtx, hawk_rtx_makeintval(rtx, rx)); hawk_rtx_setretval (rtx, hawk_rtx_makeintval(rtx, rx));
return 0; return 0;