• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #include <vector>
16 #include <utility>
17 #include <map>
18 #include <memory>
19 #include <string>
20 
21 #include "i18n_ffi.h"
22 #include "i18n_hilog.h"
23 #include "i18n_util_ffi.h"
24 #include "locale_config.h"
25 #include "locale_info.h"
26 #include "character.h"
27 #include "utils.h"
28 #include "unicode/locid.h"
29 #include "unicode/datefmt.h"
30 #include "unicode/smpdtfmt.h"
31 #include "i18n_struct.h"
32 #include "locale_matcher.h"
33 #include "measure_data.h"
34 #include "number_format.h"
35 #include "date_time_sequence.h"
36 
37 namespace OHOS {
38 namespace Global {
39 namespace I18n {
convert2CppStringArray(const CArrStr & carrStr)40 std::vector<std::string> convert2CppStringArray(const CArrStr& carrStr)
41 {
42     std::vector<std::string> cppStringArray;
43     for (int i = 0; i < carrStr.length; ++i) {
44         cppStringArray.push_back(carrStr.data[i]);
45     }
46     return cppStringArray;
47 }
48 
49 extern "C" {
ReleaseParam(LocaleInfo * locale,std::vector<LocaleInfo * > & candidateLocales)50 void ReleaseParam(LocaleInfo *locale, std::vector<LocaleInfo*> &candidateLocales)
51 {
52     delete locale;
53     for (auto it = candidateLocales.begin(); it != candidateLocales.end(); ++it) {
54         delete *it;
55     }
56 }
57 
GetLocaleInfo(std::string localeStr,int32_t * errcode)58 LocaleInfo* GetLocaleInfo(std::string localeStr, int32_t* errcode)
59 {
60     UErrorCode status = U_ZERO_ERROR;
61     icu::Locale locale = icu::Locale::forLanguageTag(localeStr, status);
62     if (U_FAILURE(status) || !IsValidLocaleTag(locale)) {
63         *errcode = I18N_NOT_VALID;
64         return nullptr;
65     }
66     return new LocaleInfo(localeStr);
67 }
68 
ProcessLocaleList(std::vector<std::string> localeTagList,std::vector<LocaleInfo * > & candidateLocales,LocaleInfo * requestLocale,int32_t * errcode)69 bool ProcessLocaleList(std::vector<std::string> localeTagList,
70     std::vector<LocaleInfo*> &candidateLocales, LocaleInfo *requestLocale, int32_t* errcode)
71     {
72     if (localeTagList.size() == 0) {
73         *errcode = I18N_NOT_VALID;
74         return true;
75     }
76     for (auto it = localeTagList.begin(); it != localeTagList.end(); ++it) {
77         UErrorCode icuStatus = U_ZERO_ERROR;
78         icu::Locale locale = icu::Locale::forLanguageTag(it->data(), icuStatus);
79         if (U_FAILURE(icuStatus) || !IsValidLocaleTag(locale)) {
80             *errcode = I18N_NOT_VALID;
81             return false;
82         }
83         LocaleInfo *temp = new LocaleInfo(*it);
84         if (LocaleMatcher::Match(requestLocale, temp)) {
85             candidateLocales.push_back(temp);
86         } else {
87             delete temp;
88         }
89     }
90     return true;
91 }
92 
FfiI18nUtilUnitConvert(UnitInfo fromUnit,UnitInfo toUnit,double value,char * locale,char * style)93 char* FfiI18nUtilUnitConvert(UnitInfo fromUnit, UnitInfo toUnit, double value, char* locale, char* style)
94 {
95     double number = value;
96     std::string fromInfoUnit(fromUnit.unit);
97     std::string fromInfoMeasureSystem(fromUnit.measureSystem);
98     std::string toInfoUnit(toUnit.unit);
99     std::string toInfoMeasureSystem(toUnit.measureSystem);
100 
101     int32_t convertStatus = Convert(number, fromInfoUnit, fromInfoMeasureSystem, toInfoUnit, toInfoMeasureSystem);
102 
103     std::vector<std::string> localeTags;
104     std::map<std::string, std::string> map = {};
105 
106     map.insert(std::make_pair("style", "unit"));
107     if (!convertStatus) {
108         map.insert(std::make_pair("unit", fromInfoUnit));
109     } else {
110         map.insert(std::make_pair("unit", toInfoUnit));
111     }
112     map.insert(std::make_pair("unitDisplay", std::string(style)));
113     std::string localeTag(locale);
114     localeTags.push_back(localeTag);
115     std::unique_ptr<NumberFormat> numberFmt = nullptr;
116     numberFmt = std::make_unique<NumberFormat>(localeTags, map);
117     std::string result = numberFmt->Format(number);
118     char* res = MallocCString(result);
119     return res;
120 }
121 
FfiI18nUtilGetBestMatchLocale(char * locale,CArrStr localeList,int32_t * errCode)122 char* FfiI18nUtilGetBestMatchLocale(char* locale, CArrStr localeList, int32_t* errCode)
123 {
124     std::vector<std::string> localeArr = convert2CppStringArray(localeList);
125     std::string localeStr(locale);
126     LocaleInfo *requestLocale = GetLocaleInfo(localeStr, errCode);
127     if (requestLocale == nullptr) {
128         return nullptr;
129     }
130     std::vector<LocaleInfo*> candidateLocales;
131     bool isVaildParam = ProcessLocaleList(localeArr, candidateLocales, requestLocale, errCode);
132     if (!isVaildParam) {
133         *errCode = I18N_NOT_VALID;
134         ReleaseParam(requestLocale, candidateLocales);
135         return nullptr;
136     }
137     std::string bestMatchLocaleTag = "";
138     if (candidateLocales.size() > 0) {
139         LocaleInfo *bestMatch = candidateLocales[0];
140         for (size_t i = 1; i < candidateLocales.size(); ++i) {
141             if (LocaleMatcher::IsMoreSuitable(bestMatch, candidateLocales[i], requestLocale) < 0) {
142                 bestMatch = candidateLocales[i];
143             }
144         }
145         bestMatchLocaleTag = bestMatch->ToString();
146     }
147     ReleaseParam(requestLocale, candidateLocales);
148     char* res = MallocCString(bestMatchLocaleTag);
149     return res;
150 }
151 
FfiI18nUtilGetDateOrder(char * locale)152 char* FfiI18nUtilGetDateOrder(char* locale)
153 {
154     std::string loacleStr(locale);
155     char* res = MallocCString(DateTimeSequence::GetDateOrder(loacleStr));
156     return res;
157 }
158 
FfiI18nUtilGetTimePeriodName(int32_t hour,char * locale,int32_t * errcode)159 char* FfiI18nUtilGetTimePeriodName(int32_t hour, char* locale, int32_t* errcode)
160 {
161     std::string localeTag;
162     if (locale == nullptr) {
163         localeTag = LocaleConfig::GetSystemLocale();
164     } else {
165         localeTag = std::string(locale);
166     }
167     UErrorCode status = U_ZERO_ERROR;
168     icu::Locale localeIcu = icu::Locale::forLanguageTag(localeTag, status);
169     if (U_FAILURE(status) || !IsValidLocaleTag(localeIcu)) {
170         *errcode = I18N_NOT_VALID;
171         return nullptr;
172     }
173     icu::DateFormat* dateFormatter = icu::DateFormat::createDateInstance(icu::DateFormat::EStyle::kDefault, locale);
174     if (dateFormatter == nullptr) {
175         *errcode = I18N_NOT_VALID;
176         return nullptr;
177     }
178     icu::SimpleDateFormat* formatter = static_cast<icu::SimpleDateFormat*>(dateFormatter);
179     formatter->applyPattern("B");
180     std::string temp;
181     icu::UnicodeString name;
182     icu::Calendar *calendar = icu::Calendar::createInstance(locale, status);
183     if (calendar == nullptr) {
184         *errcode = I18N_NOT_VALID;
185         delete formatter;
186         return nullptr;
187     }
188     calendar->set(UCalendarDateFields::UCAL_HOUR_OF_DAY, hour);
189     formatter->format(calendar->getTime(status), name);
190     name.toUTF8String(temp);
191     char* res = MallocCString(PseudoLocalizationProcessor(temp));
192     delete formatter;
193     delete calendar;
194     return res;
195 }
196 
FfiI18nUtilGetThreeLetterLanguage(char * locale,int32_t * errcode)197 char* FfiI18nUtilGetThreeLetterLanguage(char* locale, int32_t* errcode)
198 {
199     std::string language = GetISO3Language(std::string(locale));
200     if (language.empty()) {
201         *errcode = I18N_NOT_VALID;
202         HILOG_ERROR_I18N("GetThreeLetterLanguage create string fail or empty");
203         return nullptr;
204     }
205     char* res = MallocCString(language);
206     return res;
207 }
208 
FfiI18nUtilGetThreeLetterRegion(char * locale,int32_t * errcode)209 char* FfiI18nUtilGetThreeLetterRegion(char* locale, int32_t* errcode)
210 {
211     std::string country = GetISO3Country(std::string(locale));
212     if (country.empty()) {
213         HILOG_ERROR_I18N("GetThreeLetterRegion create string fail or empty");
214         *errcode = I18N_NOT_VALID;
215         return nullptr;
216     }
217     char* res = MallocCString(country);
218     return res;
219 }
220 }
221 }  // namespace I18n
222 }  // namespace Global
223 }  // namespace OHOS
224