Browse Source

CPP: port Java changes libphonenumber 4.9

pull/567/head
David Yonge-Mallo 14 years ago
committed by Mihaela Rosca
parent
commit
d2c96cafb4
11 changed files with 591 additions and 49 deletions
  1. +3
    -0
      cpp/CMakeLists.txt
  2. +1
    -1
      cpp/src/phonenumbers/lite_metadata.cc
  3. +1
    -1
      cpp/src/phonenumbers/metadata.cc
  4. +3
    -0
      cpp/src/phonenumbers/phonenumbermatcher.h
  5. +72
    -32
      cpp/src/phonenumbers/phonenumberutil.cc
  6. +11
    -1
      cpp/src/phonenumbers/phonenumberutil.h
  7. +78
    -0
      cpp/src/phonenumbers/shortnumberutil.cc
  8. +73
    -0
      cpp/src/phonenumbers/shortnumberutil.h
  9. +184
    -14
      cpp/test/phonenumbers/phonenumberutil_test.cc
  10. +161
    -0
      cpp/test/phonenumbers/shortnumberutil_test.cc
  11. +4
    -0
      cpp/test/phonenumbers/test_util.h

+ 3
- 0
cpp/CMakeLists.txt View File

@ -189,6 +189,7 @@ set (
"src/phonenumbers/phonenumber.pb.cc" # Generated by Protocol Buffers. "src/phonenumbers/phonenumber.pb.cc" # Generated by Protocol Buffers.
"src/phonenumbers/phonenumberutil.cc" "src/phonenumbers/phonenumberutil.cc"
"src/phonenumbers/regexp_cache.cc" "src/phonenumbers/regexp_cache.cc"
"src/phonenumbers/shortnumberutil.cc"
"src/phonenumbers/string_byte_sink.cc" "src/phonenumbers/string_byte_sink.cc"
"src/phonenumbers/stringutil.cc" "src/phonenumbers/stringutil.cc"
"src/phonenumbers/unicodestring.cc" "src/phonenumbers/unicodestring.cc"
@ -357,6 +358,7 @@ set (TEST_SOURCES
"test/phonenumbers/regexp_adapter_test.cc" "test/phonenumbers/regexp_adapter_test.cc"
"test/phonenumbers/regexp_cache_test.cc" "test/phonenumbers/regexp_cache_test.cc"
"test/phonenumbers/run_tests.cc" "test/phonenumbers/run_tests.cc"
"test/phonenumbers/shortnumberutil_test.cc"
"test/phonenumbers/stringutil_test.cc" "test/phonenumbers/stringutil_test.cc"
"test/phonenumbers/test_util.cc" "test/phonenumbers/test_util.cc"
"test/phonenumbers/unicodestring_test.cc" "test/phonenumbers/unicodestring_test.cc"
@ -395,6 +397,7 @@ install (FILES
"src/phonenumbers/phonenumberutil.h" "src/phonenumbers/phonenumberutil.h"
"src/phonenumbers/regexp_adapter.h" "src/phonenumbers/regexp_adapter.h"
"src/phonenumbers/regexp_cache.h" "src/phonenumbers/regexp_cache.h"
"src/phonenumbers/shortnumberutil.h"
"src/phonenumbers/unicodestring.h" "src/phonenumbers/unicodestring.h"
DESTINATION include/phonenumbers/ DESTINATION include/phonenumbers/
) )


+ 1
- 1
cpp/src/phonenumbers/lite_metadata.cc View File

@ -3189,7 +3189,7 @@ static const unsigned char data[] = {
0x7B, 0x37, 0x7D, 0x7C, 0x31, 0x28, 0x3F, 0x3A, 0x28, 0x3F, 0x3A, 0x31, 0x28, 0x7B, 0x37, 0x7D, 0x7C, 0x31, 0x28, 0x3F, 0x3A, 0x28, 0x3F, 0x3A, 0x31, 0x28,
0x3F, 0x3A, 0x33, 0x5B, 0x30, 0x2D, 0x34, 0x38, 0x5D, 0x7C, 0x5B, 0x34, 0x36, 0x3F, 0x3A, 0x33, 0x5B, 0x30, 0x2D, 0x34, 0x38, 0x5D, 0x7C, 0x5B, 0x34, 0x36,
0x5D, 0x5B, 0x30, 0x2D, 0x34, 0x5D, 0x7C, 0x35, 0x5B, 0x30, 0x31, 0x32, 0x37, 0x5D, 0x5B, 0x30, 0x2D, 0x34, 0x5D, 0x7C, 0x35, 0x5B, 0x30, 0x31, 0x32, 0x37,
0x38, 0x39, 0x5D, 0x7C, 0x37, 0x5B, 0x30, 0x2D, 0x33, 0x39, 0x5D, 0x7C, 0x38,
0x38, 0x39, 0x5D, 0x7C, 0x37, 0x5B, 0x30, 0x2D, 0x34, 0x39, 0x5D, 0x7C, 0x38,
0x5B, 0x30, 0x31, 0x33, 0x34, 0x39, 0x5D, 0x29, 0x7C, 0x32, 0x31, 0x5B, 0x30, 0x5B, 0x30, 0x31, 0x33, 0x34, 0x39, 0x5D, 0x29, 0x7C, 0x32, 0x31, 0x5B, 0x30,
0x2D, 0x37, 0x5D, 0x7C, 0x33, 0x31, 0x5B, 0x30, 0x2D, 0x38, 0x5D, 0x7C, 0x5B, 0x2D, 0x37, 0x5D, 0x7C, 0x33, 0x31, 0x5B, 0x30, 0x2D, 0x38, 0x5D, 0x7C, 0x5B,
0x34, 0x35, 0x39, 0x5D, 0x31, 0x5C, 0x64, 0x7C, 0x36, 0x31, 0x5B, 0x30, 0x2D, 0x34, 0x35, 0x39, 0x5D, 0x31, 0x5C, 0x64, 0x7C, 0x36, 0x31, 0x5B, 0x30, 0x2D,


+ 1
- 1
cpp/src/phonenumbers/metadata.cc View File

@ -3483,7 +3483,7 @@ static const unsigned char data[] = {
0x28, 0x3F, 0x3A, 0x31, 0x28, 0x3F, 0x3A, 0x33, 0x5B, 0x30, 0x2D, 0x34, 0x38, 0x28, 0x3F, 0x3A, 0x31, 0x28, 0x3F, 0x3A, 0x33, 0x5B, 0x30, 0x2D, 0x34, 0x38,
0x5D, 0x7C, 0x5B, 0x34, 0x36, 0x5D, 0x5B, 0x30, 0x2D, 0x34, 0x5D, 0x7C, 0x35, 0x5D, 0x7C, 0x5B, 0x34, 0x36, 0x5D, 0x5B, 0x30, 0x2D, 0x34, 0x5D, 0x7C, 0x35,
0x5B, 0x30, 0x31, 0x32, 0x37, 0x38, 0x39, 0x5D, 0x7C, 0x37, 0x5B, 0x30, 0x2D, 0x5B, 0x30, 0x31, 0x32, 0x37, 0x38, 0x39, 0x5D, 0x7C, 0x37, 0x5B, 0x30, 0x2D,
0x33, 0x39, 0x5D, 0x7C, 0x38, 0x5B, 0x30, 0x31, 0x33, 0x34, 0x39, 0x5D, 0x29,
0x34, 0x39, 0x5D, 0x7C, 0x38, 0x5B, 0x30, 0x31, 0x33, 0x34, 0x39, 0x5D, 0x29,
0x7C, 0x32, 0x31, 0x5B, 0x30, 0x2D, 0x37, 0x5D, 0x7C, 0x33, 0x31, 0x5B, 0x30, 0x7C, 0x32, 0x31, 0x5B, 0x30, 0x2D, 0x37, 0x5D, 0x7C, 0x33, 0x31, 0x5B, 0x30,
0x2D, 0x38, 0x5D, 0x7C, 0x5B, 0x34, 0x35, 0x39, 0x5D, 0x31, 0x5C, 0x64, 0x7C, 0x2D, 0x38, 0x5D, 0x7C, 0x5B, 0x34, 0x35, 0x39, 0x5D, 0x31, 0x5C, 0x64, 0x7C,
0x36, 0x31, 0x5B, 0x30, 0x2D, 0x34, 0x36, 0x2D, 0x39, 0x5D, 0x29, 0x29, 0x5C, 0x36, 0x31, 0x5B, 0x30, 0x2D, 0x34, 0x36, 0x2D, 0x39, 0x5D, 0x29, 0x29, 0x5C,


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

@ -33,6 +33,9 @@
namespace i18n { namespace i18n {
namespace phonenumbers { namespace phonenumbers {
template <class R, class A1, class A2, class A3, class A4>
class ResultCallback4;
using std::string; using std::string;
using std::vector; using std::vector;


+ 72
- 32
cpp/src/phonenumbers/phonenumberutil.cc View File

@ -17,9 +17,9 @@
#include "phonenumbers/phonenumberutil.h" #include "phonenumbers/phonenumberutil.h"
#include <string.h>
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include <cstddef>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <iterator> #include <iterator>
@ -73,10 +73,10 @@ const char PhoneNumberUtil::kPlusChars[] = "+\xEF\xBC\x8B"; /* "++" */
// unicode character. // unicode character.
// static // static
const char PhoneNumberUtil::kValidPunctuation[] = const char PhoneNumberUtil::kValidPunctuation[] =
/* "-x‐-―−ー--/  <U+200B><U+2060> ()()[].\\[\\]/~⁓∼" */
/* "-x‐-―−ー--/  ­<U+200B><U+2060> ()()[].\\[\\]/~⁓∼" */
"-x\xE2\x80\x90-\xE2\x80\x95\xE2\x88\x92\xE3\x83\xBC\xEF\xBC\x8D-\xEF\xBC" "-x\xE2\x80\x90-\xE2\x80\x95\xE2\x88\x92\xE3\x83\xBC\xEF\xBC\x8D-\xEF\xBC"
"\x8F \xC2\xA0\xE2\x80\x8B\xE2\x81\xA0\xE3\x80\x80()\xEF\xBC\x88\xEF\xBC"
"\x89\xEF\xBC\xBB\xEF\xBC\xBD.\\[\\]/~\xE2\x81\x93\xE2\x88\xBC";
"\x8F \xC2\xA0\xC2\xAD\xE2\x80\x8B\xE2\x81\xA0\xE3\x80\x80()\xEF\xBC\x88"
"\xEF\xBC\x89\xEF\xBC\xBB\xEF\xBC\xBD.\\[\\]/~\xE2\x81\x93\xE2\x88\xBC";
// static // static
const char PhoneNumberUtil::kCaptureUpToSecondNumberStart[] = "(.*)[\\\\/] *x"; const char PhoneNumberUtil::kCaptureUpToSecondNumberStart[] = "(.*)[\\\\/] *x";
@ -97,9 +97,8 @@ const char kStarSign[] = "*";
const char kRfc3966ExtnPrefix[] = ";ext="; const char kRfc3966ExtnPrefix[] = ";ext=";
const char kRfc3966Prefix[] = "tel:"; 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 kRfc3966PhoneContext[] = ";phone-context=";
const char kRfc3966IsdnSubaddress[] = ";isub=";
const char kDigits[] = "\\p{Nd}"; const char kDigits[] = "\\p{Nd}";
// We accept alpha characters in phone numbers, ASCII only. We store lower-case // We accept alpha characters in phone numbers, ASCII only. We store lower-case
@ -588,8 +587,8 @@ class PhoneNumberRegExpsAndMappings {
kStarSign)), kStarSign)),
valid_phone_number_( valid_phone_number_(
StrCat("[", PhoneNumberUtil::kPlusChars, "]*(?:[", StrCat("[", PhoneNumberUtil::kPlusChars, "]*(?:[",
punctuation_and_star_sign_, "]*[",
kDigits, "]){3,}[", kValidAlpha,
punctuation_and_star_sign_, "]*",
kDigits, "){3,}[", kValidAlpha,
punctuation_and_star_sign_, kDigits, punctuation_and_star_sign_, kDigits,
"]*")), "]*")),
extn_patterns_for_parsing_( extn_patterns_for_parsing_(
@ -740,6 +739,13 @@ const string& PhoneNumberUtil::GetExtnPatternsForMatching() const {
return reg_exps_->extn_patterns_for_matching_; return reg_exps_->extn_patterns_for_matching_;
} }
bool PhoneNumberUtil::StartsWithPlusCharsPattern(const string& number)
const {
const scoped_ptr<RegExpInput> number_string_piece(
reg_exps_->regexp_factory_->CreateInput(number));
return reg_exps_->plus_chars_pattern_->Consume(number_string_piece.get());
}
bool PhoneNumberUtil::ContainsOnlyValidDigits(const string& s) const { bool PhoneNumberUtil::ContainsOnlyValidDigits(const string& s) const {
return reg_exps_->digits_pattern_->FullMatch(s); return reg_exps_->digits_pattern_->FullMatch(s);
} }
@ -1202,9 +1208,11 @@ void PhoneNumberUtil::FormatInOriginalFormat(const PhoneNumber& number,
// user entered. // user entered.
if (!formatted_number->empty()) { if (!formatted_number->empty()) {
string formatted_number_copy(*formatted_number); string formatted_number_copy(*formatted_number);
NormalizeDigitsOnly(&formatted_number_copy);
NormalizeHelper(reg_exps_->diallable_char_mappings_,
true /* remove non matches */, &formatted_number_copy);
string raw_input_copy(number.raw_input()); string raw_input_copy(number.raw_input());
NormalizeDigitsOnly(&raw_input_copy);
NormalizeHelper(reg_exps_->diallable_char_mappings_,
true /* remove non matches */, &raw_input_copy);
if (formatted_number_copy != raw_input_copy) { if (formatted_number_copy != raw_input_copy) {
formatted_number->assign(number.raw_input()); formatted_number->assign(number.raw_input());
} }
@ -1698,38 +1706,70 @@ bool PhoneNumberUtil::CheckRegionForParsing(
return true; return true;
} }
PhoneNumberUtil::ErrorType PhoneNumberUtil::ParseHelper(
const string& number_to_parse,
const string& default_region,
bool keep_raw_input,
bool check_region,
PhoneNumber* phone_number) const {
DCHECK(phone_number);
// Converts number_to_parse to a form that we can parse and write it to
// national_number if it is written in RFC3966; otherwise extract a possible
// number out of it and write to national_number.
void PhoneNumberUtil::BuildNationalNumberForParsing(
const string& number_to_parse, string* national_number) const {
size_t index_of_phone_context = number_to_parse.find(kRfc3966PhoneContext); size_t index_of_phone_context = number_to_parse.find(kRfc3966PhoneContext);
string national_number;
if (index_of_phone_context != string::npos) { 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));
int phone_context_start =
index_of_phone_context + strlen(kRfc3966PhoneContext);
// If the phone context contains a phone number prefix, we need to capture
// it, whereas domains will be ignored.
if (number_to_parse.at(phone_context_start) == kPlusSign[0]) {
// Additional parameters might follow the phone context. If so, we will
// remove them here because the parameters after phone context are not
// important for parsing the phone number.
size_t phone_context_end = number_to_parse.find(';', phone_context_start);
if (phone_context_end != string::npos) {
StrAppend(
national_number, number_to_parse.substr(
phone_context_start, phone_context_end - phone_context_start));
} else {
StrAppend(national_number, number_to_parse.substr(phone_context_start));
}
}
// Now append everything between the "tel:" prefix and the phone-context. // Now append everything between the "tel:" prefix and the phone-context.
// This should include the national number, an optional extension or
// isdn-subaddress component.
int end_of_rfc_prefix = int end_of_rfc_prefix =
number_to_parse.find(kRfc3966Prefix) + strlen(kRfc3966Prefix); number_to_parse.find(kRfc3966Prefix) + strlen(kRfc3966Prefix);
StrAppend( StrAppend(
&national_number,
national_number,
number_to_parse.substr(end_of_rfc_prefix, number_to_parse.substr(end_of_rfc_prefix,
index_of_phone_context - 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 { } else {
// Extract a possible number from the string passed in (this strips leading // Extract a possible number from the string passed in (this strips leading
// characters that could not be the start of a phone number.) // characters that could not be the start of a phone number.)
ExtractPossibleNumber(number_to_parse, &national_number);
ExtractPossibleNumber(number_to_parse, national_number);
}
// Delete the isdn-subaddress and everything after it if it is present. Note
// extension won't appear at the same time with isdn-subaddress according to
// paragraph 5.3 of the RFC3966 spec.
size_t index_of_isdn = national_number->find(kRfc3966IsdnSubaddress);
if (index_of_isdn != string::npos) {
national_number->erase(index_of_isdn);
} }
// If both phone context and isdn-subaddress are absent but other parameters
// are present, the parameters are left in nationalNumber. This is because
// we are concerned about deleting content from a potential number string
// when there is no strong evidence that the number is actually written in
// RFC3966.
}
PhoneNumberUtil::ErrorType PhoneNumberUtil::ParseHelper(
const string& number_to_parse,
const string& default_region,
bool keep_raw_input,
bool check_region,
PhoneNumber* phone_number) const {
DCHECK(phone_number);
string national_number;
BuildNationalNumberForParsing(number_to_parse, &national_number);
if (!IsViablePhoneNumber(national_number)) { if (!IsViablePhoneNumber(national_number)) {
VLOG(2) << "The string supplied did not seem to be a phone number."; VLOG(2) << "The string supplied did not seem to be a phone number.";
@ -2390,7 +2430,7 @@ PhoneNumberUtil::ErrorType PhoneNumberUtil::MaybeExtractCountryCode(
phone_number->set_country_code_source(country_code_source); phone_number->set_country_code_source(country_code_source);
} }
if (country_code_source != PhoneNumber::FROM_DEFAULT_COUNTRY) { if (country_code_source != PhoneNumber::FROM_DEFAULT_COUNTRY) {
if (national_number->length() < kMinLengthForNsn) {
if (national_number->length() <= kMinLengthForNsn) {
VLOG(2) << "Phone number had an IDD, but after this was not " VLOG(2) << "Phone number had an IDD, but after this was not "
<< "long enough to be a viable phone number."; << "long enough to be a viable phone number.";
return TOO_SHORT_AFTER_IDD; return TOO_SHORT_AFTER_IDD;


+ 11
- 1
cpp/src/phonenumbers/phonenumberutil.h View File

@ -73,6 +73,8 @@ class PhoneNumberUtil : public Singleton<PhoneNumberUtil> {
friend class PhoneNumberMatcherTest; friend class PhoneNumberMatcherTest;
friend class PhoneNumberRegExpsAndMappings; friend class PhoneNumberRegExpsAndMappings;
friend class PhoneNumberUtilTest; friend class PhoneNumberUtilTest;
friend class ShortNumberUtil;
friend class ShortNumberUtilTest;
public: public:
~PhoneNumberUtil(); ~PhoneNumberUtil();
static const char kRegionCodeForNonGeoEntity[]; static const char kRegionCodeForNonGeoEntity[];
@ -487,6 +489,8 @@ class PhoneNumberUtil : public Singleton<PhoneNumberUtil> {
// particular region is not performed. This can be done separately with // particular region is not performed. This can be done separately with
// IsValidNumber(). // IsValidNumber().
// //
// number_to_parse can also be provided in RFC3966 format.
//
// default_region represents the country that we are expecting the number to // default_region represents the country that we are expecting the number to
// be from. This is only used if the number being parsed is not written in // be from. This is only used if the number being parsed is not written in
// international format. The country_code for the number in this case would be // international format. The country_code for the number in this case would be
@ -565,7 +569,7 @@ class PhoneNumberUtil : public Singleton<PhoneNumberUtil> {
typedef pair<int, list<string>*> IntRegionsPair; typedef pair<int, list<string>*> IntRegionsPair;
// The minimum and maximum length of the national significant number. // The minimum and maximum length of the national significant number.
static const size_t kMinLengthForNsn = 3;
static const size_t kMinLengthForNsn = 2;
// The ITU says the maximum length should be 15, but we have found longer // The ITU says the maximum length should be 15, but we have found longer
// numbers in Germany. // numbers in Germany.
static const size_t kMaxLengthForNsn = 16; static const size_t kMaxLengthForNsn = 16;
@ -622,6 +626,9 @@ class PhoneNumberUtil : public Singleton<PhoneNumberUtil> {
// in a number, for use when matching. // in a number, for use when matching.
const string& GetExtnPatternsForMatching() const; const string& GetExtnPatternsForMatching() const;
// Checks if a number matches the plus chars pattern.
bool StartsWithPlusCharsPattern(const string& number) const;
// Checks whether a string contains only valid digits. // Checks whether a string contains only valid digits.
bool ContainsOnlyValidDigits(const string& s) const; bool ContainsOnlyValidDigits(const string& s) const;
@ -748,6 +755,9 @@ class PhoneNumberUtil : public Singleton<PhoneNumberUtil> {
bool check_region, bool check_region,
PhoneNumber* phone_number) const; PhoneNumber* phone_number) const;
void BuildNationalNumberForParsing(const string& number_to_parse,
string* national_number) const;
// Returns true if the number can be dialled from outside the region, or // Returns true if the number can be dialled from outside the region, or
// unknown. If the number can only be dialled from within the region, returns // unknown. If the number can only be dialled from within the region, returns
// false. Does not check the number is a valid number. // false. Does not check the number is a valid number.


+ 78
- 0
cpp/src/phonenumbers/shortnumberutil.cc View File

@ -0,0 +1,78 @@
// 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: David Yonge-Mallo
#include "phonenumbers/shortnumberutil.h"
#include "base/memory/scoped_ptr.h"
#include "phonenumbers/phonemetadata.pb.h"
#include "phonenumbers/phonenumberutil.h"
#include "phonenumbers/regexp_adapter.h"
#include "phonenumbers/regexp_factory.h"
namespace i18n {
namespace phonenumbers {
using std::string;
ShortNumberUtil::ShortNumberUtil()
: phone_util_(*PhoneNumberUtil::GetInstance()) {
}
bool ShortNumberUtil::ConnectsToEmergencyNumber(const string& number,
const string& region_code) const {
return MatchesEmergencyNumberHelper(number, region_code,
true /* allows prefix match */);
}
bool ShortNumberUtil::IsEmergencyNumber(const string& number,
const string& region_code) const {
return MatchesEmergencyNumberHelper(number, region_code,
false /* doesn't allow prefix match */);
}
bool ShortNumberUtil::MatchesEmergencyNumberHelper(const string& number,
const string& region_code, bool allow_prefix_match) const {
string extracted_number;
phone_util_.ExtractPossibleNumber(number, &extracted_number);
if (phone_util_.StartsWithPlusCharsPattern(extracted_number)) {
// Returns false if the number starts with a plus sign. We don't believe
// dialing the country code before emergency numbers (e.g. +1911) works,
// but later, if that proves to work, we can add additional logic here to
// handle it.
return false;
}
const PhoneMetadata* metadata = phone_util_.GetMetadataForRegion(region_code);
if (!metadata || !metadata->has_emergency()) {
return false;
}
const scoped_ptr<const AbstractRegExpFactory> regexp_factory(
new RegExpFactory());
const scoped_ptr<const RegExp> emergency_number_pattern(
regexp_factory->CreateRegExp(
metadata->emergency().national_number_pattern()));
phone_util_.NormalizeDigitsOnly(&extracted_number);
const scoped_ptr<RegExpInput> normalized_number_input(
regexp_factory->CreateInput(extracted_number));
// In Brazil, it is impossible to append additional digits to an emergency
// number to dial the number.
return (!allow_prefix_match || region_code == "BR")
? emergency_number_pattern->FullMatch(extracted_number)
: emergency_number_pattern->Consume(normalized_number_input.get());
}
} // namespace phonenumbers
} // namespace i18n

+ 73
- 0
cpp/src/phonenumbers/shortnumberutil.h View File

@ -0,0 +1,73 @@
// 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.
// Utility for international short phone numbers, such as short codes and
// emergency numbers. Note most commercial short numbers are not handled here,
// but by the phonenumberutil.
//
// Author: David Yonge-Mallo
//
// This is a direct port from ShortNumberUtil.java.
// Changes to this class should also happen to the Java version, whenever it
// makes sense.
#ifndef I18N_PHONENUMBERS_SHORTNUMBERUTIL_H_
#define I18N_PHONENUMBERS_SHORTNUMBERUTIL_H_
#include <string>
#include "base/basictypes.h"
namespace i18n {
namespace phonenumbers {
using std::string;
class PhoneNumberUtil;
class ShortNumberUtil {
public:
ShortNumberUtil();
// Returns true if the number might be used to connect to an emergency service
// in the given region.
//
// This method takes into account cases where the number might contain
// formatting, or might have additional digits appended (when it is okay to do
// that in the region specified).
bool ConnectsToEmergencyNumber(const string& number,
const string& region_code) const;
// Returns true if the number exactly matches an emergency service number in
// the given region.
//
// This method takes into account cases where the number might contain
// formatting, but doesn't allow additional digits to be appended.
bool IsEmergencyNumber(const string& number,
const string& region_code) const;
private:
const PhoneNumberUtil& phone_util_;
bool MatchesEmergencyNumberHelper(const string& number,
const string& region_code,
bool allow_prefix_match) const;
DISALLOW_COPY_AND_ASSIGN(ShortNumberUtil);
};
} // namespace phonenumbers
} // namespace i18n
#endif // I18N_PHONENUMBERS_SHORTNUMBERUTIL_H_

+ 184
- 14
cpp/test/phonenumbers/phonenumberutil_test.cc View File

@ -310,6 +310,13 @@ TEST_F(PhoneNumberUtilTest, GetExampleNumberForNonGeoEntity) {
phone_util_.GetExampleNumberForNonGeoEntity(800 , &test_number); phone_util_.GetExampleNumberForNonGeoEntity(800 , &test_number);
EXPECT_TRUE(success); EXPECT_TRUE(success);
EXPECT_EQ(toll_free_number, test_number); EXPECT_EQ(toll_free_number, test_number);
PhoneNumber universal_premium_rate;
universal_premium_rate.set_country_code(979);
universal_premium_rate.set_national_number(123456789ULL);
success = phone_util_.GetExampleNumberForNonGeoEntity(979 , &test_number);
EXPECT_TRUE(success);
EXPECT_EQ(universal_premium_rate, test_number);
} }
TEST_F(PhoneNumberUtilTest, FormatUSNumber) { TEST_F(PhoneNumberUtilTest, FormatUSNumber) {
@ -1264,6 +1271,11 @@ TEST_F(PhoneNumberUtilTest, IsValidNumber) {
intl_toll_free_number.set_country_code(800); intl_toll_free_number.set_country_code(800);
intl_toll_free_number.set_national_number(12345678ULL); intl_toll_free_number.set_national_number(12345678ULL);
EXPECT_TRUE(phone_util_.IsValidNumber(intl_toll_free_number)); EXPECT_TRUE(phone_util_.IsValidNumber(intl_toll_free_number));
PhoneNumber universal_premium_rate;
universal_premium_rate.set_country_code(979);
universal_premium_rate.set_national_number(123456789ULL);
EXPECT_TRUE(phone_util_.IsValidNumber(universal_premium_rate));
} }
TEST_F(PhoneNumberUtilTest, IsValidForRegion) { TEST_F(PhoneNumberUtilTest, IsValidForRegion) {
@ -1373,6 +1385,53 @@ TEST_F(PhoneNumberUtilTest, IsNotValidNumber) {
EXPECT_FALSE(phone_util_.IsValidNumber(intl_toll_free_number_too_long)); EXPECT_FALSE(phone_util_.IsValidNumber(intl_toll_free_number_too_long));
} }
TEST_F(PhoneNumberUtilTest, GetRegionCodeForCountryCode) {
string region_code;
phone_util_.GetRegionCodeForCountryCode(1, &region_code);
EXPECT_EQ(RegionCode::US(), region_code);
phone_util_.GetRegionCodeForCountryCode(44, &region_code);
EXPECT_EQ(RegionCode::GB(), region_code);
phone_util_.GetRegionCodeForCountryCode(49, &region_code);
EXPECT_EQ(RegionCode::DE(), region_code);
phone_util_.GetRegionCodeForCountryCode(800, &region_code);
EXPECT_EQ(RegionCode::UN001(), region_code);
phone_util_.GetRegionCodeForCountryCode(979, &region_code);
EXPECT_EQ(RegionCode::UN001(), region_code);
}
TEST_F(PhoneNumberUtilTest, GetRegionCodeForNumber) {
string region_code;
PhoneNumber bs_number;
bs_number.set_country_code(1);
bs_number.set_national_number(2423232345ULL);
phone_util_.GetRegionCodeForNumber(bs_number, &region_code);
EXPECT_EQ(RegionCode::BS(), region_code);
PhoneNumber us_number;
us_number.set_country_code(1);
us_number.set_national_number(4241231234ULL);
phone_util_.GetRegionCodeForNumber(us_number, &region_code);
EXPECT_EQ(RegionCode::US(), region_code);
PhoneNumber gb_mobile;
gb_mobile.set_country_code(44);
gb_mobile.set_national_number(7912345678ULL);
phone_util_.GetRegionCodeForNumber(gb_mobile, &region_code);
EXPECT_EQ(RegionCode::GB(), region_code);
PhoneNumber intl_toll_free_number;
intl_toll_free_number.set_country_code(800);
intl_toll_free_number.set_national_number(12345678ULL);
phone_util_.GetRegionCodeForNumber(intl_toll_free_number, &region_code);
EXPECT_EQ(RegionCode::UN001(), region_code);
PhoneNumber universal_premium_rate;
universal_premium_rate.set_country_code(979);
universal_premium_rate.set_national_number(123456789ULL);
phone_util_.GetRegionCodeForNumber(universal_premium_rate, &region_code);
EXPECT_EQ(RegionCode::UN001(), region_code);
}
TEST_F(PhoneNumberUtilTest, IsPossibleNumber) { TEST_F(PhoneNumberUtilTest, IsPossibleNumber) {
PhoneNumber number; PhoneNumber number;
number.set_country_code(1); number.set_country_code(1);
@ -1469,7 +1528,7 @@ TEST_F(PhoneNumberUtilTest, IsPossibleNumberWithReason) {
EXPECT_EQ(PhoneNumberUtil::IS_POSSIBLE, EXPECT_EQ(PhoneNumberUtil::IS_POSSIBLE,
phone_util_.IsPossibleNumberWithReason(ad_number)); phone_util_.IsPossibleNumberWithReason(ad_number));
ad_number.set_country_code(376); ad_number.set_country_code(376);
ad_number.set_national_number(13ULL);
ad_number.set_national_number(1ULL);
EXPECT_EQ(PhoneNumberUtil::TOO_SHORT, EXPECT_EQ(PhoneNumberUtil::TOO_SHORT,
phone_util_.IsPossibleNumberWithReason(ad_number)); phone_util_.IsPossibleNumberWithReason(ad_number));
ad_number.set_country_code(376); ad_number.set_country_code(376);
@ -1827,6 +1886,27 @@ TEST_F(PhoneNumberUtilTest, FormatInOriginalFormat) {
phone_util_.FormatInOriginalFormat(phone_number, RegionCode::AU(), phone_util_.FormatInOriginalFormat(phone_number, RegionCode::AU(),
&formatted_number); &formatted_number);
EXPECT_EQ("0011 1 650 253 0000", formatted_number); EXPECT_EQ("0011 1 650 253 0000", formatted_number);
// Test the star sign is not removed from or added to the original input by
// this method.
phone_number.Clear();
formatted_number.clear();
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.ParseAndKeepRawInput("*1234",
RegionCode::JP(),
&phone_number));
phone_util_.FormatInOriginalFormat(phone_number, RegionCode::JP(),
&formatted_number);
EXPECT_EQ("*1234", formatted_number);
phone_number.Clear();
formatted_number.clear();
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.ParseAndKeepRawInput("1234",
RegionCode::JP(),
&phone_number));
phone_util_.FormatInOriginalFormat(phone_number, RegionCode::JP(),
&formatted_number);
EXPECT_EQ("1234", formatted_number);
} }
TEST_F(PhoneNumberUtilTest, IsPremiumRate) { TEST_F(PhoneNumberUtilTest, IsPremiumRate) {
@ -1850,6 +1930,10 @@ TEST_F(PhoneNumberUtilTest, IsPremiumRate) {
number.set_country_code(49); number.set_country_code(49);
number.set_national_number(90091234567ULL); number.set_national_number(90091234567ULL);
EXPECT_EQ(PhoneNumberUtil::PREMIUM_RATE, phone_util_.GetNumberType(number)); EXPECT_EQ(PhoneNumberUtil::PREMIUM_RATE, phone_util_.GetNumberType(number));
number.set_country_code(979);
number.set_national_number(123456789ULL);
EXPECT_EQ(PhoneNumberUtil::PREMIUM_RATE, phone_util_.GetNumberType(number));
} }
TEST_F(PhoneNumberUtilTest, IsTollFree) { TEST_F(PhoneNumberUtilTest, IsTollFree) {
@ -2047,7 +2131,7 @@ TEST_F(PhoneNumberUtilTest, ConvertAlphaCharactersInNumber) {
} }
TEST_F(PhoneNumberUtilTest, NormaliseRemovePunctuation) { TEST_F(PhoneNumberUtilTest, NormaliseRemovePunctuation) {
string input_number("034-56&+#234");
string input_number("034-56&+#2" "\xC2\xAD" "34");
Normalize(&input_number); Normalize(&input_number);
static const string kExpectedOutput("03456234"); static const string kExpectedOutput("03456234");
EXPECT_EQ(kExpectedOutput, input_number) EXPECT_EQ(kExpectedOutput, input_number)
@ -2389,6 +2473,9 @@ TEST_F(PhoneNumberUtilTest, IsNumberMatchMatches) {
EXPECT_EQ(PhoneNumberUtil::EXACT_MATCH, EXPECT_EQ(PhoneNumberUtil::EXACT_MATCH,
phone_util_.IsNumberMatchWithTwoStrings("+64 3 331-6005", phone_util_.IsNumberMatchWithTwoStrings("+64 3 331-6005",
"+6433316005")); "+6433316005"));
EXPECT_EQ(PhoneNumberUtil::EXACT_MATCH,
phone_util_.IsNumberMatchWithTwoStrings(
"+64 3 331-6005", "tel:+64-3-331-6005;isub=123"));
// Test alpha numbers. // Test alpha numbers.
EXPECT_EQ(PhoneNumberUtil::EXACT_MATCH, EXPECT_EQ(PhoneNumberUtil::EXACT_MATCH,
phone_util_.IsNumberMatchWithTwoStrings("+1800 siX-Flags", phone_util_.IsNumberMatchWithTwoStrings("+1800 siX-Flags",
@ -2439,7 +2526,7 @@ TEST_F(PhoneNumberUtilTest, IsNumberMatchMatches) {
phone_util_.IsNumberMatch(br_number_1, br_number_2)); phone_util_.IsNumberMatch(br_number_1, br_number_2));
} }
TEST_F(PhoneNumberUtilTest, IsNumberMatchNonMetches) {
TEST_F(PhoneNumberUtilTest, IsNumberMatchNonMatches) {
// NSN matches. // NSN matches.
EXPECT_EQ(PhoneNumberUtil::NO_MATCH, EXPECT_EQ(PhoneNumberUtil::NO_MATCH,
phone_util_.IsNumberMatchWithTwoStrings("03 331 6005", phone_util_.IsNumberMatchWithTwoStrings("03 331 6005",
@ -2459,6 +2546,9 @@ TEST_F(PhoneNumberUtilTest, IsNumberMatchNonMetches) {
EXPECT_EQ(PhoneNumberUtil::NO_MATCH, EXPECT_EQ(PhoneNumberUtil::NO_MATCH,
phone_util_.IsNumberMatchWithTwoStrings("+64 3 331-6005 extn 1234", phone_util_.IsNumberMatchWithTwoStrings("+64 3 331-6005 extn 1234",
"+0116433316005#1235")); "+0116433316005#1235"));
EXPECT_EQ(PhoneNumberUtil::NO_MATCH,
phone_util_.IsNumberMatchWithTwoStrings(
"+64 3 331-6005 extn 1234", "tel:+64-3-331-6005;ext=1235"));
// NSN matches, but extension is different - not the same number. // NSN matches, but extension is different - not the same number.
EXPECT_EQ(PhoneNumberUtil::NO_MATCH, EXPECT_EQ(PhoneNumberUtil::NO_MATCH,
phone_util_.IsNumberMatchWithTwoStrings("+64 3 331-6005 ext.1235", phone_util_.IsNumberMatchWithTwoStrings("+64 3 331-6005 ext.1235",
@ -2480,6 +2570,10 @@ TEST_F(PhoneNumberUtilTest, IsNumberMatchNsnMatches) {
EXPECT_EQ(PhoneNumberUtil::NSN_MATCH, EXPECT_EQ(PhoneNumberUtil::NSN_MATCH,
phone_util_.IsNumberMatchWithTwoStrings("+64 3 331-6005", phone_util_.IsNumberMatchWithTwoStrings("+64 3 331-6005",
"03 331 6005")); "03 331 6005"));
EXPECT_EQ(PhoneNumberUtil::NSN_MATCH,
phone_util_.IsNumberMatchWithTwoStrings(
"+64 3 331-6005",
"tel:03-331-6005;isub=1234;phone-context=abc.nz"));
PhoneNumber nz_number; PhoneNumber nz_number;
nz_number.set_country_code(64); nz_number.set_country_code(64);
@ -2529,6 +2623,17 @@ TEST_F(PhoneNumberUtilTest, IsNumberMatchShortNsnMatches) {
EXPECT_EQ(PhoneNumberUtil::SHORT_NSN_MATCH, EXPECT_EQ(PhoneNumberUtil::SHORT_NSN_MATCH,
phone_util_.IsNumberMatchWithTwoStrings("+64 3 331-6005", phone_util_.IsNumberMatchWithTwoStrings("+64 3 331-6005",
"331 6005")); "331 6005"));
EXPECT_EQ(PhoneNumberUtil::SHORT_NSN_MATCH,
phone_util_.IsNumberMatchWithTwoStrings(
"+64 3 331-6005", "tel:331-6005;phone-context=abc.nz"));
EXPECT_EQ(PhoneNumberUtil::SHORT_NSN_MATCH,
phone_util_.IsNumberMatchWithTwoStrings(
"+64 3 331-6005",
"tel:331-6005;isub=1234;phone-context=abc.nz"));
EXPECT_EQ(PhoneNumberUtil::SHORT_NSN_MATCH,
phone_util_.IsNumberMatchWithTwoStrings(
"+64 3 331-6005",
"tel:331-6005;isub=1234;phone-context=abc.nz;a=%A1"));
// We did not know that the "0" was a national prefix since neither number has // We did not know that the "0" was a national prefix since neither number has
// a country code, so this is considered a SHORT_NSN_MATCH. // a country code, so this is considered a SHORT_NSN_MATCH.
@ -2540,6 +2645,9 @@ TEST_F(PhoneNumberUtilTest, IsNumberMatchShortNsnMatches) {
phone_util_.IsNumberMatchWithTwoStrings("3 331-6005", phone_util_.IsNumberMatchWithTwoStrings("3 331-6005",
"331 6005")); "331 6005"));
EXPECT_EQ(PhoneNumberUtil::SHORT_NSN_MATCH,
phone_util_.IsNumberMatchWithTwoStrings(
"3 331-6005", "tel:331-6005;phone-context=abc.nz"));
EXPECT_EQ(PhoneNumberUtil::SHORT_NSN_MATCH, EXPECT_EQ(PhoneNumberUtil::SHORT_NSN_MATCH,
phone_util_.IsNumberMatchWithTwoStrings("3 331-6005", phone_util_.IsNumberMatchWithTwoStrings("3 331-6005",
"+64 331 6005")); "+64 331 6005"));
@ -2614,7 +2722,21 @@ TEST_F(PhoneNumberUtilTest, ParseNationalNumber) {
phone_util_.Parse("tel:331-6005;phone-context=+64-3", phone_util_.Parse("tel:331-6005;phone-context=+64-3",
RegionCode::US(), &test_number)); RegionCode::US(), &test_number));
EXPECT_EQ(nz_number, test_number); EXPECT_EQ(nz_number, test_number);
// Test parsing RFC3966 format with optional user-defined parameters. The
// parameters will appear after the context if present.
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("tel:03-331-6005;phone-context=+64;a=%A1",
RegionCode::NZ(), &test_number));
EXPECT_EQ(nz_number, test_number);
// Test parsing RFC3966 with an ISDN subaddress.
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("tel:03-331-6005;isub=12345;phone-context=+64",
RegionCode::NZ(), &test_number));
EXPECT_EQ(nz_number, test_number);
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("tel:+64-3-331-6005;isub=12345",
RegionCode::US(), &test_number));
EXPECT_EQ(nz_number, test_number);
// Testing international prefixes. // Testing international prefixes.
// Should strip country code. // Should strip country code.
test_number.Clear(); test_number.Clear();
@ -2652,6 +2774,34 @@ TEST_F(PhoneNumberUtilTest, ParseNationalNumber) {
RegionCode::NZ(), &test_number)); RegionCode::NZ(), &test_number));
EXPECT_EQ(nz_number, test_number); EXPECT_EQ(nz_number, test_number);
PhoneNumber us_local_number;
us_local_number.set_country_code(1);
us_local_number.set_national_number(2530000ULL);
test_number.Clear();
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("tel:253-0000;phone-context=www.google.com",
RegionCode::US(), &test_number));
EXPECT_EQ(us_local_number, test_number);
test_number.Clear();
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse(
"tel:253-0000;isub=12345;phone-context=www.google.com",
RegionCode::US(), &test_number));
EXPECT_EQ(us_local_number, test_number);
// This is invalid because no "+" sign is present as part of phone-context.
// The phone context is simply ignored in this case just as if it contains a
// domain.
test_number.Clear();
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("tel:2530000;isub=12345;phone-context=1-650",
RegionCode::US(), &test_number));
EXPECT_EQ(us_local_number, test_number);
test_number.Clear();
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("tel:2530000;isub=12345;phone-context=1234.com",
RegionCode::US(), &test_number));
EXPECT_EQ(us_local_number, test_number);
// Test for http://b/issue?id=2247493 // Test for http://b/issue?id=2247493
nz_number.Clear(); nz_number.Clear();
nz_number.set_country_code(64); nz_number.set_country_code(64);
@ -2789,6 +2939,12 @@ TEST_F(PhoneNumberUtilTest, ParseWithInternationalPrefixes) {
phone_util_.Parse("\xEF\xBC\x8B" "1 (650) 333-6000", phone_util_.Parse("\xEF\xBC\x8B" "1 (650) 333-6000",
/* "+1 (650) 333-6000" */ /* "+1 (650) 333-6000" */
RegionCode::SG(), &test_number)); RegionCode::SG(), &test_number));
// Using a soft hyphen U+00AD.
test_number.Clear();
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("1 (650) 333" "\xC2\xAD" "-6000",
/* "1 (650) 333­-6000­" */
RegionCode::US(), &test_number));
EXPECT_EQ(us_number, test_number); EXPECT_EQ(us_number, test_number);
// The whole number, including punctuation, is here represented in full-width // The whole number, including punctuation, is here represented in full-width
// form. // form.
@ -3066,15 +3222,15 @@ TEST_F(PhoneNumberUtilTest, FailedParseOnInvalidNumbers) {
EXPECT_EQ(PhoneNumber::default_instance(), test_number); EXPECT_EQ(PhoneNumber::default_instance(), test_number);
// RFC3966 phone-context is a website. // 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(PhoneNumberUtil::INVALID_COUNTRY_CODE_ERROR,
phone_util_.Parse("tel:555-1234;phone-context=www.google.com",
RegionCode::ZZ(), &test_number));
EXPECT_EQ(PhoneNumber::default_instance(), test_number); EXPECT_EQ(PhoneNumber::default_instance(), test_number);
// This is invalid because no "+" sign is present as part of phone-context. // This is invalid because no "+" sign is present as part of phone-context.
// This should not succeed in being parsed. // 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(PhoneNumberUtil::INVALID_COUNTRY_CODE_ERROR,
phone_util_.Parse("tel:555-1234;phone-context=1-331",
RegionCode::ZZ(), &test_number));
EXPECT_EQ(PhoneNumber::default_instance(), test_number); EXPECT_EQ(PhoneNumber::default_instance(), test_number);
} }
@ -3112,6 +3268,15 @@ TEST_F(PhoneNumberUtilTest, ParseNumbersWithPlusWithNoRegion) {
RegionCode::GetUnknown(), &result_proto)); RegionCode::GetUnknown(), &result_proto));
EXPECT_EQ(toll_free_number, result_proto); EXPECT_EQ(toll_free_number, result_proto);
PhoneNumber universal_premium_rate;
universal_premium_rate.set_country_code(979);
universal_premium_rate.set_national_number(123456789ULL);
result_proto.Clear();
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("+979 123 456 789",
RegionCode::GetUnknown(), &result_proto));
EXPECT_EQ(universal_premium_rate, result_proto);
result_proto.Clear(); result_proto.Clear();
// Test parsing RFC3966 format with a phone context. // Test parsing RFC3966 format with a phone context.
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR, EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
@ -3123,6 +3288,11 @@ TEST_F(PhoneNumberUtilTest, ParseNumbersWithPlusWithNoRegion) {
phone_util_.Parse(" tel:03-331-6005;phone-context=+64", phone_util_.Parse(" tel:03-331-6005;phone-context=+64",
RegionCode::GetUnknown(), &result_proto)); RegionCode::GetUnknown(), &result_proto));
EXPECT_EQ(nz_number, result_proto); EXPECT_EQ(nz_number, result_proto);
result_proto.Clear();
EXPECT_EQ(PhoneNumberUtil::NO_PARSING_ERROR,
phone_util_.Parse("tel:03-331-6005;isub=12345;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_raw_input("+64 3 331 6005");
nz_number.set_country_code_source(PhoneNumber::FROM_NUMBER_WITH_PLUS_SIGN); nz_number.set_country_code_source(PhoneNumber::FROM_NUMBER_WITH_PLUS_SIGN);
@ -3451,15 +3621,15 @@ TEST_F(PhoneNumberUtilTest, IsAlphaNumber) {
EXPECT_TRUE(phone_util_.IsAlphaNumber(kAlphaNumber)); EXPECT_TRUE(phone_util_.IsAlphaNumber(kAlphaNumber));
static const string kAlphaNumberWithExtension = "1800 six-flags ext. 1234"; static const string kAlphaNumberWithExtension = "1800 six-flags ext. 1234";
EXPECT_TRUE(phone_util_.IsAlphaNumber(kAlphaNumberWithExtension)); EXPECT_TRUE(phone_util_.IsAlphaNumber(kAlphaNumberWithExtension));
static const string kI18NAlphaNumber("+800 six-flags");
EXPECT_TRUE(phone_util_.IsAlphaNumber(kI18NAlphaNumber));
static const string kI18nAlphaNumber("+800 six-flags");
EXPECT_TRUE(phone_util_.IsAlphaNumber(kI18nAlphaNumber));
static const string kNonAlphaNumber("1800 123-1234"); static const string kNonAlphaNumber("1800 123-1234");
EXPECT_FALSE(phone_util_.IsAlphaNumber(kNonAlphaNumber)); EXPECT_FALSE(phone_util_.IsAlphaNumber(kNonAlphaNumber));
static const string kNonAlphaNumberWithExtension( static const string kNonAlphaNumberWithExtension(
"1800 123-1234 extension: 1234"); "1800 123-1234 extension: 1234");
EXPECT_FALSE(phone_util_.IsAlphaNumber(kNonAlphaNumberWithExtension)); EXPECT_FALSE(phone_util_.IsAlphaNumber(kNonAlphaNumberWithExtension));
static const string kI18NNonAlphaNumber("+800 1234-1234");
EXPECT_FALSE(phone_util_.IsAlphaNumber(kI18NNonAlphaNumber));
static const string kI18nNonAlphaNumber("+800 1234-1234");
EXPECT_FALSE(phone_util_.IsAlphaNumber(kI18nNonAlphaNumber));
} }
} // namespace phonenumbers } // namespace phonenumbers


+ 161
- 0
cpp/test/phonenumbers/shortnumberutil_test.cc View File

@ -0,0 +1,161 @@
// Copyright (C) 2009 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: David Yonge-Mallo
#include <gtest/gtest.h>
#include "phonenumbers/phonenumberutil.h"
#include "phonenumbers/shortnumberutil.h"
#include "phonenumbers/test_util.h"
namespace i18n {
namespace phonenumbers {
class ShortNumberUtilTest : public testing::Test {
protected:
ShortNumberUtilTest() : short_util_() {
}
const ShortNumberUtil short_util_;
private:
DISALLOW_COPY_AND_ASSIGN(ShortNumberUtilTest);
};
TEST_F(ShortNumberUtilTest, ConnectsToEmergencyNumber_US) {
EXPECT_TRUE(short_util_.ConnectsToEmergencyNumber("911", RegionCode::US()));
EXPECT_TRUE(short_util_.ConnectsToEmergencyNumber("119", RegionCode::US()));
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("999", RegionCode::US()));
}
TEST_F(ShortNumberUtilTest, ConnectsToEmergencyNumberLongNumber_US) {
EXPECT_TRUE(short_util_.ConnectsToEmergencyNumber("9116666666",
RegionCode::US()));
EXPECT_TRUE(short_util_.ConnectsToEmergencyNumber("1196666666",
RegionCode::US()));
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("9996666666",
RegionCode::US()));
}
TEST_F(ShortNumberUtilTest, ConnectsToEmergencyNumberWithFormatting_US) {
EXPECT_TRUE(short_util_.ConnectsToEmergencyNumber("9-1-1", RegionCode::US()));
EXPECT_TRUE(short_util_.ConnectsToEmergencyNumber("1-1-9", RegionCode::US()));
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("9-9-9",
RegionCode::US()));
}
TEST_F(ShortNumberUtilTest, ConnectsToEmergencyNumberWithPlusSign_US) {
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("+911", RegionCode::US()));
// This hex sequence is the full-width plus sign U+FF0B.
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("\xEF\xBC\x8B" "911",
RegionCode::US()));
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber(" +911",
RegionCode::US()));
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("+119", RegionCode::US()));
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("+999", RegionCode::US()));
}
TEST_F(ShortNumberUtilTest, ConnectsToEmergencyNumber_BR) {
EXPECT_TRUE(short_util_.ConnectsToEmergencyNumber("911", RegionCode::BR()));
EXPECT_TRUE(short_util_.ConnectsToEmergencyNumber("190", RegionCode::BR()));
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("999", RegionCode::BR()));
}
TEST_F(ShortNumberUtilTest, ConnectsToEmergencyNumberLongNumber_BR) {
// Brazilian emergency numbers don't work when additional digits are appended.
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("9111", RegionCode::BR()));
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("1900", RegionCode::BR()));
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("9996", RegionCode::BR()));
}
TEST_F(ShortNumberUtilTest, ConnectsToEmergencyNumber_AO) {
// Angola doesn't have any metadata for emergency numbers in the test
// metadata.
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("911", RegionCode::AO()));
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("222123456",
RegionCode::AO()));
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("923123456",
RegionCode::AO()));
}
TEST_F(ShortNumberUtilTest, ConnectsToEmergencyNumber_ZW) {
// Zimbabwe doesn't have any metadata in the test metadata.
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("911", RegionCode::ZW()));
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("01312345",
RegionCode::ZW()));
EXPECT_FALSE(short_util_.ConnectsToEmergencyNumber("0711234567",
RegionCode::ZW()));
}
TEST_F(ShortNumberUtilTest, IsEmergencyNumber_US) {
EXPECT_TRUE(short_util_.IsEmergencyNumber("911", RegionCode::US()));
EXPECT_TRUE(short_util_.IsEmergencyNumber("119", RegionCode::US()));
EXPECT_FALSE(short_util_.IsEmergencyNumber("999", RegionCode::US()));
}
TEST_F(ShortNumberUtilTest, IsEmergencyNumberLongNumber_US) {
EXPECT_FALSE(short_util_.IsEmergencyNumber("9116666666", RegionCode::US()));
EXPECT_FALSE(short_util_.IsEmergencyNumber("1196666666", RegionCode::US()));
EXPECT_FALSE(short_util_.IsEmergencyNumber("9996666666", RegionCode::US()));
}
TEST_F(ShortNumberUtilTest, IsEmergencyNumberWithFormatting_US) {
EXPECT_TRUE(short_util_.IsEmergencyNumber("9-1-1", RegionCode::US()));
EXPECT_TRUE(short_util_.IsEmergencyNumber("*911", RegionCode::US()));
EXPECT_TRUE(short_util_.IsEmergencyNumber("1-1-9", RegionCode::US()));
EXPECT_TRUE(short_util_.IsEmergencyNumber("*119", RegionCode::US()));
EXPECT_FALSE(short_util_.IsEmergencyNumber("9-9-9", RegionCode::US()));
EXPECT_FALSE(short_util_.IsEmergencyNumber("*999", RegionCode::US()));
}
TEST_F(ShortNumberUtilTest, IsEmergencyNumberWithPlusSign_US) {
EXPECT_FALSE(short_util_.IsEmergencyNumber("+911", RegionCode::US()));
// This hex sequence is the full-width plus sign U+FF0B.
EXPECT_FALSE(short_util_.IsEmergencyNumber("\xEF\xBC\x8B" "911",
RegionCode::US()));
EXPECT_FALSE(short_util_.IsEmergencyNumber(" +911", RegionCode::US()));
EXPECT_FALSE(short_util_.IsEmergencyNumber("+119", RegionCode::US()));
EXPECT_FALSE(short_util_.IsEmergencyNumber("+999", RegionCode::US()));
}
TEST_F(ShortNumberUtilTest, IsEmergencyNumber_BR) {
EXPECT_TRUE(short_util_.IsEmergencyNumber("911", RegionCode::BR()));
EXPECT_TRUE(short_util_.IsEmergencyNumber("190", RegionCode::BR()));
EXPECT_FALSE(short_util_.IsEmergencyNumber("999", RegionCode::BR()));
}
TEST_F(ShortNumberUtilTest, EmergencyNumberLongNumber_BR) {
EXPECT_FALSE(short_util_.IsEmergencyNumber("9111", RegionCode::BR()));
EXPECT_FALSE(short_util_.IsEmergencyNumber("1900", RegionCode::BR()));
EXPECT_FALSE(short_util_.IsEmergencyNumber("9996", RegionCode::BR()));
}
TEST_F(ShortNumberUtilTest, IsEmergencyNumber_AO) {
// Angola doesn't have any metadata for emergency numbers in the test
// metadata.
EXPECT_FALSE(short_util_.IsEmergencyNumber("911", RegionCode::AO()));
EXPECT_FALSE(short_util_.IsEmergencyNumber("222123456", RegionCode::AO()));
EXPECT_FALSE(short_util_.IsEmergencyNumber("923123456", RegionCode::AO()));
}
TEST_F(ShortNumberUtilTest, IsEmergencyNumber_ZW) {
// Zimbabwe doesn't have any metadata in the test metadata.
EXPECT_FALSE(short_util_.IsEmergencyNumber("911", RegionCode::ZW()));
EXPECT_FALSE(short_util_.IsEmergencyNumber("01312345", RegionCode::ZW()));
EXPECT_FALSE(short_util_.IsEmergencyNumber("0711234567", RegionCode::ZW()));
}
} // namespace phonenumbers
} // namespace i18n

+ 4
- 0
cpp/test/phonenumbers/test_util.h View File

@ -141,6 +141,10 @@ class RegionCode {
return "YT"; return "YT";
} }
static const char* ZW() {
return "ZW";
}
// 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"; return "ZZ";


Loading…
Cancel
Save