diff options
author | philip.liard@gmail.com <philip.liard@gmail.com@ee073f10-1060-11df-b6a4-87a95322a99c> | 2012-07-19 12:49:04 +0000 |
---|---|---|
committer | philip.liard@gmail.com <philip.liard@gmail.com@ee073f10-1060-11df-b6a4-87a95322a99c> | 2012-07-19 12:49:04 +0000 |
commit | bde8f64fbf8d13c7a3ac946ce7d4215af6e25681 (patch) | |
tree | 41841f2c6cd2d69af47e590ab4ff76df4be579ee | |
parent | 1a1169209e93944bc9d0a8e6e17c528f7140b8fa (diff) | |
download | phonenumbers-bde8f64fbf8d13c7a3ac946ce7d4215af6e25681.tar.gz |
CPP: Implement MappingFileProvider.
Patch contributed by pmezard.
git-svn-id: http://libphonenumber.googlecode.com/svn/trunk/cpp/src/phonenumbers@505 ee073f10-1060-11df-b6a4-87a95322a99c
-rw-r--r-- | geocoding/mapping_file_provider.cc | 175 | ||||
-rw-r--r-- | geocoding/mapping_file_provider.h | 75 |
2 files changed, 250 insertions, 0 deletions
diff --git a/geocoding/mapping_file_provider.cc b/geocoding/mapping_file_provider.cc new file mode 100644 index 0000000..82cb1a8 --- /dev/null +++ b/geocoding/mapping_file_provider.cc @@ -0,0 +1,175 @@ +// 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 diff --git a/geocoding/mapping_file_provider.h b/geocoding/mapping_file_provider.h new file mode 100644 index 0000000..1234a5e --- /dev/null +++ b/geocoding/mapping_file_provider.h @@ -0,0 +1,75 @@ +// 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 + +#ifndef I18N_PHONENUMBERS_GEOCODING_MAPPING_FILE_PROVIDER_H_ +#define I18N_PHONENUMBERS_GEOCODING_MAPPING_FILE_PROVIDER_H_ + +#include <string> + +#include "base/basictypes.h" + +namespace i18n { +namespace phonenumbers { + +using std::string; + +struct CountryLanguages; + +// A utility which knows the data files that are available for the geocoder to +// use. The data files contain mappings from phone number prefixes to text +// descriptions, and are organized by country calling code and language that the +// text descriptions are in. +class MappingFileProvider { + public: + typedef const CountryLanguages* (*country_languages_getter)(int index); + + // Initializes a MappingFileProvider with country_calling_codes, a sorted + // list of country_calling_code_size calling codes, and a function + // get_country_languages(int index) returning the CountryLanguage information + // related to the country code at index in country_calling_codes. + MappingFileProvider(const int* country_calling_codes, + int country_calling_code_size, + country_languages_getter get_country_languages); + + // Returns the name of the file that contains the mapping data for the + // country_calling_code in the language specified, or an empty string if no + // such file can be found. language is a two-letter lowercase ISO language + // codes as defined by ISO 639-1. script is a four-letter titlecase (the first + // letter is uppercase and the rest of the letters are lowercase) ISO script + // codes as defined in ISO 15924. region is a two-letter uppercase ISO country + // codes as defined by ISO 3166-1. + const string& GetFileName(int country_calling_code, const string& language, + const string& script, const string& region, string* + filename) const; + + private: + void FindBestMatchingLanguageCode(const CountryLanguages* languages, + const string& language, + const string& script, + const string& region, + string* best_match) const; + + const int* const country_calling_codes_; + const int country_calling_codes_size_; + const country_languages_getter get_country_languages_; + + DISALLOW_COPY_AND_ASSIGN(MappingFileProvider); +}; + +} // namespace phonenumbers +} // namespace i18n + +#endif // I18N_PHONENUMBERS_GEOCODING_MAPPING_FILE_PROVIDER_H_ |