1/* 2 * Copyright (c) 2021 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 "ecmascript/intl/global_intl_helper.h" 17 18#include "ecmascript/intl/locale_helper.h" 19#include "ecmascript/ecma_macros.h" 20#include "ecmascript/ecma_vm.h" 21#include "ecmascript/global_env.h" 22#include "ecmascript/object_factory.h" 23#include "ecmascript/js_object.h" 24#include "ecmascript/mem/c_string.h" 25 26namespace panda::ecmascript::intl { 27GlobalIntlHelper::GlobalIntlHelper(JSThread *thread, 28 const GlobalFormatterType matterType) 29{ 30 const GlobalEnvConstants *globalConst = thread->GlobalConstants(); 31 auto iter = optionMaps.find(matterType); 32 if (iter == optionMaps.end()) { 33 switch (matterType) { 34 case GlobalFormatterType::Collator: 35 InitCollatorData(globalConst); 36 break; 37 case GlobalFormatterType::SimpleDateFormatDate: 38 case GlobalFormatterType::SimpleDateFormatTime: 39 case GlobalFormatterType::DateFormatter: 40 InitDateData(globalConst); 41 break; 42 case GlobalFormatterType::NumberFormatter: 43 InitNumberData(globalConst); 44 break; 45 } 46 } 47} 48 49uint64_t *GlobalIntlHelper::ConvertDateToUnit(uint64_t timestamp) 50{ 51 const uint64_t baseYear = 1900; 52 const uint64_t baseTimeSec = 60; 53 const uint64_t baseTimeUTC = 8; 54 const uint64_t baseTime = 1000; 55 auto milli = timestamp + static_cast<uint64_t>(baseTimeUTC * 56 baseTimeSec * baseTimeSec * baseTime); 57 auto mTime = std::chrono::milliseconds(milli); 58 auto tp = std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>(mTime); 59 auto tt = std::chrono::system_clock::to_time_t(tp); 60 std::tm *now = std::gmtime(&tt); 61 dateUnitArr = new uint64_t[6] { 62 static_cast<uint64_t>(now->tm_year + baseYear), 63 static_cast<uint64_t>(now->tm_mon + 1), 64 static_cast<uint64_t>(now->tm_mday), 65 static_cast<uint64_t>(now->tm_hour), 66 static_cast<uint64_t>(now->tm_min), 67 static_cast<uint64_t>(now->tm_sec) 68 }; 69 return dateUnitArr; 70} 71 72void GlobalIntlHelper::InitCollatorData(const GlobalEnvConstants *globalConst) 73{ 74 std::map<std::string, JSHandle<JSTaggedValue>> collatorMap; 75 collatorMap["localeMatcher"] = globalConst->GetHandledLocaleMatcherString(); 76 collatorMap["usage"] = globalConst->GetHandledUsageString(); 77 collatorMap["sensitivity"] = globalConst->GetHandledSensitivityString(); 78 collatorMap["ignorePunctuation"] = globalConst->GetHandledIgnorePunctuationString(); 79 collatorMap["numeric"] = globalConst->GetHandledNumericString(); 80 collatorMap["caseFirst"] = globalConst->GetHandledCaseFirstString(); 81 collatorMap["collation"] = globalConst->GetHandledCollationString(); 82 optionMaps.insert(make_pair(GlobalFormatterType::Collator, collatorMap)); 83} 84 85void GlobalIntlHelper::InitDateData(const GlobalEnvConstants *globalConst) 86{ 87 std::map<std::string, JSHandle<JSTaggedValue>> collatorMap; 88 collatorMap["dateStyle"] = globalConst->GetHandledDateStyleString(); 89 collatorMap["timeStyle"] = globalConst->GetHandledTimeStyleString(); 90 collatorMap["calendar"] = globalConst->GetHandledCalendarString(); 91 collatorMap["numberingSystem"] = globalConst->GetHandledNumberingSystemString(); 92 collatorMap["localeMatcher"] = globalConst->GetHandledLocaleMatcherString(); 93 collatorMap["timeZone"] = globalConst->GetHandledTimeZoneString(); 94 collatorMap["hour12"] = globalConst->GetHandledHour12String(); 95 collatorMap["hourCycle"] = globalConst->GetHandledHourCycleString(); 96 collatorMap["formatMatcher"] = globalConst->GetHandledFormatMatcherString(); 97 collatorMap["weekday"] = globalConst->GetHandledWeekdayString(); 98 collatorMap["era"] = globalConst->GetHandledEraString(); 99 collatorMap["year"] = globalConst->GetHandledYearString(); 100 collatorMap["month"] = globalConst->GetHandledMonthString(); 101 collatorMap["day"] = globalConst->GetHandledDayString(); 102 collatorMap["hour"] = globalConst->GetHandledHourString(); 103 collatorMap["minute"] = globalConst->GetHandledMinuteString(); 104 collatorMap["second"] = globalConst->GetHandledSecondString(); 105 collatorMap["fractionalSecondDigits"] = globalConst->GetHandledFractionalSecondDigitsString(); 106 collatorMap["timeZoneName"] = globalConst->GetHandledTimeZoneNameString(); 107 optionMaps.insert(make_pair(GlobalFormatterType::DateFormatter, collatorMap)); 108} 109 110void GlobalIntlHelper::InitNumberData(const GlobalEnvConstants *globalConst) 111{ 112 std::map<std::string, JSHandle<JSTaggedValue>> collatorMap; 113 collatorMap["localeMatcher"] = globalConst->GetHandledLocaleMatcherString(); 114 collatorMap["numberingSystem"] = globalConst->GetHandledNumberingSystemString(); 115 collatorMap["notation"] = globalConst->GetHandledNotationString(); 116 collatorMap["compactDisplay"] = globalConst->GetHandledCompactDisplayString(); 117 collatorMap["useGrouping"] = globalConst->GetHandledUserGroupingString(); 118 collatorMap["signDisplay"] = globalConst->GetHandledSignDisplayString(); 119 collatorMap["style"] = globalConst->GetHandledStyleString(); 120 collatorMap["currency"] = globalConst->GetHandledCurrencyString(); 121 collatorMap["currencySign"] = globalConst->GetHandledCurrencySignString(); 122 collatorMap["currencyDisplay"] = globalConst->GetHandledCurrencyDisplayString(); 123 collatorMap["unit"] = globalConst->GetHandledUnitString(); 124 collatorMap["unitDisplay"] = globalConst->GetHandledUnitDisplayString(); 125 collatorMap["minimumIntegerDigits"] = globalConst->GetHandledMinimumIntegerDigitsString(); 126 collatorMap["minimumFractionDigits"] = globalConst->GetHandledMinimumFractionDigitsString(); 127 collatorMap["maximumFractionDigits"] = globalConst->GetHandledMaximumFractionDigitsString(); 128 collatorMap["minimumSignificantDigits"] = globalConst->GetHandledMinimumSignificantDigitsString(); 129 collatorMap["maximumSignificantDigits"] = globalConst->GetHandledMaximumSignificantDigitsString(); 130 optionMaps.insert(make_pair(GlobalFormatterType::NumberFormatter, collatorMap)); 131} 132 133std::map<std::string, std::string> GlobalIntlHelper::OptionsToMap(JSThread *thread, 134 const JSHandle<JSTaggedValue> &options, GlobalFormatterType types) 135{ 136 std::map<std::string, std::string> inputOptions; 137 JSHandle<JSObject> optionsObject; 138 if (options->IsUndefined()) { 139 return inputOptions; 140 } else { 141 optionsObject = JSTaggedValue::ToObject(thread, options); 142 } 143 if (optionMaps.size() == 0) { 144 LOG_ECMA(ERROR) << "GlobalIntlHelper::OptionsToMap size is zero"; 145 return inputOptions; 146 } 147 148 auto matterType = types; 149 if (types == GlobalFormatterType::SimpleDateFormatDate || 150 types == GlobalFormatterType::SimpleDateFormatTime) { 151 matterType = GlobalFormatterType::DateFormatter; 152 } 153 154 auto iter = optionMaps.find(matterType); 155 if (iter != optionMaps.end()) { 156 for (auto &opt : optionMaps[matterType]) { 157 OperationResult operationResult = JSObject::GetProperty(thread, optionsObject, opt.second); 158 if (!operationResult.GetValue()->IsUndefined()) { 159 std::string valueStr = std::string(EcmaConvertToStr(JSTaggedValue::ToString(thread, 160 operationResult.GetValue()))); 161 auto inOpt = inputOptions.find(opt.first); 162 if (inOpt != inputOptions.end()) { 163 inputOptions[opt.first] = valueStr; 164 } else { 165 inputOptions.insert(make_pair(opt.first, valueStr)); 166 } 167 } 168 } 169 } 170 return OptionsWithDataFormatter(inputOptions, types); 171} 172 173std::map<std::string, std::string> GlobalIntlHelper::OptionsWithDataFormatter(std::map<std::string, 174 std::string> &options, GlobalFormatterType &types) 175{ 176 std::vector<std::string> all; 177 if (types == GlobalFormatterType::DateFormatter) { 178 all = {"year", "month", "day", "hour", "minute", "second"}; 179 } 180 if (types == GlobalFormatterType::SimpleDateFormatDate) { 181 all = {"year", "month", "day"}; 182 } 183 if (types == GlobalFormatterType::SimpleDateFormatTime) { 184 all = {"hour", "minute", "second"}; 185 } 186 for (auto &item : all) { 187 auto iter = options.find(item); 188 if (iter == options.end()) { 189 options[item] = "numeric"; 190 } 191 } 192 return options; 193} 194 195int64_t GlobalIntlHelper::DoubleToInt64(double value) 196{ 197 return static_cast<int64_t>(round(value)); 198} 199 200std::string GlobalIntlHelper::EcmaConvertToStr(const JSHandle<EcmaString> &string) 201{ 202 return std::string(ConvertToString(*string, StringConvertedUsage::LOGICOPERATION)); 203} 204 205std::vector<std::string> GlobalIntlHelper::LocalesToVector(JSThread *thread, 206 const JSHandle<JSTaggedValue> &locales) 207{ 208 JSHandle<TaggedArray> tArray = intl::LocaleHelper::CanonicalizeLocaleList(thread, locales); 209 return TaggedArrayToVector(thread, tArray); 210} 211 212std::vector<std::string> GlobalIntlHelper::TaggedArrayToVector(JSThread *thread, 213 JSHandle<TaggedArray> &taggedarray) 214{ 215 std::vector<std::string> availableStringLocales; 216 JSMutableHandle<EcmaString> availableItem(thread, JSTaggedValue::Undefined()); 217 uint32_t availablecalesLength = taggedarray->GetLength(); 218 for (uint32_t i = 0; i < availablecalesLength; i++) { 219 availableItem.Update(taggedarray->Get(thread, i)); 220 availableStringLocales.emplace_back(intl::LocaleHelper::ConvertToStdString(availableItem)); 221 } 222 return availableStringLocales; 223} 224} // panda::ecmascript::base 225