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