summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorphilip.liard@gmail.com <philip.liard@gmail.com@ee073f10-1060-11df-b6a4-87a95322a99c>2012-07-19 12:49:04 +0000
committerphilip.liard@gmail.com <philip.liard@gmail.com@ee073f10-1060-11df-b6a4-87a95322a99c>2012-07-19 12:49:04 +0000
commitbde8f64fbf8d13c7a3ac946ce7d4215af6e25681 (patch)
tree41841f2c6cd2d69af47e590ab4ff76df4be579ee
parent1a1169209e93944bc9d0a8e6e17c528f7140b8fa (diff)
downloadphonenumbers-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.cc175
-rw-r--r--geocoding/mapping_file_provider.h75
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_