• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
26 namespace panda::ecmascript::intl {
GlobalIntlHelper(JSThread * thread,const GlobalFormatterType matterType)27 GlobalIntlHelper::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 
ConvertDateToUnit(uint64_t timestamp)49 uint64_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 
InitCollatorData(const GlobalEnvConstants * globalConst)72 void 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 
InitDateData(const GlobalEnvConstants * globalConst)85 void 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 
InitNumberData(const GlobalEnvConstants * globalConst)110 void 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 
OptionsToMap(JSThread * thread,const JSHandle<JSTaggedValue> & options,GlobalFormatterType types)133 std::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 
OptionsWithDataFormatter(std::map<std::string,std::string> & options,GlobalFormatterType & types)173 std::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 
DoubleToInt64(double value)195 int64_t GlobalIntlHelper::DoubleToInt64(double value)
196 {
197     return static_cast<int64_t>(round(value));
198 }
199 
EcmaConvertToStr(const JSHandle<EcmaString> & string)200 std::string GlobalIntlHelper::EcmaConvertToStr(const JSHandle<EcmaString> &string)
201 {
202     return std::string(ConvertToString(*string, StringConvertedUsage::LOGICOPERATION));
203 }
204 
LocalesToVector(JSThread * thread,const JSHandle<JSTaggedValue> & locales)205 std::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 
TaggedArrayToVector(JSThread * thread,JSHandle<TaggedArray> & taggedarray)212 std::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