Browse Source

CPP: libphonenumber 4.6.

Note that the metadata files were not uploaded to appspot because they were too
large. Here is the list of the files affected by this change (generated by
Git):

cpp/src/phonenumbers/lite_metadata.cc
cpp/src/phonenumbers/logger.h
cpp/src/phonenumbers/metadata.cc
cpp/src/phonenumbers/phonenumbermatcher.cc
cpp/src/phonenumbers/phonenumberutil.cc
cpp/src/phonenumbers/phonenumberutil.h
cpp/src/phonenumbers/region_code.h
cpp/src/phonenumbers/stringutil.cc
cpp/src/phonenumbers/stringutil.h
cpp/test/phonenumbers/asyoutypeformatter_test.cc
cpp/test/phonenumbers/phonenumbermatcher_test.cc
cpp/test/phonenumbers/phonenumberutil_test.cc
cpp/test/phonenumbers/stringutil_test.cc

This CL also fixes the issue reported by Aaron about the logger being invoked
before it is initialized.

Review URL: https://codereview.appspot.com/5786065
pull/567/head
Philippe Liard 14 years ago
committed by Mihaela Rosca
parent
commit
e55d38429c
13 changed files with 17878 additions and 17486 deletions
  1. +9692
    -9601
      cpp/src/phonenumbers/lite_metadata.cc
  2. +2
    -1
      cpp/src/phonenumbers/logger.h
  3. +7703
    -7602
      cpp/src/phonenumbers/metadata.cc
  4. +16
    -1
      cpp/src/phonenumbers/phonenumbermatcher.cc
  5. +215
    -226
      cpp/src/phonenumbers/phonenumberutil.cc
  6. +19
    -21
      cpp/src/phonenumbers/phonenumberutil.h
  7. +4
    -0
      cpp/src/phonenumbers/region_code.h
  8. +36
    -0
      cpp/src/phonenumbers/stringutil.cc
  9. +10
    -0
      cpp/src/phonenumbers/stringutil.h
  10. +17
    -0
      cpp/test/phonenumbers/asyoutypeformatter_test.cc
  11. +77
    -30
      cpp/test/phonenumbers/phonenumbermatcher_test.cc
  12. +72
    -1
      cpp/test/phonenumbers/phonenumberutil_test.cc
  13. +15
    -3
      cpp/test/phonenumbers/stringutil_test.cc

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


+ 2
- 1
cpp/src/phonenumbers/logger.h View File

