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 22namespace i18n { 23namespace phonenumbers { 24GeocodingInfo* UpdateGeocoding::geocodingInfo = nullptr; 25 26std::map<std::string, PrefixDescriptions>* UpdateGeocoding::prefixDescriptionsMap = new std::map<std::string, PrefixDescriptions>(); 27std::map<std::string, PrefixesInfo>* UpdateGeocoding::prefixesInfoMap = new std::map<std::string, PrefixesInfo>(); 28const PrefixDescriptions** UpdateGeocoding::prefixDescriptionsArray = nullptr; 29LanguageCodeInfo* UpdateGeocoding::languageCodeInfo = nullptr; 30bool UpdateGeocoding::isupdatedLanguageCodes = false; 31const char** UpdateGeocoding::preLanguageCodes = nullptr; 32const char** UpdateGeocoding::curLanguageCodes = nullptr; 33int UpdateGeocoding::curLanguageCodesSize = 0; 34int UpdateGeocoding::preLanguageCodesSize = 0; 35 36std::map<int, CountryLanguages>* UpdateGeocoding::countryLanguagesMap = new std::map<int, CountryLanguages>(); 37std::map<int, CountriesInfo>* UpdateGeocoding::countriesInfoMap = new std::map<int, CountriesInfo>(); 38const CountryLanguages** UpdateGeocoding::countryLanguagesArray = nullptr; 39CountryCodeInfo* UpdateGeocoding::countryCodeInfo = nullptr; 40bool UpdateGeocoding::isupdatedCountryCodes = false; 41const int* UpdateGeocoding::preCountryCodes = nullptr; 42int* UpdateGeocoding::curCountryCodes = nullptr; 43int UpdateGeocoding::curCountryCodesSize = 0; 44int UpdateGeocoding::preCountryCodesSize = 0; 45 46void 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 66const 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 83const 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 129int UpdateGeocoding::UpdateLanguageCodesSize() 130{ 131 if (isupdatedLanguageCodes) { 132 return curLanguageCodesSize; 133 } 134 return preLanguageCodesSize; 135} 136 137void 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 172void 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 224void 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 237const 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 252const 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 298int UpdateGeocoding::UpdateCountryCodesSize() 299{ 300 if (isupdatedCountryCodes) { 301 return curCountryCodesSize; 302 } 303 return preCountryCodesSize; 304} 305 306void 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 336int 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 349int 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 361bool UpdateGeocoding::IsLowerThan(const char* s1, const char* s2) 362{ 363 return strcmp(s1, s2) < 0; 364} 365 366char* 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}