added str::tohex() and str::fromhex()
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-12-24 02:45:14 +09:00
parent 33ba979512
commit 1475451523
4 changed files with 188 additions and 43 deletions

View File

@@ -89,29 +89,29 @@ static int trim (hawk_rtx_t* rtx, int flags)
case HAWK_VAL_MBS:
case HAWK_VAL_BOB:
{
hawk_bcs_t path;
hawk_bch_t* npath;
path.ptr = hawk_rtx_getvalbcstr(rtx, a0, &path.len);
if (HAWK_UNLIKELY(!path.ptr)) return -1;
npath = hawk_trim_bchars(path.ptr, &path.len, flags);
retv = hawk_rtx_makembsvalwithbchars(rtx, npath, path.len);
hawk_rtx_freevalbcstr (rtx, a0, path.ptr);
hawk_bcs_t str;
hawk_bch_t* nstr;
str.ptr = hawk_rtx_getvalbcstr(rtx, a0, &str.len);
if (HAWK_UNLIKELY(!str.ptr)) return -1;
nstr = hawk_trim_bchars(str.ptr, &str.len, flags);
retv = hawk_rtx_makembsvalwithbchars(rtx, nstr, str.len);
hawk_rtx_freevalbcstr(rtx, a0, str.ptr);
break;
}
default:
{
hawk_oocs_t path;
hawk_ooch_t* npath;
path.ptr = hawk_rtx_getvaloocstr(rtx, a0, &path.len);
if (HAWK_UNLIKELY(!path.ptr)) return -1;
hawk_oocs_t str;
hawk_ooch_t* nstr;
str.ptr = hawk_rtx_getvaloocstr(rtx, a0, &str.len);
if (HAWK_UNLIKELY(!str.ptr)) return -1;
/* because hawk_trim_oochars() returns the pointer and the length without
* affecting the string given, it's safe to pass the original value.
* hawk_rtx_getvaloocstr() doesn't duplicate the value if it's of
* the string type. */
npath = hawk_trim_oochars(path.ptr, &path.len, flags);
retv = hawk_rtx_makestrvalwithoochars(rtx, npath, path.len);
hawk_rtx_freevaloocstr (rtx, a0, path.ptr);
nstr = hawk_trim_oochars(str.ptr, &str.len, flags);
retv = hawk_rtx_makestrvalwithoochars(rtx, nstr, str.len);
hawk_rtx_freevaloocstr(rtx, a0, str.ptr);
break;
}
}
@@ -457,6 +457,7 @@ static int fnc_frommbs (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
*
* if you use a supported encoding name, it may look like this:
* a = str::frommbs(@b"\xC7\xD1\xB1\xDB", "cp949");
* a = str::frommbs(@b"\xEB\x8F\x99\xEA\xB7\xB8\xEB\x9D\xBC\xEB\xAF\xB8", "utf8");
* printf ("%K\n", a);
*/
hawk_val_t* a0, * r;
@@ -467,10 +468,9 @@ static int fnc_frommbs (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
hawk_val_t* a1;
hawk_oocs_t enc;
a1 = hawk_rtx_getarg(rtx, 1);
enc.ptr = hawk_rtx_getvaloocstr(rtx, a1, &enc.len);
if (!enc.ptr) return -1;
if (HAWK_UNLIKELY(!enc.ptr)) return -1;
/* if encoding name is an empty string, hawk_findcmgr() returns the default cmgr.
* i don't want that behavior. */
cmgr = (enc.len > 0 && enc.len == hawk_count_oocstr(enc.ptr))? hawk_get_cmgr_by_name(enc.ptr): HAWK_NULL;
@@ -575,6 +575,146 @@ done:
return 0;
}
static int fnc_fromhex (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{
hawk_val_t* retv;
hawk_val_t* a0;
a0 = hawk_rtx_getarg(rtx, 0);
switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{
case HAWK_VAL_BCHR:
case HAWK_VAL_MBS:
case HAWK_VAL_BOB:
{
hawk_bcs_t str;
hawk_oow_t i;
hawk_oow_t len;
hawk_uint8_t v;
hawk_oow_t x;
str.ptr = hawk_rtx_getvalbcstr(rtx, a0, &str.len);
if (HAWK_UNLIKELY(!str.ptr)) return -1;
len = str.len >> 1;
retv = hawk_rtx_makembsvalwithbchars(rtx, HAWK_NULL, len + (str.len & 1));
for (i = 0, x = 0; i < len; i++, x++)
{
if (str.ptr[x] >= '0' && str.ptr[x] <= '9') v = str.ptr[x] - '0';
else if (str.ptr[x] >= 'a' && str.ptr[x] <= 'f') v = str.ptr[x] - 'a' + 10;
else if (str.ptr[x] >= 'A' && str.ptr[x] <= 'F') v = str.ptr[x] - 'A' + 10;
else v = 0;
x = x + 1;
v <<= 4;
if (str.ptr[x] >= '0' && str.ptr[x] <= '9') v += str.ptr[x] - '0';
else if (str.ptr[x] >= 'a' && str.ptr[x] <= 'f') v += str.ptr[x] - 'a' + 10;
else if (str.ptr[x] >= 'A' && str.ptr[x] <= 'F') v += str.ptr[x] - 'A' + 10;
((hawk_val_mbs_t*)retv)->val.ptr[i] = v;
}
if (str.len & 1)
{
/* trailing digit */
if (str.ptr[x] >= '0' && str.ptr[x] <= '9') v = str.ptr[x] - '0';
else if (str.ptr[x] >= 'a' && str.ptr[x] <= 'f') v = str.ptr[x] - 'a' + 10;
else if (str.ptr[x] >= 'A' && str.ptr[x] <= 'F') v = str.ptr[x] - 'A' + 10;
else v = 0;
((hawk_val_mbs_t*)retv)->val.ptr[i] = v;
}
hawk_rtx_freevalbcstr(rtx, a0, str.ptr);
break;
}
default:
{
hawk_oocs_t str;
hawk_oow_t i;
hawk_oow_t len;
hawk_uint8_t v;
hawk_oow_t x;
str.ptr = hawk_rtx_getvaloocstr(rtx, a0, &str.len);
if (HAWK_UNLIKELY(!str.ptr)) return -1;
len = str.len >> 1;
retv = hawk_rtx_makembsvalwithbchars(rtx, HAWK_NULL, len + (str.len & 1));
for (i = 0, x = 0; i < len; i++, x++)
{
if (str.ptr[x] >= '0' && str.ptr[x] <= '9') v = str.ptr[x] - '0';
else if (str.ptr[x] >= 'a' && str.ptr[x] <= 'f') v = str.ptr[x] - 'a' + 10;
else if (str.ptr[x] >= 'A' && str.ptr[x] <= 'F') v = str.ptr[x] - 'A' + 10;
else v = 0;
x = x + 1;
v <<= 4;
if (str.ptr[x] >= '0' && str.ptr[x] <= '9') v += str.ptr[x] - '0';
else if (str.ptr[x] >= 'a' && str.ptr[x] <= 'f') v += str.ptr[x] - 'a' + 10;
else if (str.ptr[x] >= 'A' && str.ptr[x] <= 'F') v += str.ptr[x] - 'A' + 10;
((hawk_val_mbs_t*)retv)->val.ptr[i] = v;
}
if (str.len & 1)
{
/* trailing digit */
if (str.ptr[x] >= '0' && str.ptr[x] <= '9') v = str.ptr[x] - '0';
else if (str.ptr[x] >= 'a' && str.ptr[x] <= 'f') v = str.ptr[x] - 'a' + 10;
else if (str.ptr[x] >= 'A' && str.ptr[x] <= 'F') v = str.ptr[x] - 'A' + 10;
else v = 0;
((hawk_val_mbs_t*)retv)->val.ptr[i] = v;
}
hawk_rtx_freevaloocstr(rtx, a0, str.ptr);
break;
}
}
if (HAWK_UNLIKELY(!retv)) return -1;
hawk_rtx_setretval (rtx, retv);
return 0;
}
static int fnc_tohex (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{
hawk_val_t* retv;
hawk_val_t* a0;
hawk_bcs_t str;
hawk_oow_t i;
a0 = hawk_rtx_getarg(rtx, 0);
/* if the argument is not a multi-byte string, the conversion
* will be performed in the default encoding (utf-8). if you
* want a different encoding, call str::tombs() first.
* - str::tohex(@b"xyz")
* - str::tohex("🤩")
* - str::tohex(str::tombs("🤩"))
* - str::tohex(str::tombs("🤩", "utf8")) */
str.ptr = hawk_rtx_getvalbcstr(rtx, a0, &str.len);
if (HAWK_UNLIKELY(!str.ptr)) return -1;
retv = hawk_rtx_makembsvalwithbchars(rtx, HAWK_NULL, str.len * 2);
for (i = 0; i < str.len; i++)
{
hawk_fmt_uintmax_to_bcstr(
&((hawk_val_mbs_t*)retv)->val.ptr[i * 2], 2,
(hawk_uint8_t)str.ptr[i], 16 | HAWK_FMT_UINTMAX_NONULL,
2, '0', HAWK_NULL);
}
hawk_rtx_freevalbcstr(rtx, a0, str.ptr);
if (HAWK_UNLIKELY(!retv)) return -1;
hawk_rtx_setretval (rtx, retv);
return 0;
}
static int fnc_tonum (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{
/* str::tonum(value) */
@@ -693,7 +833,7 @@ static int fnc_subchar (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{
hawk_oow_t nargs;
hawk_val_t* a0, * a1, * r;
hawk_int_t lindex, lcount;
hawk_int_t lindex;
int n;
nargs = hawk_rtx_getnargs(rtx);
@@ -760,6 +900,7 @@ static hawk_mod_fnc_tab_t fnctab[] =
/* keep this table sorted for binary search in query(). */
{ HAWK_T("frombcharcode"), { { 0, A_MAX, HAWK_NULL }, fnc_frombcharcode, 0 } },
{ HAWK_T("fromcharcode"), { { 0, A_MAX, HAWK_NULL }, fnc_fromcharcode, 0 } },
{ HAWK_T("fromhex"), { { 1, 1, HAWK_NULL }, fnc_fromhex, 0 } },
{ HAWK_T("frommbs"), { { 1, 2, HAWK_NULL }, fnc_frommbs, 0 } },
{ HAWK_T("gensub"), { { 3, 4, HAWK_T("xvvv")}, hawk_fnc_gensub, 0 } },
{ HAWK_T("gsub"), { { 2, 3, HAWK_T("xvr")}, hawk_fnc_gsub, 0 } },
@@ -789,6 +930,7 @@ static hawk_mod_fnc_tab_t fnctab[] =
{ HAWK_T("subchar"), { { 2, 2, HAWK_NULL }, fnc_subchar, 0 } },
{ HAWK_T("substr"), { { 2, 3, HAWK_NULL }, hawk_fnc_substr, 0 } },
{ HAWK_T("tocharcode"), { { 1, 2, HAWK_NULL }, fnc_tocharcode, 0 } },
{ HAWK_T("tohex"), { { 1, 1, HAWK_NULL }, fnc_tohex, 0 } },
{ HAWK_T("tolower"), { { 1, 1, HAWK_NULL }, hawk_fnc_tolower, 0 } },
{ HAWK_T("tombs"), { { 1, 2, HAWK_NULL }, fnc_tombs, 0 } },
{ HAWK_T("tonum"), { { 1, 2, HAWK_NULL }, fnc_tonum, 0 } },

View File

@@ -5498,7 +5498,6 @@ static hawk_intptr_t unpack_intptr (const hawk_uint8_t* binp, int 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;
@@ -5508,7 +5507,6 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
int endian = ENDIAN_NATIVE;
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) return set_error_on_sys_list(rtx, &rdp->sys_list, HAWK_EINVAL, HAWK_T("insufficient binary data")); \
@@ -5544,10 +5542,9 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
binp += rep_cnt;
break;
case 'b':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int8_t));
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, (hawk_int8_t)*binp++);
@@ -5559,7 +5556,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
case 'B':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int8_t));
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++);
@@ -5571,7 +5568,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
case 'h':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int16_t));
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int16_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval(rtx, unpack_int16(binp, endian));
@@ -5584,7 +5581,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
case 'H':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint16_t));
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));
@@ -5597,7 +5594,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
case 'i':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int32_t));
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));
@@ -5610,7 +5607,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
case 'I':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint32_t));
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));
@@ -5623,7 +5620,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
case 'l':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_int64_t));
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));
@@ -5636,7 +5633,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
case 'L':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint64_t));
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));
@@ -5649,7 +5646,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
case 'q':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_intmax_t));
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_intmax_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval(rtx, unpack_intmax(binp, endian));
@@ -5662,7 +5659,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
case 'Q':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uintmax_t));
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uintmax_t));
for (rc = 0; rc < rep_cnt; rc++)
{
v = hawk_rtx_makeintval(rtx, unpack_uintmax(binp, endian));
@@ -5675,7 +5672,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
case 'n':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_intptr_t));
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));
@@ -5688,7 +5685,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
case 'N':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uintptr_t));
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));
@@ -5703,7 +5700,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
{
hawk_uint32_t x;
float y;
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint32_t));
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint32_t));
for (rc = 0; rc < rep_cnt; rc++)
{
x = unpack_uint32(binp, endian);
@@ -5720,7 +5717,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
{
hawk_uint64_t x;
double y;
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint64_t));
UNPACK_CHECK_ARG_AND_DATA(rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint64_t));
for (rc = 0; rc < rep_cnt; rc++)
{
x = unpack_uint64(binp, endian);
@@ -5735,7 +5732,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
case 'c':
{
UNPACK_CHECK_ARG_AND_DATA (rep_cnt, rep_cnt * HAWK_SIZEOF(hawk_uint8_t));
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++);
@@ -5748,7 +5745,7 @@ static hawk_int_t unpack_data (hawk_rtx_t* rtx, const hawk_bcs_t* bin, const haw
case 's':
case 'p':
{
UNPACK_CHECK_ARG_AND_DATA (1, rep_cnt);
UNPACK_CHECK_ARG_AND_DATA(1, rep_cnt);
v = hawk_rtx_makembsvalwithbchars(rtx, (const hawk_bch_t*)binp, rep_cnt);
binp += rep_cnt;
if (HAWK_UNLIKELY(!v)) goto oops_internal;