diff --git a/mod/str.c b/mod/str.c index 6d0ef7f..bfe4a40 100644 --- a/mod/str.c +++ b/mod/str.c @@ -122,12 +122,54 @@ static hcl_pfrc_t pf_str_length (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) return HCL_PF_SUCCESS; } +static hcl_pfrc_t pf_str_substr (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) +{ + hcl_oop_t str, substr, a1, a2; + hcl_ooi_t size; + hcl_ooi_t pos; + hcl_ooi_t len; + + str = HCL_STACK_GETARG(hcl, nargs, 0); + a1 = HCL_STACK_GETARG(hcl, nargs, 1); + a2 = HCL_STACK_GETARG(hcl, nargs, 2); + + if (!HCL_IS_STRING(hcl, str)) + { + hcl_seterrbfmt (hcl, HCL_EINVAL, "parameter not string - %O", str); + return HCL_PF_FAILURE; + } + if (!HCL_OOP_IS_SMOOI(a1)) + { + hcl_seterrbfmt (hcl, HCL_EINVAL, "position not numeric - %O", a1); + return HCL_PF_FAILURE; + } + if (!HCL_OOP_IS_SMOOI(a2)) + { + hcl_seterrbfmt (hcl, HCL_EINVAL, "length not string - %O", a2); + return HCL_PF_FAILURE; + } + + size = HCL_OBJ_GET_SIZE(str); + pos = HCL_OOP_TO_SMOOI(a1); + len = HCL_OOP_TO_SMOOI(a2); + + if (pos < 0) pos = 0; + else if (pos >= size) pos = size; + if (len >= size - pos) len = size - pos; + substr = hcl_makestring(hcl, HCL_OBJ_GET_CHAR_PTR(str, pos), len, 0); + if (HCL_UNLIKELY(!substr)) return HCL_PF_FAILURE; + + HCL_STACK_SETRET (hcl, nargs, substr); + return HCL_PF_SUCCESS; +} + static hcl_pfinfo_t pfinfos[] = { /*{ { 'V','A','R','\0' }, { HCL_PFBASE_VAR, HCL_NULL, 0, 0 } },*/ { { 'a','t','\0' }, { HCL_PFBASE_FUNC, pf_str_at, 2, 2 } }, { { 'a','t','P','u','t','\0' }, { HCL_PFBASE_FUNC, pf_str_at_put, 3, 3 } }, - { { 'l','e','n','g','t','h','\0' }, { HCL_PFBASE_FUNC, pf_str_length, 1, 1 } } + { { 'l','e','n','g','t','h','\0' }, { HCL_PFBASE_FUNC, pf_str_length, 1, 1 } }, + { { 's','u','b','s','t','r'}, { HCL_PFBASE_FUNC, pf_str_substr, 3, 3 } } }; /* ------------------------------------------------------------------------ */