@ -62,8 +62,9 @@ class Logger {
level_ = level; level_ = level;
} }
static inline void set_logger_impl(Logger* logger) {
static inline Logger* set_logger_impl(Logger* logger) {
impl_ = logger; impl_ = logger;
return logger;
} }
static inline Logger* mutable_logger_impl() { static inline Logger* mutable_logger_impl() {


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


+ 16
- 1
cpp/src/phonenumbers/phonenumbermatcher.cc View File

@ -190,6 +190,10 @@ class PhoneNumberMatcherRegExps : public Singleton<PhoneNumberMatcherRegExps> {
// Matches strings that look like dates using "/" as a separator. Examples: // Matches strings that look like dates using "/" as a separator. Examples:
// 3/10/2011, 31/10/96 or 08/31/95. // 3/10/2011, 31/10/96 or 08/31/95.
scoped_ptr<const RegExp> slash_separated_dates_; scoped_ptr<const RegExp> slash_separated_dates_;
// Matches timestamps. Examples: "2012-01-02 08:00". Note that the reg-ex does
// not include trailing ":\d\d" -- that is covered by time_stamps_suffix_.
scoped_ptr<const RegExp> time_stamps_;
scoped_ptr<const RegExp> time_stamps_suffix_;
// Pattern to check that brackets match. Opening brackets should be closed // Pattern to check that brackets match. Opening brackets should be closed
// within a phone number. This also checks that there is something inside the // within a phone number. This also checks that there is something inside the
// brackets. Having no brackets at all is also fine. // brackets. Having no brackets at all is also fine.
@ -249,6 +253,9 @@ class PhoneNumberMatcherRegExps : public Singleton<PhoneNumberMatcherRegExps> {
slash_separated_dates_(regexp_factory_->CreateRegExp( slash_separated_dates_(regexp_factory_->CreateRegExp(
"(?:(?:[0-3]?\\d/[01]?\\d)|" "(?:(?:[0-3]?\\d/[01]?\\d)|"
"(?:[01]?\\d/[0-3]?\\d))/(?:[12]\\d)?\\d{2}")), "(?:[01]?\\d/[0-3]?\\d))/(?:[12]\\d)?\\d{2}")),
time_stamps_(regexp_factory_->CreateRegExp(
"[12]\\d{3}[-/]?[01]\\d[-/]?[0-3]\\d [0-2]\\d$")),
time_stamps_suffix_(regexp_factory_->CreateRegExp(":[0-5]\\d")),
matching_brackets_(regexp_factory_->CreateRegExp( matching_brackets_(regexp_factory_->CreateRegExp(
StrCat(leading_maybe_matched_bracket_, non_parens_, "+", StrCat(leading_maybe_matched_bracket_, non_parens_, "+",
bracket_pairs_, non_parens_, "*"))), bracket_pairs_, non_parens_, "*"))),
@ -578,6 +585,15 @@ bool PhoneNumberMatcher::ExtractMatch(const string& candidate, int offset,
reg_exps_->slash_separated_dates_->PartialMatch(candidate)) { reg_exps_->slash_separated_dates_->PartialMatch(candidate)) {
return false; return false;
} }
// Skip potential time-stamps.
if (reg_exps_->time_stamps_->PartialMatch(candidate)) {
scoped_ptr<RegExpInput> following_text(
reg_exps_->regexp_factory_->CreateInput(
text_.substr(offset + candidate.size())));
if (reg_exps_->time_stamps_suffix_->Consume(following_text.get())) {
return false;
}
}
// Try to come up with a valid match given the entire candidate. // Try to come up with a valid match given the entire candidate.
if (ParseAndVerify(candidate, offset, match)) { if (ParseAndVerify(candidate, offset, match)) {
@ -659,7 +675,6 @@ bool PhoneNumberMatcher::IsNationalPrefixPresentIfRequired(
phone_util_.GetNationalSignificantNumber(number, &national_number); phone_util_.GetNationalSignificantNumber(number, &national_number);
const NumberFormat* format_rule = const NumberFormat* format_rule =
phone_util_.ChooseFormattingPatternForNumber(metadata->number_format(), phone_util_.ChooseFormattingPatternForNumber(metadata->number_format(),
national_number,
national_number); national_number);
// To do this, we check that a national prefix formatting rule was present and // To do this, we check that a national prefix formatting rule was present and
// that it wasn't just the first-group symbol ($1) with punctuation. // that it wasn't just the first-group symbol ($1) with punctuation.


+ 215
- 226
cpp/src/phonenumbers/phonenumberutil.cc View File

@ -93,6 +93,8 @@ const char kColombiaMobileToFixedLinePrefix[] = "3";
// The kPlusSign signifies the international prefix. // The kPlusSign signifies the international prefix.
const char kPlusSign[] = "+"; const char kPlusSign[] = "+";
const char kStarSign[] = "*";
const char kRfc3966ExtnPrefix[] = ";ext="; const char kRfc3966ExtnPrefix[] = ";ext=";
const char kDigits[] = "\\p{Nd}"; const char kDigits[] = "\\p{Nd}";
@ -152,36 +154,27 @@ const PhoneNumberDesc* GetNumberDescByType(
} }
// A helper function that is used by Format and FormatByPattern. // A helper function that is used by Format and FormatByPattern.
void FormatNumberByFormat(int country_calling_code,
PhoneNumberUtil::PhoneNumberFormat number_format,
const string& formatted_national_number,
const string& formatted_extension,
string* formatted_number) {
void PrefixNumberWithCountryCallingCode(
int country_calling_code,
PhoneNumberUtil::PhoneNumberFormat number_format,
string* formatted_number) {
switch (number_format) { switch (number_format) {
case PhoneNumberUtil::E164: case PhoneNumberUtil::E164:
formatted_number->assign(StrCat(kPlusSign,
SimpleItoa(country_calling_code),
formatted_national_number,
formatted_extension));
formatted_number->insert(
0, StrCat(kPlusSign, SimpleItoa(country_calling_code)));
return; return;
case PhoneNumberUtil::INTERNATIONAL: case PhoneNumberUtil::INTERNATIONAL:
formatted_number->assign(StrCat(kPlusSign,
SimpleItoa(country_calling_code),
" ",
formatted_national_number,
formatted_extension));
formatted_number->insert(
0, StrCat(kPlusSign, SimpleItoa(country_calling_code), " "));
return; return;
case PhoneNumberUtil::RFC3966: case PhoneNumberUtil::RFC3966:
formatted_number->assign(StrCat(kPlusSign,
SimpleItoa(country_calling_code),
"-",
formatted_national_number,
formatted_extension));
formatted_number->insert(
0, StrCat(kPlusSign, SimpleItoa(country_calling_code), "-"));
return; return;
case PhoneNumberUtil::NATIONAL: case PhoneNumberUtil::NATIONAL:
default: default:
formatted_number->assign(StrCat(formatted_national_number,
formatted_extension));
// Do nothing.
return;
} }
} }
@ -480,6 +473,8 @@ class PhoneNumberRegExpsAndMappings {
} }
} }
const string punctuation_and_star_sign_;
// Regular expression of viable phone numbers. This is location independent. // Regular expression of viable phone numbers. This is location independent.
// Checks we have at least three leading digits, and only valid punctuation, // Checks we have at least three leading digits, and only valid punctuation,
// alpha characters and digits in the phone number. Does not include extension // alpha characters and digits in the phone number. Does not include extension
@ -487,7 +482,8 @@ class PhoneNumberRegExpsAndMappings {
// used as a placeholder for carrier codes, for example in Brazilian phone // used as a placeholder for carrier codes, for example in Brazilian phone
// numbers. We also allow multiple plus-signs at the start. // numbers. We also allow multiple plus-signs at the start.
// Corresponds to the following: // Corresponds to the following:
// plus_sign*([punctuation]*[digits]){3,}([punctuation]|[digits]|[alpha])*
// plus_sign*(([punctuation]|[star])*[digits]){3,}
// ([punctuation]|[star]|[digits]|[alpha])*
const string valid_phone_number_; const string valid_phone_number_;
// Regexp of all possible ways to write extensions, for use when parsing. This // Regexp of all possible ways to write extensions, for use when parsing. This
@ -583,11 +579,14 @@ class PhoneNumberRegExpsAndMappings {
scoped_ptr<const RegExp> plus_chars_pattern_; scoped_ptr<const RegExp> plus_chars_pattern_;
PhoneNumberRegExpsAndMappings() PhoneNumberRegExpsAndMappings()
: valid_phone_number_(
: punctuation_and_star_sign_(StrCat(PhoneNumberUtil::kValidPunctuation,
kStarSign)),
valid_phone_number_(
StrCat("[", PhoneNumberUtil::kPlusChars, "]*(?:[", StrCat("[", PhoneNumberUtil::kPlusChars, "]*(?:[",
PhoneNumberUtil::kValidPunctuation, "]*[",
punctuation_and_star_sign_, "]*[",
kDigits, "]){3,}[", kValidAlpha, kDigits, "]){3,}[", kValidAlpha,
PhoneNumberUtil::kValidPunctuation, kDigits, "]*")),
punctuation_and_star_sign_, kDigits,
"]*")),
extn_patterns_for_parsing_( extn_patterns_for_parsing_(
CreateExtnPattern(StrCat(",", kSingleExtnSymbolsForMatching))), CreateExtnPattern(StrCat(",", kSingleExtnSymbolsForMatching))),
regexp_factory_(new RegExpFactory()), regexp_factory_(new RegExpFactory()),
@ -644,7 +643,7 @@ class PhoneNumberRegExpsAndMappings {
// Private constructor. Also takes care of initialisation. // Private constructor. Also takes care of initialisation.
PhoneNumberUtil::PhoneNumberUtil() PhoneNumberUtil::PhoneNumberUtil()
: logger_(new StdoutLogger()),
: logger_(Logger::set_logger_impl(new StdoutLogger())),
reg_exps_(new PhoneNumberRegExpsAndMappings), reg_exps_(new PhoneNumberRegExpsAndMappings),
country_calling_code_to_region_code_map_(new vector<IntRegionsPair>()), country_calling_code_to_region_code_map_(new vector<IntRegionsPair>()),
nanpa_regions_(new set<string>()), nanpa_regions_(new set<string>()),
@ -667,6 +666,7 @@ PhoneNumberUtil::PhoneNumberUtil()
it != metadata_collection.metadata().end(); it != metadata_collection.metadata().end();
++it) { ++it) {
const string& region_code = it->id(); const string& region_code = it->id();
int country_calling_code = it->country_code(); int country_calling_code = it->country_code();
if (kRegionCodeForNonGeoEntity == region_code) { if (kRegionCodeForNonGeoEntity == region_code) {
country_code_to_non_geographical_metadata_map_->insert( country_code_to_non_geographical_metadata_map_->insert(
@ -774,8 +774,8 @@ void PhoneNumberUtil::GetNddPrefixForRegion(const string& region_code,
string* national_prefix) const { string* national_prefix) const {
DCHECK(national_prefix); DCHECK(national_prefix);
if (!IsValidRegionCode(region_code)) { if (!IsValidRegionCode(region_code)) {
LOG(ERROR) << "Invalid or unknown region code (" << region_code
<< ") provided.";
LOG(WARNING) << "Invalid or unknown region code (" << region_code
<< ") provided.";
return; return;
} }
const PhoneMetadata* metadata = GetMetadataForRegion(region_code); const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
@ -842,8 +842,9 @@ void PhoneNumberUtil::Format(const PhoneNumber& number,
if (number_format == E164) { if (number_format == E164) {
// Early exit for E164 case since no formatting of the national number needs // Early exit for E164 case since no formatting of the national number needs
// to be applied. Extensions are not formatted. // to be applied. Extensions are not formatted.
FormatNumberByFormat(country_calling_code, E164,
national_significant_number, "", formatted_number);
formatted_number->assign(national_significant_number);
PrefixNumberWithCountryCallingCode(country_calling_code, E164,
formatted_number);
return; return;
} }
// Note here that all NANPA formatting rules are contained by US, so we use // Note here that all NANPA formatting rules are contained by US, so we use
@ -858,15 +859,12 @@ void PhoneNumberUtil::Format(const PhoneNumber& number,
} }
const PhoneMetadata* metadata = const PhoneMetadata* metadata =
GetMetadataForRegionOrCallingCode(country_calling_code, region_code); GetMetadataForRegionOrCallingCode(country_calling_code, region_code);
string formatted_extension;
MaybeGetFormattedExtension(number, *metadata, number_format,
&formatted_extension);
string formatted_national_number;
FormatNationalNumber(national_significant_number, *metadata, number_format,
&formatted_national_number);
FormatNumberByFormat(country_calling_code, number_format,
formatted_national_number,
formatted_extension, formatted_number);
FormatNsn(national_significant_number, *metadata, number_format,
formatted_number);
MaybeAppendFormattedExtension(number, *metadata, number_format,
formatted_number);
PrefixNumberWithCountryCallingCode(country_calling_code, number_format,
formatted_number);
} }
void PhoneNumberUtil::FormatByPattern( void PhoneNumberUtil::FormatByPattern(
@ -888,47 +886,44 @@ void PhoneNumberUtil::FormatByPattern(
formatted_number->assign(national_significant_number); formatted_number->assign(national_significant_number);
return; return;
} }
RepeatedPtrField<NumberFormat> user_defined_formats_copy;
const PhoneMetadata* metadata = const PhoneMetadata* metadata =
GetMetadataForRegionOrCallingCode(country_calling_code, region_code); GetMetadataForRegionOrCallingCode(country_calling_code, region_code);
for (RepeatedPtrField<NumberFormat>::const_iterator it =
user_defined_formats.begin();
it != user_defined_formats.end();
++it) {
const NumberFormat* formatting_pattern =
ChooseFormattingPatternForNumber(user_defined_formats,
national_significant_number);
if (!formatting_pattern) {
// If no pattern above is matched, we format the number as a whole.
formatted_number->assign(national_significant_number);
} else {
NumberFormat num_format_copy;
// Before we do a replacement of the national prefix pattern $NP with the
// national prefix, we need to copy the rule so that subsequent replacements
// for different numbers have the appropriate national prefix.
num_format_copy.MergeFrom(*formatting_pattern);
string national_prefix_formatting_rule( string national_prefix_formatting_rule(
it->national_prefix_formatting_rule());
formatting_pattern->national_prefix_formatting_rule());
if (!national_prefix_formatting_rule.empty()) { if (!national_prefix_formatting_rule.empty()) {
const string& national_prefix = metadata->national_prefix(); const string& national_prefix = metadata->national_prefix();
NumberFormat* num_format_copy = user_defined_formats_copy.Add();
num_format_copy->MergeFrom(*it);
if (!national_prefix.empty()) { if (!national_prefix.empty()) {
// Replace $NP with national prefix and $FG with the first group ($1). // Replace $NP with national prefix and $FG with the first group ($1).
GlobalReplaceSubstring("$NP", national_prefix, GlobalReplaceSubstring("$NP", national_prefix,
&national_prefix_formatting_rule); &national_prefix_formatting_rule);
GlobalReplaceSubstring("$FG", "$1", GlobalReplaceSubstring("$FG", "$1",
&national_prefix_formatting_rule); &national_prefix_formatting_rule);
num_format_copy->set_national_prefix_formatting_rule(
num_format_copy.set_national_prefix_formatting_rule(
national_prefix_formatting_rule); national_prefix_formatting_rule);
} else { } else {
// We don't want to have a rule for how to format the national prefix if // We don't want to have a rule for how to format the national prefix if
// there isn't one. // there isn't one.
num_format_copy->clear_national_prefix_formatting_rule();
num_format_copy.clear_national_prefix_formatting_rule();
} }
} else {
user_defined_formats_copy.Add()->MergeFrom(*it);
} }
FormatNsnUsingPattern(national_significant_number, num_format_copy,
number_format, formatted_number);
} }
string formatted_number_without_extension;
FormatAccordingToFormats(national_significant_number,
user_defined_formats_copy,
number_format, national_significant_number,
&formatted_number_without_extension);
string formatted_extension;
MaybeGetFormattedExtension(number, *metadata, NATIONAL,
&formatted_extension);
FormatNumberByFormat(country_calling_code, number_format,
formatted_number_without_extension, formatted_extension,
formatted_number);
MaybeAppendFormattedExtension(number, *metadata, NATIONAL, formatted_number);
PrefixNumberWithCountryCallingCode(country_calling_code, number_format,
formatted_number);
} }
void PhoneNumberUtil::FormatNationalNumberWithCarrierCode( void PhoneNumberUtil::FormatNationalNumberWithCarrierCode(
@ -949,16 +944,11 @@ void PhoneNumberUtil::FormatNationalNumberWithCarrierCode(
} }
const PhoneMetadata* metadata = const PhoneMetadata* metadata =
GetMetadataForRegionOrCallingCode(country_calling_code, region_code); GetMetadataForRegionOrCallingCode(country_calling_code, region_code);
string formatted_extension;
MaybeGetFormattedExtension(number, *metadata, NATIONAL,
&formatted_extension);
string formatted_national_number;
FormatNationalNumberWithCarrier(national_significant_number, *metadata,
NATIONAL, carrier_code,
&formatted_national_number);
FormatNumberByFormat(country_calling_code, NATIONAL,
formatted_national_number, formatted_extension,
formatted_number);
FormatNsnWithCarrier(national_significant_number, *metadata, NATIONAL,
carrier_code, formatted_number);
MaybeAppendFormattedExtension(number, *metadata, NATIONAL, formatted_number);
PrefixNumberWithCountryCallingCode(country_calling_code, NATIONAL,
formatted_number);
} }
const PhoneMetadata* PhoneNumberUtil::GetMetadataForRegionOrCallingCode( const PhoneMetadata* PhoneNumberUtil::GetMetadataForRegionOrCallingCode(
@ -1046,9 +1036,9 @@ void PhoneNumberUtil::FormatOutOfCountryCallingNumber(
string* formatted_number) const { string* formatted_number) const {
DCHECK(formatted_number); DCHECK(formatted_number);
if (!IsValidRegionCode(calling_from)) { if (!IsValidRegionCode(calling_from)) {
VLOG(1) << "Trying to format number from invalid region "
<< calling_from
<< ". International formatting applied.";
LOG(WARNING) << "Trying to format number from invalid region "
<< calling_from
<< ". International formatting applied.";
Format(number, INTERNATIONAL, formatted_number); Format(number, INTERNATIONAL, formatted_number);
return; return;
} }
@ -1063,12 +1053,11 @@ void PhoneNumberUtil::FormatOutOfCountryCallingNumber(
if (IsNANPACountry(calling_from)) { if (IsNANPACountry(calling_from)) {
// For NANPA regions, return the national format for these regions but // For NANPA regions, return the national format for these regions but
// prefix it with the country calling code. // prefix it with the country calling code.
string national_number;
Format(number, NATIONAL, &national_number);
formatted_number->assign(StrCat(country_code, " ", national_number));
Format(number, NATIONAL, formatted_number);
formatted_number->insert(0, StrCat(country_code, " "));
return; return;
} }
} else if (country_code == GetCountryCodeForRegion(calling_from)) {
} else if (country_code == GetCountryCodeForValidRegion(calling_from)) {
// If neither region is a NANPA region, then we check to see if the // If neither region is a NANPA region, then we check to see if the
// country calling code of the number and the country calling code of the // country calling code of the number and the country calling code of the
// region we are calling from are the same. // region we are calling from are the same.
@ -1099,19 +1088,16 @@ void PhoneNumberUtil::FormatOutOfCountryCallingNumber(
reg_exps_->unique_international_prefix_->FullMatch(international_prefix) reg_exps_->unique_international_prefix_->FullMatch(international_prefix)
? international_prefix ? international_prefix
: metadata_calling_from->preferred_international_prefix()); : metadata_calling_from->preferred_international_prefix());
string formatted_national_number;
FormatNationalNumber(national_significant_number, *metadata_for_region,
INTERNATIONAL, &formatted_national_number);
string formatted_extension;
MaybeGetFormattedExtension(number, *metadata_for_region, INTERNATIONAL,
&formatted_extension);
FormatNsn(national_significant_number, *metadata_for_region, INTERNATIONAL,
formatted_number);
MaybeAppendFormattedExtension(number, *metadata_for_region, INTERNATIONAL,
formatted_number);
if (!international_prefix_for_formatting.empty()) { if (!international_prefix_for_formatting.empty()) {
formatted_number->assign(
StrCat(international_prefix_for_formatting, " ", country_code, " ",
formatted_national_number, formatted_extension));
formatted_number->insert(
0, StrCat(international_prefix_for_formatting, " ", country_code, " "));
} else { } else {
FormatNumberByFormat(country_code, INTERNATIONAL, formatted_national_number,
formatted_extension, formatted_number);
PrefixNumberWithCountryCallingCode(country_code, INTERNATIONAL,
formatted_number);
} }
} }
@ -1176,7 +1162,7 @@ void PhoneNumberUtil::FormatInOriginalFormat(const PhoneNumber& number,
// HasFormattingPatternForNumber. // HasFormattingPatternForNumber.
const NumberFormat* format_rule = const NumberFormat* format_rule =
ChooseFormattingPatternForNumber(metadata->number_format(), ChooseFormattingPatternForNumber(metadata->number_format(),
national_number, national_number);
national_number);
// When the format we apply to this number doesn't contain national // When the format we apply to this number doesn't contain national
// prefix, we can just return the national format. // prefix, we can just return the national format.
// TODO: Refactor the code below with the code in // TODO: Refactor the code below with the code in
@ -1261,7 +1247,6 @@ bool PhoneNumberUtil::HasFormattingPatternForNumber(
GetNationalSignificantNumber(number, &national_number); GetNationalSignificantNumber(number, &national_number);
const NumberFormat* format_rule = const NumberFormat* format_rule =
ChooseFormattingPatternForNumber(metadata->number_format(), ChooseFormattingPatternForNumber(metadata->number_format(),
national_number,
national_number); national_number);
return format_rule; return format_rule;
} }
@ -1276,7 +1261,8 @@ void PhoneNumberUtil::FormatOutOfCountryKeepingAlphaChars(
FormatOutOfCountryCallingNumber(number, calling_from, formatted_number); FormatOutOfCountryCallingNumber(number, calling_from, formatted_number);
return; return;
} }
if (!HasValidCountryCallingCode(number.country_code())) {
int country_code = number.country_code();
if (!HasValidCountryCallingCode(country_code)) {
formatted_number->assign(number.raw_input()); formatted_number->assign(number.raw_input());
return; return;
} }
@ -1302,33 +1288,35 @@ void PhoneNumberUtil::FormatOutOfCountryKeepingAlphaChars(
const PhoneMetadata* metadata = GetMetadataForRegion(calling_from); const PhoneMetadata* metadata = GetMetadataForRegion(calling_from);
if (number.country_code() == kNanpaCountryCode) { if (number.country_code() == kNanpaCountryCode) {
if (IsNANPACountry(calling_from)) { if (IsNANPACountry(calling_from)) {
formatted_number->assign(StrCat(number.country_code(), " ",
raw_input_copy));
StrAppend(formatted_number, country_code, " ", raw_input_copy);
return; return;
} }
} else if (number.country_code() == GetCountryCodeForRegion(calling_from)) {
// Here we copy the formatting rules so we can modify the pattern we expect
// to match against.
RepeatedPtrField<NumberFormat> available_formats =
metadata->number_format();
for (RepeatedPtrField<NumberFormat>::iterator
it = available_formats.begin(); it != available_formats.end(); ++it) {
// The first group is the first group of digits that the user determined.
it->set_pattern("(\\d+)(.*)");
// Here we just concatenate them back together after the national prefix
// has been fixed.
it->set_format("$1$2");
} else if (IsValidRegionCode(calling_from) &&
country_code == GetCountryCodeForValidRegion(calling_from)) {
const NumberFormat* formatting_pattern =
ChooseFormattingPatternForNumber(metadata->number_format(),
national_number);
if (!formatting_pattern) {
// If no pattern above is matched, we format the original input.
formatted_number->assign(raw_input_copy);
return;
} }
// Now we format using these patterns instead of the default pattern, but
// with the national prefix prefixed if necessary, by choosing the format
// rule based on the leading digits present in the unformatted national
// number.
NumberFormat new_format;
new_format.MergeFrom(*formatting_pattern);
// The first group is the first group of digits that the user wrote
// together.
new_format.set_pattern("(\\d+)(.*)");
// Here we just concatenate them back together after the national prefix
// has been fixed.
new_format.set_format("$1$2");
// Now we format using this pattern instead of the default pattern, but
// with the national prefix prefixed if necessary.
// This will not work in the cases where the pattern (and not the // This will not work in the cases where the pattern (and not the
// leading digits) decide whether a national prefix needs to be used, since // leading digits) decide whether a national prefix needs to be used, since
// we have overridden the pattern to match anything, but that is not the // we have overridden the pattern to match anything, but that is not the
// case in the metadata to date. // case in the metadata to date.
FormatAccordingToFormats(national_number, available_formats,
NATIONAL, raw_input_copy, formatted_number);
FormatNsnUsingPattern(raw_input_copy, new_format, NATIONAL,
formatted_number);
return; return;
} }
@ -1344,29 +1332,30 @@ void PhoneNumberUtil::FormatOutOfCountryKeepingAlphaChars(
: metadata->preferred_international_prefix(); : metadata->preferred_international_prefix();
} }
if (!international_prefix_for_formatting.empty()) { if (!international_prefix_for_formatting.empty()) {
formatted_number->assign(
StrCat(international_prefix_for_formatting, " ", number.country_code(),
" ", raw_input_copy));
StrAppend(formatted_number, international_prefix_for_formatting, " ",
country_code, " ", raw_input_copy);
} else { } else {
// Invalid region entered as country-calling-from (so no metadata was found // Invalid region entered as country-calling-from (so no metadata was found
// for it) or the region chosen has multiple international dialling // for it) or the region chosen has multiple international dialling
// prefixes. // prefixes.
FormatNumberByFormat(number.country_code(), INTERNATIONAL, raw_input_copy,
"", formatted_number);
LOG(WARNING) << "Trying to format number from invalid region "
<< calling_from
<< ". International formatting applied.";
formatted_number->assign(raw_input_copy);
PrefixNumberWithCountryCallingCode(country_code, INTERNATIONAL,
formatted_number);
} }
} }
const NumberFormat* PhoneNumberUtil::ChooseFormattingPatternForNumber( const NumberFormat* PhoneNumberUtil::ChooseFormattingPatternForNumber(
const RepeatedPtrField<NumberFormat>& available_formats, const RepeatedPtrField<NumberFormat>& available_formats,
const string& number_for_leading_digits_match,
const string& national_number) const { const string& national_number) const {
for (RepeatedPtrField<NumberFormat>::const_iterator for (RepeatedPtrField<NumberFormat>::const_iterator
it = available_formats.begin(); it != available_formats.end(); ++it) { it = available_formats.begin(); it != available_formats.end(); ++it) {
int size = it->leading_digits_pattern_size(); int size = it->leading_digits_pattern_size();
if (size > 0) { if (size > 0) {
const scoped_ptr<RegExpInput> number_copy( const scoped_ptr<RegExpInput> number_copy(
reg_exps_->regexp_factory_->CreateInput(
number_for_leading_digits_match));
reg_exps_->regexp_factory_->CreateInput(national_number));
// We always use the last leading_digits_pattern, as it is the most // We always use the last leading_digits_pattern, as it is the most
// detailed. // detailed.
if (!reg_exps_->regexp_cache_->GetRegExp( if (!reg_exps_->regexp_cache_->GetRegExp(
@ -1384,82 +1373,75 @@ const NumberFormat* PhoneNumberUtil::ChooseFormattingPatternForNumber(
return NULL; return NULL;
} }
// The number_for_leading_digits_match is a separate parameter, because for
// alpha numbers we want to pass in the numeric version to select the right
// formatting rule, but then we actually apply the formatting pattern to the
// national_number (which in this case has alpha characters in it).
//
// Note that carrier_code is optional - if an empty string, no carrier code // Note that carrier_code is optional - if an empty string, no carrier code
// replacement will take place. // replacement will take place.
void PhoneNumberUtil::FormatAccordingToFormatsWithCarrier(
const string& number_for_leading_digits_match,
const RepeatedPtrField<NumberFormat>& available_formats,
PhoneNumberUtil::PhoneNumberFormat number_format,
void PhoneNumberUtil::FormatNsnUsingPatternWithCarrier(
const string& national_number, const string& national_number,
const NumberFormat& formatting_pattern,
PhoneNumberUtil::PhoneNumberFormat number_format,
const string& carrier_code, const string& carrier_code,
string* formatted_number) const { string* formatted_number) const {
DCHECK(formatted_number); DCHECK(formatted_number);
const NumberFormat* format = ChooseFormattingPatternForNumber(
available_formats,
number_for_leading_digits_match,
national_number);
if (!format) {
// If no pattern above is matched, we format the number as a whole.
formatted_number->assign(national_number);
return;
}
string formatting_pattern(format->format());
string number_format_rule(formatting_pattern.format());
if (number_format == PhoneNumberUtil::NATIONAL && if (number_format == PhoneNumberUtil::NATIONAL &&
carrier_code.length() > 0 && carrier_code.length() > 0 &&
format->domestic_carrier_code_formatting_rule().length() > 0) {
formatting_pattern.domestic_carrier_code_formatting_rule().length() > 0) {
// Replace the $CC in the formatting rule with the desired carrier code. // Replace the $CC in the formatting rule with the desired carrier code.
string carrier_code_formatting_rule = string carrier_code_formatting_rule =
format->domestic_carrier_code_formatting_rule();
formatting_pattern.domestic_carrier_code_formatting_rule();
reg_exps_->carrier_code_pattern_->Replace(&carrier_code_formatting_rule, reg_exps_->carrier_code_pattern_->Replace(&carrier_code_formatting_rule,
carrier_code); carrier_code);
reg_exps_->first_group_capturing_pattern_->Replace(&formatting_pattern,
carrier_code_formatting_rule);
reg_exps_->first_group_capturing_pattern_->
Replace(&number_format_rule, carrier_code_formatting_rule);
} else { } else {
// Use the national prefix formatting rule instead. // Use the national prefix formatting rule instead.
string national_prefix_formatting_rule = string national_prefix_formatting_rule =
format->national_prefix_formatting_rule();
formatting_pattern.national_prefix_formatting_rule();
if (number_format == PhoneNumberUtil::NATIONAL && if (number_format == PhoneNumberUtil::NATIONAL &&
national_prefix_formatting_rule.length() > 0) { national_prefix_formatting_rule.length() > 0) {
// Apply the national_prefix_formatting_rule as the formatting_pattern // Apply the national_prefix_formatting_rule as the formatting_pattern
// contains only information on how the national significant number // contains only information on how the national significant number
// should be formatted at this point. // should be formatted at this point.
reg_exps_->first_group_capturing_pattern_->Replace( reg_exps_->first_group_capturing_pattern_->Replace(
&formatting_pattern, national_prefix_formatting_rule);
&number_format_rule, national_prefix_formatting_rule);
} }
} }
formatted_number->assign(national_number); formatted_number->assign(national_number);
const RegExp& pattern_to_match( const RegExp& pattern_to_match(
reg_exps_->regexp_cache_->GetRegExp(format->pattern()));
pattern_to_match.GlobalReplace(formatted_number, formatting_pattern);
reg_exps_->regexp_cache_->GetRegExp(formatting_pattern.pattern()));
pattern_to_match.GlobalReplace(formatted_number, number_format_rule);
if (number_format == RFC3966) {
// First consume any leading punctuation, if any was present.
const scoped_ptr<RegExpInput> number(
reg_exps_->regexp_factory_->CreateInput(*formatted_number));
if (reg_exps_->separator_pattern_->Consume(number.get())) {
formatted_number->assign(number->ToString());
}
// Then replace all separators with a "-".
reg_exps_->separator_pattern_->GlobalReplace(formatted_number, "-");
}
} }
// Simple wrapper of FormatAccordingToFormatsWithCarrier for the common case of
// Simple wrapper of FormatNsnUsingPatternWithCarrier for the common case of
// no carrier code. // no carrier code.
void PhoneNumberUtil::FormatAccordingToFormats(
const string& number_for_leading_digits_match,
const RepeatedPtrField<NumberFormat>& available_formats,
PhoneNumberUtil::PhoneNumberFormat number_format,
void PhoneNumberUtil::FormatNsnUsingPattern(
const string& national_number, const string& national_number,
const NumberFormat& formatting_pattern,
PhoneNumberUtil::PhoneNumberFormat number_format,
string* formatted_number) const { string* formatted_number) const {
DCHECK(formatted_number); DCHECK(formatted_number);
FormatAccordingToFormatsWithCarrier(number_for_leading_digits_match,
available_formats, number_format,
national_number, "", formatted_number);
FormatNsnUsingPatternWithCarrier(national_number, formatting_pattern,
number_format, "", formatted_number);
} }
void PhoneNumberUtil::FormatNationalNumber(
const string& number,
const PhoneMetadata& metadata,
PhoneNumberFormat number_format,
string* formatted_number) const {
void PhoneNumberUtil::FormatNsn(const string& number,
const PhoneMetadata& metadata,
PhoneNumberFormat number_format,
string* formatted_number) const {
DCHECK(formatted_number); DCHECK(formatted_number);
FormatNationalNumberWithCarrier(number, metadata, number_format, "",
formatted_number);
FormatNsnWithCarrier(number, metadata, number_format, "", formatted_number);
} }
// Note in some regions, the national number can be written in two completely // Note in some regions, the national number can be written in two completely
@ -1467,12 +1449,11 @@ void PhoneNumberUtil::FormatNationalNumber(
// INTERNATIONAL format. The number_format parameter here is used to specify // INTERNATIONAL format. The number_format parameter here is used to specify
// which format to use for those cases. If a carrier_code is specified, this // which format to use for those cases. If a carrier_code is specified, this
// will be inserted into the formatted string to replace $CC. // will be inserted into the formatted string to replace $CC.
void PhoneNumberUtil::FormatNationalNumberWithCarrier(
const string& number,
const PhoneMetadata& metadata,
PhoneNumberFormat number_format,
const string& carrier_code,
string* formatted_number) const {
void PhoneNumberUtil::FormatNsnWithCarrier(const string& number,
const PhoneMetadata& metadata,
PhoneNumberFormat number_format,
const string& carrier_code,
string* formatted_number) const {
DCHECK(formatted_number); DCHECK(formatted_number);
// When the intl_number_formats exists, we use that to format national number // When the intl_number_formats exists, we use that to format national number
// for the INTERNATIONAL format instead of using the number_formats. // for the INTERNATIONAL format instead of using the number_formats.
@ -1480,45 +1461,35 @@ void PhoneNumberUtil::FormatNationalNumberWithCarrier(
(metadata.intl_number_format_size() == 0 || number_format == NATIONAL) (metadata.intl_number_format_size() == 0 || number_format == NATIONAL)
? metadata.number_format() ? metadata.number_format()
: metadata.intl_number_format(); : metadata.intl_number_format();
FormatAccordingToFormatsWithCarrier(number, available_formats, number_format,
number, carrier_code, formatted_number);
if (number_format == RFC3966) {
// Replace all separators with a "-".
reg_exps_->separator_pattern_->GlobalReplace(formatted_number, "-");
const NumberFormat* formatting_pattern =
ChooseFormattingPatternForNumber(available_formats, number);
if (!formatting_pattern) {
formatted_number->assign(number);
} else {
FormatNsnUsingPatternWithCarrier(number, *formatting_pattern, number_format,
carrier_code, formatted_number);
} }
} }
// Gets the formatted extension of a phone number, if the phone number had an
// extension specified. If not, it returns an empty string.
void PhoneNumberUtil::MaybeGetFormattedExtension(
// Appends the formatted extension of a phone number, if the phone number had an
// extension specified.
void PhoneNumberUtil::MaybeAppendFormattedExtension(
const PhoneNumber& number, const PhoneNumber& number,
const PhoneMetadata& metadata, const PhoneMetadata& metadata,
PhoneNumberFormat number_format, PhoneNumberFormat number_format,
string* extension) const {
DCHECK(extension);
if (!number.has_extension() || number.extension().length() == 0) {
extension->assign("");
} else {
string* formatted_number) const {
DCHECK(formatted_number);
if (number.has_extension() && number.extension().length() > 0) {
if (number_format == RFC3966) { if (number_format == RFC3966) {
StrAppend(extension, kRfc3966ExtnPrefix, number.extension());
return;
StrAppend(formatted_number, kRfc3966ExtnPrefix, number.extension());
} else {
if (metadata.has_preferred_extn_prefix()) {
StrAppend(formatted_number, metadata.preferred_extn_prefix(),
number.extension());
} else {
StrAppend(formatted_number, kDefaultExtnPrefix, number.extension());
}
} }
FormatExtension(number.extension(), metadata, extension);
}
}
// Formats the extension part of the phone number by prefixing it with the
// appropriate extension prefix. This will be the default extension prefix,
// unless overridden by a preferred extension prefix for this region.
void PhoneNumberUtil::FormatExtension(const string& extension_digits,
const PhoneMetadata& metadata,
string* extension) const {
DCHECK(extension);
if (metadata.has_preferred_extn_prefix()) {
extension->assign(StrCat(metadata.preferred_extn_prefix(),
extension_digits));
} else {
extension->assign(StrCat(kDefaultExtnPrefix, extension_digits));
} }
} }
@ -1558,8 +1529,8 @@ void PhoneNumberUtil::GetRegionCodeForCountryCode(
list<string> region_codes; list<string> region_codes;
GetRegionCodesForCountryCallingCode(country_calling_code, &region_codes); GetRegionCodesForCountryCallingCode(country_calling_code, &region_codes);
*region_code = (region_codes.size() > 0)
? region_codes.front() : RegionCode::GetUnknown();
*region_code = (region_codes.size() > 0) ?
region_codes.front() : RegionCode::GetUnknown();
} }
void PhoneNumberUtil::GetRegionCodeForNumber(const PhoneNumber& number, void PhoneNumberUtil::GetRegionCodeForNumber(const PhoneNumber& number,
@ -1612,10 +1583,15 @@ void PhoneNumberUtil::GetRegionCodeForNumberFromRegionList(
int PhoneNumberUtil::GetCountryCodeForRegion(const string& region_code) const { int PhoneNumberUtil::GetCountryCodeForRegion(const string& region_code) const {
if (!IsValidRegionCode(region_code)) { if (!IsValidRegionCode(region_code)) {
LOG(ERROR) << "Invalid or unknown region code (" << region_code
<< ") provided.";
LOG(WARNING) << "Invalid or unknown region code (" << region_code
<< ") provided.";
return 0; return 0;
} }
return GetCountryCodeForValidRegion(region_code);
}
int PhoneNumberUtil::GetCountryCodeForValidRegion(
const string& region_code) const {
const PhoneMetadata* metadata = GetMetadataForRegion(region_code); const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
return metadata->country_code(); return metadata->country_code();
} }
@ -1626,31 +1602,32 @@ int PhoneNumberUtil::GetCountryCodeForRegion(const string& region_code) const {
bool PhoneNumberUtil::GetExampleNumber(const string& region_code, bool PhoneNumberUtil::GetExampleNumber(const string& region_code,
PhoneNumber* number) const { PhoneNumber* number) const {
DCHECK(number); DCHECK(number);
return GetExampleNumberForType(region_code,
FIXED_LINE,
number);
return GetExampleNumberForType(region_code, FIXED_LINE, number);
} }
// Gets a valid number for the specified region_code and type. Returns false if // Gets a valid number for the specified region_code and type. Returns false if
// the country was unknown or 001 (representing non-geographical regions), or if // the country was unknown or 001 (representing non-geographical regions), or if
// the country was unknown or if no number exists.
// no number exists.
bool PhoneNumberUtil::GetExampleNumberForType( bool PhoneNumberUtil::GetExampleNumberForType(
const string& region_code, const string& region_code,
PhoneNumberUtil::PhoneNumberType type, PhoneNumberUtil::PhoneNumberType type,
PhoneNumber* number) const { PhoneNumber* number) const {
DCHECK(number); DCHECK(number);
if (!IsValidRegionCode(region_code)) { if (!IsValidRegionCode(region_code)) {
LOG(ERROR) << "Invalid or unknown region code (" << region_code
<< ") provided.";
LOG(WARNING) << "Invalid or unknown region code (" << region_code
<< ") provided.";
return false; return false;
} }
const PhoneMetadata* region_metadata = GetMetadataForRegion(region_code); const PhoneMetadata* region_metadata = GetMetadataForRegion(region_code);
const PhoneNumberDesc* description =
GetNumberDescByType(*region_metadata, type);
if (description && description->has_example_number()) {
return (Parse(description->example_number(),
region_code,
number) == NO_PARSING_ERROR);
const PhoneNumberDesc* desc = GetNumberDescByType(*region_metadata, type);
if (desc && desc->has_example_number()) {
ErrorType success = Parse(desc->example_number(), region_code, number);
if (success == NO_PARSING_ERROR) {
return true;
} else {
LOG(ERROR) << "Error parsing example number ("
<< static_cast<int>(success) << ")";
}
} }
return false; return false;
} }
@ -1663,10 +1640,20 @@ bool PhoneNumberUtil::GetExampleNumberForNonGeoEntity(
if (metadata) { if (metadata) {
const PhoneNumberDesc& desc = metadata->general_desc(); const PhoneNumberDesc& desc = metadata->general_desc();
if (desc.has_example_number()) { if (desc.has_example_number()) {
return (Parse(StrCat(kPlusSign, SimpleItoa(country_calling_code),
desc.example_number()),
"ZZ", number) == NO_PARSING_ERROR);
ErrorType success = Parse(StrCat(kPlusSign,
SimpleItoa(country_calling_code),
desc.example_number()),
RegionCode::ZZ(), number);
if (success == NO_PARSING_ERROR) {
return true;
} else {
LOG(ERROR) << "Error parsing example number ("
<< static_cast<int>(success) << ")";
}
} }
} else {
LOG(WARNING) << "Invalid or unknown country calling code provided: "
<< country_calling_code;
} }
return false; return false;
} }
@ -1949,13 +1936,15 @@ bool PhoneNumberUtil::IsValidNumber(const PhoneNumber& number) const {
bool PhoneNumberUtil::IsValidNumberForRegion(const PhoneNumber& number, bool PhoneNumberUtil::IsValidNumberForRegion(const PhoneNumber& number,
const string& region_code) const { const string& region_code) const {
int country_code = number.country_code(); int country_code = number.country_code();
if (country_code == 0 ||
(kRegionCodeForNonGeoEntity != region_code &&
country_code != GetCountryCodeForRegion(region_code))) {
return false;
}
const PhoneMetadata* metadata = const PhoneMetadata* metadata =
GetMetadataForRegionOrCallingCode(country_code, region_code); GetMetadataForRegionOrCallingCode(country_code, region_code);
if (!metadata ||
((kRegionCodeForNonGeoEntity != region_code) &&
country_code != GetCountryCodeForValidRegion(region_code))) {
// Either the region code was invalid, or the country calling code for this
// number does not match that of the region code.
return false;
}
const PhoneNumberDesc& general_desc = metadata->general_desc(); const PhoneNumberDesc& general_desc = metadata->general_desc();
string national_number; string national_number;
GetNationalSignificantNumber(number, &national_number); GetNationalSignificantNumber(number, &national_number);
@ -1977,8 +1966,8 @@ bool PhoneNumberUtil::IsValidNumberForRegion(const PhoneNumber& number,
bool PhoneNumberUtil::IsLeadingZeroPossible(int country_calling_code) const { bool PhoneNumberUtil::IsLeadingZeroPossible(int country_calling_code) const {
string region_code; string region_code;
GetRegionCodeForCountryCode(country_calling_code, &region_code); GetRegionCodeForCountryCode(country_calling_code, &region_code);
const PhoneMetadata* main_metadata_for_calling_code =
GetMetadataForRegion(region_code);
const PhoneMetadata* main_metadata_for_calling_code = GetMetadataForRegion(
region_code);
if (!main_metadata_for_calling_code) return false; if (!main_metadata_for_calling_code) return false;
return main_metadata_for_calling_code->leading_zero_possible(); return main_metadata_for_calling_code->leading_zero_possible();
} }


+ 19
- 21
cpp/src/phonenumbers/phonenumberutil.h View File

@ -647,28 +647,29 @@ class PhoneNumberUtil : public Singleton<PhoneNumberUtil> {
int country_calling_code, int country_calling_code,
const string& region_code) const; const string& region_code) const;
// As per GetCountryCodeForRegion, but assumes the validity of the region_code
// has already been checked.
int GetCountryCodeForValidRegion(const string& region_code) const;
void GetRegionCodesForCountryCallingCode( void GetRegionCodesForCountryCallingCode(
int country_calling_code, int country_calling_code,
list<string>* region_codes) const; list<string>* region_codes) const;
const NumberFormat* ChooseFormattingPatternForNumber( const NumberFormat* ChooseFormattingPatternForNumber(
const RepeatedPtrField<NumberFormat>& available_formats, const RepeatedPtrField<NumberFormat>& available_formats,
const string& number_for_leading_digits_match,
const string& national_number) const; const string& national_number) const;
void FormatAccordingToFormatsWithCarrier(
const string& number_for_leading_digits_match,
const RepeatedPtrField<NumberFormat>& available_formats,
PhoneNumberUtil::PhoneNumberFormat number_format,
void FormatNsnUsingPatternWithCarrier(
const string& national_number, const string& national_number,
const NumberFormat& formatting_pattern,
PhoneNumberUtil::PhoneNumberFormat number_format,
const string& carrier_code, const string& carrier_code,
string* formatted_number) const; string* formatted_number) const;
void FormatAccordingToFormats(
const string& number_for_leading_digits_match,
const RepeatedPtrField<NumberFormat>& available_formats,
PhoneNumberUtil::PhoneNumberFormat number_format,
void FormatNsnUsingPattern(
const string& national_number, const string& national_number,
const NumberFormat& formatting_pattern,
PhoneNumberUtil::PhoneNumberFormat number_format,
string* formatted_number) const; string* formatted_number) const;
// Check if raw_input, which is assumed to be in the national format, has a // Check if raw_input, which is assumed to be in the national format, has a
@ -685,28 +686,25 @@ class PhoneNumberUtil : public Singleton<PhoneNumberUtil> {
bool HasFormattingPatternForNumber(const PhoneNumber& number) const; bool HasFormattingPatternForNumber(const PhoneNumber& number) const;
// Simple wrapper of FormatNationalNumberWithCarrier for the common case of
// Simple wrapper of FormatNsnWithCarrier for the common case of
// no carrier code. // no carrier code.
void FormatNationalNumber(const string& number,
void FormatNsn(const string& number,
const PhoneMetadata& metadata,
PhoneNumberFormat number_format,
string* formatted_number) const;
void FormatNsnWithCarrier(const string& number,
const PhoneMetadata& metadata, const PhoneMetadata& metadata,
PhoneNumberFormat number_format, PhoneNumberFormat number_format,
const string& carrier_code,
string* formatted_number) const; string* formatted_number) const;
void FormatNationalNumberWithCarrier(const string& number,
const PhoneMetadata& metadata,
PhoneNumberFormat number_format,
const string& carrier_code,
string* formatted_number) const;
void MaybeGetFormattedExtension(
void MaybeAppendFormattedExtension(
const PhoneNumber& number, const PhoneNumber& number,
const PhoneMetadata& metadata, const PhoneMetadata& metadata,
PhoneNumberFormat number_format, PhoneNumberFormat number_format,
string* extension) const; string* extension) const;
void FormatExtension(const string& extension_digits,
const PhoneMetadata& metadata,
string* extension) const;
void GetRegionCodeForNumberFromRegionList( void GetRegionCodeForNumberFromRegionList(
const PhoneNumber& number, const PhoneNumber& number,
const list<string>& region_codes, const list<string>& region_codes,


+ 4
- 0
cpp/src/phonenumbers/region_code.h View File

@ -26,6 +26,10 @@ class RegionCode {
public: public:
// Returns a region code string representing the "unknown" region. // Returns a region code string representing the "unknown" region.
static const char* GetUnknown() { static const char* GetUnknown() {
return ZZ();
}
static const char* ZZ() {
return "ZZ"; return "ZZ";
} }
}; };


+ 36
- 0
cpp/src/phonenumbers/stringutil.cc View File

@ -374,5 +374,41 @@ void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2) {
*dest += s2; *dest += s2;
} }
void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2,
const StringHolder& s3) {
assert(dest);
dest->reserve(dest->length() + s1.Length() + s2.Length() + s3.Length() + 1);
*dest += s1;
*dest += s2;
*dest += s3;
}
void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2,
const StringHolder& s3, const StringHolder& s4) {
assert(dest);
dest->reserve(dest->length() + s1.Length() + s2.Length() + s3.Length() +
s4.Length() + 1);
*dest += s1;
*dest += s2;
*dest += s3;
*dest += s4;
}
void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2,
const StringHolder& s3, const StringHolder& s4,
const StringHolder& s5) {
assert(dest);
dest->reserve(dest->length() + s1.Length() + s2.Length() + s3.Length() +
s4.Length() + s5.Length() + 1);
*dest += s1;
*dest += s2;
*dest += s3;
*dest += s4;
*dest += s5;
}
} // namespace phonenumbers } // namespace phonenumbers
} // namespace i18n } // namespace i18n

+ 10
- 0
cpp/src/phonenumbers/stringutil.h View File

@ -149,6 +149,16 @@ void StrAppend(string* dest, const StringHolder& s1);
void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2); void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2);
void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2,
const StringHolder& s3);
void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2,
const StringHolder& s3, const StringHolder& s4);
void StrAppend(string* dest, const StringHolder& s1, const StringHolder& s2,
const StringHolder& s3, const StringHolder& s4,
const StringHolder& s5);
} // namespace phonenumbers } // namespace phonenumbers
} // namespace i18n } // namespace i18n


+ 17
- 0
cpp/test/phonenumbers/asyoutypeformatter_test.cc View File

@ -724,6 +724,23 @@ TEST_F(AsYouTypeFormatterTest, AYTF_MX) {
EXPECT_EQ("+52 1 541 234 5678", formatter_->InputDigit('8', &result_)); EXPECT_EQ("+52 1 541 234 5678", formatter_->InputDigit('8', &result_));
} }
TEST_F(AsYouTypeFormatterTest, AYTF_International_Toll_Free) {
formatter_.reset(phone_util_.GetAsYouTypeFormatter(RegionCode::US()));
// +800 1234 5678
EXPECT_EQ("+", formatter_->InputDigit('+', &result_));
EXPECT_EQ("+8", formatter_->InputDigit('8', &result_));
EXPECT_EQ("+80", formatter_->InputDigit('0', &result_));
EXPECT_EQ("+800 ", formatter_->InputDigit('0', &result_));
EXPECT_EQ("+800 1", formatter_->InputDigit('1', &result_));
EXPECT_EQ("+800 12", formatter_->InputDigit('2', &result_));
EXPECT_EQ("+800 123", formatter_->InputDigit('3', &result_));
EXPECT_EQ("+800 1234", formatter_->InputDigit('4', &result_));
EXPECT_EQ("+800 1234 5", formatter_->InputDigit('5', &result_));
EXPECT_EQ("+800 1234 56", formatter_->InputDigit('6', &result_));
EXPECT_EQ("+800 1234 567", formatter_->InputDigit('7', &result_));
EXPECT_EQ("+800 1234 5678", formatter_->InputDigit('8', &result_));
}
TEST_F(AsYouTypeFormatterTest, AYTF_MultipleLeadingDigitPatterns) { TEST_F(AsYouTypeFormatterTest, AYTF_MultipleLeadingDigitPatterns) {
formatter_.reset(phone_util_.GetAsYouTypeFormatter(RegionCode::JP())); formatter_.reset(phone_util_.GetAsYouTypeFormatter(RegionCode::JP()));


+ 77
- 30
cpp/test/phonenumbers/phonenumbermatcher_test.cc View File

@ -684,7 +684,7 @@ TEST_F(PhoneNumberMatcherTest,
} }
// Strings with number-like things that shouldn't be found under any level. // Strings with number-like things that shouldn't be found under any level.
static const NumberTest IMPOSSIBLE_CASES[] = {
static const NumberTest kImpossibleCases[] = {
NumberTest("12345", RegionCode::US()), NumberTest("12345", RegionCode::US()),
NumberTest("23456789", RegionCode::US()), NumberTest("23456789", RegionCode::US()),
NumberTest("234567890112", RegionCode::US()), NumberTest("234567890112", RegionCode::US()),
@ -694,45 +694,52 @@ static const NumberTest IMPOSSIBLE_CASES[] = {
NumberTest("31/8/2011", RegionCode::US()), NumberTest("31/8/2011", RegionCode::US()),
NumberTest("1/12/2011", RegionCode::US()), NumberTest("1/12/2011", RegionCode::US()),
NumberTest("10/12/82", RegionCode::DE()), NumberTest("10/12/82", RegionCode::DE()),
NumberTest("650x2531234", RegionCode::US()),
NumberTest("2012-01-02 08:00", RegionCode::US()),
NumberTest("2012/01/02 08:00", RegionCode::US()),
NumberTest("20120102 08:00", RegionCode::US()),
}; };
// Strings with number-like things that should only be found under "possible". // Strings with number-like things that should only be found under "possible".
static const NumberTest POSSIBLE_ONLY_CASES[] = {
NumberTest("abc8002345678", RegionCode::US()),
static const NumberTest kPossibleOnlyCases[] = {
// US numbers cannot start with 7 in the test metadata to be valid. // US numbers cannot start with 7 in the test metadata to be valid.
NumberTest("7121115678", RegionCode::US()), NumberTest("7121115678", RegionCode::US()),
// 'X' should not be found in numbers at leniencies stricter than POSSIBLE, // 'X' should not be found in numbers at leniencies stricter than POSSIBLE,
// unless it represents a carrier code or extension. // unless it represents a carrier code or extension.
NumberTest("1650 x 253 - 1234", RegionCode::US()), NumberTest("1650 x 253 - 1234", RegionCode::US()),
NumberTest("650 x 253 - 1234", RegionCode::US()), NumberTest("650 x 253 - 1234", RegionCode::US()),
NumberTest("650x2531234", RegionCode::US()),
NumberTest("6502531x234", RegionCode::US()),
NumberTest("(20) 3346 1234", RegionCode::GB()), // Non-optional NP omitted NumberTest("(20) 3346 1234", RegionCode::GB()), // Non-optional NP omitted
}; };
// Strings with number-like things that should only be found up to and including // Strings with number-like things that should only be found up to and including
// the "valid" leniency level. // the "valid" leniency level.
static const NumberTest VALID_CASES[] = {
NumberTest("65 02 53 00 00.", RegionCode::US()),
static const NumberTest kValidCases[] = {
NumberTest("65 02 53 00 00", RegionCode::US()),
NumberTest("6502 538365", RegionCode::US()), NumberTest("6502 538365", RegionCode::US()),
// 2 slashes are illegal at higher levels. // 2 slashes are illegal at higher levels.
NumberTest("650//253-1234", RegionCode::US()), NumberTest("650//253-1234", RegionCode::US()),
NumberTest("650/253/1234", RegionCode::US()), NumberTest("650/253/1234", RegionCode::US()),
NumberTest("9002309. 158", RegionCode::US()), NumberTest("9002309. 158", RegionCode::US()),
NumberTest("21 7/8 - 14 12/34 - 5", RegionCode::US()),
NumberTest("12 7/8 - 14 12/34 - 5", RegionCode::US()),
NumberTest("12.1 - 23.71 - 23.45", RegionCode::US()), NumberTest("12.1 - 23.71 - 23.45", RegionCode::US()),
NumberTest("1979-2011 100%", RegionCode::US()),
NumberTest("800 234 1 111x1111", RegionCode::US()), NumberTest("800 234 1 111x1111", RegionCode::US()),
NumberTest("1979-2011 100", RegionCode::US()),
// National number in wrong format. // National number in wrong format.
NumberTest("+494949-4-94", RegionCode::DE()), NumberTest("+494949-4-94", RegionCode::DE()),
NumberTest( NumberTest(
/* "415666-7777" */ /* "415666-7777" */
"\xEF\xBC\x94\xEF\xBC\x91\xEF\xBC\x95\xEF\xBC\x96\xEF\xBC\x96\xEF\xBC\x96" "\xEF\xBC\x94\xEF\xBC\x91\xEF\xBC\x95\xEF\xBC\x96\xEF\xBC\x96\xEF\xBC\x96"
"\x2D\xEF\xBC\x97\xEF\xBC\x97\xEF\xBC\x97\xEF\xBC\x97", RegionCode::US()), "\x2D\xEF\xBC\x97\xEF\xBC\x97\xEF\xBC\x97\xEF\xBC\x97", RegionCode::US()),
NumberTest("2012-0102 08", RegionCode::US()), // Very strange formatting.
NumberTest("2012-01-02 08", RegionCode::US()),
// Breakdown assistance number.
NumberTest("1800-10-10 22", RegionCode::AU()),
}; };
// Strings with number-like things that should only be found up to and including // Strings with number-like things that should only be found up to and including
// the "strict_grouping" leniency level. // the "strict_grouping" leniency level.
static const NumberTest STRICT_GROUPING_CASES[] = {
static const NumberTest kStrictGroupingCases[] = {
NumberTest("(415) 6667777", RegionCode::US()), NumberTest("(415) 6667777", RegionCode::US()),
NumberTest("415-6667777", RegionCode::US()), NumberTest("415-6667777", RegionCode::US()),
// Should be found by strict grouping but not exact grouping, as the last two // Should be found by strict grouping but not exact grouping, as the last two
@ -741,7 +748,7 @@ static const NumberTest STRICT_GROUPING_CASES[] = {
}; };
// Strings with number-like things that should found at all levels. // Strings with number-like things that should found at all levels.
static const NumberTest EXACT_GROUPING_CASES[] = {
static const NumberTest kExactGroupingCases[] = {
NumberTest( NumberTest(
/* "4156667777" */ /* "4156667777" */
"\xEF\xBC\x94\xEF\xBC\x91\xEF\xBC\x95\xEF\xBC\x96\xEF\xBC\x96\xEF\xBC\x96" "\xEF\xBC\x94\xEF\xBC\x91\xEF\xBC\x95\xEF\xBC\x96\xEF\xBC\x96\xEF\xBC\x96"
@ -771,46 +778,86 @@ static const NumberTest EXACT_GROUPING_CASES[] = {
NumberTest("(33) 3461 2234", RegionCode::MX()), // Optional NP omitted NumberTest("(33) 3461 2234", RegionCode::MX()), // Optional NP omitted
}; };
TEST_F(PhoneNumberMatcherTest, MatchesWithPossibleLeniency) {
vector<NumberTest> test_cases;
test_cases.insert(test_cases.begin(), kPossibleOnlyCases,
kPossibleOnlyCases + arraysize(kPossibleOnlyCases));
test_cases.insert(test_cases.begin(), kValidCases,
kValidCases + arraysize(kValidCases));
test_cases.insert(test_cases.begin(), kStrictGroupingCases,
kStrictGroupingCases + arraysize(kStrictGroupingCases));
test_cases.insert(test_cases.begin(), kExactGroupingCases,
kExactGroupingCases + arraysize(kExactGroupingCases));
DoTestNumberMatchesForLeniency(test_cases, PhoneNumberMatcher::POSSIBLE);
}
TEST_F(PhoneNumberMatcherTest, NonMatchesWithPossibleLeniency) {
vector<NumberTest> test_cases;
test_cases.insert(test_cases.begin(), kImpossibleCases,
kImpossibleCases + arraysize(kImpossibleCases));
DoTestNumberNonMatchesForLeniency(test_cases, PhoneNumberMatcher::POSSIBLE);
}
TEST_F(PhoneNumberMatcherTest, MatchesWithValidLeniency) {
vector<NumberTest> test_cases;
test_cases.insert(test_cases.begin(), kValidCases,
kValidCases + arraysize(kValidCases));
test_cases.insert(test_cases.begin(), kStrictGroupingCases,
kStrictGroupingCases + arraysize(kStrictGroupingCases));
test_cases.insert(test_cases.begin(), kExactGroupingCases,
kExactGroupingCases + arraysize(kExactGroupingCases));
DoTestNumberMatchesForLeniency(test_cases, PhoneNumberMatcher::VALID);
}
TEST_F(PhoneNumberMatcherTest, NonMatchesWithValidLeniency) {
vector<NumberTest> test_cases;
test_cases.insert(test_cases.begin(), kImpossibleCases,
kImpossibleCases + arraysize(kImpossibleCases));
test_cases.insert(test_cases.begin(), kPossibleOnlyCases,
kPossibleOnlyCases + arraysize(kPossibleOnlyCases));
DoTestNumberNonMatchesForLeniency(test_cases, PhoneNumberMatcher::VALID);
}
TEST_F(PhoneNumberMatcherTest, MatchesWithStrictGroupingLeniency) { TEST_F(PhoneNumberMatcherTest, MatchesWithStrictGroupingLeniency) {
vector<NumberTest> test_cases; vector<NumberTest> test_cases;
test_cases.insert(test_cases.begin(), STRICT_GROUPING_CASES,
STRICT_GROUPING_CASES + arraysize(STRICT_GROUPING_CASES));
test_cases.insert(test_cases.begin(), EXACT_GROUPING_CASES,
EXACT_GROUPING_CASES + arraysize(EXACT_GROUPING_CASES));
test_cases.insert(test_cases.begin(), kStrictGroupingCases,
kStrictGroupingCases + arraysize(kStrictGroupingCases));
test_cases.insert(test_cases.begin(), kExactGroupingCases,
kExactGroupingCases + arraysize(kExactGroupingCases));
DoTestNumberMatchesForLeniency(test_cases, DoTestNumberMatchesForLeniency(test_cases,
PhoneNumberMatcher::STRICT_GROUPING); PhoneNumberMatcher::STRICT_GROUPING);
} }
TEST_F(PhoneNumberMatcherTest, NonMatchesWithStrictGroupingLeniency) { TEST_F(PhoneNumberMatcherTest, NonMatchesWithStrictGroupingLeniency) {
vector<NumberTest> test_cases; vector<NumberTest> test_cases;
test_cases.insert(test_cases.begin(), IMPOSSIBLE_CASES,
IMPOSSIBLE_CASES + arraysize(IMPOSSIBLE_CASES));
test_cases.insert(test_cases.begin(), POSSIBLE_ONLY_CASES,
POSSIBLE_ONLY_CASES + arraysize(POSSIBLE_ONLY_CASES));
test_cases.insert(test_cases.begin(), VALID_CASES,
VALID_CASES + arraysize(VALID_CASES));
test_cases.insert(test_cases.begin(), kImpossibleCases,
kImpossibleCases + arraysize(kImpossibleCases));
test_cases.insert(test_cases.begin(), kPossibleOnlyCases,
kPossibleOnlyCases + arraysize(kPossibleOnlyCases));
test_cases.insert(test_cases.begin(), kValidCases,
kValidCases + arraysize(kValidCases));
DoTestNumberNonMatchesForLeniency(test_cases, DoTestNumberNonMatchesForLeniency(test_cases,
PhoneNumberMatcher::STRICT_GROUPING); PhoneNumberMatcher::STRICT_GROUPING);
} }
TEST_F(PhoneNumberMatcherTest, MatchesWithExactGroupingLeniency) { TEST_F(PhoneNumberMatcherTest, MatchesWithExactGroupingLeniency) {
vector<NumberTest> test_cases; vector<NumberTest> test_cases;
test_cases.insert(test_cases.begin(), EXACT_GROUPING_CASES,
EXACT_GROUPING_CASES + arraysize(EXACT_GROUPING_CASES));
test_cases.insert(test_cases.begin(), kExactGroupingCases,
kExactGroupingCases + arraysize(kExactGroupingCases));
DoTestNumberMatchesForLeniency(test_cases, DoTestNumberMatchesForLeniency(test_cases,
PhoneNumberMatcher::EXACT_GROUPING); PhoneNumberMatcher::EXACT_GROUPING);
} }
TEST_F(PhoneNumberMatcherTest, NonMatchesWithExactGroupingLeniency) { TEST_F(PhoneNumberMatcherTest, NonMatchesWithExactGroupingLeniency) {
vector<NumberTest> test_cases; vector<NumberTest> test_cases;
test_cases.insert(test_cases.begin(), IMPOSSIBLE_CASES,
IMPOSSIBLE_CASES + arraysize(IMPOSSIBLE_CASES));
test_cases.insert(test_cases.begin(), POSSIBLE_ONLY_CASES,
POSSIBLE_ONLY_CASES + arraysize(POSSIBLE_ONLY_CASES));
test_cases.insert(test_cases.begin(), VALID_CASES,
VALID_CASES + arraysize(VALID_CASES));
test_cases.insert(test_cases.begin(), STRICT_GROUPING_CASES,
STRICT_GROUPING_CASES + arraysize(STRICT_GROUPING_CASES));
test_cases.insert(test_cases.begin(), kImpossibleCases,
kImpossibleCases + arraysize(kImpossibleCases));
test_cases.insert(test_cases.begin(), kPossibleOnlyCases,
kPossibleOnlyCases + arraysize(kPossibleOnlyCases));
test_cases.insert(test_cases.begin(), kValidCases,
kValidCases + arraysize(kValidCases));
test_cases.insert(test_cases.begin(), kStrictGroupingCases,
kStrictGroupingCases + arraysize(kStrictGroupingCases));
DoTestNumberNonMatchesForLeniency(test_cases, DoTestNumberNonMatchesForLeniency(test_cases,
PhoneNumberMatcher::EXACT_GROUPING); PhoneNumberMatcher::EXACT_GROUPING);
} }


+ 72
- 1
cpp/test/phonenumbers/phonenumberutil_test.cc View File

@ -965,6 +965,10 @@ TEST_F(PhoneNumberUtilTest, FormatByPattern) {
number_formats, number_formats,
&formatted_number); &formatted_number);
EXPECT_EQ("+1 (650) 253-0000", formatted_number); EXPECT_EQ("+1 (650) 253-0000", formatted_number);
phone_util_.FormatByPattern(test_number, PhoneNumberUtil::RFC3966,
number_formats,
&formatted_number);
EXPECT_EQ("+1-650-253-0000", formatted_number);
// $NP is set to '1' for the US. Here we check that for other NANPA countries // $NP is set to '1' for the US. Here we check that for other NANPA countries
// the US rules are followed. // the US rules are followed.
@ -1297,7 +1301,27 @@ TEST_F(PhoneNumberUtilTest, IsValidForRegion) {
EXPECT_TRUE(phone_util_.IsValidNumberForRegion(intl_toll_free_number, EXPECT_TRUE(phone_util_.IsValidNumberForRegion(intl_toll_free_number,
RegionCode::UN001())); RegionCode::UN001()));
EXPECT_FALSE(phone_util_.IsValidNumberForRegion(intl_toll_free_number, EXPECT_FALSE(phone_util_.IsValidNumberForRegion(intl_toll_free_number,
RegionCode::US()));
RegionCode::US()));
EXPECT_FALSE(phone_util_.IsValidNumberForRegion(intl_toll_free_number,
RegionCode::ZZ()));
PhoneNumber invalid_number;
// Invalid country calling codes.
invalid_number.set_country_code(3923);
invalid_number.set_national_number(2366ULL);
EXPECT_FALSE(phone_util_.IsValidNumberForRegion(invalid_number,
RegionCode::ZZ()));
invalid_number.set_country_code(3923);
invalid_number.set_national_number(2366ULL);
EXPECT_FALSE(phone_util_.IsValidNumberForRegion(invalid_number,
RegionCode::UN001()));
invalid_number.set_country_code(0);
invalid_number.set_national_number(2366ULL);
EXPECT_FALSE(phone_util_.IsValidNumberForRegion(invalid_number,
RegionCode::UN001()));
invalid_number.set_country_code(0);
EXPECT_FALSE(phone_util_.IsValidNumberForRegion(invalid_number,
RegionCode::ZZ()));
} }
TEST_F(PhoneNumberUtilTest, IsNotValidNumber) { TEST_F(PhoneNumberUtilTest, IsNotValidNumber) {
@ -1327,6 +1351,14 @@ TEST_F(PhoneNumberUtilTest, IsNotValidNumber) {
nz_number.set_national_number(3316005ULL); nz_number.set_national_number(3316005ULL);
EXPECT_FALSE(phone_util_.IsValidNumber(nz_number)); EXPECT_FALSE(phone_util_.IsValidNumber(nz_number));
PhoneNumber invalid_number;
// Invalid country calling codes.
invalid_number.set_country_code(3923);
invalid_number.set_national_number(2366ULL);
EXPECT_FALSE(phone_util_.IsValidNumber(invalid_number));
invalid_number.set_country_code(0);
EXPECT_FALSE(phone_util_.IsValidNumber(invalid_number));
PhoneNumber intl_toll_free_number_too_long; PhoneNumber intl_toll_free_number_too_long;
intl_toll_free_number_too_long.set_country_code(800); intl_toll_free_number_too_long.set_country_code(800);
intl_toll_free_number_too_long.set_national_number(123456789ULL); intl_toll_free_number_too_long.set_national_number(123456789ULL);
@ -1671,6 +1703,16 @@ TEST_F(PhoneNumberUtilTest, FormatInOriginalFormat) {
phone_util_.FormatInOriginalFormat(phone_number, RegionCode::GB(), phone_util_.FormatInOriginalFormat(phone_number, RegionCode::GB(),
&formatted_number); &formatted_number);
EXPECT_EQ("20 8765 4321", formatted_number); EXPECT_EQ("20 8765 4321", formatted_number);
// Make sure no metadata is modified as a result of the previous function
// call.
phone_number.Clear();
formatted_number.clear();
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("+442087654321", RegionCode::GB(),
&phone_number));
phone_util_.FormatInOriginalFormat(phone_number, RegionCode::GB(),
&formatted_number);
EXPECT_EQ("(020) 8765 4321", formatted_number);
phone_number.Clear(); phone_number.Clear();
formatted_number.clear(); formatted_number.clear();
@ -1819,6 +1861,10 @@ TEST_F(PhoneNumberUtilTest, IsTollFree) {
number.set_country_code(49); number.set_country_code(49);
number.set_national_number(8001234567ULL); number.set_national_number(8001234567ULL);
EXPECT_EQ(PhoneNumberUtil::TOLL_FREE, phone_util_.GetNumberType(number)); EXPECT_EQ(PhoneNumberUtil::TOLL_FREE, phone_util_.GetNumberType(number));
number.set_country_code(800);
number.set_national_number(12345678ULL);
EXPECT_EQ(PhoneNumberUtil::TOLL_FREE, phone_util_.GetNumberType(number));
} }
TEST_F(PhoneNumberUtilTest, IsMobile) { TEST_F(PhoneNumberUtilTest, IsMobile) {
@ -2613,6 +2659,16 @@ TEST_F(PhoneNumberUtilTest, ParseNationalNumber) {
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR, EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("123-456-7890", RegionCode::US(), &test_number)); phone_util_.Parse("123-456-7890", RegionCode::US(), &test_number));
EXPECT_EQ(us_number, test_number); EXPECT_EQ(us_number, test_number);
// Test star numbers. Although this is not strictly valid, we would like to
// make sure we can parse the output we produce when formatting the number.
PhoneNumber star_number;
star_number.set_country_code(81);
star_number.set_national_number(2345ULL);
test_number.Clear();
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("+81 *2345", RegionCode::JP(), &test_number));
EXPECT_EQ(star_number, test_number);
} }
TEST_F(PhoneNumberUtilTest, ParseNumberWithAlphaCharacters) { TEST_F(PhoneNumberUtilTest, ParseNumberWithAlphaCharacters) {
@ -2929,6 +2985,21 @@ TEST_F(PhoneNumberUtilTest, FailedParseOnInvalidNumbers) {
&test_number)); &test_number));
EXPECT_EQ(PhoneNumber::default_instance(), test_number); EXPECT_EQ(PhoneNumber::default_instance(), test_number);
EXPECT_EQ(PhoneNumberUtil::NOT_A_NUMBER,
phone_util_.Parse("+---", RegionCode::DE(),
&test_number));
EXPECT_EQ(PhoneNumber::default_instance(), test_number);
EXPECT_EQ(PhoneNumberUtil::NOT_A_NUMBER,
phone_util_.Parse("+***", RegionCode::DE(),
&test_number));
EXPECT_EQ(PhoneNumber::default_instance(), test_number);
EXPECT_EQ(PhoneNumberUtil::NOT_A_NUMBER,
phone_util_.Parse("+*******91", RegionCode::DE(),
&test_number));
EXPECT_EQ(PhoneNumber::default_instance(), test_number);
EXPECT_EQ(PhoneNumberUtil::TOO_SHORT_NSN, EXPECT_EQ(PhoneNumberUtil::TOO_SHORT_NSN,
phone_util_.Parse("+49 0", RegionCode::DE(), phone_util_.Parse("+49 0", RegionCode::DE(),
&test_number)); &test_number));


+ 15
- 3
cpp/test/phonenumbers/stringutil_test.cc View File

@ -279,15 +279,27 @@ TEST(StringUtilTest, StrAppend) {
// Test with 1 argument. // Test with 1 argument.
StrAppend(&s, "a"); StrAppend(&s, "a");
EXPECT_EQ("a", s);
ASSERT_EQ("a", s);
// Test with 2 arguments. // Test with 2 arguments.
StrAppend(&s, "b", "c"); StrAppend(&s, "b", "c");
EXPECT_EQ("abc", s);
ASSERT_EQ("abc", s);
// Test with 3 arguments.
StrAppend(&s, "d", "e", "f");
ASSERT_EQ("abcdef", s);
// Test with 4 arguments.
StrAppend(&s, "g", "h", "i", "j");
ASSERT_EQ("abcdefghij", s);
// Test with 5 arguments.
StrAppend(&s, "k", "l", "m", "n", "o");
ASSERT_EQ("abcdefghijklmno", s);
// Test with int argument. // Test with int argument.
StrAppend(&s, 42); StrAppend(&s, 42);
EXPECT_EQ("abc42", s);
ASSERT_EQ("abcdefghijklmno42", s);
} }
} // namespace phonenumbers } // namespace phonenumbers


Loading…
Cancel
Save