• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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 #ifndef ECMASCRIPT_BASE_GLOBAL_INTL_HELPER_H
17 #define ECMASCRIPT_BASE_GLOBAL_INTL_HELPER_H
18 
19 #include <iostream>
20 #include <cstdint>
21 #include <cmath>
22 #include <vector>
23 #include <map>
24 #include <string>
25 #include <chrono>
26 #include <math.h>
27 
28 #include "ecmascript/ecma_vm.h"
29 #include "ecmascript/mem/native_area_allocator.h"
30 #include "ecmascript/js_handle.h"
31 #include "base/global/i18n/frameworks/intl/include/collator.h"
32 #if defined(__clang__)
33 #pragma clang diagnostic push
34 #pragma clang diagnostic ignored "-Wshadow"
35 #elif defined(__GNUC__)
36 #pragma GCC diagnostic push
37 #pragma GCC diagnostic ignored "-Wshadow"
38 #endif
39 #include "base/global/i18n/frameworks/intl/include/number_format.h"
40 #include "base/global/i18n/frameworks/intl/include/date_time_format.h"
41 #if defined(__clang__)
42 #pragma clang diagnostic pop
43 #elif defined(__GNUC__)
44 #pragma GCC diagnostic pop
45 #endif
46 
47 namespace panda::ecmascript::intl {
48 using GlobalCollator = OHOS::Global::I18n::Collator;
49 using GlobalNumberFormat = OHOS::Global::I18n::NumberFormat;
50 using GlobalDateFormatter = OHOS::Global::I18n::DateTimeFormat;
51 using GlobalCompareResult = OHOS::Global::I18n::CompareResult;
52 
53 enum class GlobalFormatterType {
54     DateFormatter,
55     SimpleDateFormatDate,
56     SimpleDateFormatTime,
57     NumberFormatter,
58     Collator
59 };
60 
61 class GlobalIntlHelper {
62 public:
63     GlobalIntlHelper(JSThread *thread, const GlobalFormatterType matterType);
~GlobalIntlHelper()64     ~GlobalIntlHelper()
65     {
66         if (dateUnitArr != nullptr) {
67             delete[] dateUnitArr;
68         }
69         globalObject = nullptr;
70     }
71 
72     template<typename T>
GetGlobalObject(JSThread * thread,const JSHandle<JSTaggedValue> & locales,const JSHandle<JSTaggedValue> & options,GlobalFormatterType types)73     std::unique_ptr<T> GetGlobalObject(JSThread *thread, const JSHandle<JSTaggedValue> &locales,
74         const JSHandle<JSTaggedValue> &options, GlobalFormatterType types)
75     {
76         std::vector<std::string> cacheEntryVector;
77         cacheEntryVector = LocalesToVector(thread, locales);
78         std::map<std::string, std::string> inputOptions;
79         if (!options->IsUndefined()) {
80             inputOptions = OptionsToMap(thread, options, types);
81         }
82         auto result = std::make_unique<T>(cacheEntryVector, inputOptions);
83         return result;
84     }
85 
86     template<typename T>
GetGlobalObject(JSThread * thread,const JSHandle<JSTaggedValue> & locales,const JSHandle<JSTaggedValue> & options,GlobalFormatterType types,const bool cache)87     T *GetGlobalObject(JSThread *thread, const JSHandle<JSTaggedValue> &locales,
88         const JSHandle<JSTaggedValue> &options, GlobalFormatterType types, const bool cache)
89     {
90         IcuFormatterType icuType;
91         switch (types) {
92             case GlobalFormatterType::Collator:
93                 icuType = IcuFormatterType::COLLATOR;
94                 break;
95             case GlobalFormatterType::SimpleDateFormatDate:
96                 icuType = IcuFormatterType::SIMPLE_DATE_FORMAT_DATE;
97                 break;
98             case GlobalFormatterType::SimpleDateFormatTime:
99                 icuType = IcuFormatterType::SIMPLE_DATE_FORMAT_TIME;
100                 break;
101             case GlobalFormatterType::DateFormatter:
102                 icuType = IcuFormatterType::SIMPLE_DATE_FORMAT_DEFAULT;
103                 break;
104             case GlobalFormatterType::NumberFormatter:
105                 icuType = IcuFormatterType::NUMBER_FORMATTER;
106                 break;
107         }
108         EcmaVM *ecmaVm = thread->GetEcmaVM();
109         std::string cacheEntry = locales->IsUndefined() ? "" :
110             EcmaStringAccessor(locales.GetTaggedValue()).ToStdString();
111         if (cache) {
112             void *cachedCollator = ecmaVm->GetIcuFormatterFromCache(icuType, cacheEntry);
113             if (cachedCollator != nullptr) {
114                 return reinterpret_cast<T *>(cachedCollator);
115             }
116         }
117         std::unique_ptr<T> tObject = GetGlobalObject<T>(thread, locales, options, types);
118         if (cache) {
119             T *cacheObject = tObject.release();
120             switch (icuType) {
121                 case IcuFormatterType::COLLATOR:
122                     ecmaVm->SetIcuFormatterToCache(icuType, cacheEntry, cacheObject, FreeCollatorFormat);
123                     break;
124                 case IcuFormatterType::SIMPLE_DATE_FORMAT_DATE:
125                 case IcuFormatterType::SIMPLE_DATE_FORMAT_TIME:
126                 case IcuFormatterType::SIMPLE_DATE_FORMAT_DEFAULT:
127                     ecmaVm->SetIcuFormatterToCache(icuType, cacheEntry, cacheObject, FreeDateTimeFormat);
128                     break;
129                 case IcuFormatterType::NUMBER_FORMATTER:
130                     ecmaVm->SetIcuFormatterToCache(icuType, cacheEntry, cacheObject, FreeNumberFormat);
131                     break;
132             }
133             return cacheObject;
134         }
135         globalObject = tObject.release();
136         return reinterpret_cast<T *>(globalObject);
137     }
FreeCollatorFormat(void * pointer,void * data)138     static void FreeCollatorFormat(void *pointer, void *data)
139     {
140         if (pointer == nullptr) {
141             return;
142         }
143         auto globalCollator = reinterpret_cast<GlobalCollator*>(pointer);
144         globalCollator->~Collator();
145         if (data != nullptr) {
146             reinterpret_cast<EcmaVM *>(data)->GetNativeAreaAllocator()->FreeBuffer(pointer);
147         }
148     }
FreeNumberFormat(void * pointer,void * data)149     static void FreeNumberFormat(void *pointer, void *data)
150     {
151         if (pointer == nullptr) {
152             return;
153         }
154         auto globalNumberFormat = reinterpret_cast<GlobalNumberFormat*>(pointer);
155         globalNumberFormat->~NumberFormat();
156         if (data != nullptr) {
157             reinterpret_cast<EcmaVM *>(data)->GetNativeAreaAllocator()->FreeBuffer(pointer);
158         }
159     }
FreeDateTimeFormat(void * pointer,void * data)160     static void FreeDateTimeFormat(void *pointer, void *data)
161     {
162         if (pointer == nullptr) {
163             return;
164         }
165         auto globalDateFormatter = reinterpret_cast<GlobalDateFormatter*>(pointer);
166         globalDateFormatter->~DateTimeFormat();
167         if (data != nullptr) {
168             reinterpret_cast<EcmaVM *>(data)->GetNativeAreaAllocator()->FreeBuffer(pointer);
169         }
170     }
171     std::vector<std::string> LocalesToVector(JSThread *thread, const JSHandle<JSTaggedValue> &locales);
172     std::map<std::string, std::string> OptionsToMap(JSThread *thread,
173         const JSHandle<JSTaggedValue> &options, GlobalFormatterType types);
174     uint64_t *ConvertDateToUnit(uint64_t timestamp);
175     static int64_t DoubleToInt64(double value);
176 private:
177     void *globalObject = nullptr;
178     uint64_t *dateUnitArr = nullptr;
179     void InitCollatorData(const GlobalEnvConstants *globalConst);
180     void InitNumberData(const GlobalEnvConstants *globalConst);
181     void InitDateData(const GlobalEnvConstants *globalConst);
182     std::map<std::string, std::string> OptionsWithDataFormatter(std::map<std::string,
183         std::string> &options, GlobalFormatterType &types);
184     std::map<GlobalFormatterType, std::map<std::string, JSHandle<JSTaggedValue>>> optionMaps;
185     std::string EcmaConvertToStr(const JSHandle<EcmaString> &string);
186     std::vector<std::string> TaggedArrayToVector(JSThread *thread, JSHandle<TaggedArray> &taggedarray);
187 };
188 }  // panda::ecmascript::base
189 #endif  // ECMASCRIPT_BASE_GLOBAL_INTL_HELPER_H