1 /* 2 * Copyright (c) 2022 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_textdecoder.h" 17 #include <algorithm> 18 #include <codecvt> 19 20 #include <locale> 21 #include <map> 22 #include <string> 23 #include <vector> 24 25 #include "ohos/init_data.h" 26 #include "securec.h" 27 #include "unicode/unistr.h" 28 #include "utils/log.h" 29 #include "util_helper.h" 30 31 namespace OHOS::Util { 32 using namespace Commonlibrary::Platform; 33 TextDecoder(const std::string & buff,std::vector<int> optionVec)34 TextDecoder::TextDecoder(const std::string &buff, std::vector<int> optionVec) 35 : label_(0), encStr_(buff), tranTool_(nullptr, nullptr) 36 { 37 uint32_t i32Flag = 0; 38 if (optionVec.size() == 2) { // 2:Meaning of optionVec size 2 39 if (optionVec[0] >= 0 && optionVec[1] >= 0) { 40 i32Flag |= optionVec[0] ? static_cast<uint32_t>(ConverterFlags::FATAL_FLG) : 0; 41 i32Flag |= optionVec[1] ? static_cast<uint32_t>(ConverterFlags::IGNORE_BOM_FLG) : 0; 42 } else if (optionVec[0] >= 0 && optionVec[1] < 0) { 43 i32Flag |= optionVec[0] ? static_cast<uint32_t>(ConverterFlags::FATAL_FLG) : 0; 44 } else if (optionVec[0] < 0 && optionVec[1] >= 0) { 45 i32Flag |= optionVec[1] ? static_cast<uint32_t>(ConverterFlags::IGNORE_BOM_FLG) : 0; 46 } 47 } 48 label_ = i32Flag; 49 #if !defined(__ARKUI_CROSS__) 50 SetHwIcuDirectory(); 51 #endif 52 bool fatal = (i32Flag & static_cast<uint32_t>(ConverterFlags::FATAL_FLG)) == 53 static_cast<uint32_t>(ConverterFlags::FATAL_FLG); 54 UErrorCode codeflag = U_ZERO_ERROR; 55 UConverter *conv = CreateConverter(encStr_, codeflag); 56 57 if (U_FAILURE(codeflag)) { 58 HILOG_ERROR("ucnv_open failed !"); 59 return; 60 } 61 if (fatal) { 62 codeflag = U_ZERO_ERROR; 63 ucnv_setToUCallBack(conv, UCNV_TO_U_CALLBACK_STOP, nullptr, nullptr, nullptr, &codeflag); 64 } 65 TransformToolPointer tempTranTool(conv, ConverterClose); 66 tranTool_ = std::move(tempTranTool); 67 } 68 69 Decode(napi_env env,napi_value src,bool iflag)70 napi_value TextDecoder::Decode(napi_env env, napi_value src, bool iflag) 71 { 72 uint8_t flags = 0; 73 flags |= (iflag ? 0 : static_cast<uint8_t>(ConverterFlags::FLUSH_FLG)); 74 UBool flush = ((flags & static_cast<uint8_t>(ConverterFlags::FLUSH_FLG))) == 75 static_cast<uint8_t>(ConverterFlags::FLUSH_FLG); 76 napi_typedarray_type type; 77 size_t length = 0; 78 void *data1 = nullptr; 79 size_t byteOffset = 0; 80 napi_value arrayBuffer = nullptr; 81 NAPI_CALL(env, napi_get_typedarray_info(env, src, &type, &length, &data1, &arrayBuffer, &byteOffset)); 82 const char *source = static_cast<char*>(data1); 83 UErrorCode codeFlag = U_ZERO_ERROR; 84 size_t limit = GetMinByteSize() * length; 85 size_t len = limit * sizeof(UChar); 86 UChar *arr = nullptr; 87 if (limit > 0) { 88 arr = new UChar[limit + 1]; 89 if (memset_s(arr, len + sizeof(UChar), 0, len + sizeof(UChar)) != EOK) { 90 HILOG_ERROR("decode arr memset_s failed"); 91 FreedMemory(arr); 92 return nullptr; 93 } 94 } else { 95 HILOG_ERROR("limit is error"); 96 return nullptr; 97 } 98 UChar *target = arr; 99 size_t tarStartPos = reinterpret_cast<uintptr_t>(arr); 100 ucnv_toUnicode(GetConverterPtr(), &target, target + len, &source, source + length, nullptr, flush, &codeFlag); 101 size_t resultLength = 0; 102 bool omitInitialBom = false; 103 DecodeArr decArr(target, tarStartPos, limit); 104 SetBomFlag(arr, codeFlag, decArr, resultLength, omitInitialBom); 105 UChar *arrDat = arr; 106 if (omitInitialBom && resultLength > 0) { 107 arrDat = &arr[2]; // 2: Obtains the 2 value of the array. 108 } 109 std::string tepStr = ConvertToString(arrDat, length); 110 napi_value resultStr = nullptr; 111 NAPI_CALL(env, napi_create_string_utf8(env, tepStr.c_str(), tepStr.size(), &resultStr)); 112 FreedMemory(arr); 113 if (flush) { 114 label_ &= static_cast<uint32_t>(ConverterFlags::BOM_SEEN_FLG); 115 Reset(); 116 } 117 return resultStr; 118 } 119 GetEncoding(napi_env env) const120 napi_value TextDecoder::GetEncoding(napi_env env) const 121 { 122 size_t length = strlen(encStr_.c_str()); 123 napi_value result = nullptr; 124 NAPI_CALL(env, napi_create_string_utf8(env, encStr_.c_str(), length, &result)); 125 return result; 126 } 127 GetFatal(napi_env env) const128 napi_value TextDecoder::GetFatal(napi_env env) const 129 { 130 uint32_t temp = label_ & static_cast<uint32_t>(ConverterFlags::FATAL_FLG); 131 bool comRst = false; 132 if (temp == static_cast<uint32_t>(ConverterFlags::FATAL_FLG)) { 133 comRst = true; 134 } else { 135 comRst = false; 136 } 137 napi_value result = nullptr; 138 NAPI_CALL(env, napi_get_boolean(env, comRst, &result)); 139 return result; 140 } 141 GetIgnoreBOM(napi_env env) const142 napi_value TextDecoder::GetIgnoreBOM(napi_env env) const 143 { 144 uint32_t temp = label_ & static_cast<uint32_t>(ConverterFlags::IGNORE_BOM_FLG); 145 bool comRst = false; 146 if (temp == static_cast<uint32_t>(ConverterFlags::IGNORE_BOM_FLG)) { 147 comRst = true; 148 } else { 149 comRst = false; 150 } 151 napi_value result; 152 NAPI_CALL(env, napi_get_boolean(env, comRst, &result)); 153 return result; 154 } 155 GetMinByteSize() const156 size_t TextDecoder::GetMinByteSize() const 157 { 158 if (tranTool_ == nullptr) { 159 return 0; 160 } 161 size_t res = static_cast<size_t>(ucnv_getMinCharSize(tranTool_.get())); 162 return res; 163 } 164 Reset() const165 void TextDecoder::Reset() const 166 { 167 if (tranTool_ == nullptr) { 168 return; 169 } 170 ucnv_reset(tranTool_.get()); 171 } 172 FreedMemory(UChar * pData)173 void TextDecoder::FreedMemory(UChar *pData) 174 { 175 if (pData != nullptr) { 176 delete[] pData; 177 pData = nullptr; 178 } 179 } 180 SetBomFlag(const UChar * arr,const UErrorCode codeFlag,const DecodeArr decArr,size_t & rstLen,bool & bomFlag)181 void TextDecoder::SetBomFlag(const UChar *arr, const UErrorCode codeFlag, const DecodeArr decArr, 182 size_t &rstLen, bool &bomFlag) 183 { 184 if (arr == nullptr) { 185 return; 186 } 187 if (U_SUCCESS(codeFlag)) { 188 if (decArr.limitLen > 0) { 189 rstLen = reinterpret_cast<uintptr_t>(decArr.target) - decArr.tarStartPos; 190 if (rstLen > 0 && IsUnicode() && !IsIgnoreBom() && !IsBomFlag()) { 191 bomFlag = (arr[0] == 0xFEFF) ? true : false; 192 label_ |= static_cast<uint32_t>(ConverterFlags::BOM_SEEN_FLG); 193 } 194 } 195 } 196 } 197 } 198