1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "js_stringdecoder.h" 17#include "util_helper.h" 18 19namespace OHOS::Util { 20using namespace Commonlibrary::Platform; 21static const char* ERROR_CODE = "401"; 22 23StringDecoder::StringDecoder(const std::string &encoding) 24{ 25 UErrorCode codeflag = U_ZERO_ERROR; 26 conv_ = CreateConverter(encoding, codeflag); 27} 28 29napi_value StringDecoder::Write(napi_env env, napi_value src, UBool flush) 30{ 31 napi_typedarray_type type; 32 size_t length = 0; 33 void *data = nullptr; 34 size_t byteOffset = 0; 35 napi_value arrayBuffer = nullptr; 36 bool result = false; 37 napi_is_typedarray(env, src, &result); 38 if (!result) { 39 napi_throw_error(env, "401", 40 "Parameter error. The type of Parameter must be Uint8Array or string."); 41 return nullptr; 42 } 43 napi_get_typedarray_info(env, src, &type, &length, &data, &arrayBuffer, &byteOffset); 44 const char *source = static_cast<char*>(data); 45 size_t limit = static_cast<size_t>(ucnv_getMinCharSize(conv_)) * length; 46 size_t len = limit * sizeof(UChar); 47 UChar *arr = nullptr; 48 if (limit > 0) { 49 arr = new UChar[limit + 1] { 0 }; 50 } else { 51 napi_throw_error(env, ERROR_CODE, "Error obtaining minimum number of input bytes"); 52 return nullptr; 53 } 54 UChar *target = arr; 55 UErrorCode codeFlag = U_ZERO_ERROR; 56 ucnv_toUnicode(conv_, &target, target + len, &source, source + length, nullptr, flush, &codeFlag); 57 if (U_FAILURE(codeFlag)) { 58 FreedMemory(arr); 59 std::string err = "decoder error, "; 60 err += u_errorName(codeFlag); 61 napi_throw_error(env, ERROR_CODE, err.c_str()); 62 return nullptr; 63 } 64 pendingLen_ = ucnv_toUCountPending(conv_, &codeFlag); 65 pend_ = source + length - pendingLen_; 66 67 napi_value resultStr = nullptr; 68 size_t resultLen = target - arr; 69 napi_create_string_utf16(env, reinterpret_cast<char16_t *>(arr), resultLen, &resultStr); 70 FreedMemory(arr); 71 return resultStr; 72} 73 74napi_value StringDecoder::End(napi_env env, napi_value src) 75{ 76 return Write(env, src, true); 77} 78 79napi_value StringDecoder::End(napi_env env) 80{ 81 napi_value resultStr = nullptr; 82 if (pendingLen_ == 0) { 83 NAPI_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &resultStr)); 84 return resultStr; 85 } 86 UErrorCode errorCode = U_ZERO_ERROR; 87 UChar outputBuffer[pendingLen_]; 88 UChar *targetEnd = outputBuffer + pendingLen_; 89 UChar *target = outputBuffer; 90 const char *src = pend_; 91 const char *sourceEnd = pend_ + pendingLen_; 92 UBool flush = true; 93 ucnv_toUnicode(conv_, &target, targetEnd, &src, sourceEnd, nullptr, flush, &errorCode); 94 if (U_FAILURE(errorCode)) { 95 std::string err = "decoder error, "; 96 err += u_errorName(errorCode); 97 napi_throw_error(env, ERROR_CODE, err.c_str()); 98 return nullptr; 99 } 100 std::string tepStr = ConvertToString(target, pendingLen_); 101 NAPI_CALL(env, napi_create_string_utf8(env, tepStr.c_str(), tepStr.size(), &resultStr)); 102 return resultStr; 103} 104 105void StringDecoder::FreedMemory(UChar *&pData) 106{ 107 if (pData != nullptr) { 108 delete[] pData; 109 pData = nullptr; 110 } 111} 112} 113