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
16 #include <dirent.h>
17 #include <fcntl.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include "update_geocoding.h"
21
22 namespace i18n {
23 namespace phonenumbers {
24 const std::string UpdateGeocoding::GEOCODING_NAME = "/system/etc/icu_tzdata/i18n/GeocodingInfo";
25
26 GeocodingInfo* UpdateGeocoding::geocodingInfo = nullptr;
27
28 std::map<std::string, PrefixDescriptions>* UpdateGeocoding::prefixDescriptionsMap = new std::map<std::string, PrefixDescriptions>();
29 std::map<std::string, PrefixesInfo>* UpdateGeocoding::prefixesInfoMap = new std::map<std::string, PrefixesInfo>();
30 const PrefixDescriptions** UpdateGeocoding::prefixDescriptionsArray = nullptr;
31 LanguageCodeInfo* UpdateGeocoding::languageCodeInfo = nullptr;
32 bool UpdateGeocoding::isupdatedLanguageCodes = false;
33 const char** UpdateGeocoding::preLanguageCodes = nullptr;
34 const char** UpdateGeocoding::curLanguageCodes = nullptr;
35 int UpdateGeocoding::curLanguageCodesSize = 0;
36 int UpdateGeocoding::preLanguageCodesSize = 0;
37
38 std::map<int, CountryLanguages>* UpdateGeocoding::countryLanguagesMap = new std::map<int, CountryLanguages>();
39 std::map<int, CountriesInfo>* UpdateGeocoding::countriesInfoMap = new std::map<int, CountriesInfo>();
40 const CountryLanguages** UpdateGeocoding::countryLanguagesArray = nullptr;
41 CountryCodeInfo* UpdateGeocoding::countryCodeInfo = nullptr;
42 bool UpdateGeocoding::isupdatedCountryCodes = false;
43 const int* UpdateGeocoding::preCountryCodes = nullptr;
44 int* UpdateGeocoding::curCountryCodes = nullptr;
45 int UpdateGeocoding::curCountryCodesSize = 0;
46 int UpdateGeocoding::preCountryCodesSize = 0;
47
LoadGeocodingData(int fd)48 void UpdateGeocoding::LoadGeocodingData(int fd)
49 {
50 if (geocodingInfo != nullptr) {
51 return;
52 }
53 if (fd == -1) {
54 return;
55 }
56 geocodingInfo = new GeocodingInfo();
57 geocodingInfo->ParseFromFileDescriptor(fd);
58 languageCodeInfo = new LanguageCodeInfo(geocodingInfo->language_code_info());
59 countryCodeInfo = new CountryCodeInfo(geocodingInfo->country_code_info());
60 for (int i = 0; i < geocodingInfo->languages_size(); i++) {
61 prefixesInfoMap->insert(std::make_pair(geocodingInfo->languages(i), geocodingInfo->prefixes_info(i)));
62 }
63 for (int i = 0; i < geocodingInfo->countries_size(); i++) {
64 countriesInfoMap->insert(std::make_pair(geocodingInfo->countries(i), geocodingInfo->countries_info(i)));
65 }
66 }
67
UpdatePrefixDescriptions(const PrefixDescriptions ** prePrefixDescriptionsArray,int index)68 const PrefixDescriptions* UpdateGeocoding::UpdatePrefixDescriptions(
69 const PrefixDescriptions** prePrefixDescriptionsArray, int index)
70 {
71 prefixDescriptionsArray = prePrefixDescriptionsArray;
72 std::string languageCode = isupdatedLanguageCodes ? curLanguageCodes[index] : preLanguageCodes[index];
73 if (prefixDescriptionsMap->find(languageCode) != prefixDescriptionsMap->end()) {
74 return &prefixDescriptionsMap->at(languageCode);
75 }
76 int preIndex = isupdatedLanguageCodes ? FindLanguageCode(languageCode) : index;
77 AddPrefixDescriptions(languageCode, preIndex);
78
79 if (prefixDescriptionsMap->find(languageCode) == prefixDescriptionsMap->end()) {
80 prefixDescriptionsMap->insert(std::make_pair(languageCode, *(prefixDescriptionsArray[preIndex])));
81 }
82 return &prefixDescriptionsMap->at(languageCode);
83 }
84
UpdateLanguageCodes(const char ** languageCodes,int languageCodesSize)85 const char** UpdateGeocoding::UpdateLanguageCodes(const char** languageCodes, int languageCodesSize)
86 {
87 preLanguageCodes = languageCodes;
88 preLanguageCodesSize = languageCodesSize;
89 if (languageCodeInfo == nullptr || languageCodeInfo->language_codes_size() == 0) {
90 return preLanguageCodes;
91 }
92 int curLength = languageCodeInfo->language_codes_num();
93 curLanguageCodesSize = curLength;
94 curLanguageCodes = (const char **)malloc(sizeof(char*) * curLength);
95 if (!curLanguageCodes) {
96 return preLanguageCodes;
97 }
98 int preIndex = 0;
99 int curIndex = 0;
100 int mdyIndex = 0;
101 while (preIndex < preLanguageCodesSize && mdyIndex < languageCodeInfo->language_codes_size()) {
102 if (strcmp(languageCodeInfo->language_codes(mdyIndex).c_str(), preLanguageCodes[preIndex]) < 0) {
103 curLanguageCodes[curIndex] = WriteStr(languageCodeInfo->language_codes(mdyIndex));
104 curIndex++;
105 mdyIndex++;
106 } else if (strcmp(languageCodeInfo->language_codes(mdyIndex).c_str(), preLanguageCodes[preIndex]) == 0) {
107 preIndex++;
108 mdyIndex++;
109 } else {
110 curLanguageCodes[curIndex] = preLanguageCodes[preIndex];
111 curIndex++;
112 preIndex++;
113 }
114 }
115
116 while (preIndex < preLanguageCodesSize) {
117 curLanguageCodes[curIndex] = preLanguageCodes[preIndex];
118 curIndex++;
119 preIndex++;
120 }
121
122 while (mdyIndex < languageCodeInfo->language_codes_size()) {
123 curLanguageCodes[curIndex] = WriteStr(languageCodeInfo->language_codes(mdyIndex));
124 curIndex++;
125 mdyIndex++;
126 }
127 isupdatedLanguageCodes = true;
128 return curLanguageCodes;
129 }
130
UpdateLanguageCodesSize()131 int UpdateGeocoding::UpdateLanguageCodesSize()
132 {
133 if (isupdatedLanguageCodes) {
134 return curLanguageCodesSize;
135 }
136 return preLanguageCodesSize;
137 }
138
AddPrefixDescriptions(const std::string & languageCode,int index)139 void UpdateGeocoding::AddPrefixDescriptions(const std::string& languageCode, int index)
140 {
141 if (prefixesInfoMap->find(languageCode) == prefixesInfoMap->end()) {
142 return;
143 }
144 PrefixesInfo prefixesInfo = prefixesInfoMap->at(languageCode);
145 int prefixesSize = static_cast<int>(prefixesInfo.prefixes_num());
146 int32_t* prefixes = (int32_t*)malloc(sizeof(int32_t) * prefixesSize);
147 if (!prefixes) {
148 return;
149 }
150 memset(prefixes, 0, sizeof(int32_t) * prefixesSize);
151 const char** descriptions = (const char **)malloc(sizeof(char*) * prefixesSize);
152 if (!descriptions) {
153 return;
154 }
155 ModifyPrefixDescriptions(prefixes, descriptions, prefixesInfo, index);
156
157 int lengthsSize = prefixesInfo.lengths_num();
158 int32_t* possibleLengths = (int32_t*)malloc(sizeof(int32_t) * lengthsSize);
159 if (!possibleLengths) {
160 return;
161 }
162 ModifyPossibleLengths(possibleLengths, prefixesInfo, index);
163
164 PrefixDescriptions prefixDescriptions = {
165 prefixes,
166 prefixesSize,
167 descriptions,
168 possibleLengths,
169 lengthsSize
170 };
171 prefixDescriptionsMap->insert(std::make_pair(languageCode, prefixDescriptions));
172 }
173
ModifyPrefixDescriptions(int32_t * prefixes,const char ** descriptions,PrefixesInfo & prefixesInfo,int index)174 void UpdateGeocoding::ModifyPrefixDescriptions(int32_t* prefixes, const char** descriptions,
175 PrefixesInfo& prefixesInfo, int index)
176 {
177 int curIndex = 0;
178 int preIndex = 0;
179 int mdyIndex = 0;
180 const PrefixDescriptions* prefixDescriptions = nullptr;
181 std::string description;
182 int prefixesSize = 0;
183 if (index != -1) {
184 prefixDescriptions = prefixDescriptionsArray[index];
185 prefixesSize = prefixDescriptions->prefixes_size;
186 }
187 while (preIndex < prefixesSize && mdyIndex < prefixesInfo.prefixes_size()) {
188 int prePrefix = prefixDescriptions->prefixes[preIndex];
189 int mdyPrefix = static_cast<int>(prefixesInfo.prefixes(mdyIndex));
190 if (prePrefix == mdyPrefix) {
191 if (prefixesInfo.descriptions(mdyIndex) == "NULL") {
192 preIndex++;
193 mdyIndex++;
194 continue;
195 } else {
196 prefixes[curIndex] = mdyPrefix;
197 descriptions[curIndex] = WriteStr(prefixesInfo.descriptions(mdyIndex));
198 preIndex++;
199 mdyIndex++;
200 }
201 } else if (prePrefix > mdyPrefix) {
202 prefixes[curIndex] = mdyPrefix;
203 descriptions[curIndex] = WriteStr(prefixesInfo.descriptions(mdyIndex));
204 mdyIndex++;
205 } else {
206 prefixes[curIndex] = prePrefix;
207 descriptions[curIndex] = prefixDescriptions->descriptions[preIndex];
208 preIndex++;
209 }
210 curIndex++;
211 }
212 while (preIndex < prefixesSize) {
213 prefixes[curIndex] = prefixDescriptions->prefixes[preIndex];
214 descriptions[curIndex] = prefixDescriptions->descriptions[preIndex];
215 preIndex++;
216 curIndex++;
217 }
218 while (mdyIndex < prefixesInfo.prefixes_size()) {
219 prefixes[curIndex] = static_cast<int>(prefixesInfo.prefixes(mdyIndex));
220 descriptions[curIndex] = WriteStr(prefixesInfo.descriptions(mdyIndex));
221 mdyIndex++;
222 curIndex++;
223 }
224 }
225
ModifyPossibleLengths(int32_t * possibleLengths,PrefixesInfo & prefixesInfo,int index)226 void UpdateGeocoding::ModifyPossibleLengths(int32_t* possibleLengths, PrefixesInfo& prefixesInfo, int index)
227 {
228 if (index == -1) {
229 for (int i = 0; i < prefixesInfo.lengths_size(); i++) {
230 possibleLengths[i] = prefixesInfo.lengths(i);
231 }
232 } else {
233 for (int i = 0; i < prefixDescriptionsArray[index]->possible_lengths_size; i++) {
234 possibleLengths[i] = prefixDescriptionsArray[index]->possible_lengths[i];
235 }
236 }
237 }
238
UpdateCountryLanguages(const CountryLanguages ** preCountryLanguagesArray,int index)239 const CountryLanguages* UpdateGeocoding::UpdateCountryLanguages(const CountryLanguages** preCountryLanguagesArray, int index)
240 {
241 countryLanguagesArray = preCountryLanguagesArray;
242 int countryCode = isupdatedCountryCodes ? curCountryCodes[index] : preCountryCodes[index];
243 if (countryLanguagesMap->find(countryCode) != countryLanguagesMap->end()) {
244 return &countryLanguagesMap->at(countryCode);
245 }
246 int preIndex = isupdatedCountryCodes ? FindCountryCode(countryCode) : index;
247 AddCountryLanguages(countryCode);
248 if (countryLanguagesMap->find(countryCode) == countryLanguagesMap->end() && preIndex != -1) {
249 countryLanguagesMap->insert(std::make_pair(countryCode, *(countryLanguagesArray[preIndex])));
250 }
251 return &countryLanguagesMap->at(countryCode);
252 }
253
UpdateCountryCodes(const int * countryCodes,int countryCodesSize)254 const int* UpdateGeocoding::UpdateCountryCodes(const int* countryCodes, int countryCodesSize)
255 {
256 preCountryCodes = countryCodes;
257 preCountryCodesSize = countryCodesSize;
258 if (countryCodeInfo == nullptr || countryCodeInfo->country_codes_size() == 0) {
259 return preCountryCodes;
260 }
261 int curLength = countryCodeInfo->country_codes_num();
262 curCountryCodesSize = curLength;
263 curCountryCodes = (int *)malloc(sizeof(int) * curLength);
264 if (!curCountryCodes) {
265 return preCountryCodes;
266 }
267 int preIndex = 0;
268 int curIndex = 0;
269 int mdyIndex = 0;
270 while (preIndex < preCountryCodesSize && mdyIndex < countryCodeInfo->country_codes_size()) {
271 int preCountryCode = preCountryCodes[preIndex];
272 int mdyCountryCode = static_cast<int>(countryCodeInfo->country_codes(mdyIndex));
273 if (preCountryCode > mdyCountryCode) {
274 curCountryCodes[curIndex] = mdyCountryCode;
275 curIndex++;
276 mdyIndex++;
277 } else if (mdyCountryCode == preCountryCode) {
278 preIndex++;
279 mdyIndex++;
280 } else {
281 curCountryCodes[curIndex] = preCountryCode;
282 curIndex++;
283 preIndex++;
284 }
285 }
286 while (preIndex < preCountryCodesSize) {
287 curCountryCodes[curIndex] = preCountryCodes[preIndex];
288 curIndex++;
289 preIndex++;
290 }
291 while (mdyIndex < countryCodeInfo->country_codes_size()) {
292 curCountryCodes[curIndex] = static_cast<int>(countryCodeInfo->country_codes(mdyIndex));
293 curIndex++;
294 mdyIndex++;
295 }
296 isupdatedCountryCodes = true;
297 return curCountryCodes;
298 }
299
UpdateCountryCodesSize()300 int UpdateGeocoding::UpdateCountryCodesSize()
301 {
302 if (isupdatedCountryCodes) {
303 return curCountryCodesSize;
304 }
305 return preCountryCodesSize;
306 }
307
AddCountryLanguages(int countryCode)308 void UpdateGeocoding::AddCountryLanguages(int countryCode)
309 {
310 if (countriesInfoMap->find(countryCode) == countriesInfoMap->end()) {
311 return;
312 }
313 CountriesInfo countriesInfo = countriesInfoMap->at(countryCode);
314
315 int availableLanguagesSize = static_cast<int>(countriesInfo.country_languages_num());
316 const char** availableLanguages = (const char **)malloc(sizeof(char*) * availableLanguagesSize);
317 if (!availableLanguages) {
318 return;
319 }
320 for (int i = 0; i < countriesInfo.country_languages_size(); i++) {
321 std::string language = countriesInfo.country_languages(i);
322 int len = sizeof(char) * (language.length() + 1);
323 char* temp = (char *)malloc(len);
324 if (!temp) {
325 return;
326 }
327 memset(temp, '\0', len);
328 strncpy(temp, language.c_str(), len);
329 availableLanguages[i] = temp;
330 }
331 CountryLanguages countryLanguages = {
332 availableLanguages,
333 availableLanguagesSize
334 };
335 countryLanguagesMap->insert(std::make_pair(countryCode, countryLanguages));
336 }
337
FindLanguageCode(const std::string & languageCode)338 int UpdateGeocoding::FindLanguageCode(const std::string& languageCode)
339 {
340 const char** const preLanguageCodesEnd = preLanguageCodes + preLanguageCodesSize;
341 const char** const preIndex = std::lower_bound(preLanguageCodes,
342 preLanguageCodesEnd,
343 languageCode.c_str(),
344 IsLowerThan);
345 if (preIndex == preLanguageCodesEnd || languageCode.compare(*preIndex) != 0) {
346 return -1;
347 }
348 return preIndex - preLanguageCodes;
349 }
350
FindCountryCode(int countryCode)351 int UpdateGeocoding::FindCountryCode(int countryCode)
352 {
353 const int* const preCountryCodesEnd = preCountryCodes + preCountryCodesSize;
354 const int* const preIndex = std::lower_bound(preCountryCodes,
355 preCountryCodesEnd,
356 countryCode);
357 if (preIndex == preCountryCodesEnd || *preIndex != countryCode) {
358 return -1;
359 }
360 return preIndex - preCountryCodes;
361 }
362
IsLowerThan(const char * s1,const char * s2)363 bool UpdateGeocoding::IsLowerThan(const char* s1, const char* s2)
364 {
365 return strcmp(s1, s2) < 0;
366 }
367
WriteStr(const std::string & str)368 char* UpdateGeocoding::WriteStr(const std::string& str)
369 {
370 int len = sizeof(char) * (str.length() + 1);
371 char* result = (char*)malloc(len);
372 if (!result) {
373 return nullptr;
374 }
375 memset(result, '\0', len);
376 strncpy(result, str.c_str(), len);
377 return result;
378 }
379 }
380 }