| Index: third_party/libphonenumber/cpp/src/phonenumberutil.cc
 | 
| ===================================================================
 | 
| --- third_party/libphonenumber/cpp/src/phonenumberutil.cc	(revision 0)
 | 
| +++ third_party/libphonenumber/cpp/src/phonenumberutil.cc	(revision 0)
 | 
| @@ -0,0 +1,2266 @@
 | 
| +// Copyright (C) 2009 Google Inc.
 | 
| +//
 | 
| +// 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: Shaopeng Jia
 | 
| +// Open-sourced by: Philippe Liard
 | 
| +
 | 
| +#include "phonenumberutil.h"
 | 
| +
 | 
| +#include <algorithm>
 | 
| +#include <fstream>
 | 
| +#include <iostream>
 | 
| +#include <map>
 | 
| +#include <sstream>
 | 
| +#include <vector>
 | 
| +
 | 
| +#include <google/protobuf/message_lite.h>
 | 
| +#include <unicode/errorcode.h>
 | 
| +#include <unicode/translit.h>
 | 
| +
 | 
| +#include "base/logging.h"
 | 
| +#include "base/singleton.h"
 | 
| +#include "default_logger.h"
 | 
| +#include "logger_adapter.h"
 | 
| +#include "metadata.h"
 | 
| +#include "phonemetadata.pb.h"
 | 
| +#include "phonenumber.h"
 | 
| +#include "phonenumber.pb.h"
 | 
| +#include "regexp_adapter.h"
 | 
| +#include "stringutil.h"
 | 
| +#include "utf/unicodetext.h"
 | 
| +#include "utf/utf.h"
 | 
| +
 | 
