added str::strchar()

made str::tolower(), str::toupper(), str::tonum() character-friendly
This commit is contained in:
hyung-hwan 2020-12-08 13:27:33 +00:00
parent 083d39826d
commit 1d83f8cfe7
3 changed files with 260 additions and 73 deletions

View File

@ -765,7 +765,7 @@ int hawk_fnc_substr (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
if (lcount > (hawk_int_t)len - lindex) lcount = (hawk_int_t)len - lindex; if (lcount > (hawk_int_t)len - lindex) lcount = (hawk_int_t)len - lindex;
r = hawk_rtx_makembsvalwithbchars(rtx, &str[lindex], (hawk_oow_t)lcount); r = hawk_rtx_makembsvalwithbchars(rtx, &str[lindex], (hawk_oow_t)lcount);
if (!r) return -1; if (HAWK_UNLIKELY(!r)) return -1;
} }
else else
{ {
@ -780,7 +780,7 @@ int hawk_fnc_substr (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
r = hawk_rtx_makestrvalwithoochars(rtx, &str[lindex], (hawk_oow_t)lcount); r = hawk_rtx_makestrvalwithoochars(rtx, &str[lindex], (hawk_oow_t)lcount);
hawk_rtx_freevaloocstr (rtx, a0, str); hawk_rtx_freevaloocstr (rtx, a0, str);
if (!r) return -1; if (HAWK_UNLIKELY(!r)) return -1;
} }
hawk_rtx_setretval (rtx, r); hawk_rtx_setretval (rtx, r);
@ -1014,30 +1014,46 @@ int hawk_fnc_tolower (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
hawk_val_t* a0, * r; hawk_val_t* a0, * r;
a0 = hawk_rtx_getarg(rtx, 0); a0 = hawk_rtx_getarg(rtx, 0);
if (HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MBS) switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{ {
hawk_bcs_t str; case HAWK_VAL_MBS:
str.ptr = hawk_rtx_getvalbcstr(rtx, a0, &str.len); {
if (!str.ptr) return -1; hawk_bcs_t str;
r = hawk_rtx_makembsvalwithbcs(rtx, &str); str.ptr = hawk_rtx_getvalbcstr(rtx, a0, &str.len);
hawk_rtx_freevalbcstr (rtx, a0, str.ptr); if (!str.ptr) return -1;
if (!r) return -1; r = hawk_rtx_makembsvalwithbcs(rtx, &str);
str.ptr = ((hawk_val_mbs_t*)r)->val.ptr; hawk_rtx_freevalbcstr (rtx, a0, str.ptr);
str.len = ((hawk_val_mbs_t*)r)->val.len; if (HAWK_UNLIKELY(!r)) return -1;
for (i = 0; i < str.len; i++) str.ptr[i] = hawk_to_bch_lower(str.ptr[i]); str.ptr = ((hawk_val_mbs_t*)r)->val.ptr;
} str.len = ((hawk_val_mbs_t*)r)->val.len;
else for (i = 0; i < str.len; i++) str.ptr[i] = hawk_to_bch_lower(str.ptr[i]);
{ break;
hawk_oocs_t str; }
str.ptr = hawk_rtx_getvaloocstr(rtx, a0, &str.len);
if (!str.ptr) return -1; case HAWK_VAL_CHAR:
r = hawk_rtx_makestrvalwithoocs(rtx, &str); {
hawk_rtx_freevaloocstr (rtx, a0, str.ptr); hawk_ooch_t tmp = HAWK_RTX_GETCHARFROMVAL(rtx, a0);
if (!r) return -1; tmp = hawk_to_bch_lower(tmp);
str.ptr = ((hawk_val_str_t*)r)->val.ptr; r = hawk_rtx_makecharval(rtx, tmp);
str.len = ((hawk_val_str_t*)r)->val.len; if (HAWK_UNLIKELY(!r)) return -1;
for (i = 0; i < str.len; i++) str.ptr[i] = hawk_to_ooch_lower(str.ptr[i]); break;
}
default:
{
hawk_oocs_t str;
str.ptr = hawk_rtx_getvaloocstr(rtx, a0, &str.len);
if (!str.ptr) return -1;
r = hawk_rtx_makestrvalwithoocs(rtx, &str);
hawk_rtx_freevaloocstr (rtx, a0, str.ptr);
if (HAWK_UNLIKELY(!r)) return -1;
str.ptr = ((hawk_val_str_t*)r)->val.ptr;
str.len = ((hawk_val_str_t*)r)->val.len;
for (i = 0; i < str.len; i++) str.ptr[i] = hawk_to_ooch_lower(str.ptr[i]);
break;
}
} }
hawk_rtx_setretval (rtx, r); hawk_rtx_setretval (rtx, r);
return 0; return 0;
} }
@ -1048,30 +1064,46 @@ int hawk_fnc_toupper (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
hawk_val_t* a0, * r; hawk_val_t* a0, * r;
a0 = hawk_rtx_getarg(rtx, 0); a0 = hawk_rtx_getarg(rtx, 0);
if (HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MBS) switch (HAWK_RTX_GETVALTYPE(rtx, a0))
{ {
hawk_bcs_t str; case HAWK_VAL_MBS:
str.ptr = hawk_rtx_getvalbcstr(rtx, a0, &str.len); {
if (!str.ptr) return -1; hawk_bcs_t str;
r = hawk_rtx_makembsvalwithbcs(rtx, &str); str.ptr = hawk_rtx_getvalbcstr(rtx, a0, &str.len);
hawk_rtx_freevalbcstr (rtx, a0, str.ptr); if (!str.ptr) return -1;
if (!r) return -1; r = hawk_rtx_makembsvalwithbcs(rtx, &str);
str.ptr = ((hawk_val_mbs_t*)r)->val.ptr; hawk_rtx_freevalbcstr (rtx, a0, str.ptr);
str.len = ((hawk_val_mbs_t*)r)->val.len; if (HAWK_UNLIKELY(!r)) return -1;
for (i = 0; i < str.len; i++) str.ptr[i] = hawk_to_bch_upper(str.ptr[i]); str.ptr = ((hawk_val_mbs_t*)r)->val.ptr;
} str.len = ((hawk_val_mbs_t*)r)->val.len;
else for (i = 0; i < str.len; i++) str.ptr[i] = hawk_to_bch_upper(str.ptr[i]);
{ break;
hawk_oocs_t str; }
str.ptr = hawk_rtx_getvaloocstr(rtx, a0, &str.len);
if (!str.ptr) return -1; case HAWK_VAL_CHAR:
r = hawk_rtx_makestrvalwithoocs(rtx, &str); {
hawk_rtx_freevaloocstr (rtx, a0, str.ptr); hawk_ooch_t tmp = HAWK_RTX_GETCHARFROMVAL(rtx, a0);
if (!r) return -1; tmp = hawk_to_bch_upper(tmp);
str.ptr = ((hawk_val_str_t*)r)->val.ptr; r = hawk_rtx_makecharval(rtx, tmp);
str.len = ((hawk_val_str_t*)r)->val.len; if (HAWK_UNLIKELY(!r)) return -1;
for (i = 0; i < str.len; i++) str.ptr[i] = hawk_to_ooch_upper(str.ptr[i]); break;
}
default:
{
hawk_oocs_t str;
str.ptr = hawk_rtx_getvaloocstr(rtx, a0, &str.len);
if (!str.ptr) return -1;
r = hawk_rtx_makestrvalwithoocs(rtx, &str);
hawk_rtx_freevaloocstr (rtx, a0, str.ptr);
if (HAWK_UNLIKELY(!r)) return -1;
str.ptr = ((hawk_val_str_t*)r)->val.ptr;
str.len = ((hawk_val_str_t*)r)->val.len;
for (i = 0; i < str.len; i++) str.ptr[i] = hawk_to_ooch_upper(str.ptr[i]);
break;
}
} }
hawk_rtx_setretval (rtx, r); hawk_rtx_setretval (rtx, r);
return 0; return 0;
} }

