14514f5e3Sopenharmony_ci/** 24514f5e3Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_BASE_GLOBAL_INTL_HELPER_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_BASE_GLOBAL_INTL_HELPER_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include <iostream> 204514f5e3Sopenharmony_ci#include <cstdint> 214514f5e3Sopenharmony_ci#include <cmath> 224514f5e3Sopenharmony_ci#include <vector> 234514f5e3Sopenharmony_ci#include <map> 244514f5e3Sopenharmony_ci#include <string> 254514f5e3Sopenharmony_ci#include <chrono> 264514f5e3Sopenharmony_ci#include <math.h> 274514f5e3Sopenharmony_ci 284514f5e3Sopenharmony_ci#include "ecmascript/ecma_vm.h" 294514f5e3Sopenharmony_ci#include "ecmascript/mem/native_area_allocator.h" 304514f5e3Sopenharmony_ci#include "ecmascript/js_handle.h" 314514f5e3Sopenharmony_ci#include "base/global/i18n/frameworks/intl/include/collator.h" 324514f5e3Sopenharmony_ci#if defined(__clang__) 334514f5e3Sopenharmony_ci#pragma clang diagnostic push 344514f5e3Sopenharmony_ci#pragma clang diagnostic ignored "-Wshadow" 354514f5e3Sopenharmony_ci#elif defined(__GNUC__) 364514f5e3Sopenharmony_ci#pragma GCC diagnostic push 374514f5e3Sopenharmony_ci#pragma GCC diagnostic ignored "-Wshadow" 384514f5e3Sopenharmony_ci#endif 394514f5e3Sopenharmony_ci#include "base/global/i18n/frameworks/intl/include/number_format.h" 404514f5e3Sopenharmony_ci#include "base/global/i18n/frameworks/intl/include/date_time_format.h" 414514f5e3Sopenharmony_ci#if defined(__clang__) 424514f5e3Sopenharmony_ci#pragma clang diagnostic pop 434514f5e3Sopenharmony_ci#elif defined(__GNUC__) 444514f5e3Sopenharmony_ci#pragma GCC diagnostic pop 454514f5e3Sopenharmony_ci#endif 464514f5e3Sopenharmony_ci 474514f5e3Sopenharmony_cinamespace panda::ecmascript::intl { 484514f5e3Sopenharmony_ciusing GlobalCollator = OHOS::Global::I18n::Collator; 494514f5e3Sopenharmony_ciusing GlobalNumberFormat = OHOS::Global::I18n::NumberFormat; 504514f5e3Sopenharmony_ciusing GlobalDateFormatter = OHOS::Global::I18n::DateTimeFormat; 514514f5e3Sopenharmony_ciusing GlobalCompareResult = OHOS::Global::I18n::CompareResult; 524514f5e3Sopenharmony_ci 534514f5e3Sopenharmony_cienum class GlobalFormatterType { 544514f5e3Sopenharmony_ci DateFormatter, 554514f5e3Sopenharmony_ci SimpleDateFormatDate, 564514f5e3Sopenharmony_ci SimpleDateFormatTime, 574514f5e3Sopenharmony_ci NumberFormatter, 584514f5e3Sopenharmony_ci Collator 594514f5e3Sopenharmony_ci}; 604514f5e3Sopenharmony_ci 614514f5e3Sopenharmony_ciclass GlobalIntlHelper { 624514f5e3Sopenharmony_cipublic: 634514f5e3Sopenharmony_ci GlobalIntlHelper(JSThread *thread, const GlobalFormatterType matterType); 644514f5e3Sopenharmony_ci ~GlobalIntlHelper() 654514f5e3Sopenharmony_ci { 664514f5e3Sopenharmony_ci if (dateUnitArr != nullptr) { 674514f5e3Sopenharmony_ci delete[] dateUnitArr; 684514f5e3Sopenharmony_ci } 694514f5e3Sopenharmony_ci globalObject = nullptr; 704514f5e3Sopenharmony_ci } 714514f5e3Sopenharmony_ci 724514f5e3Sopenharmony_ci template<typename T> 734514f5e3Sopenharmony_ci std::unique_ptr<T> GetGlobalObject(JSThread *thread, const JSHandle<JSTaggedValue> &locales, 744514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &options, GlobalFormatterType types) 754514f5e3Sopenharmony_ci { 764514f5e3Sopenharmony_ci std::vector<std::string> cacheEntryVector; 774514f5e3Sopenharmony_ci cacheEntryVector = LocalesToVector(thread, locales); 784514f5e3Sopenharmony_ci std::map<std::string, std::string> inputOptions; 794514f5e3Sopenharmony_ci if (!options->IsUndefined()) { 804514f5e3Sopenharmony_ci inputOptions = OptionsToMap(thread, options, types); 814514f5e3Sopenharmony_ci } 824514f5e3Sopenharmony_ci auto result = std::make_unique<T>(cacheEntryVector, inputOptions); 834514f5e3Sopenharmony_ci return result; 844514f5e3Sopenharmony_ci } 854514f5e3Sopenharmony_ci 864514f5e3Sopenharmony_ci template<typename T> 874514f5e3Sopenharmony_ci T *GetGlobalObject(JSThread *thread, const JSHandle<JSTaggedValue> &locales, 884514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &options, GlobalFormatterType types, const bool cache) 894514f5e3Sopenharmony_ci { 904514f5e3Sopenharmony_ci IcuFormatterType icuType; 914514f5e3Sopenharmony_ci switch (types) { 924514f5e3Sopenharmony_ci case GlobalFormatterType::Collator: 934514f5e3Sopenharmony_ci icuType = IcuFormatterType::COLLATOR; 944514f5e3Sopenharmony_ci break; 954514f5e3Sopenharmony_ci case GlobalFormatterType::SimpleDateFormatDate: 964514f5e3Sopenharmony_ci icuType = IcuFormatterType::SIMPLE_DATE_FORMAT_DATE; 974514f5e3Sopenharmony_ci break; 984514f5e3Sopenharmony_ci case GlobalFormatterType::SimpleDateFormatTime: 994514f5e3Sopenharmony_ci icuType = IcuFormatterType::SIMPLE_DATE_FORMAT_TIME; 1004514f5e3Sopenharmony_ci break; 1014514f5e3Sopenharmony_ci case GlobalFormatterType::DateFormatter: 1024514f5e3Sopenharmony_ci icuType = IcuFormatterType::SIMPLE_DATE_FORMAT_DEFAULT; 1034514f5e3Sopenharmony_ci break; 1044514f5e3Sopenharmony_ci case GlobalFormatterType::NumberFormatter: 1054514f5e3Sopenharmony_ci icuType = IcuFormatterType::NUMBER_FORMATTER; 1064514f5e3Sopenharmony_ci break; 1074514f5e3Sopenharmony_ci } 1084514f5e3Sopenharmony_ci EcmaVM *ecmaVm = thread->GetEcmaVM(); 1094514f5e3Sopenharmony_ci std::string cacheEntry = locales->IsUndefined() ? "" : 1104514f5e3Sopenharmony_ci EcmaStringAccessor(locales.GetTaggedValue()).ToStdString(); 1114514f5e3Sopenharmony_ci if (cache) { 1124514f5e3Sopenharmony_ci void *cachedCollator = ecmaVm->GetIcuFormatterFromCache(icuType, cacheEntry); 1134514f5e3Sopenharmony_ci if (cachedCollator != nullptr) { 1144514f5e3Sopenharmony_ci return reinterpret_cast<T *>(cachedCollator); 1154514f5e3Sopenharmony_ci } 1164514f5e3Sopenharmony_ci } 1174514f5e3Sopenharmony_ci std::unique_ptr<T> tObject = GetGlobalObject<T>(thread, locales, options, types); 1184514f5e3Sopenharmony_ci if (cache) { 1194514f5e3Sopenharmony_ci T *cacheObject = tObject.release(); 1204514f5e3Sopenharmony_ci switch (icuType) { 1214514f5e3Sopenharmony_ci case IcuFormatterType::COLLATOR: 1224514f5e3Sopenharmony_ci ecmaVm->SetIcuFormatterToCache(icuType, cacheEntry, cacheObject, FreeCollatorFormat); 1234514f5e3Sopenharmony_ci break; 1244514f5e3Sopenharmony_ci case IcuFormatterType::SIMPLE_DATE_FORMAT_DATE: 1254514f5e3Sopenharmony_ci case IcuFormatterType::SIMPLE_DATE_FORMAT_TIME: 1264514f5e3Sopenharmony_ci case IcuFormatterType::SIMPLE_DATE_FORMAT_DEFAULT: 1274514f5e3Sopenharmony_ci ecmaVm->SetIcuFormatterToCache(icuType, cacheEntry, cacheObject, FreeDateTimeFormat); 1284514f5e3Sopenharmony_ci break; 1294514f5e3Sopenharmony_ci case IcuFormatterType::NUMBER_FORMATTER: 1304514f5e3Sopenharmony_ci ecmaVm->SetIcuFormatterToCache(icuType, cacheEntry, cacheObject, FreeNumberFormat); 1314514f5e3Sopenharmony_ci break; 1324514f5e3Sopenharmony_ci } 1334514f5e3Sopenharmony_ci return cacheObject; 1344514f5e3Sopenharmony_ci } 1354514f5e3Sopenharmony_ci globalObject = tObject.release(); 1364514f5e3Sopenharmony_ci return reinterpret_cast<T *>(globalObject); 1374514f5e3Sopenharmony_ci } 1384514f5e3Sopenharmony_ci static void FreeCollatorFormat([[maybe_unused]] void *env, void *pointer, void *data) 1394514f5e3Sopenharmony_ci { 1404514f5e3Sopenharmony_ci if (pointer == nullptr) { 1414514f5e3Sopenharmony_ci return; 1424514f5e3Sopenharmony_ci } 1434514f5e3Sopenharmony_ci auto globalCollator = reinterpret_cast<GlobalCollator*>(pointer); 1444514f5e3Sopenharmony_ci globalCollator->~Collator(); 1454514f5e3Sopenharmony_ci if (data != nullptr) { 1464514f5e3Sopenharmony_ci reinterpret_cast<EcmaVM *>(data)->GetNativeAreaAllocator()->FreeBuffer(pointer); 1474514f5e3Sopenharmony_ci } 1484514f5e3Sopenharmony_ci } 1494514f5e3Sopenharmony_ci static void FreeNumberFormat([[maybe_unused]] void *env, void *pointer, void *data) 1504514f5e3Sopenharmony_ci { 1514514f5e3Sopenharmony_ci if (pointer == nullptr) { 1524514f5e3Sopenharmony_ci return; 1534514f5e3Sopenharmony_ci } 1544514f5e3Sopenharmony_ci auto globalNumberFormat = reinterpret_cast<GlobalNumberFormat*>(pointer); 1554514f5e3Sopenharmony_ci globalNumberFormat->~NumberFormat(); 1564514f5e3Sopenharmony_ci if (data != nullptr) { 1574514f5e3Sopenharmony_ci reinterpret_cast<EcmaVM *>(data)->GetNativeAreaAllocator()->FreeBuffer(pointer); 1584514f5e3Sopenharmony_ci } 1594514f5e3Sopenharmony_ci } 1604514f5e3Sopenharmony_ci static void FreeDateTimeFormat([[maybe_unused]] void *env, void *pointer, void *data) 1614514f5e3Sopenharmony_ci { 1624514f5e3Sopenharmony_ci if (pointer == nullptr) { 1634514f5e3Sopenharmony_ci return; 1644514f5e3Sopenharmony_ci } 1654514f5e3Sopenharmony_ci auto globalDateFormatter = reinterpret_cast<GlobalDateFormatter*>(pointer); 1664514f5e3Sopenharmony_ci globalDateFormatter->~DateTimeFormat(); 1674514f5e3Sopenharmony_ci if (data != nullptr) { 1684514f5e3Sopenharmony_ci reinterpret_cast<EcmaVM *>(data)->GetNativeAreaAllocator()->FreeBuffer(pointer); 1694514f5e3Sopenharmony_ci } 1704514f5e3Sopenharmony_ci } 1714514f5e3Sopenharmony_ci std::vector<std::string> LocalesToVector(JSThread *thread, const JSHandle<JSTaggedValue> &locales); 1724514f5e3Sopenharmony_ci std::map<std::string, std::string> OptionsToMap(JSThread *thread, 1734514f5e3Sopenharmony_ci const JSHandle<JSTaggedValue> &options, GlobalFormatterType types); 1744514f5e3Sopenharmony_ci uint64_t *ConvertDateToUnit(uint64_t timestamp); 1754514f5e3Sopenharmony_ci static int64_t DoubleToInt64(double value); 1764514f5e3Sopenharmony_ciprivate: 1774514f5e3Sopenharmony_ci void *globalObject = nullptr; 1784514f5e3Sopenharmony_ci uint64_t *dateUnitArr = nullptr; 1794514f5e3Sopenharmony_ci void InitCollatorData(const GlobalEnvConstants *globalConst); 1804514f5e3Sopenharmony_ci void InitNumberData(const GlobalEnvConstants *globalConst); 1814514f5e3Sopenharmony_ci void InitDateData(const GlobalEnvConstants *globalConst); 1824514f5e3Sopenharmony_ci std::map<std::string, std::string> OptionsWithDataFormatter(std::map<std::string, 1834514f5e3Sopenharmony_ci std::string> &options, GlobalFormatterType &types); 1844514f5e3Sopenharmony_ci std::map<GlobalFormatterType, std::map<std::string, JSHandle<JSTaggedValue>>> optionMaps; 1854514f5e3Sopenharmony_ci std::string EcmaConvertToStr(const JSHandle<EcmaString> &string); 1864514f5e3Sopenharmony_ci std::vector<std::string> TaggedArrayToVector(JSThread *thread, JSHandle<TaggedArray> &taggedarray); 1874514f5e3Sopenharmony_ci}; 1884514f5e3Sopenharmony_ci} // panda::ecmascript::base 1894514f5e3Sopenharmony_ci#endif // ECMASCRIPT_BASE_GLOBAL_INTL_HELPER_H