| +namespace i18n {
 | 
| +namespace phonenumbers {
 | 
| +
 | 
| +using std::cerr;
 | 
| +using std::endl;
 | 
| +using std::ifstream;
 | 
| +using std::make_pair;
 | 
| +using std::sort;
 | 
| +using std::stringstream;
 | 
| +
 | 
| +using google::protobuf::RepeatedPtrField;
 | 
| +
 | 
| +namespace {
 | 
| +
 | 
| +scoped_ptr<LoggerAdapter> logger;
 | 
| +
 | 
| +// These objects are created in the function InitializeStaticMapsAndSets.
 | 
| +
 | 
| +// These mappings map a character (key) to a specific digit that should replace
 | 
| +// it for normalization purposes.
 | 
| +scoped_ptr<map<char32, char> > alpha_mappings;
 | 
| +// For performance reasons, amalgamate both into one map.
 | 
| +scoped_ptr<map<char32, char> > all_normalization_mappings;
 | 
| +// Separate map of all symbols that we wish to retain when formatting alpha
 | 
| +// numbers. This includes digits, ascii letters and number grouping symbols such
 | 
| +// as "-" and " ".
 | 
| +scoped_ptr<map<char32, char> > all_plus_number_grouping_symbols;
 | 
| +
 | 
| +// The kPlusSign signifies the international prefix.
 | 
| +const char kPlusSign[] = "+";
 | 
| +
 | 
| +const char kPlusChars[] = "++";
 | 
| +scoped_ptr<const reg_exp::RegularExpression> plus_chars_pattern;
 | 
| +
 | 
| +const char kRfc3966ExtnPrefix[] = ";ext=";
 | 
| +
 | 
| +// Pattern that makes it easy to distinguish whether a region has a unique
 | 
| +// international dialing prefix or not. If a region has a unique international
 | 
| +// prefix (e.g. 011 in USA), it will be represented as a string that contains a
 | 
| +// sequence of ASCII digits. If there are multiple available international
 | 
| +// prefixes in a region, they will be represented as a regex string that always
 | 
| +// contains character(s) other than ASCII digits.
 | 
| +// Note this regex also includes tilde, which signals waiting for the tone.
 | 
| +scoped_ptr<const reg_exp::RegularExpression> unique_international_prefix;
 | 
| +
 | 
| +// Digits accepted in phone numbers.
 | 
| +// Both Arabic-Indic and Eastern Arabic-Indic are supported.
 | 
| +const char kValidDigits[] = "0-90-9٠-٩۰-۹";
 | 
| +// We accept alpha characters in phone numbers, ASCII only. We store lower-case
 | 
| +// here only since our regular expressions are case-insensitive.
 | 
| +const char kValidAlpha[] = "a-z";
 | 
| +scoped_ptr<const reg_exp::RegularExpression> capturing_digit_pattern;
 | 
| +scoped_ptr<const reg_exp::RegularExpression> capturing_ascii_digits_pattern;
 | 
| +
 | 
| +// Regular expression of acceptable characters that may start a phone number
 | 
| +// for the purposes of parsing. This allows us to strip away meaningless
 | 
| +// prefixes to phone numbers that may be mistakenly given to us. This
 | 
| +// consists of digits, the plus symbol and arabic-indic digits. This does
 | 
| +// not contain alpha characters, although they may be used later in the
 | 
| +// number. It also does not include other punctuation, as this will be
 | 
| +// stripped later during parsing and is of no information value when parsing
 | 
| +// a number. The string starting with this valid character is captured.
 | 
| +// This corresponds to VALID_START_CHAR in the java version.
 | 
| +scoped_ptr<const string> valid_start_char;
 | 
| +scoped_ptr<const reg_exp::RegularExpression> valid_start_char_pattern;
 | 
| +
 | 
| +// Regular expression of characters typically used to start a second phone
 | 
| +// number for the purposes of parsing. This allows us to strip off parts of
 | 
| +// the number that are actually the start of another number, such as for:
 | 
| +// (530) 583-6985 x302/x2303 -> the second extension here makes this actually
 | 
| +// two phone numbers, (530) 583-6985 x302 and (530) 583-6985 x2303. We remove
 | 
| +// the second extension so that the first number is parsed correctly. The string
 | 
| +// preceding this is captured.
 | 
| +// This corresponds to SECOND_NUMBER_START in the java version.
 | 
| +const char kCaptureUpToSecondNumberStart[] = "(.*)[\\\\/] *x";
 | 
| +scoped_ptr<const reg_exp::RegularExpression>
 | 
| +    capture_up_to_second_number_start_pattern;
 | 
| +
 | 
| +// Regular expression of trailing characters that we want to remove. We remove
 | 
| +// all characters that are not alpha or numerical characters. The hash
 | 
| +// character is retained here, as it may signify the previous block was an
 | 
| +// extension. Note the capturing block at the start to capture the rest of the
 | 
| +// number if this was a match.
 | 
| +// This corresponds to UNWANTED_END_CHARS in the java version.
 | 
| +const char kUnwantedEndChar[] = "[^\\p{N}\\p{L}#]";
 | 
| +scoped_ptr<const reg_exp::RegularExpression> unwanted_end_char_pattern;
 | 
| +
 | 
| +// Regular expression of acceptable punctuation found in phone numbers. This
 | 
| +// excludes punctuation found as a leading character only.  This consists of
 | 
| +// dash characters, white space characters, full stops, slashes, square
 | 
| +// brackets, parentheses and tildes. It also includes the letter 'x' as that is
 | 
| +// found as a placeholder for carrier information in some phone numbers.
 | 
| +// Full-width variants are also present.
 | 
| +// To find out the unicode code-point of the characters below in vim, highlight
 | 
| +// the character and type 'ga'. Note that the - is used to express ranges of
 | 
| +// full-width punctuation below, as well as being present in the expression
 | 
| +// itself. In emacs, you can use M-x unicode-what to query information about the
 | 
| +// unicode character.
 | 
| +const char kValidPunctuation[] =
 | 
| +    "-x‐-―−ー--/   ()()[].\\[\\]/~⁓∼~";
 | 
| +
 | 
| +// Regular expression of viable phone numbers. This is location independent.
 | 
| +// Checks we have at least three leading digits, and only valid punctuation,
 | 
| +// alpha characters and digits in the phone number. Does not include extension
 | 
| +// data. The symbol 'x' is allowed here as valid punctuation since it is often
 | 
| +// used as a placeholder for carrier codes, for example in Brazilian phone
 | 
| +// numbers. We also allow multiple plus-signs at the start.
 | 
| +// Corresponds to the following:
 | 
| +// plus_sign*([punctuation]*[digits]){3,}([punctuation]|[digits]|[alpha])*
 | 
| +scoped_ptr<const string> valid_phone_number;
 | 
| +
 | 
| +// Default extension prefix to use when formatting. This will be put in front of
 | 
| +// any extension component of the number, after the main national number is
 | 
| +// formatted. For example, if you wish the default extension formatting to be "
 | 
| +// extn: 3456", then you should specify " extn: " here as the default extension
 | 
| +// prefix. This can be overridden by region-specific preferences.
 | 
| +const char kDefaultExtnPrefix[] = " ext. ";
 | 
| +
 | 
| +// Regexp of all possible ways to write extensions, for use when parsing. This
 | 
| +// will be run as a case-insensitive regexp match. Wide character versions are
 | 
| +// also provided after each ascii version. There are three regular expressions
 | 
| +// here. The first covers RFC 3966 format, where the extension is added using
 | 
| +// ";ext=". The second more generic one starts with optional white space and
 | 
| +// ends with an optional full stop (.), followed by zero or more spaces/tabs and
 | 
| +// then the numbers themselves. The third one covers the special case of
 | 
| +// American numbers where the extension is written with a hash at the end, such
 | 
| +// as "- 503#".
 | 
| +// Note that the only capturing groups should be around the digits that you want
 | 
| +// to capture as part of the extension, or else parsing will fail!
 | 
| +scoped_ptr<const string> known_extn_patterns;
 | 
| +// Regexp of all known extension prefixes used by different regions followed
 | 
| +// by 1 or more valid digits, for use when parsing.
 | 
| +scoped_ptr<const reg_exp::RegularExpression> extn_pattern;
 | 
| +
 | 
| +// We append optionally the extension pattern to the end here, as a valid phone
 | 
| +// number may have an extension prefix appended, followed by 1 or more digits.
 | 
| +scoped_ptr<const reg_exp::RegularExpression> valid_phone_number_pattern;
 | 
| +
 | 
| +// We use this pattern to check if the phone number has at least three letters
 | 
| +// in it - if so, then we treat it as a number where some phone-number digits
 | 
| +// are represented by letters.
 | 
| +scoped_ptr<const reg_exp::RegularExpression> valid_alpha_phone_pattern;
 | 
| +
 | 
| +scoped_ptr<const reg_exp::RegularExpression> first_group_capturing_pattern;
 | 
| +
 | 
| +scoped_ptr<const reg_exp::RegularExpression> carrier_code_pattern;
 | 
| +
 | 
| +void TransformRegularExpressionToRE2Syntax(string* regex) {
 | 
| +  DCHECK(regex);
 | 
| +  StripString(regex, "$", '\\');
 | 
| +}
 | 
| +
 | 
| +// Returns a pointer to the description inside the metadata of the appropriate
 | 
| +// type.
 | 
| +const PhoneNumberDesc* GetNumberDescByType(
 | 
| +    const PhoneMetadata& metadata,
 | 
| +    PhoneNumberUtil::PhoneNumberType type) {
 | 
| +  switch (type) {
 | 
| +    case PhoneNumberUtil::PREMIUM_RATE:
 | 
| +      return &metadata.premium_rate();
 | 
| +    case PhoneNumberUtil::TOLL_FREE:
 | 
| +      return &metadata.toll_free();
 | 
| +    case PhoneNumberUtil::MOBILE:
 | 
| +      return &metadata.mobile();
 | 
| +    case PhoneNumberUtil::FIXED_LINE:
 | 
| +    case PhoneNumberUtil::FIXED_LINE_OR_MOBILE:
 | 
| +      return &metadata.fixed_line();
 | 
| +    case PhoneNumberUtil::SHARED_COST:
 | 
| +      return &metadata.shared_cost();
 | 
| +    case PhoneNumberUtil::VOIP:
 | 
| +      return &metadata.voip();
 | 
| +    case PhoneNumberUtil::PERSONAL_NUMBER:
 | 
| +      return &metadata.personal_number();
 | 
| +    case PhoneNumberUtil::PAGER:
 | 
| +      return &metadata.pager();
 | 
| +    case PhoneNumberUtil::UAN:
 | 
| +      return &metadata.uan();
 | 
| +    default:
 | 
| +      return &metadata.general_desc();
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +// 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) {
 | 
| +  switch (number_format) {
 | 
| +    case PhoneNumberUtil::E164:
 | 
| +      formatted_number->assign(StrCat(kPlusSign,
 | 
| +                                      SimpleItoa(country_calling_code),
 | 
| +                                      formatted_national_number,
 | 
| +                                      formatted_extension));
 | 
| +      return;
 | 
| +    case PhoneNumberUtil::INTERNATIONAL:
 | 
| +      formatted_number->assign(StrCat(kPlusSign,
 | 
| +                                      SimpleItoa(country_calling_code),
 | 
| +                                      " ",
 | 
| +                                      formatted_national_number,
 | 
| +                                      formatted_extension));
 | 
| +      return;
 | 
| +    case PhoneNumberUtil::RFC3966:
 | 
| +      formatted_number->assign(StrCat(kPlusSign,
 | 
| +                                      SimpleItoa(country_calling_code),
 | 
| +                                      "-",
 | 
| +                                      formatted_national_number,
 | 
| +                                      formatted_extension));
 | 
| +      return;
 | 
| +    case PhoneNumberUtil::NATIONAL:
 | 
| +    default:
 | 
| +      formatted_number->assign(StrCat(formatted_national_number,
 | 
| +                                      formatted_extension));
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +// 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
 | 
| +// replacement will take place.
 | 
| +void FormatAccordingToFormatsWithCarrier(
 | 
| +    const string& number_for_leading_digits_match,
 | 
| +    const RepeatedPtrField<NumberFormat>& available_formats,
 | 
| +    PhoneNumberUtil::PhoneNumberFormat number_format,
 | 
| +    const string& national_number,
 | 
| +    const string& carrier_code,
 | 
| +    string* formatted_number) {
 | 
| +  DCHECK(formatted_number);
 | 
| +  for (RepeatedPtrField<NumberFormat>::const_iterator
 | 
| +       it = available_formats.begin(); it != available_formats.end(); ++it) {
 | 
| +    int size = it->leading_digits_pattern_size();
 | 
| +    if (size > 0) {
 | 
| +      scoped_ptr<reg_exp::RegularExpressionInput>
 | 
| +          number_copy(reg_exp::CreateRegularExpressionInput(
 | 
| +              number_for_leading_digits_match.c_str()));
 | 
| +      // We always use the last leading_digits_pattern, as it is the most
 | 
| +      // detailed.
 | 
| +      if (!number_copy->ConsumeRegExp(it->leading_digits_pattern(size - 1),
 | 
| +                                      true, NULL, NULL)) {
 | 
| +        continue;
 | 
| +      }
 | 
| +    }
 | 
| +    scoped_ptr<reg_exp::RegularExpression> pattern_to_match(
 | 
| +        reg_exp::CreateRegularExpression(it->pattern().c_str()));
 | 
| +    if (pattern_to_match->Match(national_number.c_str(), true, NULL)) {
 | 
| +      string formatting_pattern(it->format());
 | 
| +      if (number_format == PhoneNumberUtil::NATIONAL &&
 | 
| +          carrier_code.length() > 0 &&
 | 
| +          it->domestic_carrier_code_formatting_rule().length() > 0) {
 | 
| +        // Replace the $CC in the formatting rule with the desired carrier code.
 | 
| +        string carrier_code_formatting_rule =
 | 
| +            it->domestic_carrier_code_formatting_rule();
 | 
| +        carrier_code_pattern->Replace(&carrier_code_formatting_rule,
 | 
| +                                      false, carrier_code.c_str());
 | 
| +        TransformRegularExpressionToRE2Syntax(&carrier_code_formatting_rule);
 | 
| +        first_group_capturing_pattern->Replace(&formatting_pattern,
 | 
| +            false,
 | 
| +            carrier_code_formatting_rule.c_str());
 | 
| +      } else {
 | 
| +        // Use the national prefix formatting rule instead.
 | 
| +        string national_prefix_formatting_rule =
 | 
| +          it->national_prefix_formatting_rule();
 | 
| +        if (number_format == PhoneNumberUtil::NATIONAL &&
 | 
| +            national_prefix_formatting_rule.length() > 0) {
 | 
| +          // Apply the national_prefix_formatting_rule as the formatting_pattern
 | 
| +          // contains only information on how the national significant number
 | 
| +          // should be formatted at this point.
 | 
| +          TransformRegularExpressionToRE2Syntax(
 | 
| +              &national_prefix_formatting_rule);
 | 
| +          first_group_capturing_pattern->Replace(&formatting_pattern,
 | 
| +              false,
 | 
| +              national_prefix_formatting_rule.c_str());
 | 
| +        }
 | 
| +      }
 | 
| +      TransformRegularExpressionToRE2Syntax(&formatting_pattern);
 | 
| +      formatted_number->assign(national_number);
 | 
| +      pattern_to_match->Replace(formatted_number, true,
 | 
| +                                formatting_pattern.c_str());
 | 
| +      return;
 | 
| +    }
 | 
| +  }
 | 
| +  // If no pattern above is matched, we format the number as a whole.
 | 
| +  formatted_number->assign(national_number);
 | 
| +}
 | 
| +
 | 
| +// Simple wrapper of FormatAccordingToFormatsWithCarrier for the common case of
 | 
| +// no carrier code.
 | 
| +void FormatAccordingToFormats(
 | 
| +    const string& number_for_leading_digits_match,
 | 
| +    const RepeatedPtrField<NumberFormat>& available_formats,
 | 
| +    PhoneNumberUtil::PhoneNumberFormat number_format,
 | 
| +    const string& national_number,
 | 
| +    string* formatted_number) {
 | 
| +  DCHECK(formatted_number);
 | 
| +  FormatAccordingToFormatsWithCarrier(number_for_leading_digits_match,
 | 
| +                                      available_formats, number_format,
 | 
| +                                      national_number, "", formatted_number);
 | 
| +}
 | 
| +
 | 
| +// Returns true when one national number is the suffix of the other or both are
 | 
| +// the same.
 | 
| +bool IsNationalNumberSuffixOfTheOther(const PhoneNumber& first_number,
 | 
| +                                      const PhoneNumber& second_number) {
 | 
| +  const string& first_number_national_number =
 | 
| +      SimpleItoa(first_number.national_number());
 | 
| +  const string& second_number_national_number =
 | 
| +      SimpleItoa(second_number.national_number());
 | 
| +  // Note that HasSuffixString returns true if the numbers are equal.
 | 
| +  return HasSuffixString(first_number_national_number,
 | 
| +                         second_number_national_number) ||
 | 
| +         HasSuffixString(second_number_national_number,
 | 
| +                         first_number_national_number);
 | 
| +}
 | 
| +
 | 
| +bool IsNumberMatchingDesc(const string& national_number,
 | 
| +                          const PhoneNumberDesc& number_desc) {
 | 
| +  scoped_ptr<const reg_exp::RegularExpression>
 | 
| +       possible_pattern(reg_exp::CreateRegularExpression(
 | 
| +           number_desc.possible_number_pattern().c_str()));
 | 
| +  scoped_ptr<const reg_exp::RegularExpression>
 | 
| +       national_pattern(reg_exp::CreateRegularExpression(
 | 
| +           number_desc.national_number_pattern().c_str()));
 | 
| +  return (possible_pattern->Match(national_number.c_str(), true, NULL) &&
 | 
| +          national_pattern->Match(national_number.c_str(), true, NULL));
 | 
| +}
 | 
| +
 | 
| +PhoneNumberUtil::PhoneNumberType GetNumberTypeHelper(
 | 
| +    const string& national_number, const PhoneMetadata& metadata) {
 | 
| +  const PhoneNumberDesc& general_desc = metadata.general_desc();
 | 
| +  if (!general_desc.has_national_number_pattern() ||
 | 
| +      !IsNumberMatchingDesc(national_number, general_desc)) {
 | 
| +    logger->Debug("Number type unknown - "
 | 
| +        "doesn't match general national number pattern.");
 | 
| +    return PhoneNumberUtil::UNKNOWN;
 | 
| +  }
 | 
| +  if (IsNumberMatchingDesc(national_number, metadata.premium_rate())) {
 | 
| +    logger->Debug("Number is a premium number.");
 | 
| +    return PhoneNumberUtil::PREMIUM_RATE;
 | 
| +  }
 | 
| +  if (IsNumberMatchingDesc(national_number, metadata.toll_free())) {
 | 
| +    logger->Debug("Number is a toll-free number.");
 | 
| +    return PhoneNumberUtil::TOLL_FREE;
 | 
| +  }
 | 
| +  if (IsNumberMatchingDesc(national_number, metadata.shared_cost())) {
 | 
| +    logger->Debug("Number is a shared cost number.");
 | 
| +    return PhoneNumberUtil::SHARED_COST;
 | 
| +  }
 | 
| +  if (IsNumberMatchingDesc(national_number, metadata.voip())) {
 | 
| +    logger->Debug("Number is a VOIP (Voice over IP) number.");
 | 
| +    return PhoneNumberUtil::VOIP;
 | 
| +  }
 | 
| +  if (IsNumberMatchingDesc(national_number, metadata.personal_number())) {
 | 
| +    logger->Debug("Number is a personal number.");
 | 
| +    return PhoneNumberUtil::PERSONAL_NUMBER;
 | 
| +  }
 | 
| +  if (IsNumberMatchingDesc(national_number, metadata.pager())) {
 | 
| +    logger->Debug("Number is a pager number.");
 | 
| +    return PhoneNumberUtil::PAGER;
 | 
| +  }
 | 
| +  if (IsNumberMatchingDesc(national_number, metadata.uan())) {
 | 
| +    logger->Debug("Number is a UAN.");
 | 
| +    return PhoneNumberUtil::UAN;
 | 
| +  }
 | 
| +
 | 
| +  bool is_fixed_line =
 | 
| +      IsNumberMatchingDesc(national_number, metadata.fixed_line());
 | 
| +  if (is_fixed_line) {
 | 
| +    if (metadata.same_mobile_and_fixed_line_pattern()) {
 | 
| +      logger->Debug("Fixed-line and mobile patterns equal, "
 | 
| +          "number is fixed-line or mobile");
 | 
| +      return PhoneNumberUtil::FIXED_LINE_OR_MOBILE;
 | 
| +    } else if (IsNumberMatchingDesc(national_number, metadata.mobile())) {
 | 
| +      logger->Debug("Fixed-line and mobile patterns differ, but number is "
 | 
| +          "still fixed-line or mobile");
 | 
| +      return PhoneNumberUtil::FIXED_LINE_OR_MOBILE;
 | 
| +    }
 | 
| +    logger->Debug("Number is a fixed line number.");
 | 
| +    return PhoneNumberUtil::FIXED_LINE;
 | 
| +  }
 | 
| +  // Otherwise, test to see if the number is mobile. Only do this if certain
 | 
| +  // that the patterns for mobile and fixed line aren't the same.
 | 
| +  if (!metadata.same_mobile_and_fixed_line_pattern() &&
 | 
| +      IsNumberMatchingDesc(national_number, metadata.mobile())) {
 | 
| +    logger->Debug("Number is a mobile number.");
 | 
| +    return PhoneNumberUtil::MOBILE;
 | 
| +  }
 | 
| +  logger->Debug("Number type unknown - doesn't match any specific number type"
 | 
| +      " pattern.");
 | 
| +  return PhoneNumberUtil::UNKNOWN;
 | 
| +}
 | 
| +
 | 
| +int DecodeUTF8Char(const char* in, char32* out) {
 | 
| +  Rune r;
 | 
| +  int len = chartorune(&r, in);
 | 
| +  *out = r;
 | 
| +
 | 
| +  return len;
 | 
| +}
 | 
| +
 | 
| +char32 ToUnicodeCodepoint(const char* unicode_char) {
 | 
| +  char32 codepoint;
 | 
| +  DecodeUTF8Char(unicode_char, &codepoint);
 | 
| +
 | 
| +  return codepoint;
 | 
| +}
 | 
| +
 | 
| +// Initialisation helper function used to populate the regular expressions in a
 | 
| +// defined order.
 | 
| +void CreateRegularExpressions() {
 | 
| +  unique_international_prefix.reset(
 | 
| +      reg_exp::CreateRegularExpression("[\\d]+(?:[~⁓∼~][\\d]+)?"));
 | 
| +  first_group_capturing_pattern.reset(
 | 
| +      reg_exp::CreateRegularExpression("(\\$1)"));
 | 
| +  carrier_code_pattern.reset(
 | 
| +      reg_exp::CreateRegularExpression("\\$CC"));
 | 
| +  capturing_digit_pattern.reset(
 | 
| +      reg_exp::CreateRegularExpression(
 | 
| +         StrCat("([", kValidDigits, "])").c_str()));
 | 
| +  capturing_ascii_digits_pattern.reset(
 | 
| +      reg_exp::CreateRegularExpression("(\\d+)"));
 | 
| +  valid_start_char.reset(new string(StrCat(
 | 
| +      "[", kPlusChars, kValidDigits, "]")));
 | 
| +  valid_start_char_pattern.reset(
 | 
| +      reg_exp::CreateRegularExpression(valid_start_char->c_str()));
 | 
| +  capture_up_to_second_number_start_pattern.reset(
 | 
| +      reg_exp::CreateRegularExpression(kCaptureUpToSecondNumberStart));
 | 
| +  unwanted_end_char_pattern.reset(
 | 
| +      reg_exp::CreateRegularExpression(kUnwantedEndChar));
 | 
| +  valid_phone_number.reset(new string(
 | 
| +      StrCat("[", kPlusChars, "]*(?:[", kValidPunctuation, "]*[", kValidDigits,
 | 
| +             "]){3,}[", kValidAlpha, kValidPunctuation, kValidDigits, "]*")));
 | 
| +  // Canonical-equivalence doesn't seem to be an option with RE2, so we allow
 | 
| +  // two options for representing the ó - the character itself, and one in the
 | 
| +  // unicode decomposed form with the combining acute accent. Note that there
 | 
| +  // are currently three capturing groups for the extension itself - if this
 | 
| +  // number is changed, MaybeStripExtension needs to be updated.
 | 
| +  const string capturing_extn_digits = StrCat("([", kValidDigits, "]{1,7})");
 | 
| +  known_extn_patterns.reset(new string(
 | 
| +      StrCat(kRfc3966ExtnPrefix, capturing_extn_digits, "|"
 | 
| +             "[  \\t,]*(?:ext(?:ensi(?:ó?|ó))?n?|extn?|[,xx##~~]|"
 | 
| +             "int|int|anexo)"
 | 
| +             "[:\\..]?[  \\t,-]*", capturing_extn_digits, "#?|"
 | 
| +             "[- ]+([", kValidDigits, "]{1,5})#")));
 | 
| +  extn_pattern.reset(reg_exp::CreateRegularExpression(
 | 
| +      StrCat("(?i)(?:", *known_extn_patterns, ")$").c_str()));
 | 
| +  valid_phone_number_pattern.reset(reg_exp::CreateRegularExpression(
 | 
| +      StrCat("(?i)", *valid_phone_number, "(?:", *known_extn_patterns,
 | 
| +             ")?").c_str()));
 | 
| +  valid_alpha_phone_pattern.reset(reg_exp::CreateRegularExpression(
 | 
| +      StrCat("(?i)(?:.*?[", kValidAlpha, "]){3}").c_str()));
 | 
| +  plus_chars_pattern.reset(reg_exp::CreateRegularExpression(
 | 
| +      StrCat("[", kPlusChars, "]+").c_str()));
 | 
| +}
 | 
| +
 | 
| +void InitializeStaticMapsAndSets() {
 | 
| +  // Create global objects.
 | 
| +  all_plus_number_grouping_symbols.reset(new map<char32, char>);
 | 
| +  alpha_mappings.reset(new map<char32, char>);
 | 
| +  all_normalization_mappings.reset(new map<char32, char>);
 | 
| +
 | 
| +  // Punctuation that we wish to respect in alpha numbers, as they show number
 | 
| +  // groupings are mapped here.
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint("-"), '-'));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint("-"), '-'));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint("‐"), '-'));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint("‑"), '-'));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint("‒"), '-'));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint("–"), '-'));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint("—"), '-'));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint("―"), '-'));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint("−"), '-'));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint("/"), '/'));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint("/"), '/'));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint(" "), ' '));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint(" "), ' '));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint(""), ' '));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint("."), '.'));
 | 
| +  all_plus_number_grouping_symbols->insert(
 | 
| +      make_pair(ToUnicodeCodepoint("."), '.'));
 | 
| +  // Only the upper-case letters are added here - the lower-case versions are
 | 
