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