14d6c458bSopenharmony_ci/*
24d6c458bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
34d6c458bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44d6c458bSopenharmony_ci * you may not use this file except in compliance with the License.
54d6c458bSopenharmony_ci * You may obtain a copy of the License at
64d6c458bSopenharmony_ci *
74d6c458bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84d6c458bSopenharmony_ci *
94d6c458bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104d6c458bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114d6c458bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124d6c458bSopenharmony_ci * See the License for the specific language governing permissions and
134d6c458bSopenharmony_ci * limitations under the License.
144d6c458bSopenharmony_ci */
154d6c458bSopenharmony_ci
164d6c458bSopenharmony_ci#include "js_stringdecoder.h"
174d6c458bSopenharmony_ci#include "util_helper.h"
184d6c458bSopenharmony_ci
194d6c458bSopenharmony_cinamespace OHOS::Util {
204d6c458bSopenharmony_ciusing namespace Commonlibrary::Platform;
214d6c458bSopenharmony_cistatic const char* ERROR_CODE = "401";
224d6c458bSopenharmony_ci
234d6c458bSopenharmony_ciStringDecoder::StringDecoder(const std::string &encoding)
244d6c458bSopenharmony_ci{
254d6c458bSopenharmony_ci    UErrorCode codeflag = U_ZERO_ERROR;
264d6c458bSopenharmony_ci    conv_ = CreateConverter(encoding, codeflag);
274d6c458bSopenharmony_ci}
284d6c458bSopenharmony_ci
294d6c458bSopenharmony_cinapi_value StringDecoder::Write(napi_env env, napi_value src, UBool flush)
304d6c458bSopenharmony_ci{
314d6c458bSopenharmony_ci    napi_typedarray_type type;
324d6c458bSopenharmony_ci    size_t length = 0;
334d6c458bSopenharmony_ci    void *data = nullptr;
344d6c458bSopenharmony_ci    size_t byteOffset = 0;
354d6c458bSopenharmony_ci    napi_value arrayBuffer = nullptr;
364d6c458bSopenharmony_ci    bool result = false;
374d6c458bSopenharmony_ci    napi_is_typedarray(env, src, &result);
384d6c458bSopenharmony_ci    if (!result) {
394d6c458bSopenharmony_ci        napi_throw_error(env, "401",
404d6c458bSopenharmony_ci            "Parameter error. The type of Parameter must be Uint8Array or string.");
414d6c458bSopenharmony_ci        return nullptr;
424d6c458bSopenharmony_ci    }
434d6c458bSopenharmony_ci    napi_get_typedarray_info(env, src, &type, &length, &data, &arrayBuffer, &byteOffset);
444d6c458bSopenharmony_ci    const char *source = static_cast<char*>(data);
454d6c458bSopenharmony_ci    size_t limit = static_cast<size_t>(ucnv_getMinCharSize(conv_)) * length;
464d6c458bSopenharmony_ci    size_t len = limit * sizeof(UChar);
474d6c458bSopenharmony_ci    UChar *arr = nullptr;
484d6c458bSopenharmony_ci    if (limit > 0) {
494d6c458bSopenharmony_ci        arr = new UChar[limit + 1] { 0 };
504d6c458bSopenharmony_ci    } else {
514d6c458bSopenharmony_ci        napi_throw_error(env, ERROR_CODE, "Error obtaining minimum number of input bytes");
524d6c458bSopenharmony_ci        return nullptr;
534d6c458bSopenharmony_ci    }
544d6c458bSopenharmony_ci    UChar *target = arr;
554d6c458bSopenharmony_ci    UErrorCode codeFlag = U_ZERO_ERROR;
564d6c458bSopenharmony_ci    ucnv_toUnicode(conv_, &target, target + len, &source, source + length, nullptr, flush, &codeFlag);
574d6c458bSopenharmony_ci    if (U_FAILURE(codeFlag)) {
584d6c458bSopenharmony_ci        FreedMemory(arr);
594d6c458bSopenharmony_ci        std::string err = "decoder error, ";
604d6c458bSopenharmony_ci        err += u_errorName(codeFlag);
614d6c458bSopenharmony_ci        napi_throw_error(env, ERROR_CODE, err.c_str());
624d6c458bSopenharmony_ci        return nullptr;
634d6c458bSopenharmony_ci    }
644d6c458bSopenharmony_ci    pendingLen_ = ucnv_toUCountPending(conv_, &codeFlag);
654d6c458bSopenharmony_ci    pend_ = source + length - pendingLen_;
664d6c458bSopenharmony_ci
674d6c458bSopenharmony_ci    napi_value resultStr = nullptr;
684d6c458bSopenharmony_ci    size_t resultLen = target - arr;
694d6c458bSopenharmony_ci    napi_create_string_utf16(env, reinterpret_cast<char16_t *>(arr), resultLen, &resultStr);
704d6c458bSopenharmony_ci    FreedMemory(arr);
714d6c458bSopenharmony_ci    return resultStr;
724d6c458bSopenharmony_ci}
734d6c458bSopenharmony_ci
744d6c458bSopenharmony_cinapi_value StringDecoder::End(napi_env env, napi_value src)
754d6c458bSopenharmony_ci{
764d6c458bSopenharmony_ci    return Write(env, src, true);
774d6c458bSopenharmony_ci}
784d6c458bSopenharmony_ci
794d6c458bSopenharmony_cinapi_value StringDecoder::End(napi_env env)
804d6c458bSopenharmony_ci{
814d6c458bSopenharmony_ci    napi_value resultStr = nullptr;
824d6c458bSopenharmony_ci    if (pendingLen_ == 0) {
834d6c458bSopenharmony_ci        NAPI_CALL(env, napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &resultStr));
844d6c458bSopenharmony_ci        return resultStr;
854d6c458bSopenharmony_ci    }
864d6c458bSopenharmony_ci    UErrorCode errorCode = U_ZERO_ERROR;
874d6c458bSopenharmony_ci    UChar outputBuffer[pendingLen_];
884d6c458bSopenharmony_ci    UChar *targetEnd = outputBuffer + pendingLen_;
894d6c458bSopenharmony_ci    UChar *target = outputBuffer;
904d6c458bSopenharmony_ci    const char *src = pend_;
914d6c458bSopenharmony_ci    const char *sourceEnd = pend_ + pendingLen_;
924d6c458bSopenharmony_ci    UBool flush = true;
934d6c458bSopenharmony_ci    ucnv_toUnicode(conv_, &target, targetEnd, &src, sourceEnd, nullptr, flush, &errorCode);
944d6c458bSopenharmony_ci    if (U_FAILURE(errorCode)) {
954d6c458bSopenharmony_ci        std::string err = "decoder error, ";
964d6c458bSopenharmony_ci        err += u_errorName(errorCode);
974d6c458bSopenharmony_ci        napi_throw_error(env, ERROR_CODE, err.c_str());
984d6c458bSopenharmony_ci        return nullptr;
994d6c458bSopenharmony_ci    }
1004d6c458bSopenharmony_ci    std::string tepStr = ConvertToString(target, pendingLen_);
1014d6c458bSopenharmony_ci    NAPI_CALL(env, napi_create_string_utf8(env, tepStr.c_str(), tepStr.size(), &resultStr));
1024d6c458bSopenharmony_ci    return resultStr;
1034d6c458bSopenharmony_ci}
1044d6c458bSopenharmony_ci
1054d6c458bSopenharmony_civoid StringDecoder::FreedMemory(UChar *&pData)
1064d6c458bSopenharmony_ci{
1074d6c458bSopenharmony_ci    if (pData != nullptr) {
1084d6c458bSopenharmony_ci        delete[] pData;
1094d6c458bSopenharmony_ci        pData = nullptr;
1104d6c458bSopenharmony_ci    }
1114d6c458bSopenharmony_ci}
1124d6c458bSopenharmony_ci}
113