11767c5feSopenharmony_ci// Copyright (C) 2012 The Libphonenumber Authors
21767c5feSopenharmony_ci//
31767c5feSopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
41767c5feSopenharmony_ci// you may not use this file except in compliance with the License.
51767c5feSopenharmony_ci// You may obtain a copy of the License at
61767c5feSopenharmony_ci//
71767c5feSopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0
81767c5feSopenharmony_ci//
91767c5feSopenharmony_ci// Unless required by applicable law or agreed to in writing, software
101767c5feSopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
111767c5feSopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121767c5feSopenharmony_ci// See the License for the specific language governing permissions and
131767c5feSopenharmony_ci// limitations under the License.
141767c5feSopenharmony_ci//
151767c5feSopenharmony_ci// Author: Patrick Mezard
161767c5feSopenharmony_ci
171767c5feSopenharmony_ci#include "phonenumbers/geocoding/mapping_file_provider.h"
181767c5feSopenharmony_ci
191767c5feSopenharmony_ci#include <algorithm>
201767c5feSopenharmony_ci#include <cstddef>
211767c5feSopenharmony_ci#include <cstring>
221767c5feSopenharmony_ci#include <sstream>
231767c5feSopenharmony_ci#include <string>
241767c5feSopenharmony_ci
251767c5feSopenharmony_ci#include "phonenumbers/geocoding/geocoding_data.h"
261767c5feSopenharmony_ci
271767c5feSopenharmony_cinamespace i18n {
281767c5feSopenharmony_cinamespace phonenumbers {
291767c5feSopenharmony_ci
301767c5feSopenharmony_ciusing std::string;
311767c5feSopenharmony_ci
321767c5feSopenharmony_cinamespace {
331767c5feSopenharmony_ci
341767c5feSopenharmony_cistruct NormalizedLocale {
351767c5feSopenharmony_ci  const char* locale;
361767c5feSopenharmony_ci  const char* normalized_locale;
371767c5feSopenharmony_ci};
381767c5feSopenharmony_ci
391767c5feSopenharmony_ciconst NormalizedLocale kNormalizedLocales[] = {
401767c5feSopenharmony_ci  {"zh_TW", "zh_Hant"},
411767c5feSopenharmony_ci  {"zh_HK", "zh_Hant"},
421767c5feSopenharmony_ci  {"zh_MO", "zh_Hant"},
431767c5feSopenharmony_ci};
441767c5feSopenharmony_ci
451767c5feSopenharmony_ciconst char* GetNormalizedLocale(const string& full_locale) {
461767c5feSopenharmony_ci  const int size = sizeof(kNormalizedLocales) / sizeof(*kNormalizedLocales);
471767c5feSopenharmony_ci  for (int i = 0; i != size; ++i) {
481767c5feSopenharmony_ci    if (full_locale.compare(kNormalizedLocales[i].locale) == 0) {
491767c5feSopenharmony_ci      return kNormalizedLocales[i].normalized_locale;
501767c5feSopenharmony_ci    }
511767c5feSopenharmony_ci  }
521767c5feSopenharmony_ci  return NULL;
531767c5feSopenharmony_ci}
541767c5feSopenharmony_ci
551767c5feSopenharmony_civoid AppendLocalePart(const string& part, string* full_locale) {
561767c5feSopenharmony_ci  if (!part.empty()) {
571767c5feSopenharmony_ci    full_locale->append("_");
581767c5feSopenharmony_ci    full_locale->append(part);
591767c5feSopenharmony_ci  }
601767c5feSopenharmony_ci}
611767c5feSopenharmony_ci
621767c5feSopenharmony_civoid ConstructFullLocale(const string& language, const string& script, const
631767c5feSopenharmony_ci                         string& region, string* full_locale) {
641767c5feSopenharmony_ci  full_locale->assign(language);
651767c5feSopenharmony_ci  AppendLocalePart(script, full_locale);
661767c5feSopenharmony_ci  AppendLocalePart(region, full_locale);
671767c5feSopenharmony_ci}
681767c5feSopenharmony_ci
691767c5feSopenharmony_ci// Returns true if s1 comes strictly before s2 in lexicographic order.
701767c5feSopenharmony_cibool IsLowerThan(const char* s1, const char* s2) {
711767c5feSopenharmony_ci  return strcmp(s1, s2) < 0;
721767c5feSopenharmony_ci}
731767c5feSopenharmony_ci
741767c5feSopenharmony_ci// Returns true if languages contains language.
751767c5feSopenharmony_cibool HasLanguage(const CountryLanguages* languages, const string& language) {
761767c5feSopenharmony_ci  const char** const start = languages->available_languages;
771767c5feSopenharmony_ci  const char** const end = start + languages->available_languages_size;
781767c5feSopenharmony_ci  const char** const it =
791767c5feSopenharmony_ci      std::lower_bound(start, end, language.c_str(), IsLowerThan);
801767c5feSopenharmony_ci  return it != end && strcmp(language.c_str(), *it) == 0;
811767c5feSopenharmony_ci}
821767c5feSopenharmony_ci
831767c5feSopenharmony_ci}  // namespace
841767c5feSopenharmony_ci
851767c5feSopenharmony_ciMappingFileProvider::MappingFileProvider(
861767c5feSopenharmony_ci    const int* country_calling_codes, int country_calling_codes_size,
871767c5feSopenharmony_ci    country_languages_getter get_country_languages)
881767c5feSopenharmony_ci  : country_calling_codes_(country_calling_codes),
891767c5feSopenharmony_ci    country_calling_codes_size_(country_calling_codes_size),
901767c5feSopenharmony_ci    get_country_languages_(get_country_languages) {
911767c5feSopenharmony_ci}
921767c5feSopenharmony_ci
931767c5feSopenharmony_ciconst string& MappingFileProvider::GetFileName(int country_calling_code,
941767c5feSopenharmony_ci                                               const string& language,
951767c5feSopenharmony_ci                                               const string& script,
961767c5feSopenharmony_ci                                               const string& region,
971767c5feSopenharmony_ci                                               string* filename) const {
981767c5feSopenharmony_ci  filename->clear();
991767c5feSopenharmony_ci  if (language.empty()) {
1001767c5feSopenharmony_ci    return *filename;
1011767c5feSopenharmony_ci  }
1021767c5feSopenharmony_ci  const int* const country_calling_codes_end = country_calling_codes_ +
1031767c5feSopenharmony_ci      country_calling_codes_size_;
1041767c5feSopenharmony_ci  const int* const it =
1051767c5feSopenharmony_ci      std::lower_bound(country_calling_codes_,
1061767c5feSopenharmony_ci                       country_calling_codes_end,
1071767c5feSopenharmony_ci                       country_calling_code);
1081767c5feSopenharmony_ci  if (it == country_calling_codes_end || *it != country_calling_code) {
1091767c5feSopenharmony_ci    return *filename;
1101767c5feSopenharmony_ci  }
1111767c5feSopenharmony_ci  const CountryLanguages* const langs =
1121767c5feSopenharmony_ci      get_country_languages_(it - country_calling_codes_);
1131767c5feSopenharmony_ci  if (langs->available_languages_size > 0) {
1141767c5feSopenharmony_ci    string language_code;
1151767c5feSopenharmony_ci    FindBestMatchingLanguageCode(langs, language, script, region,
1161767c5feSopenharmony_ci                                 &language_code);
1171767c5feSopenharmony_ci  if (!language_code.empty()) {
1181767c5feSopenharmony_ci    std::stringstream filename_buf;
1191767c5feSopenharmony_ci    filename_buf << country_calling_code << "_" << language_code;
1201767c5feSopenharmony_ci    *filename = filename_buf.str();
1211767c5feSopenharmony_ci    }
1221767c5feSopenharmony_ci  }
1231767c5feSopenharmony_ci  return *filename;
1241767c5feSopenharmony_ci}
1251767c5feSopenharmony_ci
1261767c5feSopenharmony_civoid MappingFileProvider::FindBestMatchingLanguageCode(
1271767c5feSopenharmony_ci  const CountryLanguages* languages, const string& language,
1281767c5feSopenharmony_ci  const string& script, const string& region, string* best_match) const {
1291767c5feSopenharmony_ci  string full_locale;
1301767c5feSopenharmony_ci  ConstructFullLocale(language, script, region, &full_locale);
1311767c5feSopenharmony_ci  const char* const normalized_locale = GetNormalizedLocale(full_locale);
1321767c5feSopenharmony_ci  if (normalized_locale != NULL) {
1331767c5feSopenharmony_ci    string normalized_locale_str(normalized_locale);
1341767c5feSopenharmony_ci    if (HasLanguage(languages, normalized_locale_str)) {
1351767c5feSopenharmony_ci      best_match->swap(normalized_locale_str);
1361767c5feSopenharmony_ci      return;
1371767c5feSopenharmony_ci    }
1381767c5feSopenharmony_ci  }
1391767c5feSopenharmony_ci
1401767c5feSopenharmony_ci  if (HasLanguage(languages, full_locale)) {
1411767c5feSopenharmony_ci    best_match->swap(full_locale);
1421767c5feSopenharmony_ci    return;
1431767c5feSopenharmony_ci  }
1441767c5feSopenharmony_ci
1451767c5feSopenharmony_ci  if (script.empty() != region.empty()) {
1461767c5feSopenharmony_ci    if (HasLanguage(languages, language)) {
1471767c5feSopenharmony_ci      *best_match = language;
1481767c5feSopenharmony_ci      return;
1491767c5feSopenharmony_ci    }
1501767c5feSopenharmony_ci  } else if (!script.empty() && !region.empty()) {
1511767c5feSopenharmony_ci    string lang_with_script(language);
1521767c5feSopenharmony_ci    lang_with_script.append("_");
1531767c5feSopenharmony_ci    lang_with_script.append(script);
1541767c5feSopenharmony_ci    if (HasLanguage(languages, lang_with_script)) {
1551767c5feSopenharmony_ci      best_match->swap(lang_with_script);
1561767c5feSopenharmony_ci      return;
1571767c5feSopenharmony_ci    }
1581767c5feSopenharmony_ci  }
1591767c5feSopenharmony_ci
1601767c5feSopenharmony_ci  string lang_with_region(language);
1611767c5feSopenharmony_ci  lang_with_region.append("_");
1621767c5feSopenharmony_ci  lang_with_region.append(region);
1631767c5feSopenharmony_ci  if (HasLanguage(languages, lang_with_region)) {
1641767c5feSopenharmony_ci    best_match->swap(lang_with_region);
1651767c5feSopenharmony_ci    return;
1661767c5feSopenharmony_ci  }
1671767c5feSopenharmony_ci  if (HasLanguage(languages, language)) {
1681767c5feSopenharmony_ci    *best_match = language;
1691767c5feSopenharmony_ci    return;
1701767c5feSopenharmony_ci  }
1711767c5feSopenharmony_ci  best_match->clear();
1721767c5feSopenharmony_ci}
1731767c5feSopenharmony_ci
1741767c5feSopenharmony_ci}  // namespace phonenumbers
1751767c5feSopenharmony_ci}  // namespace i18n
176