Browse Source

CPP: libphonenumber 4.8.

pull/567/head
Philippe Liard 14 years ago
committed by Mihaela Rosca
parent
commit
4e11857f14
9 changed files with 20311 additions and 19907 deletions
  1. +1
    -0
      cpp/CMakeLists.txt
  2. +87
    -0
      cpp/src/phonenumbers/callback.h
  3. +9378
    -9301
      cpp/src/phonenumbers/lite_metadata.cc
  4. +10563
    -10481
      cpp/src/phonenumbers/metadata.cc
  5. +163
    -115
      cpp/src/phonenumbers/phonenumbermatcher.cc
  6. +21
    -0
      cpp/src/phonenumbers/phonenumbermatcher.h
  7. +38
    -5
      cpp/src/phonenumbers/phonenumberutil.cc
  8. +5
    -1
      cpp/test/phonenumbers/phonenumbermatcher_test.cc
  9. +55
    -4
      cpp/test/phonenumbers/phonenumberutil_test.cc

+ 1
- 0
cpp/CMakeLists.txt View File

@ -340,6 +340,7 @@ add_custom_target(test COMMAND libphonenumber_test DEPENDS libphonenumber_test)
# Install rules.
install (FILES
"src/phonenumbers/asyoutypeformatter.h"
"src/phonenumbers/callback.h"
"src/phonenumbers/logger.h"
"src/phonenumbers/phonenumber.pb.h"
"src/phonenumbers/phonemetadata.pb.h"


+ 87
- 0
cpp/src/phonenumbers/callback.h View File

@ -0,0 +1,87 @@
// 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: Philippe Liard.
//
// Light implementation emulating base/callback.h. This is an internal header,
// users should not depend on it.
// Note that this implementation is very limited for now and
// libphonenumber-specific.
#ifndef I18N_PHONENUMBERS_CALLBACK_H_
#define I18N_PHONENUMBERS_CALLBACK_H_
namespace i18n {
namespace phonenumbers {
template <typename R, typename A1, typename A2, typename A3, typename A4>
struct ResultCallback4 {
virtual ~ResultCallback4() {}
virtual R Run(A1 a1, A2 a2, A3 a3, A4 a4) = 0;
};
template <typename R, typename A1, typename A2, typename A3, typename A4>
class FunctionCallback4 : public ResultCallback4<R, A1, A2, A3, A4> {
public:
typedef R (FunctionType)(A1, A2, A3, A4);
explicit FunctionCallback4(FunctionType* function) : function_(function) {}
virtual ~FunctionCallback4() {}
virtual R Run(A1 a1, A2 a2, A3 a3, A4 a4) {
return function_(a1, a2, a3, a4);
}
private:
FunctionType* const function_;
};
template <typename T, typename R, typename A1, typename A2, typename A3,
typename A4>
class ConstMethodCallback4 : public ResultCallback4<R, A1, A2, A3, A4> {
public:
typedef R (T::*MethodType)(A1, A2, A3, A4) const;
ConstMethodCallback4(const T* instance, MethodType method)
: instance_(instance),
method_(method) {}
virtual ~ConstMethodCallback4() {}
virtual R Run(A1 a1, A2 a2, A3 a3, A4 a4) {
return (instance_->*method_)(a1, a2, a3, a4);
}
private:
const T* const instance_;
MethodType const method_;
};
template <typename R, typename A1, typename A2, typename A3, typename A4>
ResultCallback4<R, A1, A2, A3, A4>* NewPermanentCallback(
R (*function)(A1, A2, A3, A4)) {
return new FunctionCallback4<R, A1, A2, A3, A4>(function);
}
template <typename T, typename R, typename A1, typename A2, typename A3,
typename A4>
ResultCallback4<R, A1, A2, A3, A4>* NewPermanentCallback(
const T* instance,
R (T::*method)(A1, A2, A3, A4) const) {
return new ConstMethodCallback4<T, R, A1, A2, A3, A4>(instance, method);
}
} // namespace phonenumbers
} // namespace i18n
#endif // I18N_PHONENUMBERS_CALLBACK_H_

+ 9378
- 9301
cpp/src/phonenumbers/lite_metadata.cc
File diff suppressed because it is too large
View File


+ 10563
- 10481
cpp/src/phonenumbers/metadata.cc
File diff suppressed because it is too large
View File


+ 163
- 115
cpp/src/phonenumbers/phonenumbermatcher.cc View File

@ -35,6 +35,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "phonenumbers/callback.h"
#include "phonenumbers/default_logger.h"
#include "phonenumbers/encoding_utils.h"
#include "phonenumbers/normalize_utf8.h"
@ -70,28 +71,6 @@ bool IsInvalidPunctuationSymbol(char32 character) {
return character == '%' || u_charType(character) == U_CURRENCY_SYMBOL;
}
// Helper method to get the national-number part of a number, formatted without
// any national prefix, and return it as a set of digit blocks that would be
// formatted together.
void GetNationalNumberGroups(const PhoneNumberUtil& util,
const PhoneNumber& number,
vector<string>* digit_blocks) {
// This will be in the format +CC-DG;ext=EXT where DG represents groups of
// digits.
string rfc3966_format;
util.Format(number, PhoneNumberUtil::RFC3966, &rfc3966_format);
// We remove the extension part from the formatted string before splitting it
// into different groups.
size_t end_index = rfc3966_format.find(';');
if (end_index == string::npos) {
end_index = rfc3966_format.length();
}
// The country-code will have a '-' following it.
size_t start_index = rfc3966_format.find('-') + 1;
SplitStringUsing(rfc3966_format.substr(start_index, end_index - start_index),
"-", digit_blocks);
}
bool ContainsOnlyValidXChars(const PhoneNumber& number, const string& candidate,
const PhoneNumberUtil& util) {
// The characters 'x' and 'X' can be (1) a carrier code, in which case they
@ -128,6 +107,48 @@ bool ContainsOnlyValidXChars(const PhoneNumber& number, const string& candidate,
}
return true;
}
bool AllNumberGroupsRemainGrouped(
const PhoneNumberUtil& util,
const PhoneNumber& phone_number,
const string& normalized_candidate,
const vector<string>& formatted_number_groups) {
size_t from_index = 0;
// Check each group of consecutive digits are not broken into separate
// groupings in the normalized_candidate string.
for (size_t i = 0; i < formatted_number_groups.size(); ++i) {
// Fails if the substring of normalized_candidate starting from from_index
// doesn't contain the consecutive digits in formatted_number_groups.at(i).
from_index = normalized_candidate.find(formatted_number_groups.at(i),
from_index);
if (from_index == string::npos) {
return false;
}
// Moves from_index forward.
from_index += formatted_number_groups.at(i).length();
if (i == 0 && from_index < normalized_candidate.length()) {
// We are at the position right after the NDC. Note although
// normalized_candidate might contain non-ASCII formatting characters,
// they won't be treated as ASCII digits when converted to a char.
if (isdigit(normalized_candidate.at(from_index))) {
// This means there is no formatting symbol after the NDC. In this case,
// we only accept the number if there is no formatting symbol at all in
// the number, except for extensions.
string national_significant_number;
util.GetNationalSignificantNumber(
phone_number, &national_significant_number);
return HasPrefixString(normalized_candidate.substr(
from_index - formatted_number_groups.at(i).length()),
national_significant_number);
}
}
}
// The check here makes sure that we haven't mistakenly already used the
// extension to match the last group of the subscriber number. Note the
// extension cannot have formatting in-between digits.
return normalized_candidate.substr(from_index)
.find(phone_number.extension()) != string::npos;
}
} // namespace
#ifdef USE_GOOGLE_BASE
@ -411,49 +432,12 @@ bool PhoneNumberMatcher::VerifyAccordingToLeniency(
!IsNationalPrefixPresentIfRequired(number)) {
return false;
}
// TODO(lararennie,shaopengjia): Evaluate how this works for other locales
// (testing has been limited to NANPA regions) and optimise if necessary.
string normalized_candidate =
NormalizeUTF8::NormalizeDecimalDigits(candidate);
vector<string> formatted_number_groups;
GetNationalNumberGroups(phone_util_, number, &formatted_number_groups);
size_t from_index = 0;
// Check each group of consecutive digits are not broken into separate
// groups in the normalized_candidate string.
for (size_t i = 0; i < formatted_number_groups.size(); ++i) {
// Fails if the substring of normalized_candidate starting from
// from_index doesn't contain the consecutive digits in digit_group.
from_index = normalized_candidate.find(formatted_number_groups.at(i),
from_index);
if (from_index == string::npos) {
return false;
}
// Moves from_index forward.
from_index += formatted_number_groups.at(i).length();
if (i == 0 && from_index < normalized_candidate.length()) {
// We are at the position right after the NDC. Note although
// normalized_candidate might contain non-ASCII formatting characters,
// they won't be treated as ASCII digits when converted to a char.
if (isdigit(normalized_candidate.at(from_index))) {
// This means there is no formatting symbol after the NDC. In this
// case, we only accept the number if there is no formatting
// symbol at all in the number, except for extensions.
string national_significant_number;
phone_util_.GetNationalSignificantNumber(
number, &national_significant_number);
return HasPrefixString(
normalized_candidate.substr(
from_index - formatted_number_groups.at(i).length()),
national_significant_number);
}
}
}
// The check here makes sure that we haven't mistakenly already used the
// extension to match the last group of the subscriber number. Note the
// extension cannot have formatting in-between digits.
return
normalized_candidate.substr(from_index).find(number.extension()) !=
string::npos;
ResultCallback4<bool, const PhoneNumberUtil&, const PhoneNumber&,
const string&, const vector<string>&>* callback =
NewPermanentCallback(&AllNumberGroupsRemainGrouped);
bool is_valid = CheckNumberGroupingIsValid(number, candidate, callback);
delete(callback);
return is_valid;
}
case PhoneNumberMatcher::EXACT_GROUPING: {
if (!phone_util_.IsValidNumber(number) ||
@ -463,56 +447,13 @@ bool PhoneNumberMatcher::VerifyAccordingToLeniency(
!IsNationalPrefixPresentIfRequired(number)) {
return false;
}
// TODO(lararennie,shaopengjia): Evaluate how this works for other locales
// (testing has been limited to NANPA regions) and optimise if necessary.
vector<string> candidate_groups;
string normalized_candidate =
NormalizeUTF8::NormalizeDecimalDigits(candidate);
const scoped_ptr<RegExpInput> candidate_number(
reg_exps_->regexp_factory_->CreateInput(normalized_candidate));
string digit_block;
while (reg_exps_->capturing_ascii_digits_pattern_->FindAndConsume(
candidate_number.get(),
&digit_block)) {
candidate_groups.push_back(digit_block);
}
// Set this to the last group, skipping it if the number has an extension.
int candidate_number_group_index =
number.has_extension() ? candidate_groups.size() - 2
: candidate_groups.size() - 1;
// First we check if the national significant number is formatted as a
// block. We use contains and not equals, since the national significant
// number may be present with a prefix such as a national number prefix,
// or the country code itself.
string national_significant_number;
phone_util_.GetNationalSignificantNumber(number,
&national_significant_number);
if (candidate_groups.size() == 1 ||
candidate_groups.at(candidate_number_group_index).find(
national_significant_number) != string::npos) {
return true;
}
vector<string> formatted_number_groups;
GetNationalNumberGroups(phone_util_, number, &formatted_number_groups);
// Starting from the end, go through in reverse, excluding the first
// group, and check the candidate and number groups are the same.
for (int formatted_number_group_index =
(formatted_number_groups.size() - 1);
formatted_number_group_index > 0 &&
candidate_number_group_index >= 0;
--formatted_number_group_index, --candidate_number_group_index) {
if (candidate_groups.at(candidate_number_group_index) !=
formatted_number_groups.at(formatted_number_group_index)) {
return false;
}
}
// Now check the first group. There may be a national prefix at the start,
// so we only check that the candidate group ends with the formatted
// number group.
return (candidate_number_group_index >= 0 &&
HasSuffixString(candidate_groups.at(candidate_number_group_index),
formatted_number_groups.at(0)));
ResultCallback4<bool, const PhoneNumberUtil&, const PhoneNumber&,
const string&, const vector<string>&>* callback =
NewPermanentCallback(
this, &PhoneNumberMatcher::AllNumberGroupsAreExactlyPresent);
bool is_valid = CheckNumberGroupingIsValid(number, candidate, callback);
delete(callback);
return is_valid;
}
default:
LOG(ERROR) << "No implementation defined for verification for leniency "
@ -655,6 +596,62 @@ bool PhoneNumberMatcher::Find(int index, PhoneNumberMatch* match) {
return false;
}
bool PhoneNumberMatcher::CheckNumberGroupingIsValid(
const PhoneNumber& phone_number,
const string& candidate,
ResultCallback4<bool, const PhoneNumberUtil&, const PhoneNumber&,
const string&, const vector<string>&>* checker) const {
DCHECK(checker);
// TODO: Evaluate how this works for other locales (testing has been limited
// to NANPA regions) and optimise if necessary.
string normalized_candidate =
NormalizeUTF8::NormalizeDecimalDigits(candidate);
vector<string> formatted_number_groups;
GetNationalNumberGroups(phone_number, NULL, // Use default formatting pattern
&formatted_number_groups);
if (checker->Run(phone_util_, phone_number, normalized_candidate,
formatted_number_groups)) {
return true;
}
return false;
}
// Helper method to get the national-number part of a number, formatted without
// any national prefix, and return it as a set of digit blocks that would be
// formatted together.
void PhoneNumberMatcher::GetNationalNumberGroups(
const PhoneNumber& number,
const NumberFormat* formatting_pattern,
vector<string>* digit_blocks) const {
string rfc3966_format;
if (!formatting_pattern) {
// This will be in the format +CC-DG;ext=EXT where DG represents groups of
// digits.
phone_util_.Format(number, PhoneNumberUtil::RFC3966, &rfc3966_format);
// We remove the extension part from the formatted string before splitting
// it into different groups.
size_t end_index = rfc3966_format.find(';');
if (end_index == string::npos) {
end_index = rfc3966_format.length();
}
// The country-code will have a '-' following it.
size_t start_index = rfc3966_format.find('-') + 1;
SplitStringUsing(rfc3966_format.substr(start_index,
end_index - start_index),
"-", digit_blocks);
} else {
// We format the NSN only, and split that according to the separator.
string national_significant_number;
phone_util_.GetNationalSignificantNumber(number,
&national_significant_number);
phone_util_.FormatNsnUsingPattern(national_significant_number,
*formatting_pattern,
PhoneNumberUtil::RFC3966,
&rfc3966_format);
SplitStringUsing(rfc3966_format, "-", digit_blocks);
}
}
bool PhoneNumberMatcher::IsNationalPrefixPresentIfRequired(
const PhoneNumber& number) const {
// First, check how we deduced the country code. If it was written in
@ -709,5 +706,56 @@ bool PhoneNumberMatcher::IsNationalPrefixPresentIfRequired(
return true;
}
bool PhoneNumberMatcher::AllNumberGroupsAreExactlyPresent(
const PhoneNumberUtil& util,
const PhoneNumber& phone_number,
const string& normalized_candidate,
const vector<string>& formatted_number_groups) const {
const scoped_ptr<RegExpInput> candidate_number(
reg_exps_->regexp_factory_->CreateInput(normalized_candidate));
vector<string> candidate_groups;
string digit_block;
while (reg_exps_->capturing_ascii_digits_pattern_->FindAndConsume(
candidate_number.get(),
&digit_block)) {
candidate_groups.push_back(digit_block);
}
// Set this to the last group, skipping it if the number has an extension.
int candidate_number_group_index =
phone_number.has_extension() ? candidate_groups.size() - 2
: candidate_groups.size() - 1;
// First we check if the national significant number is formatted as a block.
// We use find and not equals, since the national significant number may be
// present with a prefix such as a national number prefix, or the country code
// itself.
string national_significant_number;
util.GetNationalSignificantNumber(phone_number,
&national_significant_number);
if (candidate_groups.size() == 1 ||
candidate_groups.at(candidate_number_group_index).find(
national_significant_number) != string::npos) {
return true;
}
// Starting from the end, go through in reverse, excluding the first group,
// and check the candidate and number groups are the same.
for (int formatted_number_group_index =
(formatted_number_groups.size() - 1);
formatted_number_group_index > 0 &&
candidate_number_group_index >= 0;
--formatted_number_group_index, --candidate_number_group_index) {
if (candidate_groups.at(candidate_number_group_index) !=
formatted_number_groups.at(formatted_number_group_index)) {
return false;
}
}
// Now check the first group. There may be a national prefix at the start, so
// we only check that the candidate group ends with the formatted number
// group.
return (candidate_number_group_index >= 0 &&
HasSuffixString(candidate_groups.at(candidate_number_group_index),
formatted_number_groups.at(0)));
}
} // namespace phonenumbers
} // namespace i18n