View File

@ -450,7 +450,7 @@ static int fnc_tombs (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
{ {
hawk_bcs_t str; hawk_bcs_t str;
str.ptr = hawk_rtx_getvalbcstrwithcmgr(rtx, a0, &str.len, cmgr); str.ptr = hawk_rtx_getvalbcstrwithcmgr(rtx, a0, &str.len, cmgr);
if (!str.ptr) return -1; if (HAWK_UNLIKELY(!str.ptr)) return -1;
r = hawk_rtx_makembsvalwithbcs(rtx, &str); r = hawk_rtx_makembsvalwithbcs(rtx, &str);
hawk_rtx_freevalbcstr (rtx, a0, str.ptr); hawk_rtx_freevalbcstr (rtx, a0, str.ptr);
if (!r) return -1; if (!r) return -1;
@ -477,38 +477,67 @@ static int fnc_tonum (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
a0 = hawk_rtx_getarg(rtx, 0); a0 = hawk_rtx_getarg(rtx, 0);
if (HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MBS && hawk_rtx_getnargs(rtx) >= 2) if (hawk_rtx_getnargs(rtx) >= 2)
{ {
/* if the value is known to be a byte string, it supports the optional switch (HAWK_RTX_GETVALTYPE(rtx, a0))
* base parameter */ {
hawk_val_t* a1 = hawk_rtx_getarg(rtx, 1); case HAWK_VAL_MBS:
hawk_int_t base; {
/* if the value is known to be a byte string, it supports the optional
* base parameter */
hawk_val_t* a1 = hawk_rtx_getarg(rtx, 1);
hawk_int_t base;
if (hawk_rtx_valtoint(rtx, a1, &base) <= -1) return -1; if (hawk_rtx_valtoint(rtx, a1, &base) <= -1) return -1;
rx = hawk_bchars_to_num( rx = hawk_bchars_to_num(
HAWK_OOCHARS_TO_NUM_MAKE_OPTION(0, 0, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), base), HAWK_OOCHARS_TO_NUM_MAKE_OPTION(0, 0, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), base),
((hawk_val_mbs_t*)a0)->val.ptr, ((hawk_val_mbs_t*)a0)->val.ptr,
((hawk_val_mbs_t*)a0)->val.len, ((hawk_val_mbs_t*)a0)->val.len,
&lv, &rv &lv, &rv
); );
} break;
else if (HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_STR && hawk_rtx_getnargs(rtx) >= 2) }
{
/* if the value is known to be a string, it supports the optional
* base parameter */
hawk_val_t* a1 = hawk_rtx_getarg(rtx, 1);
hawk_int_t base;
if (hawk_rtx_valtoint(rtx, a1, &base) <= -1) return -1; case HAWK_VAL_CHAR:
rx = hawk_oochars_to_num( {
HAWK_OOCHARS_TO_NUM_MAKE_OPTION(0, 0, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), base), /* if the value is known to be a string, it supports the optional
((hawk_val_str_t*)a0)->val.ptr, * base parameter */
((hawk_val_str_t*)a0)->val.len, hawk_val_t* a1 = hawk_rtx_getarg(rtx, 1);
&lv, &rv hawk_int_t base;
); hawk_ooch_t tmp = HAWK_RTX_GETCHARFROMVAL(rtx, a0);
if (hawk_rtx_valtoint(rtx, a1, &base) <= -1) return -1;
rx = hawk_oochars_to_num(
HAWK_OOCHARS_TO_NUM_MAKE_OPTION(0, 0, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), base),
&tmp, 1, &lv, &rv
);
break;
}
case HAWK_VAL_STR:
{
/* if the value is known to be a string, it supports the optional
* base parameter */
hawk_val_t* a1 = hawk_rtx_getarg(rtx, 1);
hawk_int_t base;
if (hawk_rtx_valtoint(rtx, a1, &base) <= -1) return -1;
rx = hawk_oochars_to_num(
HAWK_OOCHARS_TO_NUM_MAKE_OPTION(0, 0, HAWK_RTX_IS_STRIPSTRSPC_ON(rtx), base),
((hawk_val_str_t*)a0)->val.ptr,
((hawk_val_str_t*)a0)->val.len,
&lv, &rv
);
break;
}
default:
goto val_to_num;
}
} }
else else
{ {
val_to_num:
rx = hawk_rtx_valtonum(rtx, a0, &lv, &rv); rx = hawk_rtx_valtonum(rtx, a0, &lv, &rv);
} }
@ -531,6 +560,60 @@ static int fnc_tonum (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
return 0; return 0;
} }
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;
int n;
nargs = hawk_rtx_getnargs(rtx);
HAWK_ASSERT (nargs >= 2 && nargs <= 3);
a0 = hawk_rtx_getarg(rtx, 0);
a1 = hawk_rtx_getarg(rtx, 1);
n = hawk_rtx_valtoint(rtx, a1, &lindex);
if (n <= -1) return -1;
lindex = lindex - 1;
if (HAWK_RTX_GETVALTYPE(rtx, a0) == HAWK_VAL_MBS)
{
hawk_bch_t* str;
hawk_oow_t len;
str = ((hawk_val_mbs_t*)a0)->val.ptr;
len = ((hawk_val_mbs_t*)a0)->val.len;
if (lindex >= 0 && lindex < (hawk_int_t)len)
r = hawk_rtx_makecharval(rtx, str[lindex]);
else
r = hawk_rtx_makenilval(rtx);
if (HAWK_UNLIKELY(!r)) return -1;
}
else
{
hawk_ooch_t* str;
hawk_oow_t len;
str = hawk_rtx_getvaloocstr(rtx, a0, &len);
if (!str) return -1;
if (lindex >= 0 && lindex < (hawk_int_t)len)
r = hawk_rtx_makecharval(rtx, str[lindex]);
else
r = hawk_rtx_makenilval(rtx);
hawk_rtx_freevaloocstr (rtx, a0, str);
if (HAWK_UNLIKELY(!r)) return -1;
}
hawk_rtx_setretval (rtx, r);
return 0;
}
typedef struct fnctab_t fnctab_t; typedef struct fnctab_t fnctab_t;
struct fnctab_t struct fnctab_t
{ {
@ -576,6 +659,7 @@ static fnctab_t fnctab[] =
{ HAWK_T("split"), { { 2, 3, HAWK_T("vrx") }, hawk_fnc_split, 0 } }, { HAWK_T("split"), { { 2, 3, HAWK_T("vrx") }, hawk_fnc_split, 0 } },
{ HAWK_T("splita"), { { 2, 3, HAWK_T("vrx") }, hawk_fnc_splita, 0 } }, /* split to array. asplit is not a good name for this */ { HAWK_T("splita"), { { 2, 3, HAWK_T("vrx") }, hawk_fnc_splita, 0 } }, /* split to array. asplit is not a good name for this */
{ HAWK_T("sub"), { { 2, 3, HAWK_T("xvr") }, hawk_fnc_sub, 0 } }, { HAWK_T("sub"), { { 2, 3, HAWK_T("xvr") }, hawk_fnc_sub, 0 } },
{ HAWK_T("subchar"), { { 2, 2, HAWK_NULL }, fnc_subchar, 0 } },
{ HAWK_T("substr"), { { 2, 3, HAWK_NULL }, hawk_fnc_substr, 0 } }, { HAWK_T("substr"), { { 2, 3, HAWK_NULL }, hawk_fnc_substr, 0 } },
{ HAWK_T("tocharcode"), { { 1, 2, HAWK_NULL }, fnc_tocharcode, 0 } }, { HAWK_T("tocharcode"), { { 1, 2, HAWK_NULL }, fnc_tocharcode, 0 } },
{ HAWK_T("tolower"), { { 1, 1, HAWK_NULL }, hawk_fnc_tolower, 0 } }, { HAWK_T("tolower"), { { 1, 1, HAWK_NULL }, hawk_fnc_tolower, 0 } },

View File

@ -33,6 +33,12 @@ function main()
ensure (x, "x\\y", @SCRIPTNAME, @SCRIPTLINE); ensure (x, "x\\y", @SCRIPTNAME, @SCRIPTLINE);
ensure (y, "xAy", @SCRIPTNAME, @SCRIPTLINE); ensure (y, "xAy", @SCRIPTNAME, @SCRIPTLINE);
x = y = "x\\y";
gsub(/\\\\/, 'A', x);
gsub("\\\\", 'A', y);
ensure (x, "x\\y", @SCRIPTNAME, @SCRIPTLINE);
ensure (y, "xAy", @SCRIPTNAME, @SCRIPTLINE);
x = y = "x\\\\y"; x = y = "x\\\\y";
gsub(/\\\\/, "A", x); gsub(/\\\\/, "A", x);
gsub("\\\\", "A", y); gsub("\\\\", "A", y);
@ -275,6 +281,28 @@ function main()
ensure (substr(1000+5000, 2) === "000", 1, @SCRIPTNAME, @SCRIPTLINE); ensure (substr(1000+5000, 2) === "000", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (substr(1000+10000, 2) === "1000", 1, @SCRIPTNAME, @SCRIPTLINE); ensure (substr(1000+10000, 2) === "1000", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (substr(1000+5000, 2) === "000", 1, @SCRIPTNAME, @SCRIPTLINE); ensure (substr(1000+5000, 2) === "000", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::subchar("abc", -1) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar("abc", 0) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar("abc", 1) === 'a', 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar("abc", 2) === 'b', 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar("abc", 3) === 'c', 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar("abc", 4) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar("☕⛄", -1) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar("☕⛄", 0) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar("☕⛄", 1) === '☕', 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar("☕⛄", 2) === '⛄', 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar("☕⛄", 3) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar("☕⛄", 4) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar(@b"abc", -1) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar(@b"abc", 0) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar(@b"abc", 1) === 'a', 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar(@b"abc", 2) === 'b', 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar(@b"abc", 3) === 'c', 1, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::subchar(@b"abc", 4) === @nil, 1, @SCRIPTNAME, @SCRIPTNAME);
} }
@ -348,6 +376,49 @@ function main()
} }
{
## character class functions in the str modules
ensure (str::isalnum('a'), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isalpha('a'), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isblank('a'), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::iscntrl('a'), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isdigit('a'), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isgraph('a'), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::islower('a'), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isprint('a'), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::ispunct('a'), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isspace('a'), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isupper('a'), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isxdigit('a'), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::toupper('a') === 'A', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::tolower('A') === 'a', 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isalnum("a"), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isalpha("a"), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isblank("a"), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::iscntrl("a"), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isdigit("a"), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isgraph("a"), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::islower("a"), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isprint("a"), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::ispunct("a"), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isspace("a"), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isupper("a"), 0, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::isxdigit("a"), 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::toupper("abc") === "ABC", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::tolower("ABC") === "abc", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::toupper(@b"abc") === @b"ABC", 1, @SCRIPTNAME, @SCRIPTLINE);
ensure (str::tolower(@b"ABC") === @b"abc", 1, @SCRIPTNAME, @SCRIPTLINE);
}
{
ensure (str::tocharcode(str::fromcharcode('2')), 2, @SCRIPTNAME, @SCRIPTNAME);
ensure (str::tonum('a', 16), 10, @SCRIPTNAME, @SCRIPTNAME);
}
print "SUCCESS"; print "SUCCESS";
} }