Berry add `string.starstwith`, `string.endswith` and `%q` format ()

* Berry add `string.starstwith`, `string.endswith` and `%q` format

* Fix typo

---------

Co-authored-by: Jason2866 <24528715+Jason2866@users.noreply.github.com>
This commit is contained in:
s-hadinger 2024-03-10 14:31:15 +01:00 committed by GitHub
parent 224a9fb717
commit bb07ded475
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 111 additions and 0 deletions
CHANGELOG.md
lib/libesp32/berry

View File

@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
- HASPmota support for spangroup (styled text) (#20852)
- HASPmota support for led (#20857)
- HASPmota improve arc and img (#20894)
- Berry add `string.starstwith`, `string.endswith` and `%q` format
### Breaking Changed
- Drop support for old (insecure) fingerprint format (#20842)

View File

@ -669,6 +669,17 @@ int be_str_format(bvm *vm)
}
break;
}
case 'q': {
const char *s = be_toescape(vm, index, 'q');
int len = be_strlen(vm, index);
if (len > 100 && strlen(mode) == 2) {
be_pushvalue(vm, index);
} else {
snprintf(buf, sizeof(buf), "%s", s);
be_pushstring(vm, buf);
}
break;
}
default: /* error */
be_raise(vm, "runtime_error", be_pushfstring(vm,
"invalid option '%%%c' to 'format'", *p));
@ -940,6 +951,60 @@ static int str_escape(bvm *vm)
be_return_nil(vm);
}
static int str_startswith(bvm *vm)
{
int top = be_top(vm);
if (top >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) {
bbool case_insensitive = bfalse;
if (top >= 3 && be_isbool(vm, 3)) {
case_insensitive = be_tobool(vm, 3);
}
bbool result = bfalse;
const char *s = be_tostring(vm, 1);
const char *p = be_tostring(vm, 2);
size_t len = (size_t)be_strlen(vm, 2);
if (case_insensitive) {
if (strncasecmp(s, p, len) == 0) {
result = btrue;
}
} else {
if (strncmp(s, p, len) == 0) {
result = btrue;
}
}
be_pushbool(vm, result);
be_return(vm);
}
be_return_nil(vm);
}
static int str_endswith(bvm *vm)
{
int top = be_top(vm);
if (top >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) {
bbool case_insensitive = bfalse;
if (top >= 3 && be_isbool(vm, 3)) {
case_insensitive = be_tobool(vm, 3);
}
bbool result = bfalse;
const char *s = be_tostring(vm, 1);
const char *p = be_tostring(vm, 2);
size_t len = (size_t)be_strlen(vm, 2);
if (case_insensitive) {
if (strncasecmp(s + (int)strlen(s) - (int)len, p, len) == 0) {
result = btrue;
}
} else {
if (strncmp(s + (int)strlen(s) - (int)len, p, len) == 0) {
result = btrue;
}
}
be_pushbool(vm, result);
be_return(vm);
}
be_return_nil(vm);
}
#if !BE_USE_PRECOMPILED_OBJECT
be_native_module_attr_table(string) {
be_native_module_function("format", be_str_format),
@ -954,6 +1019,8 @@ be_native_module_attr_table(string) {
be_native_module_function("tr", str_tr),
be_native_module_function("escape", str_escape),
be_native_module_function("replace", str_replace),
be_native_module_function("startswith", str_startswith),
be_native_module_function("endswith", str_endswith),
};
be_define_native_module(string, NULL);
@ -972,6 +1039,8 @@ module string (scope: global, depend: BE_USE_STRING_MODULE) {
tr, func(str_tr)
escape, func(str_escape)
replace, func(str_replace)
startswith, func(str_startswith)
endswith, func(str_endswith)
}
@const_object_info_end */
#include "../generate/be_fixed_string.h"

View File

@ -147,6 +147,8 @@ assert(string.format("%s", nil) == 'nil')
assert(string.format("%s", true) == 'true')
assert(string.format("%s", false) == 'false')
assert(string.format("%q", "\ntest") == '\'\\ntest\'')
# format is now synonym to string.format
assert(format == string.format)
assert(format("%.1f", 3) == '3.0')
@ -169,3 +171,42 @@ var a = 'foobar{0}'
assert(f"S = {a}" == 'S = foobar{0}')
assert(f"S = {a:i}" == 'S = 0')
assert(f"{a=}" == 'a=foobar{0}')
# startswith case sensitive
assert(string.startswith("", "") == true)
assert(string.startswith("qwerty", "qw") == true)
assert(string.startswith("qwerty", "qwerty") == true)
assert(string.startswith("qwerty", "") == true)
assert(string.startswith("qwerty", "qW") == false)
assert(string.startswith("qwerty", "QW") == false)
assert(string.startswith("qwerty", "qz") == false)
assert(string.startswith("qwerty", "qwertyw") == false)
# startswith case insensitive
assert(string.startswith("qwerty", "qw", true) == true)
assert(string.startswith("qwerty", "qwerty", true) == true)
assert(string.startswith("qwerty", "", true) == true)
assert(string.startswith("qwerty", "qW", true) == true)
assert(string.startswith("qwerty", "QW", true) == true)
assert(string.startswith("qwerty", "qz", true) == false)
assert(string.startswith("qwerty", "qwertyw", true) == false)
# endswith case sensitive
assert(string.endswith("", "") == true)
assert(string.endswith("qwerty", "ty") == true)
assert(string.endswith("qwerty", "qwerty") == true)
assert(string.endswith("qwerty", "") == true)
assert(string.endswith("qwerty", "tY") == false)
assert(string.endswith("qwerty", "TY") == false)
assert(string.endswith("qwerty", "tr") == false)
assert(string.endswith("qwerty", "qwertyw") == false)
# endswith case insensitive
assert(string.endswith("", "", true) == true)
assert(string.endswith("qwerty", "ty", true) == true)
assert(string.endswith("qwerty", "qwerty", true) == true)
assert(string.endswith("qwerty", "", true) == true)
assert(string.endswith("qwerty", "tY", true) == true)
assert(string.endswith("qwerty", "TY", true) == true)
assert(string.endswith("qwerty", "tr", true) == false)
assert(string.endswith("qwerty", "qwertyw", true) == false)