• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Decode(napi_env env,napi_value src,bool iflag)69     napi_value TextDecoder::Decode(napi_env env, napi_value src, bool iflag)
70     {
71         uint8_t flags = 0;
72         flags |= (iflag ? 0 : static_cast<uint8_t>(ConverterFlags::FLUSH_FLG));
73         UBool flush = ((flags & static_cast<uint8_t>(ConverterFlags::FLUSH_FLG))) ==
74         static_cast<uint8_t>(ConverterFlags::FLUSH_FLG);
75         napi_typedarray_type type;
76         size_t length = 0;
77         void *data1 = nullptr;
78         size_t byteOffset = 0;
79         napi_value arrayBuffer = nullptr;
80         NAPI_CALL(env, napi_get_typedarray_info(env, src, &type, &length, &data1, &arrayBuffer, &byteOffset));
81         const char *source = static_cast<char*>(data1);
82         size_t limit = GetMinByteSize() * length;
83         size_t len = limit * sizeof(UChar);
84         UChar *arr = nullptr;
85         if (limit > 0) {
86             arr = new UChar[limit + 1];
87             if (memset_s(arr, len + sizeof(UChar), 0, len + sizeof(UChar)) != EOK) {
88                 HILOG_ERROR("decode arr memset_s failed");
89                 FreedMemory(arr);
90                 return nullptr;
91             }
92         } else {
93             HILOG_DEBUG("limit is error");
94             return nullptr;
95         }
96         UChar *target = arr;
97         size_t tarStartPos = reinterpret_cast<uintptr_t>(arr);
98         UErrorCode codeFlag = U_ZERO_ERROR;
99         ucnv_toUnicode(GetConverterPtr(), &target, target + len, &source, source + length, nullptr, flush, &codeFlag);
100         if (codeFlag != U_ZERO_ERROR) {
101             return ThrowError(env, "TextDecoder decoding error.");
102         }
103 
104         size_t resultLength = 0;
105         bool omitInitialBom = false;
106         DecodeArr decArr(target, tarStartPos, limit);
107         SetBomFlag(arr, codeFlag, decArr, resultLength, omitInitialBom);
108         UChar *arrDat = arr;
109         if (omitInitialBom && resultLength > 0) {
110             arrDat = &arr[2]; // 2: Obtains the 2 value of the array.
111         }
112         std::string tepStr = ConvertToString(arrDat, length);
113         napi_value resultStr = nullptr;
114         NAPI_CALL(env, napi_create_string_utf8(env, tepStr.c_str(), tepStr.size(), &resultStr));
115         FreedMemory(arr);
116         if (flush) {
117             label_ &= static_cast<uint32_t>(ConverterFlags::BOM_SEEN_FLG);
118             Reset();
119         }
120         return resultStr;
121     }
122 
GetEncoding(napi_env env) const123     napi_value TextDecoder::GetEncoding(napi_env env) const
124     {
125         size_t length = strlen(encStr_.c_str());
126         napi_value result = nullptr;
127         NAPI_CALL(env, napi_create_string_utf8(env, encStr_.c_str(), length, &result));
128         return result;
129     }
130 
GetFatal(napi_env env) const131     napi_value TextDecoder::GetFatal(napi_env env) const
132     {
133         uint32_t temp = label_ & static_cast<uint32_t>(ConverterFlags::FATAL_FLG);
134         bool comRst = false;
135         if (temp == static_cast<uint32_t>(ConverterFlags::FATAL_FLG)) {
136             comRst = true;
137         } else {
138             comRst = false;
139         }
140         napi_value result = nullptr;
141         NAPI_CALL(env, napi_get_boolean(env, comRst, &result));
142         return result;
143     }
144 
GetIgnoreBOM(napi_env env) const145     napi_value TextDecoder::GetIgnoreBOM(napi_env env) const
146     {
147         uint32_t temp = label_ & static_cast<uint32_t>(ConverterFlags::IGNORE_BOM_FLG);
148         bool comRst = false;
149         if (temp == static_cast<uint32_t>(ConverterFlags::IGNORE_BOM_FLG)) {
150             comRst = true;
151         } else {
152             comRst = false;
153         }
154         napi_value result;
155         NAPI_CALL(env, napi_get_boolean(env, comRst, &result));
156         return result;
157     }
158 
GetMinByteSize() const159     size_t TextDecoder::GetMinByteSize() const
160     {
161         if (tranTool_ == nullptr) {
162             return 0;
163         }
164         size_t res = static_cast<size_t>(ucnv_getMinCharSize(tranTool_.get()));
165         return res;
166     }
167 
Reset() const168     void TextDecoder::Reset() const
169     {
170         if (tranTool_ == nullptr) {
171             return;
172         }
173         ucnv_reset(tranTool_.get());
174     }
175 
FreedMemory(UChar * pData)176     void TextDecoder::FreedMemory(UChar *pData)
177     {
178         if (pData != nullptr) {
179             delete[] pData;
180             pData = nullptr;
181         }
182     }
183 
SetBomFlag(const UChar * arr,const UErrorCode codeFlag,const DecodeArr decArr,size_t & rstLen,bool & bomFlag)184     void TextDecoder::SetBomFlag(const UChar *arr, const UErrorCode codeFlag, const DecodeArr decArr,
185                                  size_t &rstLen, bool &bomFlag)
186     {
187         if (arr == nullptr) {
188             return;
189         }
190         if (U_SUCCESS(codeFlag)) {
191             if (decArr.limitLen > 0) {
192                 rstLen = reinterpret_cast<uintptr_t>(decArr.target) - decArr.tarStartPos;
193                 if (rstLen > 0 && IsUnicode() && !IsIgnoreBom() && !IsBomFlag()) {
194                     bomFlag = (arr[0] == 0xFEFF) ? true : false;
195                     label_ |= static_cast<uint32_t>(ConverterFlags::BOM_SEEN_FLG);
196                 }
197             }
198         }
199     }
200 
ThrowError(napi_env env,const char * errMessage)201     napi_value TextDecoder::ThrowError(napi_env env, const char* errMessage)
202     {
203         napi_value utilError = nullptr;
204         napi_value code = nullptr;
205         uint32_t errCode = 10200019;
206         napi_create_uint32(env, errCode, &code);
207         napi_value name = nullptr;
208         std::string errName = "BusinessError";
209         napi_value msg = nullptr;
210         napi_create_string_utf8(env, errMessage, NAPI_AUTO_LENGTH, &msg);
211         napi_create_string_utf8(env, errName.c_str(), NAPI_AUTO_LENGTH, &name);
212         napi_create_error(env, nullptr, msg, &utilError);
213         napi_set_named_property(env, utilError, "code", code);
214         napi_set_named_property(env, utilError, "name", name);
215         napi_throw(env, utilError);
216         napi_value res = nullptr;
217         NAPI_CALL(env, napi_get_undefined(env, &res));
218         return res;
219     }
220 }
221