+ 21
- 0
cpp/src/phonenumbers/phonenumbermatcher.h View File

@ -23,16 +23,20 @@
#define I18N_PHONENUMBERS_PHONENUMBERMATCHER_H_
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "phonenumbers/callback.h"
#include "phonenumbers/regexp_adapter.h"
namespace i18n {
namespace phonenumbers {
using std::string;
using std::vector;
class NumberFormat;
class PhoneNumber;
class PhoneNumberMatch;
class PhoneNumberMatcherRegExps;
@ -121,6 +125,23 @@ class PhoneNumberMatcher {
bool ParseAndVerify(const string& candidate, int offset,
PhoneNumberMatch* match);
bool CheckNumberGroupingIsValid(
const PhoneNumber& phone_number,
const string& candidate,
ResultCallback4<bool, const PhoneNumberUtil&, const PhoneNumber&,
const string&, const vector<string>&>* checker) const;
void GetNationalNumberGroups(
const PhoneNumber& number,
const NumberFormat* formatting_pattern,
vector<string>* digit_blocks) const;
bool AllNumberGroupsAreExactlyPresent(
const PhoneNumberUtil& util,
const PhoneNumber& phone_number,
const string& normalized_candidate,
const vector<string>& formatted_number_groups) const;
bool VerifyAccordingToLeniency(Leniency leniency, const PhoneNumber& number,
const string& candidate) const;


+ 38
- 5
cpp/src/phonenumbers/phonenumberutil.cc View File

@ -96,6 +96,10 @@ const char kPlusSign[] = "+";
const char kStarSign[] = "*";
const char kRfc3966ExtnPrefix[] = ";ext=";
const char kRfc3966Prefix[] = "tel:";
// We include the "+" here since RFC3966 format specifies that the context must
// be specified in international format.
const char kRfc3966PhoneContext[] = ";phone-context=+";
const char kDigits[] = "\\p{Nd}";
// We accept alpha characters in phone numbers, ASCII only. We store lower-case
@ -169,7 +173,8 @@ void PrefixNumberWithCountryCallingCode(
return;
case PhoneNumberUtil::RFC3966:
formatted_number->insert(
0, StrCat(kPlusSign, SimpleItoa(country_calling_code), "-"));
0, StrCat(kRfc3966Prefix, kPlusSign,
SimpleItoa(country_calling_code), "-"));
return;
case PhoneNumberUtil::NATIONAL:
default:
@ -666,6 +671,9 @@ PhoneNumberUtil::PhoneNumberUtil()
it != metadata_collection.metadata().end();
++it) {
const string& region_code = it->id();
if (region_code == RegionCode::GetUnknown()) {
continue;
}
int country_calling_code = it->country_code();
if (kRegionCodeForNonGeoEntity == region_code) {
@ -1697,10 +1705,32 @@ PhoneNumberUtil::ErrorType PhoneNumberUtil::ParseHelper(
bool check_region,
PhoneNumber* phone_number) const {
DCHECK(phone_number);
// Extract a possible number from the string passed in (this strips leading
// characters that could not be the start of a phone number.)
size_t index_of_phone_context = number_to_parse.find(kRfc3966PhoneContext);
string national_number;
ExtractPossibleNumber(number_to_parse, &national_number);
if (index_of_phone_context != string::npos) {
// Prefix the number with the phone context. The offset here is because the
// context we are expecting to match should start with a "+" sign, and we
// want to include this at the start of the number.
StrAppend(
&national_number,
number_to_parse.substr(
index_of_phone_context + strlen(kRfc3966PhoneContext) - 1));
// Now append everything between the "tel:" prefix and the phone-context.
int end_of_rfc_prefix =
number_to_parse.find(kRfc3966Prefix) + strlen(kRfc3966Prefix);
StrAppend(
&national_number,
number_to_parse.substr(end_of_rfc_prefix,
index_of_phone_context - end_of_rfc_prefix));
// Note that phone-contexts that are URLs will not be parsed -
// IsViablePhoneNumber will throw an exception below.
} else {
// Extract a possible number from the string passed in (this strips leading
// characters that could not be the start of a phone number.)
ExtractPossibleNumber(number_to_parse, &national_number);
}
if (!IsViablePhoneNumber(national_number)) {
VLOG(2) << "The string supplied did not seem to be a phone number.";
return NOT_A_NUMBER;
@ -1991,7 +2021,10 @@ int PhoneNumberUtil::GetLengthOfGeographicalAreaCode(
}
const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
DCHECK(metadata);
if (!metadata->has_national_prefix()) {
// If a country doesn't use a national prefix, and this number doesn't have an
// Italian leading zero, we assume it is a closed dialling plan with no area
// codes.
if (!metadata->has_national_prefix() && !number.italian_leading_zero()) {
return 0;
}


+ 5
- 1
cpp/test/phonenumbers/phonenumbermatcher_test.cc View File

@ -536,6 +536,10 @@ TEST_F(PhoneNumberMatcherTest, IsLatinLetter) {
EXPECT_FALSE(IsLatinLetter(' '));
EXPECT_FALSE(
IsLatinLetter(UnicodeString::fromUTF8("\xE6\x88\x91" /* "我" */)[0]));
/* Hiragana letter no (の) - this should neither seem to start or end with a
Latin letter. */
EXPECT_FALSE(IsLatinLetter(UnicodeString::fromUTF8("\xE3\x81\xAE")[0]));
EXPECT_FALSE(IsLatinLetter(UnicodeString::fromUTF8("\xE3\x81\xAE")[2]));
}
TEST_F(PhoneNumberMatcherTest, MatchesWithSurroundingLatinChars) {
@ -747,7 +751,7 @@ static const NumberTest kStrictGroupingCases[] = {
NumberTest("0800-2491234", RegionCode::DE()),
};
// Strings with number-like things that should found at all levels.
// Strings with number-like things that should be found at all levels.
static const NumberTest kExactGroupingCases[] = {
NumberTest(
/* "4156667777" */


+ 55
- 4
cpp/test/phonenumbers/phonenumberutil_test.cc View File

@ -337,7 +337,7 @@ TEST_F(PhoneNumberUtilTest, FormatUSNumber) {
&formatted_number);
EXPECT_EQ("+1 900 253 0000", formatted_number);
phone_util_.Format(test_number, PhoneNumberUtil::RFC3966, &formatted_number);
EXPECT_EQ("+1-900-253-0000", formatted_number);
EXPECT_EQ("tel:+1-900-253-0000", formatted_number);
test_number.set_national_number(0ULL);
phone_util_.Format(test_number, PhoneNumberUtil::NATIONAL, &formatted_number);
EXPECT_EQ("0", formatted_number);
@ -405,7 +405,7 @@ TEST_F(PhoneNumberUtilTest, FormatDENumber) {
&formatted_number);
EXPECT_EQ("+49 30/1234", formatted_number);
phone_util_.Format(test_number, PhoneNumberUtil::RFC3966, &formatted_number);
EXPECT_EQ("+49-30-1234", formatted_number);
EXPECT_EQ("tel:+49-30-1234", formatted_number);
test_number.set_national_number(291123ULL);
phone_util_.Format(test_number, PhoneNumberUtil::NATIONAL, &formatted_number);
@ -968,7 +968,7 @@ TEST_F(PhoneNumberUtilTest, FormatByPattern) {
phone_util_.FormatByPattern(test_number, PhoneNumberUtil::RFC3966,
number_formats,
&formatted_number);
EXPECT_EQ("+1-650-253-0000", formatted_number);
EXPECT_EQ("tel:+1-650-253-0000", formatted_number);
// $NP is set to '1' for the US. Here we check that for other NANPA countries
// the US rules are followed.
@ -1057,7 +1057,7 @@ TEST_F(PhoneNumberUtilTest, FormatNumberWithExtension) {
EXPECT_EQ("03-331 6005 ext. 1234", formatted_number);
// Uses RFC 3966 syntax.
phone_util_.Format(nz_number, PhoneNumberUtil::RFC3966, &formatted_number);
EXPECT_EQ("+64-3-331-6005;ext=1234", formatted_number);
EXPECT_EQ("tel:+64-3-331-6005;ext=1234", formatted_number);
// Extension prefix overridden in the territory information for the US:
PhoneNumber us_number_with_extension;
us_number_with_extension.set_country_code(1);
@ -1105,9 +1105,17 @@ TEST_F(PhoneNumberUtilTest, GetLengthOfGeographicalAreaCode) {
number.set_national_number(293744000ULL);
EXPECT_EQ(1, phone_util_.GetLengthOfGeographicalAreaCode(number));
// Italian numbers - there is no national prefix, but it still has an area
// code.
number.set_country_code(39);
number.set_national_number(236618300ULL);
number.set_italian_leading_zero(true);
EXPECT_EQ(2, phone_util_.GetLengthOfGeographicalAreaCode(number));
// Google Singapore. Singapore has no area code and no national prefix.
number.set_country_code(65);
number.set_national_number(65218000ULL);
number.set_italian_leading_zero(false);
EXPECT_EQ(0, phone_util_.GetLengthOfGeographicalAreaCode(number));
// An international toll free number, which has no area code.
@ -2593,6 +2601,19 @@ TEST_F(PhoneNumberUtilTest, ParseNationalNumber) {
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("03 331 6005", RegionCode::NZ(), &test_number));
EXPECT_EQ(nz_number, test_number);
// Test parsing RFC3966 format with a phone context.
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("tel:03-331-6005;phone-context=+64",
RegionCode::NZ(), &test_number));
EXPECT_EQ(nz_number, test_number);
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("tel:331-6005;phone-context=+64-3",
RegionCode::NZ(), &test_number));
EXPECT_EQ(nz_number, test_number);
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("tel:331-6005;phone-context=+64-3",
RegionCode::US(), &test_number));
EXPECT_EQ(nz_number, test_number);
// Testing international prefixes.
// Should strip country code.
@ -3043,6 +3064,18 @@ TEST_F(PhoneNumberUtilTest, FailedParseOnInvalidNumbers) {
phone_util_.Parse("0119", RegionCode::US(),
&test_number));
EXPECT_EQ(PhoneNumber::default_instance(), test_number);
// RFC3966 phone-context is a website.
EXPECT_EQ(PhoneNumberUtil::NOT_A_NUMBER,
phone_util_.Parse("tel:555-1234;phone-context:www.google.com",
RegionCode::US(), &test_number));
EXPECT_EQ(PhoneNumber::default_instance(), test_number);
// This is invalid because no "+" sign is present as part of phone-context.
// This should not succeed in being parsed.
EXPECT_EQ(PhoneNumberUtil::NOT_A_NUMBER,
phone_util_.Parse("tel:555-1234;phone-context:1-331",
RegionCode::US(), &test_number));
EXPECT_EQ(PhoneNumber::default_instance(), test_number);
}
TEST_F(PhoneNumberUtilTest, ParseNumbersWithPlusWithNoRegion) {
@ -3079,6 +3112,18 @@ TEST_F(PhoneNumberUtilTest, ParseNumbersWithPlusWithNoRegion) {
RegionCode::GetUnknown(), &result_proto));
EXPECT_EQ(toll_free_number, result_proto);
result_proto.Clear();
// Test parsing RFC3966 format with a phone context.
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("tel:03-331-6005;phone-context=+64",
RegionCode::GetUnknown(), &result_proto));
EXPECT_EQ(nz_number, result_proto);
result_proto.Clear();
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse(" tel:03-331-6005;phone-context=+64",
RegionCode::GetUnknown(), &result_proto));
EXPECT_EQ(nz_number, result_proto);
nz_number.set_raw_input("+64 3 331 6005");
nz_number.set_country_code_source(PhoneNumber::FROM_NUMBER_WITH_PLUS_SIGN);
// It is important that we set this to an empty string, since we used
@ -3206,6 +3251,12 @@ TEST_F(PhoneNumberUtilTest, ParseExtensions) {
phone_util_.Parse("+44-2034567890;ext=456", RegionCode::GB(),
&test_number));
EXPECT_EQ(uk_number, test_number);
test_number.Clear();
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("tel:2034567890;ext=456;phone-context=+44",
RegionCode::ZZ(), &test_number));
EXPECT_EQ(uk_number, test_number);
// Full-width extension, "extn" only.
test_number.Clear();
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,


Loading…
Cancel
Save