From 71fbdd0b19b8a46cc496da3128c0f44af745c3a9 Mon Sep 17 00:00:00 2001 From: sunyaozu Date: Mon, 28 Mar 2022 17:58:10 +0800 Subject: [PATCH] achieve lowercase and uppercase with locale Signed-off-by: sunyaozu --- BUILD.gn | 9 ++++- quickjs.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 119 insertions(+), 3 deletions(-) diff --git a/BUILD.gn b/BUILD.gn index 2e13ebb..f7b7c74 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -25,7 +25,10 @@ config("qjs_inner_config") { "-Os", "-fsigned-char", ] - include_dirs = [ "." ] + include_dirs = [ + ".", + "//third_party/icu/icu4c/source/common", + ] } config("qjs_debug_config") { @@ -49,6 +52,7 @@ ohos_static_library("qjs_debugger") { "debugger.c", "message_server.cpp", ] + deps = [ "//third_party/icu/icu4c:shared_icuuc" ] external_deps = [] if (!is_wearable_product) { external_deps += [ "utils_base:utils" ] @@ -65,6 +69,7 @@ ohos_static_library("qjs_debugger") { ohos_static_library("qjs") { sources = qjs_sources configs = [ ":qjs_inner_config" ] + deps = [ "//third_party/icu/icu4c:shared_icuuc" ] } ohos_executable("qjsc") { @@ -88,6 +93,8 @@ ohos_executable("qjsc") { libs = [ "pthread" ] } + deps = [ "//third_party/icu/icu4c:shared_icuuc" ] + subsystem_name = "ace" part_name = "ace_engine_full" } diff --git a/quickjs.c b/quickjs.c index 3bc2c38..5f31aa0 100644 --- a/quickjs.c +++ b/quickjs.c @@ -43,6 +43,7 @@ #include "list.h" #include "quickjs.h" #include "libregexp.h" +#include "unicode/ustring.h" #ifdef ENABLE_JS_DEBUG #include "debugger.h" #endif @@ -3573,6 +3574,11 @@ static inline int string_buffer_init(JSContext *ctx, StringBuffer *s, int size) return string_buffer_init2(ctx, s, size, 0); } +static inline int string_buffer_init_uint16_t(JSContext *ctx, StringBuffer *s, int size) +{ + return string_buffer_init2(ctx, s, size, 1); +} + static void string_buffer_free(StringBuffer *s) { js_free(s->ctx, s->str); @@ -41273,6 +41279,109 @@ static JSValue js_string_toLowerCase(JSContext *ctx, JSValueConst this_val, return JS_EXCEPTION; } +static UChar *get_src(JSContext *ctx, JSString *p) +{ + UChar *src; + int32_t i; + src = (UChar *) js_malloc(ctx, p->len * sizeof(UChar)); + if (p->is_wide_char) { + for (i = 0; i < p->len; i++) { + src[i] = (UChar) p->u.str16[i]; + } + } else { + for (i = 0; i < p->len; i++) { + src[i] = (UChar) p->u.str8[i]; + } + } + return src; +} + +static char *get_locale(JSContext *ctx, JSString *locale_p) +{ + char *locale; + int32_t i; + locale = (char *) js_malloc(ctx, (locale_p->len + 1) * sizeof(char)); + if (locale_p->is_wide_char) { + for (i = 0; i < locale_p->len; i++) { + locale[i] = (char) locale_p->u.str16[i]; + } + } else { + for (i = 0; i < locale_p->len; i++) { + locale[i] = (char) locale_p->u.str8[i]; + } + } + locale[locale_p->len] = '\0'; + return locale; +} + +static UChar *toLocaleLowerCase(JSContext *ctx, UChar *src, int32_t src_len, int to_lower, + char *locale, int32_t *res_len, UErrorCode *status) +{ + UChar *dest; + int32_t dest_len; + *status = U_ZERO_ERROR; + if (to_lower) + dest_len = u_strToLower(NULL, 0, src, src_len, locale, status); + else + dest_len = u_strToUpper(NULL, 0, src, src_len, locale, status); + *res_len = dest_len; + if (*status == U_BUFFER_OVERFLOW_ERROR) + *status = U_ZERO_ERROR; + dest = (UChar *) js_malloc(ctx, dest_len * sizeof(UChar)); + if (to_lower) + u_strToLower(dest, dest_len, src, src_len, locale, status); + else + u_strToUpper(dest, dest_len, src, src_len, locale, status); + return dest; +} + +static JSValue js_string_toLocaleLowerCase(JSContext *ctx, JSValueConst this_val, + int argc, JSValueConst *argv, int to_lower) +{ + JSValue val, locale_val; + JSString *p, *locale_p; + StringBuffer b_s, *b = &b_s; + UChar *src, *dest; + char *locale; + int32_t dest_len, i; + UErrorCode status; + + val = JS_ToStringCheckObject(ctx, this_val); + if (JS_IsException(val)) + return val; + p = JS_VALUE_GET_STRING(val); + if (p->len == 0 || argc == 0) + return val; + locale_val = JS_ToStringCheckObject(ctx, argv[0]); + if (JS_IsException(locale_val)) + return val; + locale_p = JS_VALUE_GET_STRING(locale_val); + locale = get_locale(ctx, locale_p); + src = get_src(ctx, p); + dest = toLocaleLowerCase(ctx, src, p->len, to_lower, locale, &dest_len, &status); + + if (U_FAILURE(status) || string_buffer_init(ctx, b, dest_len)) + goto fail; + for (i = 0; i < dest_len; i++) { + if (string_buffer_putc(b, dest[i])) + goto fail; + } + JS_FreeValue(ctx, val); + JS_FreeValue(ctx, locale_val); + js_free(ctx, src); + js_free(ctx, dest); + js_free(ctx, locale); + return string_buffer_end(b); +fail: + JS_FreeValue(ctx, val); + JS_FreeValue(ctx, locale_val); + js_free(ctx, src); + js_free(ctx, dest); + js_free(ctx, locale); + string_buffer_free(b); + return JS_EXCEPTION; +} + #ifdef CONFIG_ALL_UNICODE /* return (-1, NULL) if exception, otherwise (len, buf) */ @@ -41581,8 +41690,8 @@ static const JSCFunctionListEntry js_string_proto_funcs[] = { JS_CFUNC_DEF("localeCompare", 1, js_string_localeCompare ), JS_CFUNC_MAGIC_DEF("toLowerCase", 0, js_string_toLowerCase, 1 ), JS_CFUNC_MAGIC_DEF("toUpperCase", 0, js_string_toLowerCase, 0 ), - JS_CFUNC_MAGIC_DEF("toLocaleLowerCase", 0, js_string_toLowerCase, 1 ), - JS_CFUNC_MAGIC_DEF("toLocaleUpperCase", 0, js_string_toLowerCase, 0 ), + JS_CFUNC_MAGIC_DEF("toLocaleLowerCase", 0, js_string_toLocaleLowerCase, 1 ), + JS_CFUNC_MAGIC_DEF("toLocaleUpperCase", 0, js_string_toLocaleLowerCase, 0 ), JS_CFUNC_MAGIC_DEF("[Symbol.iterator]", 0, js_create_array_iterator, JS_ITERATOR_KIND_VALUE | 4 ), /* ES6 Annex B 2.3.2 etc. */ JS_CFUNC_MAGIC_DEF("anchor", 1, js_string_CreateHTML, magic_string_anchor ), -- Gitee