From 72c9b4470dd4232da5639e72de73bc1fbfa98460 Mon Sep 17 00:00:00 2001 From: xliu Date: Fri, 20 Aug 2021 09:53:53 +0800 Subject: [PATCH] add textdecoder and textencoder Signed-off-by: xliu Change-Id: I8df05485d71536165df3e73d4f0fc12783575dc7 --- LICENSE | 177 +++++++++++++++++ ohos.build | 16 ++ textcoder/BUILD.gn | 47 +++++ textcoder/js_textdecoder.cpp | 179 +++++++++++++++++ textcoder/js_textdecoder.h | 88 +++++++++ textcoder/js_textencoder.cpp | 94 +++++++++ textcoder/js_textencoder.h | 39 ++++ textcoder/native_module_util.cpp | 326 +++++++++++++++++++++++++++++++ 8 files changed, 966 insertions(+) create mode 100755 LICENSE create mode 100755 ohos.build create mode 100755 textcoder/BUILD.gn create mode 100755 textcoder/js_textdecoder.cpp create mode 100755 textcoder/js_textdecoder.h create mode 100755 textcoder/js_textencoder.cpp create mode 100755 textcoder/js_textencoder.h create mode 100755 textcoder/native_module_util.cpp diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..f433b1a --- /dev/null +++ b/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/ohos.build b/ohos.build new file mode 100755 index 0000000..9683641 --- /dev/null +++ b/ohos.build @@ -0,0 +1,16 @@ +{ + "subsystem": "ccruntime", + "parts": { + "jsapi_util": { + "variants": [ + "wearable", + "phone" + ], + "module_list": [ + "//base/compileruntime/js_util_module/textcoder:util" + ], + "test_list": [ + ] + } + } +} diff --git a/textcoder/BUILD.gn b/textcoder/BUILD.gn new file mode 100755 index 0000000..03e5cbe --- /dev/null +++ b/textcoder/BUILD.gn @@ -0,0 +1,47 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#import("//ark/runtime/ark_config.gni") +import("//build/ohos.gni") +ohos_shared_library("util") { + include_dirs = [ + "//foundation/ace/napi", + "//foundation/ace/napi/native_engine", + "//third_party/icu/icu4c/source/common", + "//third_party/node/src", + "//foundation/ace/napi/interfaces/kits", + "//base/compileruntime/js_util_module/textcoder", + ] + + sources = [ + "js_textdecoder.cpp", + "js_textencoder.cpp", + "native_module_util.cpp", + ] + + deps = [ + "//foundation/ace/napi:ace_napi", + "//foundation/ace/napi:ace_napi_quickjs", + "//third_party/icu/icu4c:static_icuuc", + "//utils/native/base:utils", + ] + if (is_standard_system) { + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + } else { + external_deps = [ "hilog:libhilog" ] + } + subsystem_name = "ccruntime" + part_name = "jsapi_util" + + relative_install_dir = "module" +} diff --git a/textcoder/js_textdecoder.cpp b/textcoder/js_textdecoder.cpp new file mode 100755 index 0000000..c059f1e --- /dev/null +++ b/textcoder/js_textdecoder.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js_textdecoder.h" +#include +#include +#include +#include +#include +#include +#include "utils/log.h" +#include "unicode/unistr.h" +#include "securec.h" + +TextDecoder::TextDecoder(napi_env env, std::string buff, std::vector optionVec) + : env_(env), label_(0), encStr_(buff), tranTool_(nullptr, nullptr) +{ + uint32_t i32Flag = 0; + if (optionVec.size() == 2) { // 2:Meaning of optionVec size 2 + if (optionVec[0] >= 0 && optionVec[1] >= 0) { + i32Flag |= optionVec[0] ? FATAL_FLG : 0; + i32Flag |= optionVec[1] ? IGNORE_BOM_FLG : 0; + } else if (optionVec[0] >= 0 && optionVec[1] < 0) { + i32Flag |= optionVec[0] ? FATAL_FLG : 0; + } else if (optionVec[0] < 0 && optionVec[1] >= 0) { + i32Flag |= optionVec[1] ? IGNORE_BOM_FLG : 0; + } + } + label_ = i32Flag; + bool fatal = + (i32Flag & FATAL_FLG) == FATAL_FLG; + UErrorCode codeflag = U_ZERO_ERROR; + char* pStr = const_cast(encStr_.c_str()); + UConverter* conv = ucnv_open(pStr, &codeflag); + if (U_FAILURE(codeflag)) { + HILOG_ERROR("ucnv_open failed !"); + return; + } + if (fatal) { + codeflag = U_ZERO_ERROR; + ucnv_setToUCallBack(conv, UCNV_TO_U_CALLBACK_STOP, nullptr, nullptr, nullptr, &codeflag); + } + TransformToolPointer tempTranTool(conv, ConverterClose); + tranTool_ = std::move(tempTranTool); +} + +napi_value TextDecoder::Decode(napi_value src, bool iflag) +{ + uint32_t flags = 0; + flags |= iflag ? 0 : FLUSH_FLG; + UBool flush = ((flags & FLUSH_FLG)) == FLUSH_FLG; + napi_typedarray_type type; + size_t length = 0; + void* data1 = nullptr; + napi_value arrayBuffer = nullptr; + size_t byteOffset = 0; + NAPI_CALL(env_, napi_get_typedarray_info(env_, src, &type, &length, &data1, &arrayBuffer, &byteOffset)); + const char* source = static_cast(data1); + size_t sourceLength = length; + UErrorCode codeflag = U_ZERO_ERROR; + size_t limit = GetMinByteSize() * sourceLength; + size_t len = limit * sizeof(UChar); + UChar* arr = nullptr; + if (limit > 0) { + arr = new UChar[limit + 1]; + if (memset_s(arr, len + sizeof(UChar), 0x0, len + sizeof(UChar)) != 0) { + HILOG_ERROR("decode arr memset_s failed"); + if (arr != nullptr) { + delete[] arr; + arr = nullptr; + } + return nullptr; + } + } else { + HILOG_ERROR("limit is error"); + return nullptr; + } + UChar* target = arr; + size_t tarStartPos = (intptr_t)arr; + ucnv_toUnicode(GetConverterPtr(), &target, target + len, &source, source + sourceLength, nullptr, flush, &codeflag); + size_t resultLength = 0; + bool omitInitialBom = false; + if (U_SUCCESS(codeflag)) { + if (limit > 0) { + resultLength = (intptr_t)target - tarStartPos; + if (resultLength > 0 && IsUnicode() && !IsIgnoreBom() && !IsBomFlag()) { + if (arr[0] == 0xFEFF) { + omitInitialBom = true; + } + label_ |= BOM_SEEN_FLG; + } + } + } + UChar* arrDat = arr; + if (omitInitialBom && resultLength > 0) { + arrDat = &arr[2]; // 2: Obtains the 2 value of the array. + } + std::u16string tempStr16(arrDat); + std::string tepStr = std::wstring_convert< std::codecvt_utf8_utf16, char16_t > {}.to_bytes(tempStr16); + const char* tempCh = tepStr.c_str(); + char* rstCh = const_cast(tempCh); + napi_value resultStr = nullptr; + HILOG_ERROR("textcoder strlen(rstCh): %{public}d", strlen(rstCh)); + NAPI_CALL(env_, napi_create_string_utf8(env_, rstCh, strlen(rstCh), &resultStr)); + if (arr != nullptr) { + delete[] arr; + arr = nullptr; + } + if (flush) { + label_ &= BOM_SEEN_FLG; + Reset(); + } + return resultStr; +} + +napi_value TextDecoder::GetEncoding() const +{ + size_t length = strlen(encStr_.c_str()); + napi_value result = nullptr; + NAPI_CALL(env_, napi_create_string_utf8(env_, encStr_.c_str(), length, &result)); + return result; +} + +napi_value TextDecoder::GetFatal() const +{ + uint32_t temp = label_ & FATAL_FLG; + bool comRst = false; + if (temp == FATAL_FLG) { + comRst = true; + } else { + comRst = false; + } + napi_value result = nullptr; + NAPI_CALL(env_, napi_get_boolean(env_, comRst, &result)); + return result; +} + +napi_value TextDecoder::GetIgnoreBOM() const +{ + uint32_t temp = label_ & IGNORE_BOM_FLG; + bool comRst = false; + if (temp == IGNORE_BOM_FLG) { + comRst = true; + } else { + comRst = false; + } + napi_value result; + NAPI_CALL(env_, napi_get_boolean(env_, comRst, &result)); + return result; +} + +size_t TextDecoder::GetMinByteSize() const +{ + if (tranTool_ == nullptr) { + return -1; + } + size_t res = ucnv_getMinCharSize(tranTool_.get()); + return res; +} + +void TextDecoder::Reset() const +{ + if (tranTool_ == nullptr) { + return; + } + ucnv_reset(tranTool_.get()); +} diff --git a/textcoder/js_textdecoder.h b/textcoder/js_textdecoder.h new file mode 100755 index 0000000..b1786dd --- /dev/null +++ b/textcoder/js_textdecoder.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_CCRUNTIME_TEXTCODER_JS_TEXTDECODER_H +#define FOUNDATION_CCRUNTIME_TEXTCODER_JS_TEXTDECODER_H + +#include +#include +#include +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "unicode/ucnv.h" + +using TransformToolPointer = std::unique_ptr; + +class TextDecoder { +public: + enum ConverterFlags { + FLUSH_FLG = 0x1, + FATAL_FLG = 0x2, + IGNORE_BOM_FLG = 0x4, + UNICODE_FLG = 0x8, + BOM_SEEN_FLG = 0x10, + }; +public: + TextDecoder(napi_env env, std::string buff, std::vector optionVec); + virtual ~TextDecoder() {} + napi_value Decode(napi_value src, bool iflag); + napi_value GetEncoding() const; + napi_value GetFatal() const; + napi_value GetIgnoreBOM() const; + size_t GetMinByteSize() const; + void Reset() const; + UConverter *GetConverterPtr() const + { + return tranTool_.get(); + } + bool IsBomFlag() const + { + uint32_t temp = label_ & BOM_SEEN_FLG; + if (temp == BOM_SEEN_FLG) { + return true; + } else { + return false; + } + } + bool IsUnicode() const + { + uint32_t temp = label_ & UNICODE_FLG; + if (temp == UNICODE_FLG) { + return true; + } else { + return false; + } + } + bool IsIgnoreBom() const + { + uint32_t temp = label_ & IGNORE_BOM_FLG; + if (temp == IGNORE_BOM_FLG) { + return true; + } else { + return false; + } + } + static void ConverterClose(UConverter* pointer) + { + ucnv_close(pointer); + } +private: + void FreedMemory(UChar *pData); + napi_env env_; + uint32_t label_; + std::string encStr_; + TransformToolPointer tranTool_; +}; +#endif /* FOUNDATION_CCRUNTIME_TEXTCODER_JS_TEXTDECODER_H */ diff --git a/textcoder/js_textencoder.cpp b/textcoder/js_textencoder.cpp new file mode 100755 index 0000000..ee8e080 --- /dev/null +++ b/textcoder/js_textencoder.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "js_textencoder.h" + +#include + +#include "native_engine.h" +#include "securec.h" +#include "utils/log.h" + +TextEncoder::TextEncoder(napi_env env) : env_(env), encoding_("utf-8") +{ +} + +napi_value TextEncoder::GetEncoding() const +{ + napi_value result = nullptr; + NAPI_CALL(env_, napi_create_string_utf8(env_, encoding_.c_str(), encoding_.length(), &result)); + + return result; +} + +napi_value TextEncoder::Encode(napi_value src) const +{ + char *buffer = nullptr; + size_t bufferSize = 0; + + NAPI_CALL(env_, napi_get_value_string_utf8(env_, src, buffer, 0, &bufferSize)); + NAPI_ASSERT(env_, bufferSize > 0, "bufferSize == 0"); + buffer = new char[bufferSize + 1]; + + NAPI_CALL(env_, napi_get_value_string_utf8(env_, src, buffer, bufferSize + 1, &bufferSize)); + + void* data = nullptr; + napi_value arrayBuffer = nullptr; + NAPI_CALL(env_, napi_create_arraybuffer(env_, bufferSize, &data, &arrayBuffer)); + if (memcpy_s(data, bufferSize, reinterpret_cast(buffer), bufferSize) != 0) { + HILOG_ERROR("copy buffer to arraybuffer error"); + return nullptr; + } + + delete []buffer; + + napi_value result = nullptr; + NAPI_CALL(env_, napi_create_typedarray(env_, napi_uint8_array, bufferSize, arrayBuffer, 0, &result)); + + return result; +} + +napi_value TextEncoder::EncodeInto(napi_value src, napi_value dest) const +{ + napi_typedarray_type type; + size_t byteOffset = 0; + size_t length = 0; + void* resultData = nullptr; + napi_value resultBuffer = nullptr; + NAPI_CALL(env_, napi_get_typedarray_info(env_, dest, &type, &length, &resultData, &resultBuffer, &byteOffset)); + + char* writeResult = static_cast(resultData) + byteOffset; + + int32_t nchars = 0; + int32_t written = 0; + NativeEngine* engine = reinterpret_cast(env_); + NativeValue* nativeValue = reinterpret_cast(src); + engine->EncodeToUtf8(nativeValue, writeResult, &written, length, &nchars); + + napi_value result = nullptr; + NAPI_CALL(env_, napi_create_object(env_, &result)); + + napi_value read = nullptr; + NAPI_CALL(env_, napi_create_uint32(env_, nchars, &read)); + + NAPI_CALL(env_, napi_set_named_property(env_, result, "read", read)); + + napi_value resWritten = nullptr; + NAPI_CALL(env_, napi_create_uint32(env_, written, &resWritten)); + + NAPI_CALL(env_, napi_set_named_property(env_, result, "written", resWritten)); + + return result; +} diff --git a/textcoder/js_textencoder.h b/textcoder/js_textencoder.h new file mode 100755 index 0000000..ed6bb55 --- /dev/null +++ b/textcoder/js_textencoder.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_CCRUNTIME_TEXTCODER_JS_TEXTENCODER_H +#define FOUNDATION_CCRUNTIME_TEXTCODER_JS_TEXTENCODER_H + +#include + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +class TextEncoder { +public: + explicit TextEncoder(napi_env env); + + virtual ~TextEncoder() {} + + napi_value GetEncoding() const; + napi_value Encode(napi_value src) const; + napi_value EncodeInto(napi_value src, napi_value dest) const; + +private: + napi_env env_; + std::string encoding_; +}; + +#endif /* FOUNDATION_CCRUNTIME_TEXTCODER_JS_TEXTENCODER_H */ \ No newline at end of file diff --git a/textcoder/native_module_util.cpp b/textcoder/native_module_util.cpp new file mode 100755 index 0000000..972592e --- /dev/null +++ b/textcoder/native_module_util.cpp @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "js_textdecoder.h" +#include "js_textencoder.h" + +#include "napi/native_api.h" +#include "napi/native_node_api.h" +#include "utils/log.h" + +static const int NUM_OF_DATA = 2; +// Decoder +static void SetVec(const napi_status fatSta, const napi_status bomSta, const bool fat, const bool bom, + std::vector ¶Vec) +{ + if (paraVec.size() != 2) { + return; + } + if (fatSta == napi_ok) { + if (fat) { + paraVec[0] = 1; + } else { + paraVec[0] = 0; + } + } + if (bomSta == napi_ok) { + if (bom) { + paraVec[1] = 1; + } else { + paraVec[1] = 0; + } + } +} + +static napi_value TextdecoderConstructor(napi_env env, napi_callback_info info) +{ + size_t tempArgc = 0; + napi_value thisVar = nullptr; + napi_get_cb_info(env, info, &tempArgc, nullptr, &thisVar, nullptr); + size_t argc = 0; + void* data = nullptr; + char* type = nullptr; + size_t typeLen = 0; + std::vector paraVec(2, 0); // 2: Specifies the size of the container to be applied for. + if (tempArgc == 1) { + argc = 1; + napi_value argv = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, nullptr, &data)); + // first para + NAPI_CALL(env, napi_get_value_string_utf8(env, argv, nullptr, 0, &typeLen)); + if (typeLen > 0) { + type = new char[typeLen + 1](); + } + NAPI_CALL(env, napi_get_value_string_utf8(env, argv, type, typeLen + 1, &typeLen)); + } else if (tempArgc == NUM_OF_DATA) { + argc = NUM_OF_DATA; + napi_value argv[2] = { 0 }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, &data)); + // first para + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], nullptr, 0, &typeLen)); + if (typeLen > 0) { + type = new char[typeLen + 1](); + } + NAPI_CALL(env, napi_get_value_string_utf8(env, argv[0], type, typeLen + 1, &typeLen)); + // second para + napi_value messageKeyFatal = nullptr; + const char* messageKeyStrFatal = "fatal"; + napi_value messageKeyIgnorebom = nullptr; + const char* messageKeyStrIgnorebom = "ignoreBOM"; + napi_value resultFatal = nullptr; + napi_value resultIgnorebom = nullptr; + bool bResultFat = false; + bool bResultIgnbom = false; + NAPI_CALL(env, napi_create_string_utf8(env, messageKeyStrFatal, strlen(messageKeyStrFatal), &messageKeyFatal)); + NAPI_CALL(env, napi_create_string_utf8(env, messageKeyStrIgnorebom, strlen(messageKeyStrIgnorebom), + &messageKeyIgnorebom)); + NAPI_CALL(env, napi_get_property(env, argv[1], messageKeyFatal, &resultFatal)); + NAPI_CALL(env, napi_get_property(env, argv[1], messageKeyIgnorebom, &resultIgnorebom)); + napi_status naFat = napi_get_value_bool(env, resultFatal, &bResultFat); + napi_status naBom = napi_get_value_bool(env, resultIgnorebom, &bResultIgnbom); + SetVec(naFat, naBom, bResultFat, bResultIgnbom, paraVec); + } + std::string enconding = "utf-8"; + if (type != nullptr) { + enconding = type; + } + if (type != nullptr) { + delete []type; + type = nullptr; + } + auto objectInfo = new TextDecoder(env, enconding, paraVec); + NAPI_CALL(env, napi_wrap( + env, thisVar, objectInfo, + [](napi_env env, void* data, void* hint) { + auto objectInfo = (TextDecoder*)data; + if (objectInfo != nullptr) { + delete objectInfo; + } + }, + nullptr, nullptr)); + return thisVar; +} + +static napi_value TextdecoderDecode(napi_env env, napi_callback_info info) +{ + size_t tempArgc = 2; + napi_value thisVar = nullptr; + napi_get_cb_info(env, info, &tempArgc, nullptr, &thisVar, nullptr); + size_t argc = 0; + void* dataPara = nullptr; + napi_typedarray_type type; + size_t length = 0; + void* data = nullptr; + napi_value arraybuffer = nullptr; + size_t byteOffset = 0; + bool iStream = true; + TextDecoder* textDecoder = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&textDecoder)); + napi_value valStr = nullptr; + if (tempArgc == 1) { + argc = 1; + napi_value argv = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &argv, nullptr, &dataPara)); + // first para + NAPI_CALL(env, napi_get_typedarray_info(env, argv, &type, &length, &data, &arraybuffer, &byteOffset)); + valStr = textDecoder->Decode(argv, iStream); + } else if (tempArgc == NUM_OF_DATA) { + argc = NUM_OF_DATA; + napi_value argv[2] = { 0 }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, &dataPara)); + // first para + NAPI_CALL(env, napi_get_typedarray_info(env, argv[0], &type, &length, &data, &arraybuffer, &byteOffset)); + // second para + napi_value messageKeyStream = nullptr; + const char* messageKeyStrStream = "stream"; + + napi_value resultStream = nullptr; + NAPI_CALL(env, napi_create_string_utf8(env, messageKeyStrStream, strlen(messageKeyStrStream), + &messageKeyStream)); + NAPI_CALL(env, napi_get_property(env, argv[1], messageKeyStream, &resultStream)); + NAPI_CALL(env, napi_get_value_bool(env, resultStream, &iStream)); + valStr = textDecoder->Decode(argv[0], iStream); + } + return valStr; +} + +static napi_value TextdecoderGetEncoding(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + TextDecoder* textDecoder = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&textDecoder)); + napi_value retVal = textDecoder->GetEncoding(); + return retVal; +} + +static napi_value TextdecoderGetFatal(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + TextDecoder* textDecoder = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&textDecoder)); + napi_value retVal = textDecoder->GetFatal(); + return retVal; +} + +static napi_value TextdecoderGetIgnoreBOM(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + TextDecoder* textDecoder = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&textDecoder)); + napi_value retVal = textDecoder->GetIgnoreBOM(); + return retVal; +} + +// Encoder +static napi_value TextEncoderConstructor(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + void* data = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, &data)); + + auto object = new TextEncoder(env); + NAPI_CALL(env, napi_wrap( + env, thisVar, object, + [](napi_env env, void* data, void* hint) { + auto object = (TextEncoder*)data; + if (object != nullptr) { + delete object; + } + }, + nullptr, nullptr)); + + return thisVar; +} + +static napi_value GetEncoding(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr)); + + TextEncoder* object = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&object)); + + return object->GetEncoding(); +} + +static napi_value Encode(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t requireArgc = 1; + size_t argc = 1; + napi_value args = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, &args, &thisVar, nullptr)); + + NAPI_ASSERT(env, argc >= requireArgc, "Wrong number of arguments"); + + napi_valuetype valuetype; + NAPI_CALL(env, napi_typeof(env, args, &valuetype)); + + NAPI_ASSERT(env, valuetype == napi_string, "Wrong argument type. String expected."); + + TextEncoder* object = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&object)); + + napi_value result = object->Encode(args); + + return result; +} + +static napi_value EncodeInto(napi_env env, napi_callback_info info) +{ + napi_value thisVar = nullptr; + size_t requireArgc = 2; + size_t argc = 2; + napi_value args[2] = { nullptr }; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &thisVar, nullptr)); + + NAPI_ASSERT(env, argc >= requireArgc, "Wrong number of arguments"); + + napi_valuetype valuetype0; + NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0)); + + napi_typedarray_type valuetype1; + size_t length = 0; + void* data = nullptr; + napi_value arraybuffer = nullptr; + size_t byteOffset = 0; + NAPI_CALL(env, napi_get_typedarray_info(env, args[1], &valuetype1, &length, &data, &arraybuffer, &byteOffset)); + + NAPI_ASSERT(env, valuetype0 == napi_string, "Wrong argument type. String expected."); + NAPI_ASSERT(env, valuetype1 == napi_uint8_array, "Wrong argument type. napi_uint8_array expected."); + + TextEncoder* object = nullptr; + NAPI_CALL(env, napi_unwrap(env, thisVar, (void**)&object)); + + napi_value result = object->EncodeInto(args[0], args[1]); + + return result; +} + +static napi_value TextcoderInit(napi_env env, napi_value exports) +{ + const char* textEncoderClassName = "TextEncoder"; + napi_value textEncoderClass = nullptr; + static napi_property_descriptor textEncoderDesc[] = { + DECLARE_NAPI_GETTER("encoding", GetEncoding), + DECLARE_NAPI_FUNCTION("encode", Encode), + DECLARE_NAPI_FUNCTION("encodeInto", EncodeInto), + }; + NAPI_CALL(env, napi_define_class(env, textEncoderClassName, strlen(textEncoderClassName), TextEncoderConstructor, + nullptr, sizeof(textEncoderDesc) / sizeof(textEncoderDesc[0]), textEncoderDesc, + &textEncoderClass)); + + const char* textDecoderClassName = "TextDecoder"; + napi_value textDecoderClass = nullptr; + static napi_property_descriptor textdecoderDesc[] = { + DECLARE_NAPI_FUNCTION("decode", TextdecoderDecode), + DECLARE_NAPI_GETTER("encoding", TextdecoderGetEncoding), + DECLARE_NAPI_GETTER("fatal", TextdecoderGetFatal), + DECLARE_NAPI_GETTER("ignoreBOM", TextdecoderGetIgnoreBOM), + }; + NAPI_CALL(env, napi_define_class(env, textDecoderClassName, strlen(textDecoderClassName), TextdecoderConstructor, + nullptr, sizeof(textdecoderDesc) / sizeof(textdecoderDesc[0]), textdecoderDesc, + &textDecoderClass)); + + static napi_property_descriptor desc[] = { + DECLARE_NAPI_PROPERTY("TextEncoder", textEncoderClass), + DECLARE_NAPI_PROPERTY("TextDecoder", textDecoderClass), + }; + + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); + return exports; +} + +// util modules +static napi_module utilModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = TextcoderInit, + .nm_modname = "util", + .nm_priv = ((void*)0), + .reserved = { 0 }, +}; + +// util module register +extern "C" __attribute__((constructor)) void utilRegister() +{ + napi_module_register(&utilModule); +}