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 ®ion_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 ®ion_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 ®ion_codes); 1801767c5feSopenharmony_ci string region_code; 1811767c5feSopenharmony_ci GetRegionCodeForShortNumberFromRegionList(number, region_codes, ®ion_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 ®ion_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 ®ion_codes); 3761767c5feSopenharmony_ci string region_code; 3771767c5feSopenharmony_ci GetRegionCodeForShortNumberFromRegionList(number, region_codes, ®ion_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