| +  // added programmatically.
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("A"), '2'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("B"), '2'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("C"), '2'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("D"), '3'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("E"), '3'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("F"), '3'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("G"), '4'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("H"), '4'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("I"), '4'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("J"), '5'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("K"), '5'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("L"), '5'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("M"), '6'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("N"), '6'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("O"), '6'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("P"), '7'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("Q"), '7'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("R"), '7'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("S"), '7'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("T"), '8'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("U"), '8'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("V"), '8'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("W"), '9'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("X"), '9'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("Y"), '9'));
 | 
| +  alpha_mappings->insert(make_pair(ToUnicodeCodepoint("Z"), '9'));
 | 
| +  map<char32, char> lower_case_mappings;
 | 
| +  map<char32, char> alpha_letters;
 | 
| +  for (map<char32, char>::const_iterator it = alpha_mappings->begin();
 | 
| +       it != alpha_mappings->end();
 | 
| +       ++it) {
 | 
| +    // Convert all the upper-case ASCII letters to lower-case.
 | 
| +    if (it->first < 128) {
 | 
| +      char letter_as_upper = static_cast<char>(it->first);
 | 
| +      char32 letter_as_lower = static_cast<char32>(tolower(letter_as_upper));
 | 
| +      lower_case_mappings.insert(make_pair(letter_as_lower, it->second));
 | 
| +      // Add the letters in both variants to the alpha_letters map. This just
 | 
| +      // pairs each letter with its upper-case representation so that it can be
 | 
| +      // retained when normalising alpha numbers.
 | 
| +      alpha_letters.insert(make_pair(letter_as_lower, letter_as_upper));
 | 
| +      alpha_letters.insert(make_pair(it->first, letter_as_upper));
 | 
| +    }
 | 
| +  }
 | 
| +  // In the Java version we don't insert the lower-case mappings in the map,
 | 
| +  // because we convert to upper case on the fly. Doing this here would involve
 | 
| +  // pulling in all of ICU, which we don't want to do if we don't have to.
 | 
| +  alpha_mappings->insert(lower_case_mappings.begin(),
 | 
| +                         lower_case_mappings.end());
 | 
| +  all_normalization_mappings->insert(alpha_mappings->begin(),
 | 
| +                                     alpha_mappings->end());
 | 
| +  all_plus_number_grouping_symbols->insert(alpha_letters.begin(),
 | 
| +                                           alpha_letters.end());
 | 
| +  // Add the ASCII digits so that they don't get deleted by NormalizeHelper().
 | 
| +  for (char c = '0'; c <= '9'; ++c) {
 | 
| +    all_normalization_mappings->insert(make_pair(c, c));
 | 
| +    all_plus_number_grouping_symbols->insert(make_pair(c, c));
 | 
| +  }
 | 
| +  CreateRegularExpressions();
 | 
| +}
 | 
| +
 | 
| +// Normalizes a string of characters representing a phone number by replacing
 | 
| +// all characters found in the accompanying map with the values therein, and
 | 
| +// stripping all other characters if remove_non_matches is true.
 | 
| +// Parameters:
 | 
| +// number - a pointer to a string of characters representing a phone number to
 | 
| +//   be normalized.
 | 
| +// normalization_replacements - a mapping of characters to what they should be
 | 
| +//   replaced by in the normalized version of the phone number
 | 
| +// remove_non_matches - indicates whether characters that are not able to be
 | 
| +//   replaced should be stripped from the number. If this is false, they will be
 | 
| +//   left unchanged in the number.
 | 
| +void NormalizeHelper(const map<char32, char>& normalization_replacements,
 | 
| +                     bool remove_non_matches,
 | 
| +                     string* number) {
 | 
| +  DCHECK(number);
 | 
| +  UnicodeText number_as_unicode;
 | 
| +  number_as_unicode.PointToUTF8(number->data(), number->size());
 | 
| +  string normalized_number;
 | 
| +  for (UnicodeText::const_iterator it = number_as_unicode.begin();
 | 
| +       it != number_as_unicode.end();
 | 
| +       ++it) {
 | 
| +    map<char32, char>::const_iterator found_glyph_pair =
 | 
| +        normalization_replacements.find(*it);
 | 
| +    if (found_glyph_pair != normalization_replacements.end()) {
 | 
| +      normalized_number.push_back(found_glyph_pair->second);
 | 
| +    } else if (!remove_non_matches) {
 | 
| +      normalized_number.append(it.utf8_data());
 | 
| +    }
 | 
| +    // If neither of the above are true, we remove this character.
 | 
| +  }
 | 
| +  number->assign(normalized_number);
 | 
| +}
 | 
| +
 | 
| +// Strips the IDD from the start of the number if present. Helper function used
 | 
| +// by MaybeStripInternationalPrefixAndNormalize.
 | 
| +bool ParsePrefixAsIdd(const reg_exp::RegularExpression* idd_pattern,
 | 
| +                      string* number) {
 | 
| +  DCHECK(number);
 | 
| +  scoped_ptr<reg_exp::RegularExpressionInput> number_copy(
 | 
| +      reg_exp::CreateRegularExpressionInput(number->c_str()));
 | 
| +  // First attempt to strip the idd_pattern at the start, if present. We make a
 | 
| +  // copy so that we can revert to the original string if necessary.
 | 
| +  if (idd_pattern->Consume(number_copy.get(), true, NULL, NULL)) {
 | 
| +    // Only strip this if the first digit after the match is not a 0, since
 | 
| +    // country calling codes cannot begin with 0.
 | 
| +    string extracted_digit;
 | 
| +    if (capturing_digit_pattern->Match(number_copy->ToString().c_str(), false,
 | 
| +                                       &extracted_digit)) {
 | 
| +      PhoneNumberUtil::NormalizeDigitsOnly(&extracted_digit);
 | 
| +      if (extracted_digit == "0") {
 | 
| +        return false;
 | 
| +      }
 | 
| +    }
 | 
| +    number->assign(number_copy->ToString());
 | 
| +    return true;
 | 
| +  }
 | 
| +  return false;
 | 
| +}
 | 
| +
 | 
