From 130d24544f7508ecde19f0e5e95f95733a093f7e Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Mon, 14 Dec 2020 15:25:07 +0000 Subject: [PATCH] added c, n, N to sys::pack() and sys::unpack() --- hawk/lib/mod-sys.c | 178 +++++++++++++++++++++++++++++++++++++++------ hawk/t/h-002.hawk | 27 +++++++ 2 files changed, 183 insertions(+), 22 deletions(-) diff --git a/hawk/lib/mod-sys.c b/hawk/lib/mod-sys.c index f9228a0f..9ad1ff71 100644 --- a/hawk/lib/mod-sys.c +++ b/hawk/lib/mod-sys.c @@ -4846,7 +4846,7 @@ done: # define ENDIAN_NATIVE ENDIAN_LITTLE #endif -static hawk_oow_t pack_int16_t (hawk_uint8_t* dst, hawk_uint16_t val, int endian) +static hawk_oow_t pack_uint16_t (hawk_uint8_t* dst, hawk_uint16_t val, int endian) { if (endian == ENDIAN_NATIVE) { @@ -4862,7 +4862,7 @@ static hawk_oow_t pack_int16_t (hawk_uint8_t* dst, hawk_uint16_t val, int endian return 2; } -static hawk_oow_t pack_int32_t (hawk_uint8_t* dst, hawk_uint32_t val, int endian) +static hawk_oow_t pack_uint32_t (hawk_uint8_t* dst, hawk_uint32_t val, int endian) { if (endian == ENDIAN_NATIVE) { @@ -4882,7 +4882,7 @@ static hawk_oow_t pack_int32_t (hawk_uint8_t* dst, hawk_uint32_t val, int endian return 4; } -static hawk_oow_t pack_int64_t (hawk_uint8_t* dst, hawk_uint64_t val, int endian) +static hawk_oow_t pack_uint64_t (hawk_uint8_t* dst, hawk_uint64_t val, int endian) { if (endian == ENDIAN_NATIVE) { @@ -4910,6 +4910,21 @@ static hawk_oow_t pack_int64_t (hawk_uint8_t* dst, hawk_uint64_t val, int endian return 8; } +static hawk_oow_t pack_uintptr_t (hawk_uint8_t* dst, hawk_oow_t val, int endian) +{ + hawk_oow_t i; + + if (endian == ENDIAN_NATIVE) + { + for (i = 0; i < HAWK_SIZEOF(hawk_oow_t); i++) *dst++ = val >> (i * 8); + } + else + { + for (i = HAWK_SIZEOF(hawk_oow_t); i > 0; ) *dst++ = val >> ((--i) * 8); + } + return HAWK_SIZEOF(hawk_oow_t); +} + static int ensure_pack_buf (hawk_rtx_t* rtx, rtx_data_t* rdp, hawk_oow_t reqsz) { if (reqsz > rdp->pack.capa - rdp->pack.len) @@ -4962,19 +4977,29 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk { switch (*fmtp) { - case '=': /* native */ + #if 0 + case '@': /* native size, native alignment */ + break; + #endif + + case '=': /* native endian, no alignment */ endian = ENDIAN_NATIVE; break; - case '<': /* little-endian */ + case '<': /* little-endian, no alignment */ endian = ENDIAN_LITTLE; break; - case '>': /* big-endian */ - case '!': /* network */ + case '>': /* big-endian, no alignment */ + case '!': /* network, no alignment */ endian = ENDIAN_BIG; break; + case 'x': /* zero-padding */ + PACK_CHECK_ARG_AND_BUF (0, rep_cnt * HAWK_SIZEOF(hawk_uint8_t)); + for (rc = 0; rc < rep_cnt; rc++) rdp->pack.ptr[rdp->pack.len++] = 0; + break; + case 'b': /* byte, char */ { hawk_int_t v; @@ -5006,7 +5031,7 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk for (rc = 0; rc < rep_cnt; rc++) { if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal; - rdp->pack.len += pack_int16_t(&rdp->pack.ptr[rdp->pack.len], (hawk_int16_t)v, endian); + rdp->pack.len += pack_uint16_t(&rdp->pack.ptr[rdp->pack.len], (hawk_int16_t)v, endian); } break; } @@ -5018,7 +5043,7 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk for (rc = 0; rc < rep_cnt; rc++) { if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal; - rdp->pack.len += pack_int16_t(&rdp->pack.ptr[rdp->pack.len], (hawk_uint16_t)v, endian); + rdp->pack.len += pack_uint16_t(&rdp->pack.ptr[rdp->pack.len], (hawk_uint16_t)v, endian); } break; } @@ -5031,7 +5056,7 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk for (rc = 0; rc < rep_cnt; rc++) { if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal; - rdp->pack.len += pack_int32_t(&rdp->pack.ptr[rdp->pack.len], (hawk_int32_t)v, endian); + rdp->pack.len += pack_uint32_t(&rdp->pack.ptr[rdp->pack.len], (hawk_int32_t)v, endian); } break; } @@ -5044,7 +5069,7 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk for (rc = 0; rc < rep_cnt; rc++) { if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal; - rdp->pack.len += pack_int16_t(&rdp->pack.ptr[rdp->pack.len], (hawk_uint32_t)v, endian); + rdp->pack.len += pack_uint16_t(&rdp->pack.ptr[rdp->pack.len], (hawk_uint32_t)v, endian); } break; } @@ -5056,7 +5081,7 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk for (rc = 0; rc < rep_cnt; rc++) { if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal; - rdp->pack.len += pack_int64_t(rdp->pack.ptr, (hawk_int64_t)v, endian); + rdp->pack.len += pack_uint64_t(rdp->pack.ptr, (hawk_int64_t)v, endian); } break; } @@ -5068,11 +5093,36 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk for (rc = 0; rc < rep_cnt; rc++) { if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal; - rdp->pack.len += pack_int64_t(rdp->pack.ptr, (hawk_uint64_t)v, endian); + rdp->pack.len += pack_uint64_t(rdp->pack.ptr, (hawk_uint64_t)v, endian); } break; } + case 'n': + { + hawk_int_t v; + PACK_CHECK_ARG_AND_BUF (rep_cnt, HAWK_SIZEOF(hawk_intptr_t) * rep_cnt); + for (rc = 0; rc < rep_cnt; rc++) + { + if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal; + rdp->pack.len += pack_uintptr_t(rdp->pack.ptr, (hawk_intptr_t)v, endian); + } + break; + } + + case 'N': + { + hawk_int_t v; + PACK_CHECK_ARG_AND_BUF (rep_cnt, HAWK_SIZEOF(hawk_uintptr_t) * rep_cnt); + for (rc = 0; rc < rep_cnt; rc++) + { + if (hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, arg_idx++), &v) <= -1) goto oops_internal; + rdp->pack.len += pack_uintptr_t(rdp->pack.ptr, (hawk_uintptr_t)v, endian); + } + break; + } + + #if 0 case 'f': f = va_arg(args, double); @@ -5085,6 +5135,31 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk break; #endif + case 'c': + { + hawk_val_t* a; + hawk_bcs_t tmp; + + PACK_CHECK_ARG_AND_BUF (rep_cnt, HAWK_SIZEOF(hawk_uint8_t) * rep_cnt); + + for (rc = 0; rc < rep_cnt; rc++) + { + a = hawk_rtx_getarg(rtx, arg_idx++); + + tmp.ptr = hawk_rtx_getvalbcstr(rtx, a, &tmp.len); + if (HAWK_UNLIKELY(!tmp.ptr)) goto oops_internal; + + if (tmp.len < 1) + { + hawk_rtx_freevalbcstr (rtx, a, tmp.ptr); + return set_error_on_sys_list (rtx, &rdp->sys_list, HAWK_EINVAL, HAWK_T("data too short for '%jc'"), *fmtp); + } + rdp->pack.ptr[rdp->pack.len++] = tmp.ptr[0]; + hawk_rtx_freevalbcstr (rtx, a, tmp.ptr); + } + break; + } + case 's': case 'p': @@ -5109,11 +5184,6 @@ static hawk_int_t pack_data (hawk_rtx_t* rtx, const hawk_oocs_t* fmt, const hawk break; } - case 'x': /* zero-padding */ - PACK_CHECK_ARG_AND_BUF (0, rep_cnt * HAWK_SIZEOF(hawk_uint8_t)); - for (rc = 0; rc < rep_cnt; rc++) rdp->pack.ptr[rdp->pack.len++] = 0; - break; - default: /* handle below outside 'switch' */ if (hawk_is_ooch_digit(*fmtp)) @@ -5230,6 +5300,29 @@ static hawk_int64_t unpack_int64 (const hawk_uint8_t* binp, int 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_uintptr_t unpack_uintptr (const hawk_uint8_t* binp, int endian) +{ + hawk_uintptr_t v = 0; + hawk_oow_t i; + + if (endian == ENDIAN_NATIVE) + { + for (i = 0; i < HAWK_SIZEOF(hawk_uintptr_t); i++) v |= (hawk_uintptr_t)(*binp++) << (i * 8); + } + else + { + for (i = HAWK_SIZEOF(hawk_uintptr_t); i > 0; ) v |= (hawk_uintptr_t)(*binp++) << ((--i) * 8); + } + return v; +} + +static hawk_intptr_t unpack_intptr (const hawk_uint8_t* binp, int endian) +{ + hawk_uintptr_t v = unpack_uintptr(binp, endian); + return (v <= HAWK_TYPE_MAX(hawk_intptr_t))? (hawk_intptr_t)v: ((hawk_intptr_t)-1 - (hawk_intptr_t)(HAWK_TYPE_MAX(hawk_uintptr_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) { const hawk_ooch_t* fmtp, * fmte; @@ -5272,6 +5365,11 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw endian = ENDIAN_BIG; break; + case 'x': + binp += rep_cnt; + break; + + case 'b': { UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int8_t)); @@ -5377,11 +5475,51 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw break; } + case 'n': + { + UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_intptr_t)); + for (rc = 0; rc < rep_cnt; rc++) + { + v = hawk_rtx_makeintval(rtx, unpack_intptr(binp, endian)); + binp += HAWK_SIZEOF(hawk_intptr_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 'N': + { + UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uintptr_t)); + for (rc = 0; rc < rep_cnt; rc++) + { + v = hawk_rtx_makeintval(rtx, unpack_uintptr(binp, endian)); + binp += HAWK_SIZEOF(hawk_uintptr_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 'c': + { + UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint8_t)); + for (rc = 0; rc < rep_cnt; rc++) + { + v = hawk_rtx_makebchrval(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 's': case 'p': { @@ -5393,10 +5531,6 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw break; } - case 'x': - binp += rep_cnt; - break; - default: /* handle below outside 'switch' */ if (hawk_is_ooch_digit(*fmtp)) diff --git a/hawk/t/h-002.hawk b/hawk/t/h-002.hawk index 57536d85..83cb06fb 100644 --- a/hawk/t/h-002.hawk +++ b/hawk/t/h-002.hawk @@ -552,6 +552,33 @@ function main() ensure (str::trim(@b" hello world ", str::TRIM_PAC_SPACES) === @b"hello world", 1, @SCRIPTNAME, @SCRIPTLINE); } + + { + @local a, b, c, d; + sys::pack(a, ">hhl", 1, 2, 3); + ensure (a === @b"\x00\x01\x00\x02\x00\x00\x00\x03", 1, @SCRIPTNAME, @SCRIPTLINE); + + sys::pack(a, ">ci", @b'*', 0x12131415); + ensure (a === @b"*\x12\x13\x14\x15", 1, @SCRIPTNAME, @SCRIPTLINE); + + sys::pack(a, ">ic", 0x12131415, @b"*+-"); + ensure (a === @b"\x12\x13\x14\x15*", 1, @SCRIPTNAME, @SCRIPTLINE); + + sys::pack(a, "3c", @b"*+-", 't', "pack"); + ensure (a === @b"*tp", 1, @SCRIPTNAME, @SCRIPTLINE); + + sys::unpack (@b"raymond \x32\x12\x08\x01\x08", "<10sHHb", a, b, c, d); + ensure (a === @b"raymond ", 1, @SCRIPTNAME, @SCRIPTLINE); + ensure (b === 4658, 1, @SCRIPTNAME, @SCRIPTLINE); + ensure (c === 264, 1, @SCRIPTNAME, @SCRIPTLINE); + ensure (d === 8, 1, @SCRIPTNAME, @SCRIPTLINE); + + sys::unpack (@b"raymond", "3c", a, b, c); + ensure (a === @b'r' , 1, @SCRIPTNAME, @SCRIPTLINE); + ensure (b === @b'a' , 1, @SCRIPTNAME, @SCRIPTLINE); + ensure (c === @b'y' , 1, @SCRIPTNAME, @SCRIPTLINE); + } + print "SUCCESS"; }