• 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 
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 }