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 }