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#include "phonenumbers/shortnumberinfo.h"
161767c5feSopenharmony_ci
171767c5feSopenharmony_ci#include <algorithm>
181767c5feSopenharmony_ci#include <string.h>
191767c5feSopenharmony_ci#include <iterator>
201767c5feSopenharmony_ci#include <map>
211767c5feSopenharmony_ci
221767c5feSopenharmony_ci#include "phonenumbers/default_logger.h"
231767c5feSopenharmony_ci#include "phonenumbers/matcher_api.h"
241767c5feSopenharmony_ci#ifdef LIBPHONENUMBER_UPGRADE
251767c5feSopenharmony_ci#include "phonenumbers/ohos/update_metadata.h"
261767c5feSopenharmony_ci#include "phonenumbers/ohos/update_libphonenumber.h"
271767c5feSopenharmony_ci#endif
281767c5feSopenharmony_ci#include "phonenumbers/phonemetadata.pb.h"
291767c5feSopenharmony_ci#include "phonenumbers/phonenumberutil.h"
301767c5feSopenharmony_ci#include "phonenumbers/regex_based_matcher.h"
311767c5feSopenharmony_ci#include "phonenumbers/region_code.h"
321767c5feSopenharmony_ci#include "phonenumbers/short_metadata.h"
331767c5feSopenharmony_ci
341767c5feSopenharmony_cinamespace i18n {
351767c5feSopenharmony_cinamespace phonenumbers {
361767c5feSopenharmony_ci
371767c5feSopenharmony_ciusing google::protobuf::RepeatedField;
381767c5feSopenharmony_ciusing std::map;
391767c5feSopenharmony_ciusing std::string;
401767c5feSopenharmony_ci
411767c5feSopenharmony_cibool LoadCompiledInMetadata(PhoneMetadataCollection* metadata) {
421767c5feSopenharmony_ci  if (!metadata->ParseFromArray(short_metadata_get(), short_metadata_size())) {
431767c5feSopenharmony_ci    LOG(ERROR) << "Could not parse binary data.";
441767c5feSopenharmony_ci    return false;
451767c5feSopenharmony_ci  }
461767c5feSopenharmony_ci  return true;
471767c5feSopenharmony_ci}
481767c5feSopenharmony_ci
491767c5feSopenharmony_ciShortNumberInfo::ShortNumberInfo()
501767c5feSopenharmony_ci    : phone_util_(*PhoneNumberUtil::GetInstance()),
511767c5feSopenharmony_ci      matcher_api_(new RegexBasedMatcher()),
521767c5feSopenharmony_ci      region_to_short_metadata_map_(new std::map<string, PhoneMetadata>()),
531767c5feSopenharmony_ci      regions_where_emergency_numbers_must_be_exact_(new std::set<string>()) {
541767c5feSopenharmony_ci  PhoneMetadataCollection metadata_collection;
551767c5feSopenharmony_ci  if (!LoadCompiledInMetadata(&metadata_collection)) {
561767c5feSopenharmony_ci    LOG(DFATAL) << "Could not parse compiled-in metadata.";
571767c5feSopenharmony_ci    return;
581767c5feSopenharmony_ci  }
591767c5feSopenharmony_ci  for (const auto& metadata : metadata_collection.metadata()) {
601767c5feSopenharmony_ci    const string& region_code = metadata.id();
611767c5feSopenharmony_ci    region_to_short_metadata_map_->insert(std::make_pair(region_code, metadata));
621767c5feSopenharmony_ci  }
631767c5feSopenharmony_ci  regions_where_emergency_numbers_must_be_exact_->insert("BR");
641767c5feSopenharmony_ci  regions_where_emergency_numbers_must_be_exact_->insert("CL");
651767c5feSopenharmony_ci  regions_where_emergency_numbers_must_be_exact_->insert("NI");
661767c5feSopenharmony_ci
671767c5feSopenharmony_ci#ifdef LIBPHONENUMBER_UPGRADE
681767c5feSopenharmony_ci  UpdateLibphonenumber::LoadUpdateData();
691767c5feSopenharmony_ci  UpdateMetadata::UpdateShortNumber(region_to_short_metadata_map_);
701767c5feSopenharmony_ci#endif
711767c5feSopenharmony_ci}
721767c5feSopenharmony_ci
731767c5feSopenharmony_ciShortNumberInfo::~ShortNumberInfo() {}
741767c5feSopenharmony_ci
751767c5feSopenharmony_ci// Returns a pointer to the phone metadata for the appropriate region or NULL
761767c5feSopenharmony_ci// if the region code is invalid or unknown.
771767c5feSopenharmony_ciconst PhoneMetadata* ShortNumberInfo::GetMetadataForRegion(
781767c5feSopenharmony_ci    const string& region_code) const {
791767c5feSopenharmony_ci  auto it = region_to_short_metadata_map_->find(region_code);
801767c5feSopenharmony_ci  if (it != region_to_short_metadata_map_->end()) {
811767c5feSopenharmony_ci    return &it->second;
821767c5feSopenharmony_ci  }
831767c5feSopenharmony_ci  return nullptr;
841767c5feSopenharmony_ci}
851767c5feSopenharmony_ci
861767c5feSopenharmony_cinamespace {
871767c5feSopenharmony_ci// TODO: Once we have benchmarked ShortNumberInfo, consider if it is
881767c5feSopenharmony_ci// worth keeping this performance optimization.
891767c5feSopenharmony_cibool MatchesPossibleNumberAndNationalNumber(
901767c5feSopenharmony_ci    const MatcherApi& matcher_api,
911767c5feSopenharmony_ci    const string& number,
921767c5feSopenharmony_ci    const PhoneNumberDesc& desc) {
931767c5feSopenharmony_ci  const RepeatedField<int>& lengths = desc.possible_length();
941767c5feSopenharmony_ci  if (desc.possible_length_size() > 0 &&
951767c5feSopenharmony_ci      std::find(lengths.begin(), lengths.end(), number.length()) ==
961767c5feSopenharmony_ci          lengths.end()) {
971767c5feSopenharmony_ci    return false;
981767c5feSopenharmony_ci  }
991767c5feSopenharmony_ci  return matcher_api.MatchNationalNumber(number, desc, false);
1001767c5feSopenharmony_ci}
1011767c5feSopenharmony_ci}  // namespace
1021767c5feSopenharmony_ci
1031767c5feSopenharmony_ci// Helper method to check that the country calling code of the number matches
1041767c5feSopenharmony_ci// the region it's being dialed from.
1051767c5feSopenharmony_cibool ShortNumberInfo::RegionDialingFromMatchesNumber(const PhoneNumber& number,
1061767c5feSopenharmony_ci    const string& region_dialing_from) const {
1071767c5feSopenharmony_ci  list<string> region_codes;
1081767c5feSopenharmony_ci  phone_util_.GetRegionCodesForCountryCallingCode(number.country_code(),
1091767c5feSopenharmony_ci                                                  &region_codes);
1101767c5feSopenharmony_ci  return std::find(region_codes.begin(),
1111767c5feSopenharmony_ci                   region_codes.end(),
1121767c5feSopenharmony_ci                   region_dialing_from) != region_codes.end();
1131767c5feSopenharmony_ci}
1141767c5feSopenharmony_ci
1151767c5feSopenharmony_cibool ShortNumberInfo::IsPossibleShortNumberForRegion(const PhoneNumber& number,
1161767c5feSopenharmony_ci    const string& region_dialing_from) const {
1171767c5feSopenharmony_ci  if (!RegionDialingFromMatchesNumber(number, region_dialing_from)) {
1181767c5feSopenharmony_ci    return false;
1191767c5feSopenharmony_ci  }
1201767c5feSopenharmony_ci  const PhoneMetadata* phone_metadata =
1211767c5feSopenharmony_ci      GetMetadataForRegion(region_dialing_from);
1221767c5feSopenharmony_ci  if (!phone_metadata) {
1231767c5feSopenharmony_ci    return false;
1241767c5feSopenharmony_ci  }
1251767c5feSopenharmony_ci  string short_number;
1261767c5feSopenharmony_ci  phone_util_.GetNationalSignificantNumber(number, &short_number);
1271767c5feSopenharmony_ci  const RepeatedField<int>& lengths =
1281767c5feSopenharmony_ci      phone_metadata->general_desc().possible_length();
1291767c5feSopenharmony_ci  return (std::find(lengths.begin(), lengths.end(), short_number.length()) !=
1301767c5feSopenharmony_ci      lengths.end());
1311767c5feSopenharmony_ci}
1321767c5feSopenharmony_ci
1331767c5feSopenharmony_cibool ShortNumberInfo::IsPossibleShortNumber(const PhoneNumber& number) const {
1341767c5feSopenharmony_ci  list<string> region_codes;
1351767c5feSopenharmony_ci  phone_util_.GetRegionCodesForCountryCallingCode(number.country_code(),
1361767c5feSopenharmony_ci                                                  &region_codes);
1371767c5feSopenharmony_ci  string short_number;
1381767c5feSopenharmony_ci  phone_util_.GetNationalSignificantNumber(number, &short_number);
1391767c5feSopenharmony_ci  for (const auto& region_code : region_codes) {
1401767c5feSopenharmony_ci    const PhoneMetadata* phone_metadata = GetMetadataForRegion(region_code);
1411767c5feSopenharmony_ci    if (!phone_metadata) {
1421767c5feSopenharmony_ci      continue;
1431767c5feSopenharmony_ci    }
1441767c5feSopenharmony_ci    const RepeatedField<int>& lengths =
1451767c5feSopenharmony_ci        phone_metadata->general_desc().possible_length();
1461767c5feSopenharmony_ci    if (std::find(lengths.begin(), lengths.end(), short_number.length()) !=
1471767c5feSopenharmony_ci        lengths.end()) {
1481767c5feSopenharmony_ci      return true;
1491767c5feSopenharmony_ci    }
1501767c5feSopenharmony_ci  }
1511767c5feSopenharmony_ci  return false;
1521767c5feSopenharmony_ci}
1531767c5feSopenharmony_ci
1541767c5feSopenharmony_cibool ShortNumberInfo::IsValidShortNumberForRegion(
1551767c5feSopenharmony_ci    const PhoneNumber& number, const string& region_dialing_from) const {
1561767c5feSopenharmony_ci  if (!RegionDialingFromMatchesNumber(number, region_dialing_from)) {
1571767c5feSopenharmony_ci    return false;
1581767c5feSopenharmony_ci  }
1591767c5feSopenharmony_ci  const PhoneMetadata* phone_metadata =
1601767c5feSopenharmony_ci      GetMetadataForRegion(region_dialing_from);
1611767c5feSopenharmony_ci  if (!phone_metadata) {
1621767c5feSopenharmony_ci    return false;
1631767c5feSopenharmony_ci  }
1641767c5feSopenharmony_ci  string short_number;
1651767c5feSopenharmony_ci  phone_util_.GetNationalSignificantNumber(number, &short_number);
1661767c5feSopenharmony_ci  const PhoneNumberDesc& general_desc = phone_metadata->general_desc();
1671767c5feSopenharmony_ci  if (!MatchesPossibleNumberAndNationalNumber(*matcher_api_, short_number,
1681767c5feSopenharmony_ci                                              general_desc)) {
1691767c5feSopenharmony_ci    return false;
1701767c5feSopenharmony_ci  }
1711767c5feSopenharmony_ci  const PhoneNumberDesc& short_number_desc = phone_metadata->short_code();
1721767c5feSopenharmony_ci  return MatchesPossibleNumberAndNationalNumber(*matcher_api_, short_number,
1731767c5feSopenharmony_ci                                                short_number_desc);
1741767c5feSopenharmony_ci}
1751767c5feSopenharmony_ci
1761767c5feSopenharmony_cibool ShortNumberInfo::IsValidShortNumber(const PhoneNumber& number) const {
1771767c5feSopenharmony_ci  list<string> region_codes;
1781767c5feSopenharmony_ci  phone_util_.GetRegionCodesForCountryCallingCode(number.country_code(),
1791767c5feSopenharmony_ci                                                  &region_codes);
1801767c5feSopenharmony_ci  string region_code;
1811767c5feSopenharmony_ci  GetRegionCodeForShortNumberFromRegionList(number, region_codes, &region_code);
1821767c5feSopenharmony_ci  if (region_codes.size() > 1 && region_code != RegionCode::GetUnknown()) {
1831767c5feSopenharmony_ci    return true;
1841767c5feSopenharmony_ci  }
1851767c5feSopenharmony_ci  return IsValidShortNumberForRegion(number, region_code);
1861767c5feSopenharmony_ci}
1871767c5feSopenharmony_ci
1881767c5feSopenharmony_ciShortNumberInfo::ShortNumberCost ShortNumberInfo::GetExpectedCostForRegion(
1891767c5feSopenharmony_ci    const PhoneNumber& number, const string& region_dialing_from) const {
1901767c5feSopenharmony_ci  if (!RegionDialingFromMatchesNumber(number, region_dialing_from)) {
1911767c5feSopenharmony_ci    return ShortNumberInfo::UNKNOWN_COST;
1921767c5feSopenharmony_ci  }
1931767c5feSopenharmony_ci  const PhoneMetadata* phone_metadata =
1941767c5feSopenharmony_ci      GetMetadataForRegion(region_dialing_from);
1951767c5feSopenharmony_ci  if (!phone_metadata) {
1961767c5feSopenharmony_ci    return ShortNumberInfo::UNKNOWN_COST;
1971767c5feSopenharmony_ci  }
1981767c5feSopenharmony_ci  string short_number;
1991767c5feSopenharmony_ci  phone_util_.GetNationalSignificantNumber(number, &short_number);
2001767c5feSopenharmony_ci
2011767c5feSopenharmony_ci  // The possible lengths are not present for a particular sub-type if they
2021767c5feSopenharmony_ci  // match the general description; for this reason, we check the possible
2031767c5feSopenharmony_ci  // lengths against the general description first to allow an early exit if
2041767c5feSopenharmony_ci  // possible.
2051767c5feSopenharmony_ci  const RepeatedField<int>& lengths =
2061767c5feSopenharmony_ci      phone_metadata->general_desc().possible_length();
2071767c5feSopenharmony_ci  if (std::find(lengths.begin(), lengths.end(), short_number.length()) ==
2081767c5feSopenharmony_ci      lengths.end()) {
2091767c5feSopenharmony_ci    return ShortNumberInfo::UNKNOWN_COST;
2101767c5feSopenharmony_ci  }
2111767c5feSopenharmony_ci
2121767c5feSopenharmony_ci  // The cost categories are tested in order of decreasing expense, since if
2131767c5feSopenharmony_ci  // for some reason the patterns overlap the most expensive matching cost
2141767c5feSopenharmony_ci  // category should be returned.
2151767c5feSopenharmony_ci  if (MatchesPossibleNumberAndNationalNumber(*matcher_api_, short_number,
2161767c5feSopenharmony_ci                                             phone_metadata->premium_rate())) {
2171767c5feSopenharmony_ci    return ShortNumberInfo::PREMIUM_RATE;
2181767c5feSopenharmony_ci  }
2191767c5feSopenharmony_ci  if (MatchesPossibleNumberAndNationalNumber(*matcher_api_, short_number,
2201767c5feSopenharmony_ci                                             phone_metadata->standard_rate())) {
2211767c5feSopenharmony_ci    return ShortNumberInfo::STANDARD_RATE;
2221767c5feSopenharmony_ci  }
2231767c5feSopenharmony_ci  if (MatchesPossibleNumberAndNationalNumber(*matcher_api_, short_number,
2241767c5feSopenharmony_ci                                             phone_metadata->toll_free())) {
2251767c5feSopenharmony_ci    return ShortNumberInfo::TOLL_FREE;
2261767c5feSopenharmony_ci  }
2271767c5feSopenharmony_ci  if (IsEmergencyNumber(short_number, region_dialing_from)) {
2281767c5feSopenharmony_ci    // Emergency numbers are implicitly toll-free.
2291767c5feSopenharmony_ci    return ShortNumberInfo::TOLL_FREE;
2301767c5feSopenharmony_ci  }
2311767c5feSopenharmony_ci  return ShortNumberInfo::UNKNOWN_COST;
2321767c5feSopenharmony_ci}
2331767c5feSopenharmony_ci
2341767c5feSopenharmony_ciShortNumberInfo::ShortNumberCost ShortNumberInfo::GetExpectedCost(
2351767c5feSopenharmony_ci    const PhoneNumber& number) const {
2361767c5feSopenharmony_ci  list<string> region_codes;
2371767c5feSopenharmony_ci  phone_util_.GetRegionCodesForCountryCallingCode(number.country_code(),
2381767c5feSopenharmony_ci                                                  &region_codes);
2391767c5feSopenharmony_ci  if (region_codes.size() == 0) {
2401767c5feSopenharmony_ci    return ShortNumberInfo::UNKNOWN_COST;
2411767c5feSopenharmony_ci  }
2421767c5feSopenharmony_ci  if (region_codes.size() == 1) {
2431767c5feSopenharmony_ci    return GetExpectedCostForRegion(number, region_codes.front());
2441767c5feSopenharmony_ci  }
2451767c5feSopenharmony_ci  ShortNumberInfo::ShortNumberCost cost = ShortNumberInfo::TOLL_FREE;
2461767c5feSopenharmony_ci  for (const auto& region_code : region_codes) {
2471767c5feSopenharmony_ci    ShortNumberInfo::ShortNumberCost cost_for_region =
2481767c5feSopenharmony_ci        GetExpectedCostForRegion(number, region_code);
2491767c5feSopenharmony_ci    switch (cost_for_region) {
2501767c5feSopenharmony_ci     case ShortNumberInfo::PREMIUM_RATE:
2511767c5feSopenharmony_ci       return ShortNumberInfo::PREMIUM_RATE;
2521767c5feSopenharmony_ci     case ShortNumberInfo::UNKNOWN_COST:
2531767c5feSopenharmony_ci       return ShortNumberInfo::UNKNOWN_COST;
2541767c5feSopenharmony_ci     case ShortNumberInfo::STANDARD_RATE:
2551767c5feSopenharmony_ci       if (cost != ShortNumberInfo::UNKNOWN_COST) {
2561767c5feSopenharmony_ci         cost = ShortNumberInfo::STANDARD_RATE;
2571767c5feSopenharmony_ci       }
2581767c5feSopenharmony_ci       break;
2591767c5feSopenharmony_ci     case ShortNumberInfo::TOLL_FREE:
2601767c5feSopenharmony_ci       // Do nothing.
2611767c5feSopenharmony_ci       break;
2621767c5feSopenharmony_ci     default:
2631767c5feSopenharmony_ci       LOG(ERROR) << "Unrecognised cost for region: "
2641767c5feSopenharmony_ci                  << static_cast<int>(cost_for_region);
2651767c5feSopenharmony_ci       break;
2661767c5feSopenharmony_ci    }
2671767c5feSopenharmony_ci  }
2681767c5feSopenharmony_ci  return cost;
2691767c5feSopenharmony_ci}
2701767c5feSopenharmony_ci
2711767c5feSopenharmony_civoid ShortNumberInfo::GetRegionCodeForShortNumberFromRegionList(
2721767c5feSopenharmony_ci    const PhoneNumber& number, const list<string>& region_codes,
2731767c5feSopenharmony_ci    string* region_code) const {
2741767c5feSopenharmony_ci  if (region_codes.size() == 0) {
2751767c5feSopenharmony_ci    region_code->assign(RegionCode::GetUnknown());
2761767c5feSopenharmony_ci    return;
2771767c5feSopenharmony_ci  } else if (region_codes.size() == 1) {
2781767c5feSopenharmony_ci    region_code->assign(region_codes.front());
2791767c5feSopenharmony_ci    return;
2801767c5feSopenharmony_ci  }
2811767c5feSopenharmony_ci  string national_number;
2821767c5feSopenharmony_ci  phone_util_.GetNationalSignificantNumber(number, &national_number);
2831767c5feSopenharmony_ci  for (const auto& region_code_it : region_codes) {
2841767c5feSopenharmony_ci    const PhoneMetadata* phone_metadata = GetMetadataForRegion(region_code_it);
2851767c5feSopenharmony_ci    if (phone_metadata != nullptr &&
2861767c5feSopenharmony_ci        MatchesPossibleNumberAndNationalNumber(*matcher_api_, national_number,
2871767c5feSopenharmony_ci                                               phone_metadata->short_code())) {
2881767c5feSopenharmony_ci      // The number is valid for this region.
2891767c5feSopenharmony_ci      region_code->assign(region_code_it);
2901767c5feSopenharmony_ci      return;
2911767c5feSopenharmony_ci    }
2921767c5feSopenharmony_ci  }
2931767c5feSopenharmony_ci  region_code->assign(RegionCode::GetUnknown());
2941767c5feSopenharmony_ci}
2951767c5feSopenharmony_ci
2961767c5feSopenharmony_cistring ShortNumberInfo::GetExampleShortNumber(const string& region_code) const {
2971767c5feSopenharmony_ci  const PhoneMetadata* phone_metadata = GetMetadataForRegion(region_code);
2981767c5feSopenharmony_ci  if (!phone_metadata) {
2991767c5feSopenharmony_ci    return "";
3001767c5feSopenharmony_ci  }
3011767c5feSopenharmony_ci  const PhoneNumberDesc& desc = phone_metadata->short_code();
3021767c5feSopenharmony_ci  if (desc.has_example_number()) {
3031767c5feSopenharmony_ci    return desc.example_number();
3041767c5feSopenharmony_ci  }
3051767c5feSopenharmony_ci  return "";
3061767c5feSopenharmony_ci}
3071767c5feSopenharmony_ci
3081767c5feSopenharmony_cistring ShortNumberInfo::GetExampleShortNumberForCost(const string& region_code,
3091767c5feSopenharmony_ci    ShortNumberInfo::ShortNumberCost cost) const {
3101767c5feSopenharmony_ci  const PhoneMetadata* phone_metadata = GetMetadataForRegion(region_code);
3111767c5feSopenharmony_ci  if (!phone_metadata) {
3121767c5feSopenharmony_ci    return "";
3131767c5feSopenharmony_ci  }
3141767c5feSopenharmony_ci  const PhoneNumberDesc* desc = nullptr;
3151767c5feSopenharmony_ci  switch (cost) {
3161767c5feSopenharmony_ci    case TOLL_FREE:
3171767c5feSopenharmony_ci      desc = &(phone_metadata->toll_free());
3181767c5feSopenharmony_ci      break;
3191767c5feSopenharmony_ci    case STANDARD_RATE:
3201767c5feSopenharmony_ci      desc = &(phone_metadata->standard_rate());
3211767c5feSopenharmony_ci      break;
3221767c5feSopenharmony_ci    case PREMIUM_RATE:
3231767c5feSopenharmony_ci      desc = &(phone_metadata->premium_rate());
3241767c5feSopenharmony_ci      break;
3251767c5feSopenharmony_ci    default:
3261767c5feSopenharmony_ci      // UNKNOWN_COST numbers are computed by the process of elimination from
3271767c5feSopenharmony_ci      // the other cost categories.
3281767c5feSopenharmony_ci      break;
3291767c5feSopenharmony_ci  }
3301767c5feSopenharmony_ci  if (desc != nullptr && desc->has_example_number()) {
3311767c5feSopenharmony_ci    return desc->example_number();
3321767c5feSopenharmony_ci  }
3331767c5feSopenharmony_ci  return "";
3341767c5feSopenharmony_ci}
3351767c5feSopenharmony_ci
3361767c5feSopenharmony_cibool ShortNumberInfo::ConnectsToEmergencyNumber(const string& number,
3371767c5feSopenharmony_ci    const string& region_code) const {
3381767c5feSopenharmony_ci  return MatchesEmergencyNumberHelper(number, region_code,
3391767c5feSopenharmony_ci      true /* allows prefix match */);
3401767c5feSopenharmony_ci}
3411767c5feSopenharmony_ci
3421767c5feSopenharmony_cibool ShortNumberInfo::IsEmergencyNumber(const string& number,
3431767c5feSopenharmony_ci    const string& region_code) const {
3441767c5feSopenharmony_ci  return MatchesEmergencyNumberHelper(number, region_code,
3451767c5feSopenharmony_ci      false /* doesn't allow prefix match */);
3461767c5feSopenharmony_ci}
3471767c5feSopenharmony_ci
3481767c5feSopenharmony_cibool ShortNumberInfo::MatchesEmergencyNumberHelper(const string& number,
3491767c5feSopenharmony_ci    const string& region_code, bool allow_prefix_match) const {
3501767c5feSopenharmony_ci  string extracted_number;
3511767c5feSopenharmony_ci  phone_util_.ExtractPossibleNumber(number, &extracted_number);
3521767c5feSopenharmony_ci  if (phone_util_.StartsWithPlusCharsPattern(extracted_number)) {
3531767c5feSopenharmony_ci    // Returns false if the number starts with a plus sign. We don't believe
3541767c5feSopenharmony_ci    // dialing the country code before emergency numbers (e.g. +1911) works,
3551767c5feSopenharmony_ci    // but later, if that proves to work, we can add additional logic here to
3561767c5feSopenharmony_ci    // handle it.
3571767c5feSopenharmony_ci    return false;
3581767c5feSopenharmony_ci  }
3591767c5feSopenharmony_ci  const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
3601767c5feSopenharmony_ci  if (!metadata || !metadata->has_emergency()) {
3611767c5feSopenharmony_ci    return false;
3621767c5feSopenharmony_ci  }
3631767c5feSopenharmony_ci  phone_util_.NormalizeDigitsOnly(&extracted_number);
3641767c5feSopenharmony_ci  bool allow_prefix_match_for_region =
3651767c5feSopenharmony_ci      allow_prefix_match &&
3661767c5feSopenharmony_ci      regions_where_emergency_numbers_must_be_exact_->find(region_code) ==
3671767c5feSopenharmony_ci          regions_where_emergency_numbers_must_be_exact_->end();
3681767c5feSopenharmony_ci  return matcher_api_->MatchNationalNumber(
3691767c5feSopenharmony_ci      extracted_number, metadata->emergency(), allow_prefix_match_for_region);
3701767c5feSopenharmony_ci}
3711767c5feSopenharmony_ci
3721767c5feSopenharmony_cibool ShortNumberInfo::IsCarrierSpecific(const PhoneNumber& number) const {
3731767c5feSopenharmony_ci  list<string> region_codes;
3741767c5feSopenharmony_ci  phone_util_.GetRegionCodesForCountryCallingCode(number.country_code(),
3751767c5feSopenharmony_ci                                                  &region_codes);
3761767c5feSopenharmony_ci  string region_code;
3771767c5feSopenharmony_ci  GetRegionCodeForShortNumberFromRegionList(number, region_codes, &region_code);
3781767c5feSopenharmony_ci  string national_number;
3791767c5feSopenharmony_ci  phone_util_.GetNationalSignificantNumber(number, &national_number);
3801767c5feSopenharmony_ci  const PhoneMetadata* phone_metadata = GetMetadataForRegion(region_code);
3811767c5feSopenharmony_ci  return phone_metadata &&
3821767c5feSopenharmony_ci         MatchesPossibleNumberAndNationalNumber(*matcher_api_, national_number,
3831767c5feSopenharmony_ci             phone_metadata->carrier_specific());
3841767c5feSopenharmony_ci}
3851767c5feSopenharmony_ci
3861767c5feSopenharmony_cibool ShortNumberInfo::IsCarrierSpecificForRegion(const PhoneNumber& number,
3871767c5feSopenharmony_ci    const string& region_dialing_from) const {
3881767c5feSopenharmony_ci  if (!RegionDialingFromMatchesNumber(number, region_dialing_from)) {
3891767c5feSopenharmony_ci    return false;
3901767c5feSopenharmony_ci  }
3911767c5feSopenharmony_ci  string national_number;
3921767c5feSopenharmony_ci  phone_util_.GetNationalSignificantNumber(number, &national_number);
3931767c5feSopenharmony_ci  const PhoneMetadata* phone_metadata =
3941767c5feSopenharmony_ci      GetMetadataForRegion(region_dialing_from);
3951767c5feSopenharmony_ci  return phone_metadata &&
3961767c5feSopenharmony_ci         MatchesPossibleNumberAndNationalNumber(*matcher_api_, national_number,
3971767c5feSopenharmony_ci             phone_metadata->carrier_specific());
3981767c5feSopenharmony_ci}
3991767c5feSopenharmony_ci
4001767c5feSopenharmony_cibool ShortNumberInfo::IsSmsServiceForRegion(const PhoneNumber& number,
4011767c5feSopenharmony_ci    const string& region_dialing_from) const {
4021767c5feSopenharmony_ci  if (!RegionDialingFromMatchesNumber(number, region_dialing_from)) {
4031767c5feSopenharmony_ci    return false;
4041767c5feSopenharmony_ci  }
4051767c5feSopenharmony_ci  string national_number;
4061767c5feSopenharmony_ci  phone_util_.GetNationalSignificantNumber(number, &national_number);
4071767c5feSopenharmony_ci  const PhoneMetadata* phone_metadata =
4081767c5feSopenharmony_ci      GetMetadataForRegion(region_dialing_from);
4091767c5feSopenharmony_ci  return phone_metadata &&
4101767c5feSopenharmony_ci         MatchesPossibleNumberAndNationalNumber(*matcher_api_, national_number,
4111767c5feSopenharmony_ci             phone_metadata->sms_services());
4121767c5feSopenharmony_ci}
4131767c5feSopenharmony_ci
4141767c5feSopenharmony_ci}  // namespace phonenumbers
4151767c5feSopenharmony_ci}  // namespace i18n
416