| // 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 <algorithm> |
| #include <cstddef> |
| #include <cstring> |
| #include <sstream> |
| #include <string> |
| |
| #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 |