diff --git a/applications/system/js_app/examples/apps/Scripts/stringutils.js b/applications/system/js_app/examples/apps/Scripts/stringutils.js new file mode 100644 index 000000000..2191e2518 --- /dev/null +++ b/applications/system/js_app/examples/apps/Scripts/stringutils.js @@ -0,0 +1,19 @@ +let sampleText = "Hello, World!"; + +let lengthOfText = "Length of text: " + to_string(StringUtils.GetLength(sampleText)); +print(lengthOfText); + +let start = 7; +let end = 12; +let substringResult = StringUtils.substring(sampleText, start, end); +print(substringResult); + +let searchStr = "World"; +let result2 = to_string(StringUtils.indexOf(sampleText, searchStr)); +print(result2); + +let upperCaseText = "Text in upper case: " + StringUtils.toUpperCase(sampleText); +print(upperCaseText); + +let lowerCaseText = "Text in lower case: " + StringUtils.toLowerCase(sampleText); +print(lowerCaseText); diff --git a/applications/system/js_app/js_thread.c b/applications/system/js_app/js_thread.c index 5ca365404..003d8239b 100644 --- a/applications/system/js_app/js_thread.c +++ b/applications/system/js_app/js_thread.c @@ -8,6 +8,7 @@ #include "js_thread.h" #include "js_thread_i.h" #include "js_modules.h" +#include "modules/js_string.h" #define TAG "JS" @@ -202,6 +203,40 @@ static void js_global_to_string(struct mjs* mjs) { mjs_return(mjs, ret); } +static void js_parse_int(struct mjs* mjs) { + mjs_val_t arg = mjs_arg(mjs, 0); + size_t str_len; + const char* str = NULL; + if(mjs_is_string(arg)) { + str = mjs_get_string(mjs, &arg, &str_len); + } else { + mjs_return(mjs, mjs_mk_number(mjs, 0)); + return; + } + + int num = 0; + int sign = 1; + size_t i = 0; + + if(str[0] == '-') { + sign = -1; + i = 1; + } else if(str[0] == '+') { + i = 1; + } + + for(; i < str_len; i++) { + if(str[i] >= '0' && str[i] <= '9') { + num = num * 10 + (str[i] - '0'); + } else { + break; + } + } + num *= sign; + + mjs_return(mjs, mjs_mk_number(mjs, num)); +} + static void js_global_to_hex_string(struct mjs* mjs) { double num = mjs_get_int(mjs, mjs_arg(mjs, 0)); char tmp_str[] = "-FFFFFFFF"; @@ -237,12 +272,16 @@ static int32_t js_thread(void* arg) { struct mjs* mjs = mjs_create(worker); worker->modules = js_modules_create(mjs, worker->resolver); mjs_val_t global = mjs_get_global(mjs); + mjs_set(mjs, global, "print", ~0, MJS_MK_FN(js_print)); mjs_set(mjs, global, "delay", ~0, MJS_MK_FN(js_delay)); mjs_set(mjs, global, "to_string", ~0, MJS_MK_FN(js_global_to_string)); mjs_set(mjs, global, "to_hex_string", ~0, MJS_MK_FN(js_global_to_hex_string)); mjs_set(mjs, global, "ffi_address", ~0, MJS_MK_FN(js_ffi_address)); mjs_set(mjs, global, "require", ~0, MJS_MK_FN(js_require)); + mjs_set(mjs, global, "parseint", ~0, MJS_MK_FN(js_parse_int)); + + string_utils_init(mjs); mjs_val_t console_obj = mjs_mk_object(mjs); mjs_set(mjs, console_obj, "log", ~0, MJS_MK_FN(js_console_log)); diff --git a/applications/system/js_app/modules/js_string.h b/applications/system/js_app/modules/js_string.h new file mode 100644 index 000000000..e7dbf8454 --- /dev/null +++ b/applications/system/js_app/modules/js_string.h @@ -0,0 +1,150 @@ +#include "../js_modules.h" + +static void js_string_substring(struct mjs* mjs) { + mjs_val_t arg0 = mjs_arg(mjs, 0); + mjs_val_t arg1 = mjs_arg(mjs, 1); + mjs_val_t arg2 = mjs_arg(mjs, 2); + + size_t str_len; + const char* str = NULL; + if(mjs_is_string(arg0)) { + str = mjs_get_string(mjs, &arg0, &str_len); + } else { + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + size_t start = mjs_is_number(arg1) ? (size_t)mjs_get_int(mjs, arg1) : (size_t)-1; + size_t end = mjs_is_number(arg2) ? (size_t)mjs_get_int(mjs, arg2) : (size_t)str_len; + + if((int)start < 0 || end > str_len || start > end) { + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + mjs_val_t substr_obj = mjs_mk_string(mjs, str + start, end - start, 1); + mjs_return(mjs, substr_obj); +} + +static void js_string_get_length(struct mjs* mjs) { + mjs_val_t arg0 = mjs_arg(mjs, 0); + size_t str_len; + if(mjs_is_string(arg0)) { + const char* str = mjs_get_string(mjs, &arg0, &str_len); + UNUSED(str); + mjs_return(mjs, mjs_mk_number(mjs, str_len)); + } else { + mjs_return(mjs, MJS_UNDEFINED); + } +} + +static void js_string_slice(struct mjs* mjs) { + mjs_val_t arg0 = mjs_arg(mjs, 0); + mjs_val_t arg1 = mjs_arg(mjs, 1); + mjs_val_t arg2 = mjs_arg(mjs, 2); + + size_t str_len; + const char* str = NULL; + if(mjs_is_string(arg0)) { + str = mjs_get_string(mjs, &arg0, &str_len); + } else { + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + int start = mjs_is_number(arg1) ? mjs_get_int(mjs, arg1) : 0; + int end = mjs_is_number(arg2) ? mjs_get_int(mjs, arg2) : (int)str_len; + + if(start < 0) start = (int)str_len + start < 0 ? 0 : (int)str_len + start; + if(end < 0) end = (int)str_len + end < 0 ? 0 : (int)str_len + end; + start = start > (int)str_len ? (int)str_len : start; + end = end > (int)str_len ? (int)str_len : end; + + if(end < start) end = start; + + mjs_val_t resultStr = mjs_mk_string(mjs, str + start, end - start, 1); + mjs_return(mjs, resultStr); +} + +static void js_string_index_of(struct mjs* mjs) { + mjs_val_t arg0 = mjs_arg(mjs, 0); + mjs_val_t arg1 = mjs_arg(mjs, 1); + + size_t str_len; + const char* str = NULL; + if(mjs_is_string(arg0)) { + str = mjs_get_string(mjs, &arg0, &str_len); + } else { + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + const char* searchValue = NULL; + if(mjs_is_string(arg1)) { + searchValue = mjs_get_string(mjs, &arg1, NULL); + } else { + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + char* found = strstr(str, searchValue); + int position = found ? (int)(found - str) : -1; + + mjs_return(mjs, mjs_mk_number(mjs, position)); +} + +static void js_string_to_upper_case(struct mjs* mjs) { + mjs_val_t arg0 = mjs_arg(mjs, 0); + + size_t str_len; + const char* str = NULL; + if(mjs_is_string(arg0)) { + str = mjs_get_string(mjs, &arg0, &str_len); + } else { + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + char* upperStr = strdup(str); + for(size_t i = 0; i < str_len; i++) { + upperStr[i] = toupper(upperStr[i]); + } + + mjs_val_t resultStr = mjs_mk_string(mjs, upperStr, str_len, 1); + free(upperStr); + mjs_return(mjs, resultStr); +} + +static void js_string_to_lower_case(struct mjs* mjs) { + mjs_val_t arg0 = mjs_arg(mjs, 0); + + size_t str_len; + const char* str = NULL; + if(mjs_is_string(arg0)) { + str = mjs_get_string(mjs, &arg0, &str_len); + } else { + mjs_return(mjs, MJS_UNDEFINED); + return; + } + + char* lowerStr = strdup(str); + for(size_t i = 0; i < str_len; i++) { + lowerStr[i] = tolower(lowerStr[i]); + } + + mjs_val_t resultStr = mjs_mk_string(mjs, lowerStr, str_len, 1); + free(lowerStr); + mjs_return(mjs, resultStr); +} + +static void string_utils_init(struct mjs* mjs) { + mjs_val_t string_utils_obj = mjs_mk_object(mjs); + mjs_set(mjs, string_utils_obj, "substring", ~0, MJS_MK_FN(js_string_substring)); + mjs_set(mjs, string_utils_obj, "slice", ~0, MJS_MK_FN(js_string_slice)); + mjs_set(mjs, string_utils_obj, "indexOf", ~0, MJS_MK_FN(js_string_index_of)); + mjs_set(mjs, string_utils_obj, "toUpperCase", ~0, MJS_MK_FN(js_string_to_upper_case)); + mjs_set(mjs, string_utils_obj, "toLowerCase", ~0, MJS_MK_FN(js_string_to_lower_case)); + mjs_set(mjs, string_utils_obj, "GetLength", ~0, MJS_MK_FN(js_string_get_length)); + mjs_val_t global = mjs_get_global(mjs); + mjs_set(mjs, global, "StringUtils", ~0, string_utils_obj); +} \ No newline at end of file