// Copyright (C) 2012 The Libphonenumber Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // Author: Patrick Mezard #include "phonenumbers/geocoding/mapping_file_provider.h" #include #include #include #include #include #include "phonenumbers/geocoding/geocoding_data.h" namespace i18n { namespace phonenumbers { using std::string; namespace { struct NormalizedLocale { const char* locale; const char* normalized_locale; }; const NormalizedLocale kNormalizedLocales[] = { {"zh_TW", "zh_Hant"}, {"zh_HK", "zh_Hant"}, {"zh_MO", "zh_Hant"}, }; const char* GetNormalizedLocale(const string& full_locale) { const int size = sizeof(kNormalizedLocales) / sizeof(*kNormalizedLocales); for (int i = 0; i != size; ++i) { if (full_locale.compare(kNormalizedLocales[i].locale) == 0) { return kNormalizedLocales[i].normalized_locale; } } return NULL; } void AppendLocalePart(const string& part, string* full_locale) { if (!part.empty()) { full_locale->append("_"); full_locale->append(part); } } void ConstructFullLocale(const string& language, const string& script, const string& region, string* full_locale) { full_locale->assign(language); AppendLocalePart(script, full_locale); AppendLocalePart(region, full_locale); } // Returns true if s1 comes strictly before s2 in lexicographic order. bool IsLowerThan(const char* s1, const char* s2) { return strcmp(s1, s2) < 0; } // Returns true if languages contains language. bool HasLanguage(const CountryLanguages* languages, const string& language) { const char** const start = languages->available_languages; const char** const end = start + languages->available_languages_size; const char** const it = std::lower_bound(start, end, language.c_str(), IsLowerThan); return it != end && strcmp(language.c_str(), *it) == 0; } } // namespace MappingFileProvider::MappingFileProvider( const int* country_calling_codes, int country_calling_codes_size, country_languages_getter get_country_languages) : country_calling_codes_(country_calling_codes), country_calling_codes_size_(country_calling_codes_size), get_country_languages_(get_country_languages) { } const string& MappingFileProvider::GetFileName(int country_calling_code, const string& language, const string& script, const string& region, string* filename) const { filename->clear(); if (language.empty()) { return *filename; } const int* const country_calling_codes_end = country_calling_codes_ + country_calling_codes_size_; const int* const it = std::lower_bound(country_calling_codes_, country_calling_codes_end, country_calling_code); if (it == country_calling_codes_end || *it != country_calling_code) { return *filename; } const CountryLanguages* const langs = get_country_languages_(it - country_calling_codes_); if (langs->available_languages_size > 0) { string language_code; FindBestMatchingLanguageCode(langs, language, script, region, &language_code); if (!language_code.empty()) { std::stringstream filename_buf; filename_buf << country_calling_code << "_" << language_code; *filename = filename_buf.str(); } } return *filename; } void MappingFileProvider::FindBestMatchingLanguageCode( const CountryLanguages* languages, const string& language, const string& script, const string& region, string* best_match) const { string full_locale; ConstructFullLocale(language, script, region, &full_locale); const char* const normalized_locale = GetNormalizedLocale(full_locale); if (normalized_locale != NULL) { string normalized_locale_str(normalized_locale); if (HasLanguage(languages, normalized_locale_str)) { best_match->swap(normalized_locale_str); return; } } if (HasLanguage(languages, full_locale)) { best_match->swap(full_locale); return; } if (script.empty() != region.empty()) { if (HasLanguage(languages, language)) { *best_match = language; return; } } else if (!script.empty() && !region.empty()) { string lang_with_script(language); lang_with_script.append("_"); lang_with_script.append(script); if (HasLanguage(languages, lang_with_script)) { best_match->swap(lang_with_script); return; } } string lang_with_region(language); lang_with_region.append("_"); lang_with_region.append(region); if (HasLanguage(languages, lang_with_region)) { best_match->swap(lang_with_region); return; } if (HasLanguage(languages, language)) { *best_match = language; return; } best_match->clear(); } } // namespace phonenumbers } // namespace i18n