| +PhoneNumberUtil::ValidationResult TestNumberLengthAgainstPattern(
 | 
| +    const reg_exp::RegularExpression* number_pattern, const string& number) {
 | 
| +  string extracted_number;
 | 
| +  if (number_pattern->Match(number.c_str(), true, &extracted_number)) {
 | 
| +    return PhoneNumberUtil::IS_POSSIBLE;
 | 
| +  }
 | 
| +  if (number_pattern->Match(number.c_str(), false, &extracted_number)) {
 | 
| +    return PhoneNumberUtil::TOO_LONG;
 | 
| +  } else {
 | 
| +    return PhoneNumberUtil::TOO_SHORT;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
| +// Fetch the metadata which are actually already available in the address space
 | 
| +// (embedded).
 | 
| +class DefaultMetadataProvider : public PhoneNumberUtil::MetadataProvider {
 | 
| + public:
 | 
| +  virtual ~DefaultMetadataProvider() {}
 | 
| +
 | 
| +  virtual pair<const void*, unsigned> operator()() {
 | 
| +    return make_pair(metadata_get(), metadata_size());
 | 
| +  }
 | 
| +};
 | 
| +
 | 
| +bool PhoneNumberUtil::LoadMetadata(PhoneMetadataCollection* metadata,
 | 
| +    MetadataProvider& provider) {
 | 
| +
 | 
| +  pair<const void*, unsigned> p = provider();
 | 
| +  const void* metadata_start = p.first;
 | 
| +  unsigned size = p.second;
 | 
| +
 | 
| +  if (!metadata->ParseFromArray(metadata_start, size)) {
 | 
| +    cerr << "Could not parse binary data." << endl;
 | 
| +    return false;
 | 
| +  }
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::SetLoggerAdapter(LoggerAdapter* logger_adapter) {
 | 
| +  logger.reset(logger_adapter);
 | 
| +}
 | 
| +
 | 
| +// Private constructor. Also takes care of initialisation.
 | 
| +PhoneNumberUtil::PhoneNumberUtil(MetadataProvider* provider)
 | 
| +    : country_calling_code_to_region_code_map_(new vector<IntRegionsPair>()),
 | 
| +      nanpa_regions_(new set<string>()),
 | 
| +      region_to_metadata_map_(new map<string, PhoneMetadata>()) {
 | 
| +
 | 
| +  if (logger == NULL) {
 | 
| +    SetLoggerAdapter(new DefaultLogger());
 | 
| +  }
 | 
| +  PhoneMetadataCollection metadata_collection;
 | 
| +  DefaultMetadataProvider default_provider;
 | 
| +
 | 
| +  if (!LoadMetadata(&metadata_collection, provider ? *provider
 | 
| +                                                   : default_provider)) {
 | 
| +    logger->Fatal("Could not load metadata");
 | 
| +    return;
 | 
| +  }
 | 
| +  // Storing data in a temporary map to make it easier to find other regions
 | 
| +  // that share a country calling code when inserting data.
 | 
| +  map<int, list<string>* > country_calling_code_to_region_map;
 | 
| +  for (RepeatedPtrField<PhoneMetadata>::const_iterator it =
 | 
| +           metadata_collection.metadata().begin();
 | 
| +       it != metadata_collection.metadata().end();
 | 
| +       ++it) {
 | 
| +    const PhoneMetadata& phone_metadata = *it;
 | 
| +    const string& region_code = phone_metadata.id();
 | 
| +    region_to_metadata_map_->insert(make_pair(region_code, *it));
 | 
| +    int country_calling_code = it->country_code();
 | 
| +    map<int, list<string>*>::iterator calling_code_in_map =
 | 
| +        country_calling_code_to_region_map.find(country_calling_code);
 | 
| +    if (calling_code_in_map != country_calling_code_to_region_map.end()) {
 | 
| +      if (it->main_country_for_code()) {
 | 
| +        calling_code_in_map->second->push_front(region_code);
 | 
| +      } else {
 | 
| +        calling_code_in_map->second->push_back(region_code);
 | 
| +      }
 | 
| +    } else {
 | 
| +      // For most country calling codes, there will be only one region code.
 | 
| +      list<string>* list_with_region_code = new list<string>();
 | 
| +      list_with_region_code->push_back(region_code);
 | 
| +      country_calling_code_to_region_map.insert(
 | 
| +          make_pair(country_calling_code, list_with_region_code));
 | 
| +    }
 | 
| +    if (country_calling_code == kNanpaCountryCode) {
 | 
| +        nanpa_regions_->insert(region_code);
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  country_calling_code_to_region_code_map_->insert(
 | 
| +      country_calling_code_to_region_code_map_->begin(),
 | 
| +      country_calling_code_to_region_map.begin(),
 | 
| +      country_calling_code_to_region_map.end());
 | 
| +  // Sort all the pairs in ascending order according to country calling code.
 | 
| +  sort(country_calling_code_to_region_code_map_->begin(),
 | 
| +       country_calling_code_to_region_code_map_->end(),
 | 
| +       CompareFirst());
 | 
| +
 | 
| +  InitializeStaticMapsAndSets();
 | 
| +}
 | 
| +
 | 
| +PhoneNumberUtil::~PhoneNumberUtil() {
 | 
| +  for (vector<IntRegionsPair>::const_iterator it =
 | 
| +           country_calling_code_to_region_code_map_->begin();
 | 
| +       it != country_calling_code_to_region_code_map_->end();
 | 
| +       ++it) {
 | 
| +    delete it->second;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +// Public wrapper function to get a PhoneNumberUtil instance with the default
 | 
| +// metadata file.
 | 
| +// static
 | 
| +PhoneNumberUtil* PhoneNumberUtil::GetInstance() {
 | 
| +  return Singleton<PhoneNumberUtil>::get();
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::GetSupportedRegions(set<string>* regions) const {
 | 
| +  DCHECK(regions);
 | 
| +  for (map<string, PhoneMetadata>::const_iterator it =
 | 
| +       region_to_metadata_map_->begin(); it != region_to_metadata_map_->end();
 | 
| +       ++it) {
 | 
| +    regions->insert(it->first);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::GetNddPrefixForRegion(const string& region_code,
 | 
| +                                            bool strip_non_digits,
 | 
| +                                            string* national_prefix) const {
 | 
| +  DCHECK(national_prefix);
 | 
| +  if (!IsValidRegionCode(region_code)) {
 | 
| +    logger->Error("Invalid region code provided.");
 | 
| +    return;
 | 
| +  }
 | 
| +  const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
 | 
| +  national_prefix->assign(metadata->national_prefix());
 | 
| +  if (strip_non_digits) {
 | 
| +    // Note: if any other non-numeric symbols are ever used in national
 | 
| +    // prefixes, these would have to be removed here as well.
 | 
| +    strrmm(national_prefix, "~");
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +bool PhoneNumberUtil::IsValidRegionCode(const string& region_code) const {
 | 
| +  return (region_to_metadata_map_->find(region_code) !=
 | 
| +          region_to_metadata_map_->end());
 | 
| +}
 | 
| +
 | 
| +bool PhoneNumberUtil::HasValidRegionCode(const string& region_code,
 | 
| +                                         int country_code,
 | 
| +                                         const string& number) const {
 | 
| +  if (!IsValidRegionCode(region_code)) {
 | 
| +    logger->Info(string("Number ") + number +
 | 
| +            " has invalid or missing country code (" + country_code + ")");
 | 
| +    return false;
 | 
| +  }
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +// Returns a pointer to the phone metadata for the appropriate region.
 | 
| +const PhoneMetadata* PhoneNumberUtil::GetMetadataForRegion(
 | 
| +    const string& region_code) const {
 | 
| +  map<string, PhoneMetadata>::const_iterator it =
 | 
| +      region_to_metadata_map_->find(region_code);
 | 
| +  if (it != region_to_metadata_map_->end()) {
 | 
| +    return &it->second;
 | 
| +  }
 | 
| +  return NULL;
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::Format(const PhoneNumber& number,
 | 
| +                             PhoneNumberFormat number_format,
 | 
| +                             string* formatted_number) const {
 | 
| +  DCHECK(formatted_number);
 | 
| +  int country_calling_code = number.country_code();
 | 
| +  string national_significant_number;
 | 
| +  GetNationalSignificantNumber(number, &national_significant_number);
 | 
| +  if (number_format == E164) {
 | 
| +    // Early exit for E164 case since no formatting of the national number needs
 | 
| +    // to be applied. Extensions are not formatted.
 | 
| +    FormatNumberByFormat(country_calling_code, E164,
 | 
| +                         national_significant_number, "", formatted_number);
 | 
| +    return;
 | 
| +  }
 | 
| +  // Note here that all NANPA formatting rules are contained by US, so we use
 | 
| +  // that to format NANPA numbers. The same applies to Russian Fed regions -
 | 
| +  // rules are contained by Russia. French Indian Ocean country rules are
 | 
| +  // contained by Réunion.
 | 
| +  string region_code;
 | 
| +  GetRegionCodeForCountryCode(country_calling_code, ®ion_code);
 | 
| +  if (!HasValidRegionCode(region_code, country_calling_code,
 | 
| +                          national_significant_number)) {
 | 
| +    formatted_number->assign(national_significant_number);
 | 
| +    return;
 | 
| +  }
 | 
| +  string formatted_extension;
 | 
| +  MaybeGetFormattedExtension(number, region_code, number_format,
 | 
| +                             &formatted_extension);
 | 
| +  string formatted_national_number;
 | 
| +  FormatNationalNumber(national_significant_number, region_code, number_format,
 | 
| +                       &formatted_national_number);
 | 
| +  FormatNumberByFormat(country_calling_code, number_format,
 | 
| +                       formatted_national_number,
 | 
| +                       formatted_extension, formatted_number);
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::FormatByPattern(
 | 
| +    const PhoneNumber& number,
 | 
| +    PhoneNumberFormat number_format,
 | 
| +    const RepeatedPtrField<NumberFormat>& user_defined_formats,
 | 
| +    string* formatted_number) const {
 | 
| +  static scoped_ptr<const reg_exp::RegularExpression>
 | 
| +      national_prefix_pattern(reg_exp::CreateRegularExpression("\\$NP"));
 | 
| +  static scoped_ptr<const reg_exp::RegularExpression>
 | 
| +      first_group_pattern(reg_exp::CreateRegularExpression("\\$FG"));
 | 
| +  DCHECK(formatted_number);
 | 
| +  int country_calling_code = number.country_code();
 | 
| +  // Note GetRegionCodeForCountryCode() is used because formatting information
 | 
| +  // for regions which share a country calling code is contained by only one
 | 
| +  // region for performance reasons. For example, for NANPA regions it will be
 | 
| +  // contained in the metadata for US.
 | 
| +  string region_code;
 | 
| +  GetRegionCodeForCountryCode(country_calling_code, ®ion_code);
 | 
| +  string national_significant_number;
 | 
| +  GetNationalSignificantNumber(number, &national_significant_number);
 | 
| +  if (!HasValidRegionCode(region_code, country_calling_code,
 | 
| +                          national_significant_number)) {
 | 
| +    formatted_number->assign(national_significant_number);
 | 
| +    return;
 | 
| +  }
 | 
| +  RepeatedPtrField<NumberFormat> user_defined_formats_copy;
 | 
| +  for (RepeatedPtrField<NumberFormat>::const_iterator it =
 | 
| +           user_defined_formats.begin();
 | 
| +       it != user_defined_formats.end();
 | 
| +       ++it) {
 | 
| +    string national_prefix_formatting_rule(
 | 
| +        it->national_prefix_formatting_rule());
 | 
| +    if (!national_prefix_formatting_rule.empty()) {
 | 
| +      const string& national_prefix =
 | 
| +          GetMetadataForRegion(region_code)->national_prefix();
 | 
| +      NumberFormat* num_format_copy = user_defined_formats_copy.Add();
 | 
| +      num_format_copy->MergeFrom(*it);
 | 
| +      if (!national_prefix.empty()) {
 | 
| +        // Replace $NP with national prefix and $FG with the first group ($1).
 | 
| +        national_prefix_pattern->Replace(&national_prefix_formatting_rule,
 | 
| +                                         false,
 | 
| +                                         national_prefix.c_str());
 | 
| +        first_group_pattern->Replace(&national_prefix_formatting_rule,
 | 
| +                                     false,
 | 
| +                                     "$1");
 | 
| +        num_format_copy->set_national_prefix_formatting_rule(
 | 
| +            national_prefix_formatting_rule);
 | 
| +      } else {
 | 
| +        // We don't want to have a rule for how to format the national prefix if
 | 
| +        // there isn't one.
 | 
| +        num_format_copy->clear_national_prefix_formatting_rule();
 | 
| +      }
 | 
| +    } else {
 | 
| +      user_defined_formats_copy.Add()->MergeFrom(*it);
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  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, region_code, NATIONAL,
 | 
| +                             &formatted_extension);
 | 
| +  FormatNumberByFormat(country_calling_code, number_format,
 | 
| +                       formatted_number_without_extension, formatted_extension,
 | 
| +                       formatted_number);
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::FormatNationalNumberWithCarrierCode(
 | 
| +    const PhoneNumber& number,
 | 
| +    const string& carrier_code,
 | 
| +    string* formatted_number) const {
 | 
| +  int country_calling_code = number.country_code();
 | 
| +  string national_significant_number;
 | 
| +  GetNationalSignificantNumber(number, &national_significant_number);
 | 
| +  // Note GetRegionCodeForCountryCode() is used because formatting information
 | 
| +  // for regions which share a country calling code is contained by only one
 | 
| +  // region for performance reasons. For example, for NANPA regions it will be
 | 
| +  // contained in the metadata for US.
 | 
| +  string region_code;
 | 
| +  GetRegionCodeForCountryCode(country_calling_code, ®ion_code);
 | 
| +  if (!HasValidRegionCode(region_code, country_calling_code,
 | 
| +                          national_significant_number)) {
 | 
| +    formatted_number->assign(national_significant_number);
 | 
| +  }
 | 
| +  string formatted_extension;
 | 
| +  MaybeGetFormattedExtension(number, region_code, NATIONAL,
 | 
| +                             &formatted_extension);
 | 
| +  string formatted_national_number;
 | 
| +  FormatNationalNumberWithCarrier(national_significant_number, region_code,
 | 
| +                                  NATIONAL, carrier_code,
 | 
| +                                  &formatted_national_number);
 | 
| +  FormatNumberByFormat(country_calling_code, NATIONAL,
 | 
| +                       formatted_national_number, formatted_extension,
 | 
| +                       formatted_number);
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::FormatNationalNumberWithPreferredCarrierCode(
 | 
| +    const PhoneNumber& number,
 | 
| +    const string& fallback_carrier_code,
 | 
| +    string* formatted_number) const {
 | 
| +  FormatNationalNumberWithCarrierCode(
 | 
| +      number,
 | 
| +      number.has_preferred_domestic_carrier_code()
 | 
| +          ? number.preferred_domestic_carrier_code()
 | 
| +          : fallback_carrier_code,
 | 
| +      formatted_number);
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::FormatOutOfCountryCallingNumber(
 | 
| +    const PhoneNumber& number,
 | 
| +    const string& calling_from,
 | 
| +    string* formatted_number) const {
 | 
| +  DCHECK(formatted_number);
 | 
| +  if (!IsValidRegionCode(calling_from)) {
 | 
| +    logger->Info("Trying to format number from invalid region. International"
 | 
| +        " formatting applied.");
 | 
| +    Format(number, INTERNATIONAL, formatted_number);
 | 
| +    return;
 | 
| +  }
 | 
| +  int country_code = number.country_code();
 | 
| +  string region_code;
 | 
| +  GetRegionCodeForCountryCode(country_code, ®ion_code);
 | 
| +  string national_significant_number;
 | 
| +  GetNationalSignificantNumber(number, &national_significant_number);
 | 
| +  if (!HasValidRegionCode(region_code, country_code,
 | 
| +                          national_significant_number)) {
 | 
| +    formatted_number->assign(national_significant_number);
 | 
| +    return;
 | 
| +  }
 | 
| +  if (country_code == kNanpaCountryCode) {
 | 
| +    if (IsNANPACountry(calling_from)) {
 | 
| +      // For NANPA regions, return the national format for these regions but
 | 
| +      // prefix it with the country calling code.
 | 
| +      string national_number;
 | 
| +      Format(number, NATIONAL, &national_number);
 | 
| +      formatted_number->assign(StrCat(country_code, " ", national_number));
 | 
| +      return;
 | 
| +    }
 | 
| +  } else if (country_code == GetCountryCodeForRegion(calling_from)) {
 | 
| +    // 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
 | 
| +    // region we are calling from are the same.
 | 
| +    // For regions that share a country calling code, the country calling code
 | 
| +    // need not be dialled. This also applies when dialling within a region, so
 | 
| +    // this if clause covers both these cases.
 | 
| +    // Technically this is the case for dialling from la Réunion to other
 | 
| +    // overseas departments of France (French Guiana, Martinique, Guadeloupe),
 | 
| +    // but not vice versa - so we don't cover this edge case for now and for
 | 
| +    // those cases return the version including country calling code.
 | 
| +    // Details here:
 | 
| +    // http://www.petitfute.com/voyage/225-info-pratiques-reunion
 | 
| +    Format(number, NATIONAL, formatted_number);
 | 
| +    return;
 | 
| +  }
 | 
| +  string formatted_national_number;
 | 
| +  FormatNationalNumber(national_significant_number, region_code, INTERNATIONAL,
 | 
| +                       &formatted_national_number);
 | 
| +  const PhoneMetadata* metadata = GetMetadataForRegion(calling_from);
 | 
| +  const string& international_prefix = metadata->international_prefix();
 | 
| +  string formatted_extension;
 | 
| +  MaybeGetFormattedExtension(number, region_code, INTERNATIONAL,
 | 
| +                             &formatted_extension);
 | 
| +  // For regions that have multiple international prefixes, the international
 | 
| +  // format of the number is returned, unless there is a preferred international
 | 
| +  // prefix.
 | 
| +  string international_prefix_for_formatting(
 | 
| +      unique_international_prefix->Match(international_prefix.c_str(),
 | 
| +                                         true, NULL)
 | 
| +      ? international_prefix
 | 
| +      : metadata->preferred_international_prefix());
 | 
| +  if (!international_prefix_for_formatting.empty()) {
 | 
| +    formatted_number->assign(
 | 
| +        StrCat(international_prefix_for_formatting, " ", country_code, " ",
 | 
| +               formatted_national_number, formatted_extension));
 | 
| +  } else {
 | 
| +    FormatNumberByFormat(country_code, INTERNATIONAL, formatted_national_number,
 | 
| +                         formatted_extension, formatted_number);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::FormatInOriginalFormat(const PhoneNumber& number,
 | 
| +                                             const string& region_calling_from,
 | 
| +                                             string* formatted_number) const {
 | 
| +  DCHECK(formatted_number);
 | 
| +
 | 
| +  if (!number.has_country_code_source()) {
 | 
| +    Format(number, NATIONAL, formatted_number);
 | 
| +    return;
 | 
| +  }
 | 
| +  switch (number.country_code_source()) {
 | 
| +    case PhoneNumber::FROM_NUMBER_WITH_PLUS_SIGN:
 | 
| +      Format(number, INTERNATIONAL, formatted_number);
 | 
| +      return;
 | 
| +    case PhoneNumber::FROM_NUMBER_WITH_IDD:
 | 
| +      FormatOutOfCountryCallingNumber(number, region_calling_from,
 | 
| +                                      formatted_number);
 | 
| +      return;
 | 
| +    case PhoneNumber::FROM_NUMBER_WITHOUT_PLUS_SIGN:
 | 
| +      Format(number, INTERNATIONAL, formatted_number);
 | 
| +      formatted_number->erase(formatted_number->begin());
 | 
| +      return;
 | 
| +    case PhoneNumber::FROM_DEFAULT_COUNTRY:
 | 
| +    default:
 | 
| +      Format(number, NATIONAL, formatted_number);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::FormatOutOfCountryKeepingAlphaChars(
 | 
| +    const PhoneNumber& number,
 | 
| +    const string& calling_from,
 | 
| +    string* formatted_number) const {
 | 
| +  // If there is no raw input, then we can't keep alpha characters because there
 | 
| +  // aren't any. In this case, we return FormatOutOfCountryCallingNumber.
 | 
| +  if (number.raw_input().empty()) {
 | 
| +    FormatOutOfCountryCallingNumber(number, calling_from, formatted_number);
 | 
| +    return;
 | 
| +  }
 | 
| +  string region_code;
 | 
| +  GetRegionCodeForCountryCode(number.country_code(), ®ion_code);
 | 
| +  if (!HasValidRegionCode(region_code, number.country_code(),
 | 
| +                          number.raw_input())) {
 | 
| +    formatted_number->assign(number.raw_input());
 | 
| +    return;
 | 
| +  }
 | 
| +  // Strip any prefix such as country calling code, IDD, that was present. We do
 | 
| +  // this by comparing the number in raw_input with the parsed number.
 | 
| +  string raw_input_copy(number.raw_input());
 | 
| +  // Normalize punctuation. We retain number grouping symbols such as " " only.
 | 
| +  NormalizeHelper(*all_plus_number_grouping_symbols, true, &raw_input_copy);
 | 
| +  // Now we trim everything before the first three digits in the parsed number.
 | 
| +  // We choose three because all valid alpha numbers have 3 digits at the start
 | 
| +  // - if it does not, then we don't trim anything at all. Similarly, if the
 | 
| +  // national number was less than three digits, we don't trim anything at all.
 | 
| +  string national_number;
 | 
| +  GetNationalSignificantNumber(number, &national_number);
 | 
| +  if (national_number.length() > 3) {
 | 
| +    size_t first_national_number_digit =
 | 
| +        raw_input_copy.find(national_number.substr(0, 3));
 | 
| +    if (first_national_number_digit != string::npos) {
 | 
| +      raw_input_copy = raw_input_copy.substr(first_national_number_digit);
 | 
| +    }
 | 
| +  }
 | 
| +  const PhoneMetadata* metadata = GetMetadataForRegion(calling_from);
 | 
| +  if (number.country_code() == kNanpaCountryCode) {
 | 
| +    if (IsNANPACountry(calling_from)) {
 | 
| +      formatted_number->assign(StrCat(number.country_code(), " ",
 | 
| +                                      raw_input_copy));
 | 
| +      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");
 | 
| +    }
 | 
| +    // 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.
 | 
| +    // 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
 | 
| +    // we have overridden the pattern to match anything, but that is not the
 | 
| +    // case in the metadata to date.
 | 
| +    FormatAccordingToFormats(national_number, available_formats,
 | 
| +                             NATIONAL, raw_input_copy, formatted_number);
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  const string& international_prefix = metadata->international_prefix();
 | 
| +  // For regions that have multiple international prefixes, the international
 | 
| +  // format of the number is returned, unless there is a preferred international
 | 
| +  // prefix.
 | 
| +  string international_prefix_for_formatting(
 | 
| +      unique_international_prefix->Match(international_prefix.c_str(),
 | 
| +                                         true, NULL)
 | 
| +      ? international_prefix
 | 
| +      : metadata->preferred_international_prefix());
 | 
| +  if (!international_prefix_for_formatting.empty()) {
 | 
| +    formatted_number->assign(
 | 
| +        StrCat(international_prefix_for_formatting, " ", number.country_code(),
 | 
| +               " ", raw_input_copy));
 | 
| +  } else {
 | 
| +    FormatNumberByFormat(number.country_code(), INTERNATIONAL, raw_input_copy,
 | 
| +                         "", formatted_number);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::FormatNationalNumber(
 | 
| +    const string& number,
 | 
| +    const string& region_code,
 | 
| +    PhoneNumberFormat number_format,
 | 
| +    string* formatted_number) const {
 | 
| +  DCHECK(formatted_number);
 | 
| +  FormatNationalNumberWithCarrier(number, region_code, number_format, "",
 | 
| +                                  formatted_number);
 | 
| +}
 | 
| +
 | 
| +// Note in some regions, the national number can be written in two completely
 | 
| +// different ways depending on whether it forms part of the NATIONAL format or
 | 
| +// 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
 | 
| +// will be inserted into the formatted string to replace $CC.
 | 
| +void PhoneNumberUtil::FormatNationalNumberWithCarrier(
 | 
| +    const string& number,
 | 
| +    const string& region_code,
 | 
| +    PhoneNumberFormat number_format,
 | 
| +    const string& carrier_code,
 | 
| +    string* formatted_number) const {
 | 
| +  DCHECK(formatted_number);
 | 
| +  const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
 | 
| +  // When the intl_number_formats exists, we use that to format national number
 | 
| +  // for the INTERNATIONAL format instead of using the number_formats.
 | 
| +  const RepeatedPtrField<NumberFormat> available_formats =
 | 
| +      (metadata->intl_number_format_size() == 0 || number_format == NATIONAL)
 | 
| +      ? metadata->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 "-".
 | 
| +    scoped_ptr<const reg_exp::RegularExpression> separator_pattern(
 | 
| +        reg_exp::CreateRegularExpression(
 | 
| +            StrCat("[", kValidPunctuation, "]+").c_str()));
 | 
| +    separator_pattern->Replace(formatted_number, true, "-");
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +// 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(
 | 
| +    const PhoneNumber& number,
 | 
| +    const string& region_code,
 | 
| +    PhoneNumberFormat number_format,
 | 
| +    string* extension) const {
 | 
| +  DCHECK(extension);
 | 
| +  if (!number.has_extension() || number.extension().length() == 0) {
 | 
| +    extension->assign("");
 | 
| +  } else {
 | 
| +    if (number_format == RFC3966) {
 | 
| +      StrAppend(extension, kRfc3966ExtnPrefix, number.extension());
 | 
| +      return;
 | 
| +    }
 | 
| +    FormatExtension(number.extension(), region_code, 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 string& region_code,
 | 
| +                                      string* extension) const {
 | 
| +  DCHECK(extension);
 | 
| +  const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
 | 
| +  if (metadata->has_preferred_extn_prefix()) {
 | 
| +    extension->assign(StrCat(metadata->preferred_extn_prefix(),
 | 
| +                             extension_digits));
 | 
| +  } else {
 | 
| +    extension->assign(StrCat(kDefaultExtnPrefix, extension_digits));
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +bool PhoneNumberUtil::IsNANPACountry(const string& region_code) const {
 | 
| +  return nanpa_regions_->find(region_code) != nanpa_regions_->end();
 | 
| +}
 | 
| +
 | 
| +// Returns the region codes that matches the specific country calling code. In
 | 
| +// the case of no region code being found, region_codes will be left empty.
 | 
| +void PhoneNumberUtil::GetRegionCodesForCountryCallingCode(
 | 
| +    int country_calling_code,
 | 
| +    list<string>* region_codes) const {
 | 
| +  DCHECK(region_codes);
 | 
| +  // Create a IntRegionsPair with the country_code passed in, and use it to
 | 
| +  // locate the pair with the same country_code in the sorted vector.
 | 
| +  IntRegionsPair target_pair;
 | 
| +  target_pair.first = country_calling_code;
 | 
| +  typedef vector<IntRegionsPair>::const_iterator ConstIterator;
 | 
| +  pair<ConstIterator, ConstIterator> range = equal_range(
 | 
| +      country_calling_code_to_region_code_map_->begin(),
 | 
| +      country_calling_code_to_region_code_map_->end(),
 | 
| +      target_pair, CompareFirst());
 | 
| +  if (range.first != range.second) {
 | 
| +    region_codes->insert(region_codes->begin(),
 | 
| +                         range.first->second->begin(),
 | 
| +                         range.first->second->end());
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +// Returns the region code that matches the specific country calling code. In
 | 
| +// the case of no region code being found, ZZ will be returned.
 | 
| +void PhoneNumberUtil::GetRegionCodeForCountryCode(
 | 
| +    int country_calling_code,
 | 
| +    string* region_code) const {
 | 
| +  DCHECK(region_code);
 | 
| +  list<string> region_codes;
 | 
| +
 | 
| +  GetRegionCodesForCountryCallingCode(country_calling_code, ®ion_codes);
 | 
| +  *region_code = region_codes.size() != 0 ? region_codes.front() : "ZZ";
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::GetRegionCodeForNumber(const PhoneNumber& number,
 | 
| +                                             string* region_code) const {
 | 
| +  DCHECK(region_code);
 | 
| +  int country_calling_code = number.country_code();
 | 
| +  list<string> region_codes;
 | 
| +  GetRegionCodesForCountryCallingCode(country_calling_code, ®ion_codes);
 | 
| +  if (region_codes.size() == 0) {
 | 
| +    string number_string;
 | 
| +    GetNationalSignificantNumber(number, &number_string);
 | 
| +    logger->Warning(string("Missing/invalid country code (") +
 | 
| +        SimpleItoa(country_calling_code) + ") for number " + number_string);
 | 
| +    *region_code = "ZZ";
 | 
| +    return;
 | 
| +  }
 | 
| +  if (region_codes.size() == 1) {
 | 
| +    *region_code = region_codes.front();
 | 
| +  } else {
 | 
| +    GetRegionCodeForNumberFromRegionList(number, region_codes, region_code);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::GetRegionCodeForNumberFromRegionList(
 | 
| +    const PhoneNumber& number, const list<string>& region_codes,
 | 
| +    string* region_code) const {
 | 
| +  DCHECK(region_code);
 | 
| +  string national_number;
 | 
| +  GetNationalSignificantNumber(number, &national_number);
 | 
| +  for (list<string>::const_iterator it = region_codes.begin();
 | 
| +       it != region_codes.end(); ++it) {
 | 
| +    const PhoneMetadata* metadata = GetMetadataForRegion(*it);
 | 
| +    if (metadata->has_leading_digits()) {
 | 
| +      scoped_ptr<reg_exp::RegularExpressionInput> number(
 | 
| +          reg_exp::CreateRegularExpressionInput(national_number.c_str()));
 | 
| +      if (number->ConsumeRegExp(metadata->leading_digits(), true, NULL, NULL)) {
 | 
| +        *region_code = *it;
 | 
| +        return;
 | 
| +      }
 | 
| +    } else if (GetNumberTypeHelper(national_number, *metadata) != UNKNOWN) {
 | 
| +      *region_code = *it;
 | 
| +      return;
 | 
| +    }
 | 
| +  }
 | 
| +  *region_code = "ZZ";
 | 
| +}
 | 
| +
 | 
| +int PhoneNumberUtil::GetCountryCodeForRegion(const string& region_code) const {
 | 
| +  if (!IsValidRegionCode(region_code)) {
 | 
| +    logger->Info("Invalid or unknown country code provided.");
 | 
| +    return 0;
 | 
| +  }
 | 
| +  const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
 | 
| +  if (!metadata) {
 | 
| +    logger->Error("Unsupported country code provided.");
 | 
| +    return 0;
 | 
| +  }
 | 
| +  return metadata->country_code();
 | 
| +}
 | 
| +
 | 
| +// Gets a valid fixed-line number for the specified region_code. Returns false
 | 
| +// if the country was unknown or if no number exists.
 | 
| +bool PhoneNumberUtil::GetExampleNumber(const string& region_code,
 | 
| +                                       PhoneNumber* number) const {
 | 
| +  DCHECK(number);
 | 
| +  return GetExampleNumberForType(region_code,
 | 
| +                                 FIXED_LINE,
 | 
| +                                 number);
 | 
| +}
 | 
| +
 | 
| +// Gets a valid number for the specified region_code and type.  Returns false if
 | 
| +// the country was unknown or if no number exists.
 | 
| +bool PhoneNumberUtil::GetExampleNumberForType(
 | 
| +    const string& region_code,
 | 
| +    PhoneNumberUtil::PhoneNumberType type,
 | 
| +    PhoneNumber* number) const {
 | 
| +  DCHECK(number);
 | 
| +  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);
 | 
| +  }
 | 
| +  return false;
 | 
| +}
 | 
| +
 | 
| +PhoneNumberUtil::ErrorType PhoneNumberUtil::Parse(const string& number_to_parse,
 | 
| +                                                  const string& default_region,
 | 
| +                                                  PhoneNumber* number) const {
 | 
| +  DCHECK(number);
 | 
| +  return ParseHelper(number_to_parse, default_region, false, true, number);
 | 
| +}
 | 
| +
 | 
| +PhoneNumberUtil::ErrorType PhoneNumberUtil::ParseAndKeepRawInput(
 | 
| +    const string& number_to_parse,
 | 
| +    const string& default_region,
 | 
| +    PhoneNumber* number) const {
 | 
| +  DCHECK(number);
 | 
| +  return ParseHelper(number_to_parse, default_region, true, true, number);
 | 
| +}
 | 
| +
 | 
| +// Checks to see that the region code used is valid, or if it is not valid, that
 | 
| +// the number to parse starts with a + symbol so that we can attempt to infer
 | 
| +// the country from the number. Returns false if it cannot use the region
 | 
| +// provided and the region cannot be inferred.
 | 
| +bool PhoneNumberUtil::CheckRegionForParsing(
 | 
| +    const string& number_to_parse,
 | 
| +    const string& default_region) const {
 | 
| +  if (!IsValidRegionCode(default_region) && !number_to_parse.empty()) {
 | 
| +    scoped_ptr<reg_exp::RegularExpressionInput> number_as_string_piece(
 | 
| +        reg_exp::CreateRegularExpressionInput(number_to_parse.c_str()));
 | 
| +    if (!plus_chars_pattern->Consume(number_as_string_piece.get(),
 | 
| +                                     true, NULL, NULL)) {
 | 
| +      return false;
 | 
| +    }
 | 
| +  }
 | 
| +  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);
 | 
| +  // Extract a possible number from the string passed in (this strips leading
 | 
| +  // characters that could not be the start of a phone number.)
 | 
| +  string national_number;
 | 
| +  ExtractPossibleNumber(number_to_parse, &national_number);
 | 
| +  if (!IsViablePhoneNumber(national_number)) {
 | 
| +    logger->Debug("The string supplied did not seem to be a phone number.");
 | 
| +    return NOT_A_NUMBER;
 | 
| +  }
 | 
| +
 | 
| +  if (check_region &&
 | 
| +      !CheckRegionForParsing(national_number, default_region)) {
 | 
| +    logger->Info("Missing or invalid default country.");
 | 
| +    return INVALID_COUNTRY_CODE_ERROR;
 | 
| +  }
 | 
| +  PhoneNumber temp_number;
 | 
| +  if (keep_raw_input) {
 | 
| +    temp_number.set_raw_input(number_to_parse);
 | 
| +  }
 | 
| +  // Attempt to parse extension first, since it doesn't require country-specific
 | 
| +  // data and we want to have the non-normalised number here.
 | 
| +  string extension;
 | 
| +  MaybeStripExtension(&national_number, &extension);
 | 
| +  if (!extension.empty()) {
 | 
| +    temp_number.set_extension(extension);
 | 
| +  }
 | 
| +  const PhoneMetadata* country_metadata = GetMetadataForRegion(default_region);
 | 
| +  // Check to see if the number is given in international format so we know
 | 
| +  // whether this number is from the default country or not.
 | 
| +  string normalized_national_number(national_number);
 | 
| +  ErrorType country_code_error =
 | 
| +      MaybeExtractCountryCode(country_metadata, keep_raw_input,
 | 
| +                              &normalized_national_number, &temp_number);
 | 
| +  int country_code = temp_number.country_code();
 | 
| +  if (country_code_error != NO_PARSING_ERROR) {
 | 
| +    return country_code_error;
 | 
| +  }
 | 
| +  if (country_code != 0) {
 | 
| +    string phone_number_region;
 | 
| +    GetRegionCodeForCountryCode(country_code, &phone_number_region);
 | 
| +    if (phone_number_region != default_region) {
 | 
| +      country_metadata = GetMetadataForRegion(phone_number_region);
 | 
| +    }
 | 
| +  } else if (country_metadata) {
 | 
| +    // If no extracted country calling code, use the region supplied instead.
 | 
| +    // Note that the national number was already normalized by
 | 
| +    // MaybeExtractCountryCode.
 | 
| +    country_code = country_metadata->country_code();
 | 
| +  }
 | 
| +  if (normalized_national_number.length() < kMinLengthForNsn) {
 | 
| +    logger->Debug("The string supplied is too short to be a phone number.");
 | 
| +    return TOO_SHORT_NSN;
 | 
| +  }
 | 
| +  if (country_metadata) {
 | 
| +    string* carrier_code = keep_raw_input ?
 | 
| +        temp_number.mutable_preferred_domestic_carrier_code() : NULL;
 | 
| +    MaybeStripNationalPrefixAndCarrierCode(*country_metadata,
 | 
| +                                           &normalized_national_number,
 | 
| +                                           carrier_code);
 | 
| +  }
 | 
| +  size_t normalized_national_number_length =
 | 
| +      normalized_national_number.length();
 | 
| +  if (normalized_national_number_length < kMinLengthForNsn) {
 | 
| +    logger->Debug("The string supplied is too short to be a phone number.");
 | 
| +    return TOO_SHORT_NSN;
 | 
| +  }
 | 
| +  if (normalized_national_number_length > kMaxLengthForNsn) {
 | 
| +    logger->Debug("The string supplied is too long to be a phone number.");
 | 
| +    return TOO_LONG_NSN;
 | 
| +  }
 | 
| +  temp_number.set_country_code(country_code);
 | 
| +  if (country_metadata &&
 | 
| +      country_metadata->leading_zero_possible() &&
 | 
| +      normalized_national_number[0] == '0') {
 | 
| +    temp_number.set_italian_leading_zero(true);
 | 
| +  }
 | 
| +  uint64 number_as_int;
 | 
| +  safe_strtou64(normalized_national_number, &number_as_int);
 | 
| +  temp_number.set_national_number(number_as_int);
 | 
| +  phone_number->MergeFrom(temp_number);
 | 
| +  return NO_PARSING_ERROR;
 | 
| +}
 | 
| +
 | 
| +// Attempts to extract a possible number from the string passed in. This
 | 
| +// currently strips all leading characters that could not be used to start a
 | 
| +// phone number. Characters that can be used to start a phone number are
 | 
| +// defined in the valid_start_char_pattern. If none of these characters are
 | 
| +// found in the number passed in, an empty string is returned. This function
 | 
| +// also attempts to strip off any alternative extensions or endings if two or
 | 
| +// more are present, such as in the case of: (530) 583-6985 x302/x2303. The
 | 
| +// second extension here makes this actually two phone numbers, (530) 583-6985
 | 
| +// x302 and (530) 583-6985 x2303. We remove the second extension so that the
 | 
| +// first number is parsed correctly.
 | 
| +// static
 | 
| +void PhoneNumberUtil::ExtractPossibleNumber(const string& number,
 | 
| +                                            string* extracted_number) {
 | 
| +  DCHECK(extracted_number);
 | 
| +
 | 
| +  UnicodeText number_as_unicode;
 | 
| +  number_as_unicode.PointToUTF8(number.data(), number.size());
 | 
| +  char current_char[5];
 | 
| +  int len;
 | 
| +  UnicodeText::const_iterator it;
 | 
| +  for (it = number_as_unicode.begin(); it != number_as_unicode.end(); ++it) {
 | 
| +    len = it.get_utf8(current_char);
 | 
| +    current_char[len] = '\0';
 | 
| +    if (valid_start_char_pattern->Match(current_char, true, NULL)) {
 | 
| +      break;
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  if (it == number_as_unicode.end()) {
 | 
| +    // No valid start character was found. extracted_number should be set to
 | 
| +    // empty string.
 | 
| +    extracted_number->assign("");
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  UnicodeText::const_reverse_iterator reverse_it(number_as_unicode.end());
 | 
| +  for (; reverse_it.base() != it; ++reverse_it) {
 | 
| +    len = reverse_it.get_utf8(current_char);
 | 
| +    current_char[len] = '\0';
 | 
| +    if (!unwanted_end_char_pattern->Match(current_char, true, NULL)) {
 | 
| +      break;
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
| +  if (reverse_it.base() == it) {
 | 
| +    extracted_number->assign("");
 | 
| +    return;
 | 
| +  }
 | 
| +
 | 
| +  extracted_number->assign(UnicodeText::UTF8Substring(it, reverse_it.base()));
 | 
| +
 | 
| +  logger->Debug("After stripping starting and trailing characters,"
 | 
| +      " left with: " + *extracted_number);
 | 
| +
 | 
| +  // Now remove any extra numbers at the end.
 | 
| +  capture_up_to_second_number_start_pattern->Match(extracted_number->c_str(),
 | 
| +                                                   false,
 | 
| +                                                   extracted_number);
 | 
| +}
 | 
| +
 | 
| +bool PhoneNumberUtil::IsPossibleNumber(const PhoneNumber& number) const {
 | 
| +  return IsPossibleNumberWithReason(number) == IS_POSSIBLE;
 | 
| +}
 | 
| +
 | 
| +bool PhoneNumberUtil::IsPossibleNumberForString(
 | 
| +    const string& number,
 | 
| +    const string& region_dialing_from) const {
 | 
| +  PhoneNumber number_proto;
 | 
| +  if (Parse(number, region_dialing_from, &number_proto) == NO_PARSING_ERROR) {
 | 
| +    return IsPossibleNumber(number_proto);
 | 
| +  } else {
 | 
| +    return false;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +PhoneNumberUtil::ValidationResult PhoneNumberUtil::IsPossibleNumberWithReason(
 | 
| +    const PhoneNumber& number) const {
 | 
| +  string national_number;
 | 
| +  GetNationalSignificantNumber(number, &national_number);
 | 
| +  int country_code = number.country_code();
 | 
| +  // Note: For Russian Fed and NANPA numbers, we just use the rules from the
 | 
| +  // default region (US or Russia) since the GetRegionCodeForNumber will not
 | 
| +  // work if the number is possible but not valid. This would need to be
 | 
| +  // revisited if the possible number pattern ever differed between various
 | 
| +  // regions within those plans.
 | 
| +  string region_code;
 | 
| +  GetRegionCodeForCountryCode(country_code, ®ion_code);
 | 
| +  if (!HasValidRegionCode(region_code, country_code, national_number)) {
 | 
| +    return INVALID_COUNTRY_CODE;
 | 
| +  }
 | 
| +  const PhoneNumberDesc& general_num_desc =
 | 
| +      GetMetadataForRegion(region_code)->general_desc();
 | 
| +  // Handling case of numbers with no metadata.
 | 
| +  if (!general_num_desc.has_national_number_pattern()) {
 | 
| +    size_t number_length = national_number.length();
 | 
| +    if (number_length < kMinLengthForNsn) {
 | 
| +      return TOO_SHORT;
 | 
| +    } else if (number_length > kMaxLengthForNsn) {
 | 
| +      return TOO_LONG;
 | 
| +    } else {
 | 
| +      return IS_POSSIBLE;
 | 
| +    }
 | 
| +  }
 | 
| +  scoped_ptr<reg_exp::RegularExpression> possible_number_pattern(
 | 
| +      reg_exp::CreateRegularExpression(
 | 
| +      StrCat("(", general_num_desc.possible_number_pattern(), ")").c_str()));
 | 
| +  return TestNumberLengthAgainstPattern(possible_number_pattern.get(),
 | 
| +                                        national_number);
 | 
| +}
 | 
| +
 | 
| +bool PhoneNumberUtil::TruncateTooLongNumber(PhoneNumber* number) const {
 | 
| +  if (IsValidNumber(*number)) {
 | 
| +    return true;
 | 
| +  }
 | 
| +  PhoneNumber number_copy(*number);
 | 
| +  uint64 national_number = number->national_number();
 | 
| +  do {
 | 
| +    national_number /= 10;
 | 
| +    number_copy.set_national_number(national_number);
 | 
| +    if (IsPossibleNumberWithReason(number_copy) == TOO_SHORT ||
 | 
| +        national_number == 0) {
 | 
| +      return false;
 | 
| +    }
 | 
| +  } while (!IsValidNumber(number_copy));
 | 
| +  number->set_national_number(national_number);
 | 
| +  return true;
 | 
| +}
 | 
| +
 | 
| +PhoneNumberUtil::PhoneNumberType PhoneNumberUtil::GetNumberType(
 | 
| +    const PhoneNumber& number) const {
 | 
| +  string region_code;
 | 
| +  GetRegionCodeForNumber(number, ®ion_code);
 | 
| +  if (!IsValidRegionCode(region_code)) {
 | 
| +    return UNKNOWN;
 | 
| +  }
 | 
| +  string national_significant_number;
 | 
| +  GetNationalSignificantNumber(number, &national_significant_number);
 | 
| +  return GetNumberTypeHelper(national_significant_number,
 | 
| +                             *GetMetadataForRegion(region_code));
 | 
| +}
 | 
| +
 | 
| +bool PhoneNumberUtil::IsValidNumber(const PhoneNumber& number) const {
 | 
| +  string region_code;
 | 
| +  GetRegionCodeForNumber(number, ®ion_code);
 | 
| +  return IsValidRegionCode(region_code) &&
 | 
| +      IsValidNumberForRegion(number, region_code);
 | 
| +}
 | 
| +
 | 
| +bool PhoneNumberUtil::IsValidNumberForRegion(const PhoneNumber& number,
 | 
| +                                             const string& region_code) const {
 | 
| +  if (number.country_code() != GetCountryCodeForRegion(region_code)) {
 | 
| +    return false;
 | 
| +  }
 | 
| +  const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
 | 
| +  const PhoneNumberDesc& general_desc = metadata->general_desc();
 | 
| +  string national_number;
 | 
| +  GetNationalSignificantNumber(number, &national_number);
 | 
| +
 | 
| +  // For regions where we don't have metadata for PhoneNumberDesc, we treat
 | 
| +  // any number passed in as a valid number if its national significant number
 | 
| +  // is between the minimum and maximum lengths defined by ITU for a national
 | 
| +  // significant number.
 | 
| +  if (!general_desc.has_national_number_pattern()) {
 | 
| +    logger->Info("Validating number with incomplete metadata.");
 | 
| +    size_t number_length = national_number.length();
 | 
| +    return number_length > kMinLengthForNsn &&
 | 
| +        number_length <= kMaxLengthForNsn;
 | 
| +  }
 | 
| +  return GetNumberTypeHelper(national_number, *metadata) != UNKNOWN;
 | 
| +}
 | 
| +
 | 
| +bool PhoneNumberUtil::IsLeadingZeroPossible(int country_calling_code) const {
 | 
| +  string region_code;
 | 
| +  GetRegionCodeForCountryCode(country_calling_code, ®ion_code);
 | 
| +  const PhoneMetadata* main_metadata_for_calling_code =
 | 
| +      GetMetadataForRegion(region_code);
 | 
| +  if (!main_metadata_for_calling_code) return false;
 | 
| +  return main_metadata_for_calling_code->leading_zero_possible();
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::GetNationalSignificantNumber(
 | 
| +    const PhoneNumber& number,
 | 
| +    string* national_number) const {
 | 
| +  // The leading zero in the national (significant) number of an Italian phone
 | 
| +  // number has a special meaning. Unlike the rest of the world, it indicates
 | 
| +  // the number is a landline number. There have been plans to migrate landline
 | 
| +  // numbers to start with the digit two since December 2000, but it has not yet
 | 
| +  // happened.
 | 
| +  // See http://en.wikipedia.org/wiki/%2B39 for more details.
 | 
| +  // Other regions such as Cote d'Ivoire and Gabon use this for their mobile
 | 
| +  // numbers.
 | 
| +  DCHECK(national_number);
 | 
| +  StrAppend(national_number,
 | 
| +      (IsLeadingZeroPossible(number.country_code()) &&
 | 
| +       number.has_italian_leading_zero() &&
 | 
| +       number.italian_leading_zero())
 | 
| +      ? "0"
 | 
| +      : "");
 | 
| +  StrAppend(national_number, number.national_number());
 | 
| +}
 | 
| +
 | 
| +int PhoneNumberUtil::GetLengthOfGeographicalAreaCode(
 | 
| +    const PhoneNumber& number) const {
 | 
| +  string region_code;
 | 
| +  GetRegionCodeForNumber(number, ®ion_code);
 | 
| +  if (!IsValidRegionCode(region_code)) {
 | 
| +    return 0;
 | 
| +  }
 | 
| +  const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
 | 
| +  DCHECK(metadata);
 | 
| +  if (!metadata->has_national_prefix()) {
 | 
| +    return 0;
 | 
| +  }
 | 
| +
 | 
| +  string national_significant_number;
 | 
| +  GetNationalSignificantNumber(number, &national_significant_number);
 | 
| +  PhoneNumberType type = GetNumberTypeHelper(national_significant_number,
 | 
| +                                             *metadata);
 | 
| +  // Most numbers other than the two types below have to be dialled in full.
 | 
| +  if (type != FIXED_LINE && type != FIXED_LINE_OR_MOBILE) {
 | 
| +    return 0;
 | 
| +  }
 | 
| +
 | 
| +  return GetLengthOfNationalDestinationCode(number);
 | 
| +}
 | 
| +
 | 
| +int PhoneNumberUtil::GetLengthOfNationalDestinationCode(
 | 
| +    const PhoneNumber& number) const {
 | 
| +  PhoneNumber copied_proto(number);
 | 
| +  if (number.has_extension()) {
 | 
| +    // Clear the extension so it's not included when formatting.
 | 
| +    copied_proto.clear_extension();
 | 
| +  }
 | 
| +
 | 
| +  string formatted_number;
 | 
| +  Format(copied_proto, INTERNATIONAL, &formatted_number);
 | 
| +  scoped_ptr<reg_exp::RegularExpressionInput> i18n_number(
 | 
| +      reg_exp::CreateRegularExpressionInput(formatted_number.c_str()));
 | 
| +  string digit_group;
 | 
| +  string ndc;
 | 
| +  string third_group;
 | 
| +  for (int i = 0; i < 3; ++i) {
 | 
| +    if (!capturing_ascii_digits_pattern->Consume(i18n_number.get(),
 | 
| +                                                 false,
 | 
| +                                                 &digit_group,
 | 
| +                                                 NULL)) {
 | 
| +      // We should find at least three groups.
 | 
| +      return 0;
 | 
| +    }
 | 
| +    if (i == 1) {
 | 
| +      ndc = digit_group;
 | 
| +    } else if (i == 2) {
 | 
| +      third_group = digit_group;
 | 
| +    }
 | 
| +  }
 | 
| +  string region_code;
 | 
| +  GetRegionCodeForNumber(number, ®ion_code);
 | 
| +  if (region_code == "AR" &&
 | 
| +      GetNumberType(number) == MOBILE) {
 | 
| +    // Argentinian mobile numbers, when formatted in the international format,
 | 
| +    // are in the form of +54 9 NDC XXXX.... As a result, we take the length of
 | 
| +    // the third group (NDC) and add 1 for the digit 9, which also forms part of
 | 
| +    // the national significant number.
 | 
| +    return third_group.size() + 1;
 | 
| +  }
 | 
| +  return ndc.size();
 | 
| +}
 | 
| +
 | 
| +// static
 | 
| +void PhoneNumberUtil::NormalizeDigitsOnly(string* number) {
 | 
| +  DCHECK(number);
 | 
| +  // Delete everything that isn't valid digits.
 | 
| +  static scoped_ptr<reg_exp::RegularExpression> invalid_digits_pattern(
 | 
| +      reg_exp::CreateRegularExpression(StrCat("[^", kValidDigits,
 | 
| +                                              "]").c_str()));
 | 
| +  static const char *empty = "";
 | 
| +  invalid_digits_pattern->Replace(number, true, empty);
 | 
| +  // Normalize all decimal digits to ASCII digits.
 | 
| +  UParseError error;
 | 
| +  icu::ErrorCode status;
 | 
| +
 | 
| +  scoped_ptr<icu::Transliterator> transliterator(
 | 
| +    icu::Transliterator::createFromRules(
 | 
| +      "NormalizeDecimalDigits",
 | 
| +      "[[:nv=0:]-[0]-[:^nt=de:]]>0;"
 | 
| +      "[[:nv=1:]-[1]-[:^nt=de:]]>1;"
 | 
| +      "[[:nv=2:]-[2]-[:^nt=de:]]>2;"
 | 
| +      "[[:nv=3:]-[3]-[:^nt=de:]]>3;"
 | 
| +      "[[:nv=4:]-[4]-[:^nt=de:]]>4;"
 | 
| +      "[[:nv=5:]-[5]-[:^nt=de:]]>5;"
 | 
| +      "[[:nv=6:]-[6]-[:^nt=de:]]>6;"
 | 
| +      "[[:nv=7:]-[7]-[:^nt=de:]]>7;"
 | 
| +      "[[:nv=8:]-[8]-[:^nt=de:]]>8;"
 | 
| +      "[[:nv=9:]-[9]-[:^nt=de:]]>9;",
 | 
| +      UTRANS_FORWARD,
 | 
| +      error,
 | 
| +      status
 | 
| +    )
 | 
| +  );
 | 
| +  if (!status.isSuccess()) {
 | 
| +    logger->Error("Error creating ICU Transliterator");
 | 
| +    return;
 | 
| +  }
 | 
| +  icu::UnicodeString utf16(icu::UnicodeString::fromUTF8(number->c_str()));
 | 
| +  transliterator->transliterate(utf16);
 | 
| +  number->clear();
 | 
| +  utf16.toUTF8String(*number);
 | 
| +}
 | 
| +
 | 
| +bool PhoneNumberUtil::IsAlphaNumber(const string& number) const {
 | 
| +  if (!IsViablePhoneNumber(number)) {
 | 
| +    // Number is too short, or doesn't match the basic phone number pattern.
 | 
| +    return false;
 | 
| +  }
 | 
| +  // Copy the number, since we are going to try and strip the extension from it.
 | 
| +  string number_copy(number);
 | 
| +  string extension;
 | 
| +  MaybeStripExtension(&number_copy, &extension);
 | 
| +  return valid_alpha_phone_pattern->Match(number_copy.c_str(), true, NULL);
 | 
| +}
 | 
| +
 | 
| +void PhoneNumberUtil::ConvertAlphaCharactersInNumber(string* number) const {
 | 
| +  DCHECK(number);
 | 
| +  NormalizeHelper(*all_normalization_mappings, false, number);
 | 
| +}
 | 
| +
 | 
| +// Normalizes a string of characters representing a phone number. This performs
 | 
| +// the following conversions:
 | 
| +//   - Wide-ascii digits are converted to normal ASCII (European) digits.
 | 
| +//   - Letters are converted to their numeric representation on a telephone
 | 
| +//     keypad. The keypad used here is the one defined in ITU Recommendation
 | 
| +//     E.161. This is only done if there are 3 or more letters in the number, to
 | 
| +//     lessen the risk that such letters are typos - otherwise alpha characters
 | 
| +//     are stripped.
 | 
| +//   - Punctuation is stripped.
 | 
| +//   - Arabic-Indic numerals are converted to European numerals.
 | 
| +void PhoneNumberUtil::Normalize(string* number) const {
 | 
| +  DCHECK(number);
 | 
| +  if (valid_alpha_phone_pattern->Match(number->c_str(), false, NULL)) {
 | 
| +    NormalizeHelper(*all_normalization_mappings, true, number);
 | 
| +  }
 | 
| +  NormalizeDigitsOnly(number);
 | 
| +}
 | 
| +
 | 
| +// Checks to see if the string of characters could possibly be a phone number at
 | 
| +// all. At the moment, checks to see that the string begins with at least 3
 | 
| +// digits, ignoring any punctuation commonly found in phone numbers.  This
 | 
| +// method does not require the number to be normalized in advance - but does
 | 
| +// assume that leading non-number symbols have been removed, such as by the
 | 
| +// method ExtractPossibleNumber.
 | 
| +// static
 | 
| +bool PhoneNumberUtil::IsViablePhoneNumber(const string& number) {
 | 
| +  if (number.length() < kMinLengthForNsn) {
 | 
| +    logger->Debug("Number too short to be viable:" + number);
 | 
| +    return false;
 | 
| +  }
 | 
| +  return valid_phone_number_pattern->Match(number.c_str(), true, NULL);
 | 
| +}
 | 
| +
 | 
| +// Strips any international prefix (such as +, 00, 011) present in the number
 | 
| +// provided, normalizes the resulting number, and indicates if an international
 | 
| +// prefix was present.
 | 
| +//
 | 
| +// possible_idd_prefix represents the international direct dialing prefix from
 | 
| +// the region we think this number may be dialed in.
 | 
| +// Returns true if an international dialing prefix could be removed from the
 | 
| +// number, otherwise false if the number did not seem to be in international
 | 
| +// format.
 | 
| +PhoneNumber::CountryCodeSource
 | 
| +PhoneNumberUtil::MaybeStripInternationalPrefixAndNormalize(
 | 
| +    const string& possible_idd_prefix,
 | 
| +    string* number) const {
 | 
| +  DCHECK(number);
 | 
| +  if (number->empty()) {
 | 
| +    return PhoneNumber::FROM_DEFAULT_COUNTRY;
 | 
| +  }
 | 
| +  scoped_ptr<reg_exp::RegularExpressionInput> number_string_piece(
 | 
| +      reg_exp::CreateRegularExpressionInput(number->c_str()));
 | 
| +  if (plus_chars_pattern->Consume(number_string_piece.get(), true,
 | 
| +                                  NULL, NULL)) {
 | 
| +    number->assign(number_string_piece->ToString());
 | 
| +    // Can now normalize the rest of the number since we've consumed the "+"
 | 
| +    // sign at the start.
 | 
| +    Normalize(number);
 | 
| +    return PhoneNumber::FROM_NUMBER_WITH_PLUS_SIGN;
 | 
| +  }
 | 
| +  // Attempt to parse the first digits as an international prefix.
 | 
| +  scoped_ptr<reg_exp::RegularExpression> idd_pattern(
 | 
| +      reg_exp::CreateRegularExpression(possible_idd_prefix.c_str()));
 | 
| +  if (ParsePrefixAsIdd(idd_pattern.get(), number)) {
 | 
| +    Normalize(number);
 | 
| +    return PhoneNumber::FROM_NUMBER_WITH_IDD;
 | 
| +  }
 | 
| +  // If still not found, then try and normalize the number and then try again.
 | 
| +  // This shouldn't be done before, since non-numeric characters (+ and ~) may
 | 
| +  // legally be in the international prefix.
 | 
| +  Normalize(number);
 | 
| +  return ParsePrefixAsIdd(idd_pattern.get(), number)
 | 
| +      ? PhoneNumber::FROM_NUMBER_WITH_IDD
 | 
| +      : PhoneNumber::FROM_DEFAULT_COUNTRY;
 | 
| +}
 | 
| +
 | 
| +// Strips any national prefix (such as 0, 1) present in the number provided.
 | 
| +// The number passed in should be the normalized telephone number that we wish
 | 
| +// to strip any national dialing prefix from. The metadata should be for the
 | 
| +// region that we think this number is from.
 | 
| +// static
 | 
| +void PhoneNumberUtil::MaybeStripNationalPrefixAndCarrierCode(
 | 
| +    const PhoneMetadata& metadata,
 | 
| +    string* number,
 | 
| +    string* carrier_code) {
 | 
| +  DCHECK(number);
 | 
| +  string carrier_code_temp;
 | 
| +  const string& possible_national_prefix =
 | 
| +      metadata.national_prefix_for_parsing();
 | 
| +  if (number->empty() || possible_national_prefix.empty()) {
 | 
| +    // Early return for numbers of zero length or with no national prefix
 | 
| +    // possible.
 | 
| +    return;
 | 
| +  }
 | 
| +  // We use two copies here since Consume modifies the phone number, and if the
 | 
| +  // first if-clause fails the number will already be changed.
 | 
| +  scoped_ptr<reg_exp::RegularExpressionInput> number_copy(
 | 
| +      reg_exp::CreateRegularExpressionInput(number->c_str()));
 | 
| +  scoped_ptr<reg_exp::RegularExpressionInput> number_copy_without_transform(
 | 
| +      reg_exp::CreateRegularExpressionInput(number->c_str()));
 | 
| +
 | 
| +  string number_string_copy(*number);
 | 
| +  string captured_part_of_prefix;
 | 
| +  scoped_ptr<reg_exp::RegularExpression> national_number_rule(
 | 
| +      reg_exp::CreateRegularExpression(
 | 
| +      metadata.general_desc().national_number_pattern().c_str()));
 | 
| +  // Attempt to parse the first digits as a national prefix. We make a
 | 
| +  // copy so that we can revert to the original string if necessary.
 | 
| +  const string& transform_rule = metadata.national_prefix_transform_rule();
 | 
| +  if (!transform_rule.empty() &&
 | 
| +      (number_copy->ConsumeRegExp(possible_national_prefix, true,
 | 
| +                                  &carrier_code_temp,
 | 
| +                                  &captured_part_of_prefix) ||
 | 
| +       number_copy->ConsumeRegExp(possible_national_prefix, true,
 | 
| +                                  &captured_part_of_prefix, NULL)) &&
 | 
| +      !captured_part_of_prefix.empty()) {
 | 
| +    string re2_transform_rule(transform_rule);
 | 
| +    TransformRegularExpressionToRE2Syntax(&re2_transform_rule);
 | 
| +    // If this succeeded, then we must have had a transform rule and there must
 | 
| +    // have been some part of the prefix that we captured.
 | 
| +    // We make the transformation and check that the resultant number is viable.
 | 
| +    // If so, replace the number and return.
 | 
| +    scoped_ptr<reg_exp::RegularExpression> possible_national_prefix_rule(
 | 
| +        reg_exp::CreateRegularExpression(possible_national_prefix.c_str()));
 | 
| +    possible_national_prefix_rule->Replace(&number_string_copy, false,
 | 
| +                                           re2_transform_rule.c_str());
 | 
| +    if (national_number_rule->Match(number_string_copy.c_str(), true, NULL)) {
 | 
| +      number->assign(number_string_copy);
 | 
| +      if (carrier_code) {
 | 
| +        carrier_code->assign(carrier_code_temp);
 | 
| +      }
 | 
| +    }
 | 
| +  } else if (number_copy_without_transform->ConsumeRegExp(
 | 
| +                 possible_national_prefix, true, &carrier_code_temp, NULL) ||
 | 
| +             number_copy_without_transform->ConsumeRegExp(
 | 
| +                 possible_national_prefix, true, NULL, NULL)) {
 | 
| +    logger->Debug("Parsed the first digits as a national prefix.");
 | 
| +    string unconsumed_part(number_copy_without_transform->ToString());
 | 
| +    // If captured_part_of_prefix is empty, this implies nothing was captured by
 | 
| +    // the capturing groups in possible_national_prefix; therefore, no
 | 
| +    // transformation is necessary, and we just remove the national prefix.
 | 
| +    if (national_number_rule->Match(unconsumed_part.c_str(), true, NULL)) {
 | 
| +      number->assign(unconsumed_part);
 | 
| +      if (carrier_code) {
 | 
| +        carrier_code->assign(carrier_code_temp);
 | 
| +      }
 | 
| +    }
 | 
| +  } else {
 | 
| +    logger->Debug("The first digits did not match the national prefix.");
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +// Strips any extension (as in, the part of the number dialled after the call is
 | 
| +// connected, usually indicated with extn, ext, x or similar) from the end of
 | 
| +// the number, and returns it. The number passed in should be non-normalized.
 | 
| +// static
 | 
| +bool PhoneNumberUtil::MaybeStripExtension(string* number, string* extension) {
 | 
| +  DCHECK(number);
 | 
| +  DCHECK(extension);
 | 
| +  // There are three extension capturing groups in the regular expression.
 | 
| +  string possible_extension_one;
 | 
| +  string possible_extension_two;
 | 
| +  string possible_extension_three;
 | 
| +  string number_copy(*number);
 | 
| +  scoped_ptr<reg_exp::RegularExpressionInput> number_copy_regex_input(
 | 
| +      reg_exp::CreateRegularExpressionInput(number_copy.c_str()));
 | 
| + if (extn_pattern->Consume(number_copy_regex_input.get(), false,
 | 
| +                           &possible_extension_one, &possible_extension_two,
 | 
| +                           &possible_extension_three)) {
 | 
| +    // Replace the extensions in the original string here.
 | 
| +    extn_pattern->Replace(&number_copy, false, "");
 | 
| +    logger->Debug("Found an extension. Possible extension one: "
 | 
| +            + possible_extension_one
 | 
| +            + ". Possible extension two: " + possible_extension_two
 | 
| +            + ". Remaining number: " + number_copy);
 | 
| +    // If we find a potential extension, and the number preceding this is a
 | 
| +    // viable number, we assume it is an extension.
 | 
| +    if ((!possible_extension_one.empty() || !possible_extension_two.empty() ||
 | 
| +         !possible_extension_three.empty()) &&
 | 
| +        IsViablePhoneNumber(number_copy)) {
 | 
| +      number->assign(number_copy);
 | 
| +      if (!possible_extension_one.empty()) {
 | 
| +        extension->assign(possible_extension_one);
 | 
| +      } else if (!possible_extension_two.empty()) {
 | 
| +        extension->assign(possible_extension_two);
 | 
| +      } else if (!possible_extension_three.empty()) {
 | 
| +        extension->assign(possible_extension_three);
 | 
| +      }
 | 
| +      return true;
 | 
| +    }
 | 
| +  }
 | 
| +  return false;
 | 
| +}
 | 
| +
 | 
| +// Extracts country calling code from national_number, and returns it. It
 | 
| +// assumes that the leading plus sign or IDD has already been removed. Returns 0
 | 
| +// if national_number doesn't start with a valid country calling code, and
 | 
| +// leaves national_number unmodified. Assumes the national_number is at least 3
 | 
| +// characters long.
 | 
| +int PhoneNumberUtil::ExtractCountryCode(string* national_number) const {
 | 
| +  int potential_country_code;
 | 
| +  for (int i = 1; i <= 3; ++i) {
 | 
| +    safe_strto32(national_number->substr(0, i), &potential_country_code);
 | 
| +    string region_code;
 | 
| +    GetRegionCodeForCountryCode(potential_country_code, ®ion_code);
 | 
| +    if (region_code != "ZZ") {
 | 
| +      national_number->erase(0, i);
 | 
| +      return potential_country_code;
 | 
| +    }
 | 
| +  }
 | 
| +  return 0;
 | 
| +}
 | 
| +
 | 
| +// Tries to extract a country calling code from a number. Country calling codes
 | 
| +// are extracted in the following ways:
 | 
| +//   - by stripping the international dialing prefix of the region the person
 | 
| +//   is dialing from, if this is present in the number, and looking at the next
 | 
| +//   digits
 | 
| +//   - by stripping the '+' sign if present and then looking at the next digits
 | 
| +//   - by comparing the start of the number and the country calling code of the
 | 
| +//   default region. If the number is not considered possible for the numbering
 | 
| +//   plan of the default region initially, but starts with the country calling
 | 
| +//   code of this region, validation will be reattempted after stripping this
 | 
| +//   country calling code. If this number is considered a possible number, then
 | 
| +//   the first digits will be considered the country calling code and removed as
 | 
| +//   such.
 | 
| +//
 | 
| +//   Returns NO_PARSING_ERROR if a country calling code was successfully
 | 
| +//   extracted or none was present, or the appropriate error otherwise, such as
 | 
| +//   if a + was present but it was not followed by a valid country calling code.
 | 
| +//   If NO_PARSING_ERROR is returned, the national_number without the country
 | 
| +//   calling code is populated, and the country_code passed in is set to the
 | 
| +//   country calling code if found, otherwise to 0.
 | 
| +PhoneNumberUtil::ErrorType PhoneNumberUtil::MaybeExtractCountryCode(
 | 
| +    const PhoneMetadata* default_region_metadata,
 | 
| +    bool keep_raw_input,
 | 
| +    string* national_number,
 | 
| +    PhoneNumber* phone_number) const {
 | 
| +  DCHECK(national_number);
 | 
| +  DCHECK(phone_number);
 | 
| +  // Set the default prefix to be something that will never match if there is no
 | 
| +  // default region.
 | 
| +  string possible_country_idd_prefix = default_region_metadata
 | 
| +      ?  default_region_metadata->international_prefix()
 | 
| +      : "NonMatch";
 | 
| +  PhoneNumber::CountryCodeSource country_code_source =
 | 
| +      MaybeStripInternationalPrefixAndNormalize(possible_country_idd_prefix,
 | 
| +                                                national_number);
 | 
| +  if (keep_raw_input) {
 | 
| +    phone_number->set_country_code_source(country_code_source);
 | 
| +  }
 | 
| +  if (country_code_source != PhoneNumber::FROM_DEFAULT_COUNTRY) {
 | 
| +    if (national_number->length() < kMinLengthForNsn) {
 | 
| +      logger->Debug("Phone number had an IDD, but after this was not "
 | 
| +          "long enough to be a viable phone number.");
 | 
| +      return TOO_SHORT_AFTER_IDD;
 | 
| +    }
 | 
| +    int potential_country_code = ExtractCountryCode(national_number);
 | 
| +    if (potential_country_code != 0) {
 | 
| +      phone_number->set_country_code(potential_country_code);
 | 
| +      return NO_PARSING_ERROR;
 | 
| +    }
 | 
| +    // If this fails, they must be using a strange country calling code that we
 | 
| +    // don't recognize, or that doesn't exist.
 | 
| +    return INVALID_COUNTRY_CODE_ERROR;
 | 
| +  } else if (default_region_metadata) {
 | 
| +    // Check to see if the number starts with the country calling code for the
 | 
| +    // default region. If so, we remove the country calling code, and do some
 | 
| +    // checks on the validity of the number before and after.
 | 
| +    int default_country_code = default_region_metadata->country_code();
 | 
| +    string default_country_code_string(SimpleItoa(default_country_code));
 | 
| +    logger->Debug("Possible country code: " + default_country_code_string);
 | 
| +    string potential_national_number;
 | 
| +    if (TryStripPrefixString(*national_number,
 | 
| +                             default_country_code_string,
 | 
| +                             &potential_national_number)) {
 | 
| +      const PhoneNumberDesc& general_num_desc =
 | 
| +          default_region_metadata->general_desc();
 | 
| +      scoped_ptr<reg_exp::RegularExpression> valid_number_pattern(
 | 
| +          reg_exp::CreateRegularExpression(
 | 
| +          general_num_desc.national_number_pattern().c_str()));
 | 
| +
 | 
| +      MaybeStripNationalPrefixAndCarrierCode(*default_region_metadata,
 | 
| +                                             &potential_national_number,
 | 
| +                                             NULL);
 | 
| +      logger->Debug("Number without country code prefix: "
 | 
| +              + potential_national_number);
 | 
| +      string extracted_number;
 | 
| +      scoped_ptr<reg_exp::RegularExpression> possible_number_pattern(
 | 
| +          reg_exp::CreateRegularExpression(
 | 
| +          StrCat("(", general_num_desc.possible_number_pattern(),
 | 
| +                 ")").c_str()));
 | 
| +      // If the number was not valid before but is valid now, or if it was too
 | 
| +      // long before, we consider the number with the country code stripped to
 | 
| +      // be a better result and keep that instead.
 | 
| +      if ((!valid_number_pattern->Match(national_number->c_str(),
 | 
| +                                       true, NULL) &&
 | 
| +           valid_number_pattern->Match(potential_national_number.c_str(),
 | 
| +                                        true, NULL)) ||
 | 
| +          TestNumberLengthAgainstPattern(possible_number_pattern.get(),
 | 
| +                                         *national_number)
 | 
| +                == TOO_LONG) {
 | 
| +        national_number->assign(potential_national_number);
 | 
| +        if (keep_raw_input) {
 | 
| +          phone_number->set_country_code_source(
 | 
| +              PhoneNumber::FROM_NUMBER_WITHOUT_PLUS_SIGN);
 | 
| +        }
 | 
| +        phone_number->set_country_code(default_country_code);
 | 
| +        return NO_PARSING_ERROR;
 | 
| +      }
 | 
| +    }
 | 
| +  }
 | 
| +  // No country calling code present. Set the country_code to 0.
 | 
| +  phone_number->set_country_code(0);
 | 
| +  return NO_PARSING_ERROR;
 | 
| +}
 | 
| +
 | 
| +PhoneNumberUtil::MatchType PhoneNumberUtil::IsNumberMatch(
 | 
| +    const PhoneNumber& first_number_in,
 | 
| +    const PhoneNumber& second_number_in) const {
 | 
| +  // Make copies of the phone number so that the numbers passed in are not
 | 
| +  // edited.
 | 
| +  PhoneNumber first_number(first_number_in);
 | 
| +  PhoneNumber second_number(second_number_in);
 | 
| +  // First clear raw_input and country_code_source and
 | 
| +  // preferred_domestic_carrier_code fields and any empty-string extensions so
 | 
| +  // that we can use the proto-buffer equality method.
 | 
| +  first_number.clear_raw_input();
 | 
| +  first_number.clear_country_code_source();
 | 
| +  first_number.clear_preferred_domestic_carrier_code();
 | 
| +  second_number.clear_raw_input();
 | 
| +  second_number.clear_country_code_source();
 | 
| +  second_number.clear_preferred_domestic_carrier_code();
 | 
| +  if (first_number.extension().empty()) {
 | 
| +    first_number.clear_extension();
 | 
| +  }
 | 
| +  if (second_number.extension().empty()) {
 | 
| +    second_number.clear_extension();
 | 
| +  }
 | 
| +  // Early exit if both had extensions and these are different.
 | 
| +  if (first_number.has_extension() && second_number.has_extension() &&
 | 
| +      first_number.extension() != second_number.extension()) {
 | 
| +    return NO_MATCH;
 | 
| +  }
 | 
| +  int first_number_country_code = first_number.country_code();
 | 
| +  int second_number_country_code = second_number.country_code();
 | 
| +  // Both had country calling code specified.
 | 
| +  if (first_number_country_code != 0 && second_number_country_code != 0) {
 | 
| +    if (ExactlySameAs(first_number, second_number)) {
 | 
| +      return EXACT_MATCH;
 | 
| +    } else if (first_number_country_code == second_number_country_code &&
 | 
| +               IsNationalNumberSuffixOfTheOther(first_number, second_number)) {
 | 
| +      // A SHORT_NSN_MATCH occurs if there is a difference because of the
 | 
| +      // presence or absence of an 'Italian leading zero', the presence or
 | 
| +      // absence of an extension, or one NSN being a shorter variant of the
 | 
| +      // other.
 | 
| +      return SHORT_NSN_MATCH;
 | 
| +    }
 | 
| +    // This is not a match.
 | 
| +    return NO_MATCH;
 | 
| +  }
 | 
| +  // Checks cases where one or both country calling codes were not specified. To
 | 
| +  // make equality checks easier, we first set the country_code fields to be
 | 
| +  // equal.
 | 
| +  first_number.set_country_code(second_number_country_code);
 | 
| +  // If all else was the same, then this is an NSN_MATCH.
 | 
| +  if (ExactlySameAs(first_number, second_number)) {
 | 
| +    return NSN_MATCH;
 | 
| +  }
 | 
| +  if (IsNationalNumberSuffixOfTheOther(first_number, second_number)) {
 | 
| +    return SHORT_NSN_MATCH;
 | 
| +  }
 | 
| +  return NO_MATCH;
 | 
| +}
 | 
| +
 | 
| +PhoneNumberUtil::MatchType PhoneNumberUtil::IsNumberMatchWithTwoStrings(
 | 
| +    const string& first_number,
 | 
| +    const string& second_number) const {
 | 
| +  PhoneNumber first_number_as_proto;
 | 
| +  ErrorType error_type =
 | 
| +      Parse(first_number, "ZZ", &first_number_as_proto);
 | 
| +  if (error_type == NO_PARSING_ERROR) {
 | 
| +    return IsNumberMatchWithOneString(first_number_as_proto, second_number);
 | 
| +  }
 | 
| +  if (error_type == INVALID_COUNTRY_CODE_ERROR) {
 | 
| +    PhoneNumber second_number_as_proto;
 | 
| +    ErrorType error_type = Parse(second_number, "ZZ",
 | 
| +                                 &second_number_as_proto);
 | 
| +    if (error_type == NO_PARSING_ERROR) {
 | 
| +      return IsNumberMatchWithOneString(second_number_as_proto, first_number);
 | 
| +    }
 | 
| +    if (error_type == INVALID_COUNTRY_CODE_ERROR) {
 | 
| +      error_type  = ParseHelper(first_number, "ZZ", false, false,
 | 
| +                                &first_number_as_proto);
 | 
| +      if (error_type == NO_PARSING_ERROR) {
 | 
| +        error_type = ParseHelper(second_number, "ZZ", false, false,
 | 
| +                                 &second_number_as_proto);
 | 
| +        if (error_type == NO_PARSING_ERROR) {
 | 
| +          return IsNumberMatch(first_number_as_proto, second_number_as_proto);
 | 
| +        }
 | 
| +      }
 | 
| +    }
 | 
| +  }
 | 
| +  // One or more of the phone numbers we are trying to match is not a viable
 | 
| +  // phone number.
 | 
| +  return INVALID_NUMBER;
 | 
| +}
 | 
| +
 | 
| +PhoneNumberUtil::MatchType PhoneNumberUtil::IsNumberMatchWithOneString(
 | 
| +    const PhoneNumber& first_number,
 | 
| +    const string& second_number) const {
 | 
| +  // First see if the second number has an implicit country calling code, by
 | 
| +  // attempting to parse it.
 | 
| +  PhoneNumber second_number_as_proto;
 | 
| +  ErrorType error_type =
 | 
| +      Parse(second_number, "ZZ", &second_number_as_proto);
 | 
| +  if (error_type == NO_PARSING_ERROR) {
 | 
| +    return IsNumberMatch(first_number, second_number_as_proto);
 | 
| +  }
 | 
| +  if (error_type == INVALID_COUNTRY_CODE_ERROR) {
 | 
| +    // The second number has no country calling code. EXACT_MATCH is no longer
 | 
| +    // possible.  We parse it as if the region was the same as that for the
 | 
| +    // first number, and if EXACT_MATCH is returned, we replace this with
 | 
| +    // NSN_MATCH.
 | 
| +    string first_number_region;
 | 
| +    GetRegionCodeForCountryCode(first_number.country_code(),
 | 
| +                                &first_number_region);
 | 
| +    if (first_number_region != "ZZ") {
 | 
| +      PhoneNumber second_number_with_first_number_region;
 | 
| +      Parse(second_number, first_number_region,
 | 
| +            &second_number_with_first_number_region);
 | 
| +      MatchType match = IsNumberMatch(first_number,
 | 
| +                                      second_number_with_first_number_region);
 | 
| +      if (match == EXACT_MATCH) {
 | 
| +        return NSN_MATCH;
 | 
| +      }
 | 
| +      return match;
 | 
| +    } else {
 | 
| +      // If the first number didn't have a valid country calling code, then we
 | 
| +      // parse the second number without one as well.
 | 
| +      error_type = ParseHelper(second_number, "ZZ", false, false,
 | 
| +                               &second_number_as_proto);
 | 
| +      if (error_type == NO_PARSING_ERROR) {
 | 
| +        return IsNumberMatch(first_number, second_number_as_proto);
 | 
| +      }
 | 
| +    }
 | 
| +  }
 | 
| +  // One or more of the phone numbers we are trying to match is not a viable
 | 
| +  // phone number.
 | 
| +  return INVALID_NUMBER;
 | 
| +}
 | 
| +
 | 
| +}  // namespace phonenumbers
 | 
| +}  // namespace i18n
 | 
| 
 | 
| Property changes on: third_party\libphonenumber\cpp\src\phonenumberutil.cc
 | 
| ___________________________________________________________________
 | 
| Added: svn:eol-style
 | 
|    + LF
 | 
| 
 | 
| 
 |