Fully quality std::* names.
[platform/upstream/libphonenumber.git] / cpp / src / phonenumbers / phonenumberutil.cc
index 3062594..9904145 100644 (file)
 
 #include "phonenumbers/phonenumberutil.h"
 
+#include <string.h>
 #include <algorithm>
 #include <cctype>
-#include <cstddef>
-#include <fstream>
-#include <iostream>
 #include <iterator>
 #include <map>
-#include <sstream>
 #include <utility>
 #include <vector>
 
 #include <unicode/uchar.h>
 #include <unicode/utf8.h>
 
-#include "base/logging.h"
-#include "base/memory/singleton.h"
 #include "phonenumbers/asyoutypeformatter.h"
+#include "phonenumbers/base/basictypes.h"
+#include "phonenumbers/base/logging.h"
+#include "phonenumbers/base/memory/singleton.h"
 #include "phonenumbers/default_logger.h"
 #include "phonenumbers/encoding_utils.h"
 #include "phonenumbers/metadata.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;
 
+// static constants
+const size_t PhoneNumberUtil::kMinLengthForNsn;
+const size_t PhoneNumberUtil::kMaxLengthForNsn;
+const size_t PhoneNumberUtil::kMaxLengthCountryCode;
+const int PhoneNumberUtil::kNanpaCountryCode;
+
 // static
 const char PhoneNumberUtil::kPlusChars[] = "+\xEF\xBC\x8B";  /* "++" */
 // To find out the unicode code-point of the characters below in vim, highlight
@@ -72,32 +69,18 @@ const char PhoneNumberUtil::kPlusChars[] = "+\xEF\xBC\x8B";  /* "++" */
 // unicode character.
 // static
 const char PhoneNumberUtil::kValidPunctuation[] =
-    /* "-x‐-―−ー--/  <U+200B><U+2060> ()()[].\\[\\]/~⁓∼" */
+    /* "-x‐-―−ー--/  ­<U+200B><U+2060> ()()[].\\[\\]/~⁓∼" */
     "-x\xE2\x80\x90-\xE2\x80\x95\xE2\x88\x92\xE3\x83\xBC\xEF\xBC\x8D-\xEF\xBC"
-    "\x8F \xC2\xA0\xE2\x80\x8B\xE2\x81\xA0\xE3\x80\x80()\xEF\xBC\x88\xEF\xBC"
-    "\x89\xEF\xBC\xBB\xEF\xBC\xBD.\\[\\]/~\xE2\x81\x93\xE2\x88\xBC";
+    "\x8F \xC2\xA0\xC2\xAD\xE2\x80\x8B\xE2\x81\xA0\xE3\x80\x80()\xEF\xBC\x88"
+    "\xEF\xBC\x89\xEF\xBC\xBB\xEF\xBC\xBD.\\[\\]/~\xE2\x81\x93\xE2\x88\xBC";
 
 // static
 const char PhoneNumberUtil::kCaptureUpToSecondNumberStart[] = "(.*)[\\\\/] *x";
 
-namespace {
-
-scoped_ptr<Logger> logger_;
-scoped_ptr<const AbstractRegExpFactory> regexp_factory;
-scoped_ptr<RegExpCache> regexp_cache;
-
-// These objects are created in the function InitializeStaticMapsAndSets.
+// static
+const char PhoneNumberUtil::kRegionCodeForNonGeoEntity[] = "001";
 
-// 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, store a map of combining alpha_mappings with ASCII
-// digits.
-scoped_ptr<map<char32, char> > alpha_phone_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;
+namespace {
 
 // The prefix that needs to be inserted in front of a Colombian landline
 // number when dialed from a mobile phone in Colombia.
@@ -106,64 +89,17 @@ const char kColombiaMobileToFixedLinePrefix[] = "3";
 // The kPlusSign signifies the international prefix.
 const char kPlusSign[] = "+";
 
-scoped_ptr<const RegExp> plus_chars_pattern;
+const char kStarSign[] = "*";
 
 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 RegExp> unique_international_prefix;
+const char kRfc3966Prefix[] = "tel:";
+const char kRfc3966PhoneContext[] = ";phone-context=";
+const char kRfc3966IsdnSubaddress[] = ";isub=";
 
 const char kDigits[] = "\\p{Nd}";
-scoped_ptr<const RegExp> digits_pattern;
 // 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 RegExp> capturing_digit_pattern;
-scoped_ptr<const RegExp> 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 RegExp> valid_start_char_pattern;
-
-// Regular expression of valid characters before a marker that might indicate a
-// second number.
-scoped_ptr<const RegExp> 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 RegExp> unwanted_end_char_pattern;
-
-// Regular expression of groups of valid punctuation characters.
-scoped_ptr<const RegExp> separator_pattern;
-
-// 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
@@ -175,31 +111,10 @@ const char kDefaultExtnPrefix[] = " ext. ";
 // One-character symbols that can be used to indicate an extension.
 const char kSingleExtnSymbolsForMatching[] =
     "x\xEF\xBD\x98#\xEF\xBC\x83~\xEF\xBD\x9E";
-// 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.
-scoped_ptr<const string> extn_patterns_for_parsing;
-scoped_ptr<const string> extn_patterns_for_matching;
-// Regexp of all known extension prefixes used by different regions followed
-// by 1 or more valid digits, for use when parsing.
-scoped_ptr<const RegExp> 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 RegExp> 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 RegExp> valid_alpha_phone_pattern;
-
-scoped_ptr<const RegExp> first_group_capturing_pattern;
-
-scoped_ptr<const RegExp> carrier_code_pattern;
 
 bool LoadCompiledInMetadata(PhoneMetadataCollection* metadata) {
   if (!metadata->ParseFromArray(metadata_get(), metadata_size())) {
-    cerr << "Could not parse binary data." << endl;
+    LOG(ERROR) << "Could not parse binary data.";
     return false;
   }
   return true;
@@ -230,120 +145,34 @@ const PhoneNumberDesc* GetNumberDescByType(
       return &metadata.pager();
     case PhoneNumberUtil::UAN:
       return &metadata.uan();
+    case PhoneNumberUtil::VOICEMAIL:
+      return &metadata.voicemail();
     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) {
+void PrefixNumberWithCountryCallingCode(
+    int country_calling_code,
+    PhoneNumberUtil::PhoneNumberFormat number_format,
+    string* formatted_number) {
   switch (number_format) {
     case PhoneNumberUtil::E164:
-      formatted_number->assign(StrCat(kPlusSign,
-                                      SimpleItoa(country_calling_code),
-                                      formatted_national_number,
-                                      formatted_extension));
+      formatted_number->insert(0, StrCat(kPlusSign, country_calling_code));
       return;
     case PhoneNumberUtil::INTERNATIONAL:
-      formatted_number->assign(StrCat(kPlusSign,
-                                      SimpleItoa(country_calling_code),
-                                      " ",
-                                      formatted_national_number,
-                                      formatted_extension));
+      formatted_number->insert(0, StrCat(kPlusSign, country_calling_code, " "));
       return;
     case PhoneNumberUtil::RFC3966:
-      formatted_number->assign(StrCat(kPlusSign,
-                                      SimpleItoa(country_calling_code),
-                                      "-",
-                                      formatted_national_number,
-                                      formatted_extension));
+      formatted_number->insert(0, StrCat(kRfc3966Prefix, kPlusSign,
+                                         country_calling_code, "-"));
       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) {
-      const scoped_ptr<RegExpInput> number_copy(
-          regexp_factory->CreateInput(number_for_leading_digits_match));
-      // We always use the last leading_digits_pattern, as it is the most
-      // detailed.
-      if (!regexp_cache->GetRegExp(it->leading_digits_pattern(size - 1))
-              .Consume(number_copy.get())) {
-        continue;
-      }
-    }
-    const RegExp& pattern_to_match(regexp_cache->GetRegExp(it->pattern()));
-    if (pattern_to_match.FullMatch(national_number)) {
-      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,
-                                      carrier_code);
-        first_group_capturing_pattern->Replace(&formatting_pattern,
-                                               carrier_code_formatting_rule);
-      } 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.
-          first_group_capturing_pattern->Replace(
-              &formatting_pattern, national_prefix_formatting_rule);
-        }
-      }
-      formatted_number->assign(national_number);
-      pattern_to_match.GlobalReplace(formatted_number, formatting_pattern);
+      // Do nothing.
       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
@@ -361,188 +190,12 @@ bool IsNationalNumberSuffixOfTheOther(const PhoneNumber& first_number,
                          first_number_national_number);
 }
 
-bool IsNumberMatchingDesc(const string& national_number,
-                          const PhoneNumberDesc& number_desc) {
-  return regexp_cache->GetRegExp(number_desc.possible_number_pattern())
-             .FullMatch(national_number) &&
-         regexp_cache->GetRegExp(number_desc.national_number_pattern())
-             .FullMatch(national_number);
-}
-
-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)) {
-    VLOG(4) << "Number type unknown - doesn't match general national number"
-            << " pattern.";
-    return PhoneNumberUtil::UNKNOWN;
-  }
-  if (IsNumberMatchingDesc(national_number, metadata.premium_rate())) {
-    VLOG(4) << "Number is a premium number.";
-    return PhoneNumberUtil::PREMIUM_RATE;
-  }
-  if (IsNumberMatchingDesc(national_number, metadata.toll_free())) {
-    VLOG(4) << "Number is a toll-free number.";
-    return PhoneNumberUtil::TOLL_FREE;
-  }
-  if (IsNumberMatchingDesc(national_number, metadata.shared_cost())) {
-    VLOG(4) << "Number is a shared cost number.";
-    return PhoneNumberUtil::SHARED_COST;
-  }
-  if (IsNumberMatchingDesc(national_number, metadata.voip())) {
-    VLOG(4) << "Number is a VOIP (Voice over IP) number.";
-    return PhoneNumberUtil::VOIP;
-  }
-  if (IsNumberMatchingDesc(national_number, metadata.personal_number())) {
-    VLOG(4) << "Number is a personal number.";
-    return PhoneNumberUtil::PERSONAL_NUMBER;
-  }
-  if (IsNumberMatchingDesc(national_number, metadata.pager())) {
-    VLOG(4) << "Number is a pager number.";
-    return PhoneNumberUtil::PAGER;
-  }
-  if (IsNumberMatchingDesc(national_number, metadata.uan())) {
-    VLOG(4) << "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()) {
-      VLOG(4) << "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())) {
-      VLOG(4) << "Fixed-line and mobile patterns differ, but number is "
-              << "still fixed-line or mobile";
-      return PhoneNumberUtil::FIXED_LINE_OR_MOBILE;
-    }
-    VLOG(4) << "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())) {
-    VLOG(4) << "Number is a mobile number.";
-    return PhoneNumberUtil::MOBILE;
-  }
-  VLOG(4) << "Number type unknown - doesn\'t match any specific number type"
-          << " pattern.";
-  return PhoneNumberUtil::UNKNOWN;
-}
-
 char32 ToUnicodeCodepoint(const char* unicode_char) {
   char32 codepoint;
   EncodingUtils::DecodeUTF8Char(unicode_char, &codepoint);
   return codepoint;
 }
 
-void InitializeStaticMapsAndSets() {
-  // Create global objects.
-  regexp_factory.reset(new RegExpFactory());
-  regexp_cache.reset(new RegExpCache(*regexp_factory.get(), 128));
-  all_plus_number_grouping_symbols.reset(new map<char32, char>);
-  alpha_mappings.reset(new map<char32, char>);
-  alpha_phone_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("\xEF\xBC\x8D" /* "-" */), '-'));
-  all_plus_number_grouping_symbols->insert(
-      make_pair(ToUnicodeCodepoint("\xE2\x80\x90" /* "‐" */), '-'));
-  all_plus_number_grouping_symbols->insert(
-      make_pair(ToUnicodeCodepoint("\xE2\x80\x91" /* "‑" */), '-'));
-  all_plus_number_grouping_symbols->insert(
-      make_pair(ToUnicodeCodepoint("\xE2\x80\x92" /* "‒" */), '-'));
-  all_plus_number_grouping_symbols->insert(
-      make_pair(ToUnicodeCodepoint("\xE2\x80\x93" /* "–" */), '-'));
-  all_plus_number_grouping_symbols->insert(
-      make_pair(ToUnicodeCodepoint("\xE2\x80\x94" /* "—" */), '-'));
-  all_plus_number_grouping_symbols->insert(
-      make_pair(ToUnicodeCodepoint("\xE2\x80\x95" /* "―" */), '-'));
-  all_plus_number_grouping_symbols->insert(
-      make_pair(ToUnicodeCodepoint("\xE2\x88\x92" /* "−" */), '-'));
-  all_plus_number_grouping_symbols->insert(
-      make_pair(ToUnicodeCodepoint("/"), '/'));
-  all_plus_number_grouping_symbols->insert(
-      make_pair(ToUnicodeCodepoint("\xEF\xBC\x8F" /* "/" */), '/'));
-  all_plus_number_grouping_symbols->insert(
-      make_pair(ToUnicodeCodepoint(" "), ' '));
-  all_plus_number_grouping_symbols->insert(
-      make_pair(ToUnicodeCodepoint("\xE3\x80\x80" /* " " */), ' '));
-  all_plus_number_grouping_symbols->insert(
-      make_pair(ToUnicodeCodepoint("\xE2\x81\xA0"), ' '));
-  all_plus_number_grouping_symbols->insert(
-      make_pair(ToUnicodeCodepoint("."), '.'));
-  all_plus_number_grouping_symbols->insert(
-      make_pair(ToUnicodeCodepoint("\xEF\xBC\x8E" /* "." */), '.'));
-  // 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());
-  alpha_phone_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) {
-    alpha_phone_mappings->insert(make_pair(c, c));
-    all_plus_number_grouping_symbols->insert(make_pair(c, c));
-  }
-}
-
 // Helper initialiser method to create the regular-expression pattern to match
 // extensions, allowing the one-codepoint extension symbols provided by
 // single_extn_symbols.
@@ -563,11 +216,11 @@ string CreateExtnPattern(const string& single_extn_symbols) {
   // unicode decomposed form with the combining acute accent.
   return (StrCat(
       kRfc3966ExtnPrefix, capturing_extn_digits, "|"
-       /* "[  \\t,]*(?:ext(?:ensi(?:ó?|ó))?n?|extn?|single_extn_symbols|"
+       /* "[  \\t,]*(?:e?xt(?:ensi(?:ó?|ó))?n?|e?xtn?|single_extn_symbols|"
           "int|int|anexo)"
           "[:\\..]?[  \\t,-]*", capturing_extn_digits, "#?|" */
-      "[ \xC2\xA0\\t,]*(?:ext(?:ensi(?:o\xCC\x81?|\xC3\xB3))?n?|\xEF\xBD"
-      "\x85\xEF\xBD\x98\xEF\xBD\x94\xEF\xBD\x8E?|"
+      "[ \xC2\xA0\\t,]*(?:e?xt(?:ensi(?:o\xCC\x81?|\xC3\xB3))?n?|"
+      "(?:\xEF\xBD\x85)?\xEF\xBD\x98\xEF\xBD\x94(?:\xEF\xBD\x8E)?|"
       "[", single_extn_symbols, "]|int|"
       "\xEF\xBD\x89\xEF\xBD\x8E\xEF\xBD\x94|anexo)"
       "[:\\.\xEF\xBC\x8E]?[ \xC2\xA0\\t,-]*", capturing_extn_digits,
@@ -626,16 +279,315 @@ PhoneNumberUtil::ValidationResult TestNumberLengthAgainstPattern(
 }  // namespace
 
 void PhoneNumberUtil::SetLogger(Logger* logger) {
-  Logger::set_logger_impl(logger);
+  logger_.reset(logger);
+  Logger::set_logger_impl(logger_.get());
 }
 
+class PhoneNumberRegExpsAndMappings {
+ private:
+  void InitializeMapsAndSets() {
+    diallable_char_mappings_.insert(std::make_pair('+', '+'));
+    diallable_char_mappings_.insert(std::make_pair('*', '*'));
+    // Here we insert all punctuation symbols that we wish to respect when
+    // formatting alpha numbers, as they show the intended number groupings.
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("-"), '-'));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("\xEF\xBC\x8D" /* "-" */), '-'));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("\xE2\x80\x90" /* "‐" */), '-'));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("\xE2\x80\x91" /* "‑" */), '-'));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("\xE2\x80\x92" /* "‒" */), '-'));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("\xE2\x80\x93" /* "–" */), '-'));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("\xE2\x80\x94" /* "—" */), '-'));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("\xE2\x80\x95" /* "―" */), '-'));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("\xE2\x88\x92" /* "−" */), '-'));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("/"), '/'));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("\xEF\xBC\x8F" /* "/" */), '/'));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint(" "), ' '));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("\xE3\x80\x80" /* " " */), ' '));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("\xE2\x81\xA0"), ' '));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("."), '.'));
+    all_plus_number_grouping_symbols_.insert(
+        std::make_pair(ToUnicodeCodepoint("\xEF\xBC\x8E" /* "." */), '.'));
+    // Only the upper-case letters are added here - the lower-case versions are
+    // added programmatically.
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("A"), '2'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("B"), '2'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("C"), '2'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("D"), '3'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("E"), '3'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("F"), '3'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("G"), '4'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("H"), '4'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("I"), '4'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("J"), '5'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("K"), '5'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("L"), '5'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("M"), '6'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("N"), '6'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("O"), '6'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("P"), '7'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("Q"), '7'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("R"), '7'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("S"), '7'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("T"), '8'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("U"), '8'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("V"), '8'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("W"), '9'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("X"), '9'));
+    alpha_mappings_.insert(std::make_pair(ToUnicodeCodepoint("Y"), '9'));
+    alpha_mappings_.insert(std::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(std::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(std::make_pair(letter_as_lower, letter_as_upper));
+        alpha_letters.insert(std::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());
+    alpha_phone_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) {
+      diallable_char_mappings_.insert(std::make_pair(c, c));
+      alpha_phone_mappings_.insert(std::make_pair(c, c));
+      all_plus_number_grouping_symbols_.insert(std::make_pair(c, c));
+    }
+
+    mobile_token_mappings_.insert(std::make_pair(52, '1'));
+    mobile_token_mappings_.insert(std::make_pair(54, '9'));
+  }
+
+  // Small string helpers since StrCat has a maximum number of arguments. These
+  // are both used to build valid_phone_number_.
+  const string punctuation_and_star_sign_;
+  const string min_length_phone_number_pattern_;
+
+  // 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:
+  // [digits]{minLengthNsn}|
+  // plus_sign*(([punctuation]|[star])*[digits]){3,}
+  // ([punctuation]|[star]|[digits]|[alpha])*
+  //
+  // The first reg-ex is to allow short numbers (two digits long) to be parsed
+  // if they are entered as "15" etc, but only if there is no punctuation in
+  // them. The second expression restricts the number of digits to three or
+  // more, but then allows them to be in international form, and to have
+  // alpha-characters and punctuation.
+  const string valid_phone_number_;
+
+  // 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.
+  // For parsing, we are slightly more lenient in our interpretation than for
+  // matching. Here we allow a "comma" as a possible extension indicator. When
+  // matching, this is hardly ever used to indicate this.
+  const string extn_patterns_for_parsing_;
+
+ public:
+  scoped_ptr<const AbstractRegExpFactory> regexp_factory_;
+  scoped_ptr<RegExpCache> regexp_cache_;
+
+  // A map that contains characters that are essential when dialling. That means
+  // any of the characters in this map must not be removed from a number when
+  // dialing, otherwise the call will not reach the intended destination.
+  map<char32, char> diallable_char_mappings_;
+  // These mappings map a character (key) to a specific digit that should
+  // replace it for normalization purposes.
+  map<char32, char> alpha_mappings_;
+  // For performance reasons, store a map of combining alpha_mappings with ASCII
+  // digits.
+  map<char32, char> alpha_phone_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 " ".
+  map<char32, char> all_plus_number_grouping_symbols_;
+
+  // Map of country calling codes that use a mobile token before the area code.
+  // One example of when this is relevant is when determining the length of the
+  // national destination code, which should be the length of the area code plus
+  // the length of the mobile token.
+  map<int, char> mobile_token_mappings_;
+
+  // 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 RegExp> unique_international_prefix_;
+
+  scoped_ptr<const RegExp> digits_pattern_;
+  scoped_ptr<const RegExp> capturing_digit_pattern_;
+  scoped_ptr<const RegExp> 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 RegExp> valid_start_char_pattern_;
+
+  // Regular expression of valid characters before a marker that might indicate
+  // a second number.
+  scoped_ptr<const RegExp> 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_CHAR_PATTERN in the java version.
+  scoped_ptr<const RegExp> unwanted_end_char_pattern_;
+
+  // Regular expression of groups of valid punctuation characters.
+  scoped_ptr<const RegExp> separator_pattern_;
+
+  // Regexp of all possible ways to write extensions, for use when finding phone
+  // numbers in text. This will be run as a case-insensitive regexp match. Wide
+  // character versions are also provided after each ASCII version.
+  const string extn_patterns_for_matching_;
+
+  // Regexp of all known extension prefixes used by different regions followed
+  // by 1 or more valid digits, for use when parsing.
+  scoped_ptr<const RegExp> 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 RegExp> 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 RegExp> valid_alpha_phone_pattern_;
+
+  scoped_ptr<const RegExp> first_group_capturing_pattern_;
+
+  scoped_ptr<const RegExp> carrier_code_pattern_;
+
+  scoped_ptr<const RegExp> plus_chars_pattern_;
+
+  PhoneNumberRegExpsAndMappings()
+      : punctuation_and_star_sign_(StrCat(PhoneNumberUtil::kValidPunctuation,
+                                          kStarSign)),
+        min_length_phone_number_pattern_(
+            StrCat(kDigits, "{", PhoneNumberUtil::kMinLengthForNsn, "}")),
+        valid_phone_number_(
+            StrCat(min_length_phone_number_pattern_, "|[",
+                   PhoneNumberUtil::kPlusChars, "]*(?:[",
+                   punctuation_and_star_sign_, "]*",
+                   kDigits, "){3,}[", kValidAlpha,
+                   punctuation_and_star_sign_, kDigits,
+                   "]*")),
+        extn_patterns_for_parsing_(
+            CreateExtnPattern(StrCat(",", kSingleExtnSymbolsForMatching))),
+        regexp_factory_(new RegExpFactory()),
+        regexp_cache_(new RegExpCache(*regexp_factory_.get(), 128)),
+        diallable_char_mappings_(),
+        alpha_mappings_(),
+        alpha_phone_mappings_(),
+        all_plus_number_grouping_symbols_(),
+        mobile_token_mappings_(),
+        unique_international_prefix_(regexp_factory_->CreateRegExp(
+            /* "[\\d]+(?:[~⁓∼~][\\d]+)?" */
+            "[\\d]+(?:[~\xE2\x81\x93\xE2\x88\xBC\xEF\xBD\x9E][\\d]+)?")),
+        digits_pattern_(
+            regexp_factory_->CreateRegExp(StrCat("[", kDigits, "]*"))),
+        capturing_digit_pattern_(
+            regexp_factory_->CreateRegExp(StrCat("([", kDigits, "])"))),
+        capturing_ascii_digits_pattern_(
+            regexp_factory_->CreateRegExp("(\\d+)")),
+        valid_start_char_pattern_(regexp_factory_->CreateRegExp(
+            StrCat("[", PhoneNumberUtil::kPlusChars, kDigits, "]"))),
+        capture_up_to_second_number_start_pattern_(
+            regexp_factory_->CreateRegExp(
+                PhoneNumberUtil::kCaptureUpToSecondNumberStart)),
+        unwanted_end_char_pattern_(
+            regexp_factory_->CreateRegExp("[^\\p{N}\\p{L}#]")),
+        separator_pattern_(
+            regexp_factory_->CreateRegExp(
+                StrCat("[", PhoneNumberUtil::kValidPunctuation, "]+"))),
+        extn_patterns_for_matching_(
+            CreateExtnPattern(kSingleExtnSymbolsForMatching)),
+        extn_pattern_(regexp_factory_->CreateRegExp(
+            StrCat("(?i)(?:", extn_patterns_for_parsing_, ")$"))),
+        valid_phone_number_pattern_(regexp_factory_->CreateRegExp(
+            StrCat("(?i)", valid_phone_number_,
+                   "(?:", extn_patterns_for_parsing_, ")?"))),
+        valid_alpha_phone_pattern_(regexp_factory_->CreateRegExp(
+            StrCat("(?i)(?:.*?[", kValidAlpha, "]){3}"))),
+        // The first_group_capturing_pattern was originally set to $1 but there
+        // are some countries for which the first group is not used in the
+        // national pattern (e.g. Argentina) so the $1 group does not match
+        // correctly. Therefore, we use \d, so that the first group actually
+        // used in the pattern will be matched.
+        first_group_capturing_pattern_(
+            regexp_factory_->CreateRegExp("(\\$\\d)")),
+        carrier_code_pattern_(regexp_factory_->CreateRegExp("\\$CC")),
+        plus_chars_pattern_(
+            regexp_factory_->CreateRegExp(
+                StrCat("[", PhoneNumberUtil::kPlusChars, "]+"))) {
+    InitializeMapsAndSets();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PhoneNumberRegExpsAndMappings);
+};
+
 // Private constructor. Also takes care of initialisation.
 PhoneNumberUtil::PhoneNumberUtil()
-    : country_calling_code_to_region_code_map_(new vector<IntRegionsPair>()),
+    : logger_(Logger::set_logger_impl(new NullLogger())),
+      reg_exps_(new PhoneNumberRegExpsAndMappings),
+      country_calling_code_to_region_code_map_(new vector<IntRegionsPair>()),
       nanpa_regions_(new set<string>()),
-      region_to_metadata_map_(new map<string, PhoneMetadata>()) {
-  logger_.reset(new StdoutLogger());
+      region_to_metadata_map_(new map<string, PhoneMetadata>()),
+      country_code_to_non_geographical_metadata_map_(
+          new map<int, PhoneMetadata>) {
   Logger::set_logger_impl(logger_.get());
+  // TODO: Update the java version to put the contents of the init
+  // method inside the constructor as well to keep both in sync.
   PhoneMetadataCollection metadata_collection;
   if (!LoadCompiledInMetadata(&metadata_collection)) {
     LOG(DFATAL) << "Could not parse compiled-in metadata.";
@@ -648,11 +600,19 @@ PhoneNumberUtil::PhoneNumberUtil()
            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));
+    const string& region_code = it->id();
+    if (region_code == RegionCode::GetUnknown()) {
+      continue;
+    }
+
     int country_calling_code = it->country_code();
-    map<int, list<string>*>::iterator calling_code_in_map =
+    if (kRegionCodeForNonGeoEntity == region_code) {
+      country_code_to_non_geographical_metadata_map_->insert(
+          std::make_pair(country_calling_code, *it));
+    } else {
+      region_to_metadata_map_->insert(std::make_pair(region_code, *it));
+    }
+    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()) {
@@ -665,7 +625,7 @@ PhoneNumberUtil::PhoneNumberUtil()
       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));
+          std::make_pair(country_calling_code, list_with_region_code));
     }
     if (country_calling_code == kNanpaCountryCode) {
         nanpa_regions_->insert(region_code);
@@ -677,12 +637,9 @@ PhoneNumberUtil::PhoneNumberUtil()
       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(),
-       OrderByFirst());
-
-  InitializeStaticMapsAndSets();
-  CreateRegularExpressions();
+  std::sort(country_calling_code_to_region_code_map_->begin(),
+            country_calling_code_to_region_code_map_->end(),
+            OrderByFirst());
 }
 
 PhoneNumberUtil::~PhoneNumberUtil() {
@@ -691,70 +648,45 @@ PhoneNumberUtil::~PhoneNumberUtil() {
       country_calling_code_to_region_code_map_->end());
 }
 
+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::GetSupportedGlobalNetworkCallingCodes(
+    set<int>* calling_codes) const {
+  DCHECK(calling_codes);
+  for (map<int, PhoneMetadata>::const_iterator it =
+           country_code_to_non_geographical_metadata_map_->begin();
+       it != country_code_to_non_geographical_metadata_map_->end(); ++it) {
+    calling_codes->insert(it->first);
+  }
+}
+
 // Public wrapper function to get a PhoneNumberUtil instance with the default
 // metadata file.
 // static
-#ifdef USE_GOOGLE_BASE
 PhoneNumberUtil* PhoneNumberUtil::GetInstance() {
-  return Singleton<PhoneNumberUtil>::get();
-}
-#endif
-
-void PhoneNumberUtil::CreateRegularExpressions() const {
-  unique_international_prefix.reset(regexp_factory->CreateRegExp(
-     /* "[\\d]+(?:[~⁓∼~][\\d]+)?" */
-      "[\\d]+(?:[~\xE2\x81\x93\xE2\x88\xBC\xEF\xBD\x9E][\\d]+)?"));
-  // The first_group_capturing_pattern was originally set to $1 but there are
-  // some countries for which the first group is not used in the national
-  // pattern (e.g. Argentina) so the $1 group does not match correctly.
-  // Therefore, we use \d, so that the first group actually used in the pattern
-  // will be matched.
-  first_group_capturing_pattern.reset(regexp_factory->CreateRegExp("(\\$\\d)"));
-  carrier_code_pattern.reset(regexp_factory->CreateRegExp("\\$CC"));
-  digits_pattern.reset(
-      regexp_factory->CreateRegExp(StrCat("[", kDigits, "]*")));
-  capturing_digit_pattern.reset(
-      regexp_factory->CreateRegExp(StrCat("([", kDigits, "])")));
-  capturing_ascii_digits_pattern.reset(regexp_factory->CreateRegExp("(\\d+)"));
-  valid_start_char.reset(new string(StrCat("[", kPlusChars, kDigits, "]")));
-  valid_start_char_pattern.reset(
-      regexp_factory->CreateRegExp(*valid_start_char));
-  capture_up_to_second_number_start_pattern.reset(regexp_factory->CreateRegExp(
-      kCaptureUpToSecondNumberStart));
-  unwanted_end_char_pattern.reset(
-      regexp_factory->CreateRegExp(kUnwantedEndChar));
-  separator_pattern.reset(
-      regexp_factory->CreateRegExp(StrCat("[", kValidPunctuation, "]+")));
-  valid_phone_number.reset(new string(
-      StrCat("[", kPlusChars, "]*(?:[", kValidPunctuation, "]*[", kDigits,
-             "]){3,}[", kValidAlpha, kValidPunctuation, kDigits, "]*")));
-  // For parsing, we are slightly more lenient in our interpretation than for
-  // matching. Here we allow a "comma" as a possible extension indicator. When
-  // matching, this is hardly ever used to indicate this.
-  const string single_extn_symbols_for_parsing =
-      StrCat(",", kSingleExtnSymbolsForMatching);
-  extn_patterns_for_parsing.reset(
-      new string(CreateExtnPattern(single_extn_symbols_for_parsing)));
-  extn_patterns_for_matching.reset(
-      new string(CreateExtnPattern(kSingleExtnSymbolsForMatching)));
-
-  extn_pattern.reset(regexp_factory->CreateRegExp(
-      StrCat("(?i)(?:", *extn_patterns_for_parsing, ")$")));
-  valid_phone_number_pattern.reset(regexp_factory->CreateRegExp(
-      StrCat("(?i)", *valid_phone_number,
-             "(?:", *extn_patterns_for_parsing, ")?")));
-  valid_alpha_phone_pattern.reset(regexp_factory->CreateRegExp(
-      StrCat("(?i)(?:.*?[", kValidAlpha, "]){3}")));
-  plus_chars_pattern.reset(
-      regexp_factory->CreateRegExp(StrCat("[", kPlusChars, "]+")));
+  return Singleton<PhoneNumberUtil>::GetInstance();
 }
 
 const string& PhoneNumberUtil::GetExtnPatternsForMatching() const {
-  return *(extn_patterns_for_matching.get());
+  return reg_exps_->extn_patterns_for_matching_;
+}
+
+bool PhoneNumberUtil::StartsWithPlusCharsPattern(const string& number)
+    const {
+  const scoped_ptr<RegExpInput> number_string_piece(
+      reg_exps_->regexp_factory_->CreateInput(number));
+  return reg_exps_->plus_chars_pattern_->Consume(number_string_piece.get());
 }
 
 bool PhoneNumberUtil::ContainsOnlyValidDigits(const string& s) const {
-  return digits_pattern->FullMatch(s);
+  return reg_exps_->digits_pattern_->FullMatch(s);
 }
 
 void PhoneNumberUtil::TrimUnwantedEndChars(string* number) const {
@@ -767,7 +699,7 @@ void PhoneNumberUtil::TrimUnwantedEndChars(string* number) const {
   for (; reverse_it.base() != number_as_unicode.begin(); ++reverse_it) {
     len = reverse_it.get_utf8(current_char);
     current_char[len] = '\0';
-    if (!unwanted_end_char_pattern->FullMatch(current_char)) {
+    if (!reg_exps_->unwanted_end_char_pattern_->FullMatch(current_char)) {
       break;
     }
   }
@@ -784,30 +716,34 @@ bool PhoneNumberUtil::IsFormatEligibleForAsYouTypeFormatter(
   // followed by a single digit, separated by valid phone number punctuation.
   // This prevents invalid punctuation (such as the star sign in Israeli star
   // numbers) getting into the output of the AYTF.
-  const RegExp& eligible_format_pattern = regexp_cache->GetRegExp(
+  const RegExp& eligible_format_pattern = reg_exps_->regexp_cache_->GetRegExp(
       StrCat("[", kValidPunctuation, "]*", "(\\$\\d", "[",
              kValidPunctuation, "]*)+"));
   return eligible_format_pattern.FullMatch(format);
 }
 
-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);
-  }
+bool PhoneNumberUtil::FormattingRuleHasFirstGroupOnly(
+    const string& national_prefix_formatting_rule) const {
+  // A pattern that is used to determine if the national prefix formatting rule
+  // has the first group only, i.e., does not start with the national prefix.
+  // Note that the pattern explicitly allows for unbalanced parentheses.
+  const RegExp& first_group_only_prefix_pattern =
+      reg_exps_->regexp_cache_->GetRegExp("\\(?\\$1\\)?");
+  return national_prefix_formatting_rule.empty() ||
+      first_group_only_prefix_pattern.FullMatch(
+          national_prefix_formatting_rule);
 }
 
 void PhoneNumberUtil::GetNddPrefixForRegion(const string& region_code,
                                             bool strip_non_digits,
                                             string* national_prefix) const {
   DCHECK(national_prefix);
-  if (!IsValidRegionCode(region_code)) {
-    LOG(ERROR) << "Invalid region code provided.";
+  const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
+  if (!metadata) {
+    LOG(WARNING) << "Invalid or unknown region code (" << 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
@@ -821,20 +757,19 @@ bool PhoneNumberUtil::IsValidRegionCode(const string& region_code) const {
           region_to_metadata_map_->end());
 }
 
-bool PhoneNumberUtil::HasValidRegionCode(const string& region_code,
-                                         int country_calling_code,
-                                         const string& number) const {
-  if (!IsValidRegionCode(region_code)) {
-    VLOG(1) << "Number " << number
-            << " has invalid or missing country calling code ("
-            << country_calling_code
-            << ")";
-    return false;
-  }
-  return true;
+bool PhoneNumberUtil::HasValidCountryCallingCode(
+    int country_calling_code) const {
+  // Create an 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;
+  return (binary_search(country_calling_code_to_region_code_map_->begin(),
+                        country_calling_code_to_region_code_map_->end(),
+                        target_pair, OrderByFirst()));
 }
 
-// Returns a pointer to the phone metadata for the appropriate region.
+// Returns a pointer to the phone metadata for the appropriate region or NULL
+// if the region code is invalid or unknown.
 const PhoneMetadata* PhoneNumberUtil::GetMetadataForRegion(
     const string& region_code) const {
   map<string, PhoneMetadata>::const_iterator it =
@@ -845,6 +780,17 @@ const PhoneMetadata* PhoneNumberUtil::GetMetadataForRegion(
   return NULL;
 }
 
+const PhoneMetadata* PhoneNumberUtil::GetMetadataForNonGeographicalRegion(
+    int country_calling_code) const {
+  map<int, PhoneMetadata>::const_iterator it =
+      country_code_to_non_geographical_metadata_map_->find(
+          country_calling_code);
+  if (it != country_code_to_non_geographical_metadata_map_->end()) {
+    return &it->second;
+  }
+  return NULL;
+}
+
 void PhoneNumberUtil::Format(const PhoneNumber& number,
                              PhoneNumberFormat number_format,
                              string* formatted_number) const {
@@ -852,6 +798,11 @@ void PhoneNumberUtil::Format(const PhoneNumber& number,
   if (number.national_number() == 0) {
     const string& raw_input = number.raw_input();
     if (!raw_input.empty()) {
+      // Unparseable numbers that kept their raw input just use that.
+      // This is the only case where a number can be formatted as E164 without a
+      // leading '+' symbol (but the original number wasn't parseable anyway).
+      // TODO: Consider removing the 'if' above so that unparseable
+      // strings without raw input format to the empty string instead of "+00".
       formatted_number->assign(raw_input);
       return;
     }
@@ -860,10 +811,16 @@ void PhoneNumberUtil::Format(const PhoneNumber& number,
   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);
+    // Early exit for E164 case (even if the country calling code is invalid)
+    // since no formatting of the national number needs to be applied.
+    // Extensions are not formatted.
+    formatted_number->assign(national_significant_number);
+    PrefixNumberWithCountryCallingCode(country_calling_code, E164,
+                                       formatted_number);
+    return;
+  }
+  if (!HasValidCountryCallingCode(country_calling_code)) {
+    formatted_number->assign(national_significant_number);
     return;
   }
   // Note here that all NANPA formatting rules are contained by US, so we use
@@ -872,20 +829,17 @@ void PhoneNumberUtil::Format(const PhoneNumber& number,
   // contained by Réunion.
   string region_code;
   GetRegionCodeForCountryCode(country_calling_code, &region_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);
+  // Metadata cannot be NULL because the country calling code is valid (which
+  // means that the region code cannot be ZZ and must be one of our supported
+  // region codes).
+  const PhoneMetadata* metadata =
+      GetMetadataForRegionOrCallingCode(country_calling_code, region_code);
+  FormatNsn(national_significant_number, *metadata, number_format,
+            formatted_number);
+  MaybeAppendFormattedExtension(number, *metadata, number_format,
+                                formatted_number);
+  PrefixNumberWithCountryCallingCode(country_calling_code, number_format,
+                                     formatted_number);
 }
 
 void PhoneNumberUtil::FormatByPattern(
@@ -899,55 +853,53 @@ void PhoneNumberUtil::FormatByPattern(
   // 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, &region_code);
   string national_significant_number;
   GetNationalSignificantNumber(number, &national_significant_number);
-  if (!HasValidRegionCode(region_code, country_calling_code,
-                          national_significant_number)) {
+  if (!HasValidCountryCallingCode(country_calling_code)) {
     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 region_code;
+  GetRegionCodeForCountryCode(country_calling_code, &region_code);
+  // Metadata cannot be NULL because the country calling code is valid.
+  const PhoneMetadata* metadata =
+      GetMetadataForRegionOrCallingCode(country_calling_code, region_code);
+  const NumberFormat* formatting_pattern =
+      ChooseFormattingPatternForNumber(user_defined_formats,
+                                       national_significant_number);
+  if (!formatting_pattern) {
+    // If no pattern above is matched, we format the number as a whole.
+    formatted_number->assign(national_significant_number);
+  } else {
+    NumberFormat num_format_copy;
+    // Before we do a replacement of the national prefix pattern $NP with the
+    // national prefix, we need to copy the rule so that subsequent replacements
+    // for different numbers have the appropriate national prefix.
+    num_format_copy.MergeFrom(*formatting_pattern);
     string national_prefix_formatting_rule(
-        it->national_prefix_formatting_rule());
+        formatting_pattern->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);
+      const string& national_prefix = metadata->national_prefix();
       if (!national_prefix.empty()) {
         // Replace $NP with national prefix and $FG with the first group ($1).
         GlobalReplaceSubstring("$NP", national_prefix,
                                &national_prefix_formatting_rule);
         GlobalReplaceSubstring("$FG", "$1",
                                &national_prefix_formatting_rule);
-        num_format_copy->set_national_prefix_formatting_rule(
+        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();
+        num_format_copy.clear_national_prefix_formatting_rule();
       }
-    } else {
-      user_defined_formats_copy.Add()->MergeFrom(*it);
     }
+    FormatNsnUsingPattern(national_significant_number, num_format_copy,
+                          number_format, formatted_number);
   }
-  string formatted_number_without_extension;
-  FormatAccordingToFormats(national_significant_number,
-                           user_defined_formats_copy,
-                           number_format, national_significant_number,
-                           &formatted_number_without_extension);
-  string formatted_extension;
-  MaybeGetFormattedExtension(number, region_code, NATIONAL,
-                             &formatted_extension);
-  FormatNumberByFormat(country_calling_code, number_format,
-                       formatted_number_without_extension, formatted_extension,
-                       formatted_number);
+  MaybeAppendFormattedExtension(number, *metadata, NATIONAL, formatted_number);
+  PrefixNumberWithCountryCallingCode(country_calling_code, number_format,
+                                     formatted_number);
 }
 
 void PhoneNumberUtil::FormatNationalNumberWithCarrierCode(
@@ -957,26 +909,32 @@ void PhoneNumberUtil::FormatNationalNumberWithCarrierCode(
   int country_calling_code = number.country_code();
   string national_significant_number;
   GetNationalSignificantNumber(number, &national_significant_number);
+  if (!HasValidCountryCallingCode(country_calling_code)) {
+    formatted_number->assign(national_significant_number);
+    return;
+  }
+
   // 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, &region_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);
+  // Metadata cannot be NULL because the country calling code is valid.
+  const PhoneMetadata* metadata =
+      GetMetadataForRegionOrCallingCode(country_calling_code, region_code);
+  FormatNsnWithCarrier(national_significant_number, *metadata, NATIONAL,
+                       carrier_code, formatted_number);
+  MaybeAppendFormattedExtension(number, *metadata, NATIONAL, formatted_number);
+  PrefixNumberWithCountryCallingCode(country_calling_code, NATIONAL,
+                                     formatted_number);
+}
+
+const PhoneMetadata* PhoneNumberUtil::GetMetadataForRegionOrCallingCode(
+      int country_calling_code, const string& region_code) const {
+  return kRegionCodeForNonGeoEntity == region_code
+      ? GetMetadataForNonGeographicalRegion(country_calling_code)
+      : GetMetadataForRegion(region_code);
 }
 
 void PhoneNumberUtil::FormatNationalNumberWithPreferredCarrierCode(
@@ -996,48 +954,104 @@ void PhoneNumberUtil::FormatNumberForMobileDialing(
     const string& calling_from,
     bool with_formatting,
     string* formatted_number) const {
-  string region_code;
-  GetRegionCodeForNumber(number, &region_code);
-  if (!IsValidRegionCode(region_code)) {
+  int country_calling_code = number.country_code();
+  if (!HasValidCountryCallingCode(country_calling_code)) {
     formatted_number->assign(number.has_raw_input() ? number.raw_input() : "");
     return;
   }
 
+  formatted_number->assign("");
   // Clear the extension, as that part cannot normally be dialed together with
   // the main number.
   PhoneNumber number_no_extension(number);
   number_no_extension.clear_extension();
+  string region_code;
+  GetRegionCodeForCountryCode(country_calling_code, &region_code);
   PhoneNumberType number_type = GetNumberType(number_no_extension);
-  if ((region_code == "CO") && (calling_from == "CO") &&
-      (number_type == FIXED_LINE)) {
+  bool is_valid_number = (number_type != UNKNOWN);
+  if (calling_from == region_code) {
+    bool is_fixed_line_or_mobile =
+        (number_type == FIXED_LINE) || (number_type == MOBILE) ||
+        (number_type == FIXED_LINE_OR_MOBILE);
+    // Carrier codes may be needed in some countries. We handle this here.
+    if ((region_code == "CO") && (number_type == FIXED_LINE)) {
       FormatNationalNumberWithCarrierCode(
           number_no_extension, kColombiaMobileToFixedLinePrefix,
           formatted_number);
-  } else if ((region_code == "BR") && (calling_from == "BR") &&
-      ((number_type == FIXED_LINE) || (number_type == MOBILE) ||
-       (number_type == FIXED_LINE_OR_MOBILE))) {
-    if (number_no_extension.has_preferred_domestic_carrier_code()) {
+    } else if ((region_code == "BR") && (is_fixed_line_or_mobile)) {
+      if (number_no_extension.has_preferred_domestic_carrier_code()) {
       FormatNationalNumberWithPreferredCarrierCode(number_no_extension, "",
                                                    formatted_number);
+      } else {
+        // Brazilian fixed line and mobile numbers need to be dialed with a
+        // carrier code when called within Brazil. Without that, most of the
+        // carriers won't connect the call. Because of that, we return an empty
+        // string here.
+        formatted_number->assign("");
+      }
+    } else if (is_valid_number && region_code == "HU") {
+      // The national format for HU numbers doesn't contain the national prefix,
+      // because that is how numbers are normally written down. However, the
+      // national prefix is obligatory when dialing from a mobile phone, except
+      // for short numbers. As a result, we add it back here if it is a valid
+      // regular length phone number.
+      Format(number_no_extension, NATIONAL, formatted_number);
+      string hu_national_prefix;
+      GetNddPrefixForRegion(region_code, true /* strip non-digits */,
+                            &hu_national_prefix);
+      formatted_number->assign(
+          StrCat(hu_national_prefix, " ", *formatted_number));
+    } else if (country_calling_code == kNanpaCountryCode) {
+      // For NANPA countries, we output international format for numbers that
+      // can be dialed internationally, since that always works, except for
+      // numbers which might potentially be short numbers, which are always
+      // dialled in national format.
+      const PhoneMetadata* region_metadata = GetMetadataForRegion(calling_from);
+      string national_number;
+      GetNationalSignificantNumber(number_no_extension, &national_number);
+      if (CanBeInternationallyDialled(number_no_extension) &&
+          !IsShorterThanPossibleNormalNumber(region_metadata,
+              national_number)) {
+        Format(number_no_extension, INTERNATIONAL, formatted_number);
+      } else {
+        Format(number_no_extension, NATIONAL, formatted_number);
+      }
     } else {
-      // Brazilian fixed line and mobile numbers need to be dialed with a
-      // carrier code when called within Brazil. Without that, most of the
-      // carriers won't connect the call. Because of that, we return an empty
-      // string here.
-      formatted_number->assign("");
+      // For non-geographical countries, and Mexican and Chilean fixed line and
+      // mobile numbers, we output international format for numbers that can be
+      // dialed internationally as that always works.
+      if ((region_code == kRegionCodeForNonGeoEntity ||
+           // MX fixed line and mobile numbers should always be formatted in
+           // international format, even when dialed within MX. For national
+           // format to work, a carrier code needs to be used, and the correct
+           // carrier code depends on if the caller and callee are from the same
+           // local area. It is trickier to get that to work correctly than
+           // using international format, which is tested to work fine on all
+           // carriers.
+           // CL fixed line numbers need the national prefix when dialing in the
+           // national format, but don't have it when used for display. The
+           // reverse is true for mobile numbers. As a result, we output them in
+           // the international format to make it work.
+           ((region_code == "MX" || region_code == "CL") &&
+               is_fixed_line_or_mobile)) &&
+          CanBeInternationallyDialled(number_no_extension)) {
+        Format(number_no_extension, INTERNATIONAL, formatted_number);
+      } else {
+        Format(number_no_extension, NATIONAL, formatted_number);
+      }
     }
-  } else if (CanBeInternationallyDialled(number_no_extension)) {
+  } else if (is_valid_number &&
+      CanBeInternationallyDialled(number_no_extension)) {
+    // We assume that short numbers are not diallable from outside their
+    // region, so if a number is not a valid regular length phone number, we
+    // treat it as if it cannot be internationally dialled.
     with_formatting
         ? Format(number_no_extension, INTERNATIONAL, formatted_number)
         : Format(number_no_extension, E164, formatted_number);
     return;
-  } else if (calling_from == region_code) {
-    Format(number_no_extension, NATIONAL, formatted_number);
-  } else {
-    formatted_number->assign("");
   }
   if (!with_formatting) {
-    NormalizeDigitsOnly(formatted_number);
+    NormalizeDiallableCharsOnly(formatted_number);
   }
 }
 
@@ -1047,18 +1061,16 @@ void PhoneNumberUtil::FormatOutOfCountryCallingNumber(
     string* formatted_number) const {
   DCHECK(formatted_number);
   if (!IsValidRegionCode(calling_from)) {
-    VLOG(1) << "Trying to format number from invalid region. International"
-            << " formatting applied.";
+    LOG(WARNING) << "Trying to format number from invalid region "
+                 << calling_from
+                 << ". International formatting applied.";
     Format(number, INTERNATIONAL, formatted_number);
     return;
   }
   int country_code = number.country_code();
-  string region_code;
-  GetRegionCodeForCountryCode(country_code, &region_code);
   string national_significant_number;
   GetNationalSignificantNumber(number, &national_significant_number);
-  if (!HasValidRegionCode(region_code, country_code,
-                          national_significant_number)) {
+  if (!HasValidCountryCallingCode(country_code)) {
     formatted_number->assign(national_significant_number);
     return;
   }
@@ -1066,12 +1078,11 @@ void PhoneNumberUtil::FormatOutOfCountryCallingNumber(
     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));
+      Format(number, NATIONAL, formatted_number);
+      formatted_number->insert(0, StrCat(country_code, " "));
       return;
     }
-  } else if (country_code == GetCountryCodeForRegion(calling_from)) {
+  } else if (country_code == GetCountryCodeForValidRegion(calling_from)) {
     // If neither region is a NANPA region, then we check to see if the
     // country calling code of the number and the country calling code of the
     // region we are calling from are the same.
@@ -1087,28 +1098,35 @@ void PhoneNumberUtil::FormatOutOfCountryCallingNumber(
     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);
+  // Metadata cannot be NULL because we checked 'IsValidRegionCode()' above.
+  const PhoneMetadata* metadata_calling_from =
+      GetMetadataForRegion(calling_from);
+  const string& international_prefix =
+      metadata_calling_from->international_prefix();
+
   // For regions that have multiple international prefixes, the international
   // format of the number is returned, unless there is a preferred international
   // prefix.
   const string international_prefix_for_formatting(
-      unique_international_prefix->FullMatch(international_prefix)
+      reg_exps_->unique_international_prefix_->FullMatch(international_prefix)
       ? international_prefix
-      : metadata->preferred_international_prefix());
+      : metadata_calling_from->preferred_international_prefix());
+
+  string region_code;
+  GetRegionCodeForCountryCode(country_code, &region_code);
+  // Metadata cannot be NULL because the country_code is valid.
+  const PhoneMetadata* metadata_for_region =
+      GetMetadataForRegionOrCallingCode(country_code, region_code);
+  FormatNsn(national_significant_number, *metadata_for_region, INTERNATIONAL,
+            formatted_number);
+  MaybeAppendFormattedExtension(number, *metadata_for_region, INTERNATIONAL,
+                                formatted_number);
   if (!international_prefix_for_formatting.empty()) {
-    formatted_number->assign(
-        StrCat(international_prefix_for_formatting, " ", country_code, " ",
-               formatted_national_number, formatted_extension));
+    formatted_number->insert(
+        0, StrCat(international_prefix_for_formatting, " ", country_code, " "));
   } else {
-    FormatNumberByFormat(country_code, INTERNATIONAL, formatted_national_number,
-                         formatted_extension, formatted_number);
+    PrefixNumberWithCountryCallingCode(country_code, INTERNATIONAL,
+                                       formatted_number);
   }
 }
 
@@ -1117,7 +1135,11 @@ void PhoneNumberUtil::FormatInOriginalFormat(const PhoneNumber& number,
                                              string* formatted_number) const {
   DCHECK(formatted_number);
 
-  if (number.has_raw_input() && !IsValidNumber(number)) {
+  if (number.has_raw_input() &&
+      (HasUnexpectedItalianLeadingZero(number) ||
+       !HasFormattingPatternForNumber(number))) {
+    // We check if we have the formatting pattern because without that, we might
+    // format the number as a group without national prefix.
     formatted_number->assign(number.raw_input());
     return;
   }
@@ -1128,19 +1150,144 @@ void PhoneNumberUtil::FormatInOriginalFormat(const PhoneNumber& number,
   switch (number.country_code_source()) {
     case PhoneNumber::FROM_NUMBER_WITH_PLUS_SIGN:
       Format(number, INTERNATIONAL, formatted_number);
-      return;
+      break;
     case PhoneNumber::FROM_NUMBER_WITH_IDD:
       FormatOutOfCountryCallingNumber(number, region_calling_from,
                                       formatted_number);
-      return;
+      break;
     case PhoneNumber::FROM_NUMBER_WITHOUT_PLUS_SIGN:
       Format(number, INTERNATIONAL, formatted_number);
       formatted_number->erase(formatted_number->begin());
-      return;
+      break;
     case PhoneNumber::FROM_DEFAULT_COUNTRY:
+      // Fall-through to default case.
     default:
-      Format(number, NATIONAL, formatted_number);
+      string region_code;
+      GetRegionCodeForCountryCode(number.country_code(), &region_code);
+      // We strip non-digits from the NDD here, and from the raw input later, so
+      // that we can compare them easily.
+      string national_prefix;
+      GetNddPrefixForRegion(region_code, true /* strip non-digits */,
+                            &national_prefix);
+      if (national_prefix.empty()) {
+        // If the region doesn't have a national prefix at all, we can safely
+        // return the national format without worrying about a national prefix
+        // being added.
+        Format(number, NATIONAL, formatted_number);
+        break;
+      }
+      // Otherwise, we check if the original number was entered with a national
+      // prefix.
+      if (RawInputContainsNationalPrefix(number.raw_input(), national_prefix,
+                                         region_code)) {
+        // If so, we can safely return the national format.
+        Format(number, NATIONAL, formatted_number);
+        break;
+      }
+      // Metadata cannot be NULL here because GetNddPrefixForRegion() (above)
+      // leaves the prefix empty if there is no metadata for the region.
+      const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
+      string national_number;
+      GetNationalSignificantNumber(number, &national_number);
+      // This shouldn't be NULL, because we have checked that above with
+      // HasFormattingPatternForNumber.
+      const NumberFormat* format_rule =
+          ChooseFormattingPatternForNumber(metadata->number_format(),
+                                           national_number);
+      // The format rule could still be NULL here if the national number was 0
+      // and there was no raw input (this should not be possible for numbers
+      // generated by the phonenumber library as they would also not have a
+      // country calling code and we would have exited earlier).
+      if (!format_rule) {
+        Format(number, NATIONAL, formatted_number);
+        break;
+      }
+      // When the format we apply to this number doesn't contain national
+      // prefix, we can just return the national format.
+      // TODO: Refactor the code below with the code in
+      // IsNationalPrefixPresentIfRequired.
+      string candidate_national_prefix_rule(
+          format_rule->national_prefix_formatting_rule());
+      // We assume that the first-group symbol will never be _before_ the
+      // national prefix.
+      if (!candidate_national_prefix_rule.empty()) {
+        candidate_national_prefix_rule.erase(
+            candidate_national_prefix_rule.find("$1"));
+        NormalizeDigitsOnly(&candidate_national_prefix_rule);
+      }
+      if (candidate_national_prefix_rule.empty()) {
+        // National prefix not used when formatting this number.
+        Format(number, NATIONAL, formatted_number);
+        break;
+      }
+      // Otherwise, we need to remove the national prefix from our output.
+      RepeatedPtrField<NumberFormat> number_formats;
+      NumberFormat* number_format = number_formats.Add();
+      number_format->MergeFrom(*format_rule);
+      number_format->clear_national_prefix_formatting_rule();
+      FormatByPattern(number, NATIONAL, number_formats, formatted_number);
+      break;
+  }
+  // If no digit is inserted/removed/modified as a result of our formatting, we
+  // return the formatted phone number; otherwise we return the raw input the
+  // user entered.
+  if (!formatted_number->empty() && !number.raw_input().empty()) {
+    string normalized_formatted_number(*formatted_number);
+    NormalizeDiallableCharsOnly(&normalized_formatted_number);
+    string normalized_raw_input(number.raw_input());
+    NormalizeDiallableCharsOnly(&normalized_raw_input);
+    if (normalized_formatted_number != normalized_raw_input) {
+      formatted_number->assign(number.raw_input());
+    }
+  }
+}
+
+// Check if raw_input, which is assumed to be in the national format, has a
+// national prefix. The national prefix is assumed to be in digits-only form.
+bool PhoneNumberUtil::RawInputContainsNationalPrefix(
+    const string& raw_input,
+    const string& national_prefix,
+    const string& region_code) const {
+  string normalized_national_number(raw_input);
+  NormalizeDigitsOnly(&normalized_national_number);
+  if (HasPrefixString(normalized_national_number, national_prefix)) {
+    // Some Japanese numbers (e.g. 00777123) might be mistaken to contain
+    // the national prefix when written without it (e.g. 0777123) if we just
+    // do prefix matching. To tackle that, we check the validity of the
+    // number if the assumed national prefix is removed (777123 won't be
+    // valid in Japan).
+    PhoneNumber number_without_national_prefix;
+    if (Parse(normalized_national_number.substr(national_prefix.length()),
+              region_code, &number_without_national_prefix)
+        == NO_PARSING_ERROR) {
+      return IsValidNumber(number_without_national_prefix);
+    }
   }
+  return false;
+}
+
+bool PhoneNumberUtil::HasUnexpectedItalianLeadingZero(
+    const PhoneNumber& number) const {
+  return number.has_italian_leading_zero() &&
+      !IsLeadingZeroPossible(number.country_code());
+}
+
+bool PhoneNumberUtil::HasFormattingPatternForNumber(
+    const PhoneNumber& number) const {
+  int country_calling_code = number.country_code();
+  string region_code;
+  GetRegionCodeForCountryCode(country_calling_code, &region_code);
+  const PhoneMetadata* metadata =
+      GetMetadataForRegionOrCallingCode(country_calling_code, region_code);
+  if (!metadata) {
+    return false;
+  }
+  string national_number;
+  GetNationalSignificantNumber(number, &national_number);
+  const NumberFormat* format_rule =
+      ChooseFormattingPatternForNumber(metadata->number_format(),
+                                       national_number);
+  return format_rule;
 }
 
 void PhoneNumberUtil::FormatOutOfCountryKeepingAlphaChars(
@@ -1153,10 +1300,8 @@ void PhoneNumberUtil::FormatOutOfCountryKeepingAlphaChars(
     FormatOutOfCountryCallingNumber(number, calling_from, formatted_number);
     return;
   }
-  string region_code;
-  GetRegionCodeForCountryCode(number.country_code(), &region_code);
-  if (!HasValidRegionCode(region_code, number.country_code(),
-                          number.raw_input())) {
+  int country_code = number.country_code();
+  if (!HasValidCountryCallingCode(country_code)) {
     formatted_number->assign(number.raw_input());
     return;
   }
@@ -1164,7 +1309,8 @@ void PhoneNumberUtil::FormatOutOfCountryKeepingAlphaChars(
   // 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);
+  NormalizeHelper(reg_exps_->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
@@ -1179,64 +1325,162 @@ void PhoneNumberUtil::FormatOutOfCountryKeepingAlphaChars(
     }
   }
   const PhoneMetadata* metadata = GetMetadataForRegion(calling_from);
-  if (number.country_code() == kNanpaCountryCode) {
+  if (country_code == kNanpaCountryCode) {
     if (IsNANPACountry(calling_from)) {
-      formatted_number->assign(StrCat(number.country_code(), " ",
-                                      raw_input_copy));
+      StrAppend(formatted_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");
+  } else if (metadata &&
+             country_code == GetCountryCodeForValidRegion(calling_from)) {
+    const NumberFormat* formatting_pattern =
+        ChooseFormattingPatternForNumber(metadata->number_format(),
+                                         national_number);
+    if (!formatting_pattern) {
+      // If no pattern above is matched, we format the original input.
+      formatted_number->assign(raw_input_copy);
+      return;
     }
-    // Now we format using these patterns instead of the default pattern, but
-    // with the national prefix prefixed if necessary, by choosing the format
-    // rule based on the leading digits present in the unformatted national
-    // number.
+    NumberFormat new_format;
+    new_format.MergeFrom(*formatting_pattern);
+    // The first group is the first group of digits that the user wrote
+    // together.
+    new_format.set_pattern("(\\d+)(.*)");
+    // Here we just concatenate them back together after the national prefix
+    // has been fixed.
+    new_format.set_format("$1$2");
+    // Now we format using this pattern instead of the default pattern, but
+    // with the national prefix prefixed if necessary.
     // This will not work in the cases where the pattern (and not the
     // 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);
+    FormatNsnUsingPattern(raw_input_copy, new_format, NATIONAL,
+                          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.
-  const string international_prefix_for_formatting(
-      unique_international_prefix->FullMatch(international_prefix)
-      ? international_prefix
-      : metadata->preferred_international_prefix());
+  string international_prefix_for_formatting;
+  // If an unsupported region-calling-from is entered, or a country with
+  // multiple international prefixes, the international format of the number is
+  // returned, unless there is a preferred international prefix.
+  if (metadata) {
+    const string& international_prefix = metadata->international_prefix();
+    international_prefix_for_formatting =
+        reg_exps_->unique_international_prefix_->FullMatch(international_prefix)
+        ? 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));
+    StrAppend(formatted_number, international_prefix_for_formatting, " ",
+              country_code, " ", raw_input_copy);
   } else {
-    FormatNumberByFormat(number.country_code(), INTERNATIONAL, raw_input_copy,
-                         "", formatted_number);
+    // Invalid region entered as country-calling-from (so no metadata was found
+    // for it) or the region chosen has multiple international dialling
+    // prefixes.
+    LOG(WARNING) << "Trying to format number from invalid region "
+                 << calling_from
+                 << ". International formatting applied.";
+    formatted_number->assign(raw_input_copy);
+    PrefixNumberWithCountryCallingCode(country_code, INTERNATIONAL,
+                                       formatted_number);
   }
 }
 
-void PhoneNumberUtil::FormatNationalNumber(
-    const string& number,
-    const string& region_code,
-    PhoneNumberFormat number_format,
+const NumberFormat* PhoneNumberUtil::ChooseFormattingPatternForNumber(
+    const RepeatedPtrField<NumberFormat>& available_formats,
+    const string& national_number) const {
+  for (RepeatedPtrField<NumberFormat>::const_iterator
+       it = available_formats.begin(); it != available_formats.end(); ++it) {
+    int size = it->leading_digits_pattern_size();
+    if (size > 0) {
+      const scoped_ptr<RegExpInput> number_copy(
+          reg_exps_->regexp_factory_->CreateInput(national_number));
+      // We always use the last leading_digits_pattern, as it is the most
+      // detailed.
+      if (!reg_exps_->regexp_cache_->GetRegExp(
+              it->leading_digits_pattern(size - 1)).Consume(
+                  number_copy.get())) {
+        continue;
+      }
+    }
+    const RegExp& pattern_to_match(
+        reg_exps_->regexp_cache_->GetRegExp(it->pattern()));
+    if (pattern_to_match.FullMatch(national_number)) {
+      return &(*it);
+    }
+  }
+  return NULL;
+}
+
+// Note that carrier_code is optional - if an empty string, no carrier code
+// replacement will take place.
+void PhoneNumberUtil::FormatNsnUsingPatternWithCarrier(
+    const string& national_number,
+    const NumberFormat& formatting_pattern,
+    PhoneNumberUtil::PhoneNumberFormat number_format,
+    const string& carrier_code,
     string* formatted_number) const {
   DCHECK(formatted_number);
-  FormatNationalNumberWithCarrier(number, region_code, number_format, "",
-                                  formatted_number);
+  string number_format_rule(formatting_pattern.format());
+  if (number_format == PhoneNumberUtil::NATIONAL &&
+      carrier_code.length() > 0 &&
+      formatting_pattern.domestic_carrier_code_formatting_rule().length() > 0) {
+    // Replace the $CC in the formatting rule with the desired carrier code.
+    string carrier_code_formatting_rule =
+        formatting_pattern.domestic_carrier_code_formatting_rule();
+    reg_exps_->carrier_code_pattern_->Replace(&carrier_code_formatting_rule,
+                                              carrier_code);
+    reg_exps_->first_group_capturing_pattern_->
+        Replace(&number_format_rule, carrier_code_formatting_rule);
+  } else {
+    // Use the national prefix formatting rule instead.
+    string national_prefix_formatting_rule =
+        formatting_pattern.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.
+      reg_exps_->first_group_capturing_pattern_->Replace(
+          &number_format_rule, national_prefix_formatting_rule);
+    }
+  }
+  formatted_number->assign(national_number);
+
+  const RegExp& pattern_to_match(
+      reg_exps_->regexp_cache_->GetRegExp(formatting_pattern.pattern()));
+  pattern_to_match.GlobalReplace(formatted_number, number_format_rule);
+
+  if (number_format == RFC3966) {
+    // First consume any leading punctuation, if any was present.
+    const scoped_ptr<RegExpInput> number(
+        reg_exps_->regexp_factory_->CreateInput(*formatted_number));
+    if (reg_exps_->separator_pattern_->Consume(number.get())) {
+      formatted_number->assign(number->ToString());
+    }
+    // Then replace all separators with a "-".
+    reg_exps_->separator_pattern_->GlobalReplace(formatted_number, "-");
+  }
+}
+
+// Simple wrapper of FormatNsnUsingPatternWithCarrier for the common case of
+// no carrier code.
+void PhoneNumberUtil::FormatNsnUsingPattern(
+    const string& national_number,
+    const NumberFormat& formatting_pattern,
+    PhoneNumberUtil::PhoneNumberFormat number_format,
+    string* formatted_number) const {
+  DCHECK(formatted_number);
+  FormatNsnUsingPatternWithCarrier(national_number, formatting_pattern,
+                                   number_format, "", formatted_number);
+}
+
+void PhoneNumberUtil::FormatNsn(const string& number,
+                                const PhoneMetadata& metadata,
+                                PhoneNumberFormat number_format,
+                                string* formatted_number) const {
+  DCHECK(formatted_number);
+  FormatNsnWithCarrier(number, metadata, number_format, "", formatted_number);
 }
 
 // Note in some regions, the national number can be written in two completely
@@ -1244,60 +1488,47 @@ void PhoneNumberUtil::FormatNationalNumber(
 // 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 {
+void PhoneNumberUtil::FormatNsnWithCarrier(const string& number,
+                                           const PhoneMetadata& metadata,
+                                           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 "-".
-    separator_pattern->GlobalReplace(formatted_number, "-");
+      (metadata.intl_number_format_size() == 0 || number_format == NATIONAL)
+      ? metadata.number_format()
+      : metadata.intl_number_format();
+  const NumberFormat* formatting_pattern =
+      ChooseFormattingPatternForNumber(available_formats, number);
+  if (!formatting_pattern) {
+    formatted_number->assign(number);
+  } else {
+    FormatNsnUsingPatternWithCarrier(number, *formatting_pattern, number_format,
+                                     carrier_code, formatted_number);
   }
 }
 
-// Gets the formatted extension of a phone number, if the phone number had an
-// extension specified. If not, it returns an empty string.
-void PhoneNumberUtil::MaybeGetFormattedExtension(
+// Appends the formatted extension of a phone number, if the phone number had an
+// extension specified.
+void PhoneNumberUtil::MaybeAppendFormattedExtension(
     const PhoneNumber& number,
-    const string& region_code,
+    const PhoneMetadata& metadata,
     PhoneNumberFormat number_format,
-    string* extension) const {
-  DCHECK(extension);
-  if (!number.has_extension() || number.extension().length() == 0) {
-    extension->assign("");
-  } else {
+    string* formatted_number) const {
+  DCHECK(formatted_number);
+  if (number.has_extension() && number.extension().length() > 0) {
     if (number_format == RFC3966) {
-      StrAppend(extension, kRfc3966ExtnPrefix, number.extension());
-      return;
+      StrAppend(formatted_number, kRfc3966ExtnPrefix, number.extension());
+    } else {
+      if (metadata.has_preferred_extn_prefix()) {
+        StrAppend(formatted_number, metadata.preferred_extn_prefix(),
+                  number.extension());
+      } else {
+        StrAppend(formatted_number, kDefaultExtnPrefix, number.extension());
+      }
     }
-    FormatExtension(number.extension(), 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));
   }
 }
 
@@ -1337,8 +1568,8 @@ void PhoneNumberUtil::GetRegionCodeForCountryCode(
   list<string> region_codes;
 
   GetRegionCodesForCountryCallingCode(country_calling_code, &region_codes);
-  *region_code = (region_codes.size() > 0)
-      region_codes.front() : RegionCode::GetUnknown();
+  *region_code = (region_codes.size() > 0) ?
+      region_codes.front() : RegionCode::GetUnknown();
 }
 
 void PhoneNumberUtil::GetRegionCodeForNumber(const PhoneNumber& number,
@@ -1371,12 +1602,14 @@ void PhoneNumberUtil::GetRegionCodeForNumberFromRegionList(
   GetNationalSignificantNumber(number, &national_number);
   for (list<string>::const_iterator it = region_codes.begin();
        it != region_codes.end(); ++it) {
+    // Metadata cannot be NULL because the region codes come from the country
+    // calling code map.
     const PhoneMetadata* metadata = GetMetadataForRegion(*it);
     if (metadata->has_leading_digits()) {
       const scoped_ptr<RegExpInput> number(
-          regexp_factory->CreateInput(national_number));
-      if (regexp_cache->GetRegExp(metadata->leading_digits()).Consume(
-          number.get())) {
+          reg_exps_->regexp_factory_->CreateInput(national_number));
+      if (reg_exps_->regexp_cache_->
+              GetRegExp(metadata->leading_digits()).Consume(number.get())) {
         *region_code = *it;
         return;
       }
@@ -1390,41 +1623,77 @@ void PhoneNumberUtil::GetRegionCodeForNumberFromRegionList(
 
 int PhoneNumberUtil::GetCountryCodeForRegion(const string& region_code) const {
   if (!IsValidRegionCode(region_code)) {
-    LOG(ERROR) << "Invalid or unknown region code provided.";
+    LOG(WARNING) << "Invalid or unknown region code (" << region_code
+                 << ") provided.";
     return 0;
   }
+  return GetCountryCodeForValidRegion(region_code);
+}
+
+int PhoneNumberUtil::GetCountryCodeForValidRegion(
+    const string& region_code) const {
   const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
   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.
+// if the region was unknown or 001 (representing non-geographical regions), or
+// if no number exists.
 bool PhoneNumberUtil::GetExampleNumber(const string& region_code,
                                        PhoneNumber* number) const {
   DCHECK(number);
-  return GetExampleNumberForType(region_code,
-                                 FIXED_LINE,
-                                 number);
+  return GetExampleNumberForType(region_code, FIXED_LINE, number);
 }
 
 // Gets a valid number for the specified region_code and type.  Returns false if
-// the country was unknown or if no number exists.
+// the country was unknown or 001 (representing non-geographical regions), or if
+// no number exists.
 bool PhoneNumberUtil::GetExampleNumberForType(
     const string& region_code,
     PhoneNumberUtil::PhoneNumberType type,
     PhoneNumber* number) const {
   DCHECK(number);
   if (!IsValidRegionCode(region_code)) {
-    LOG(WARNING) << "Invalid or unknown region code provided.";
+    LOG(WARNING) << "Invalid or unknown region code (" << region_code
+                 << ") provided.";
     return false;
   }
   const PhoneMetadata* region_metadata = GetMetadataForRegion(region_code);
-  const PhoneNumberDesc* description =
-      GetNumberDescByType(*region_metadata, type);
-  if (description && description->has_example_number()) {
-    return (Parse(description->example_number(),
-                  region_code,
-                  number) == NO_PARSING_ERROR);
+  const PhoneNumberDesc* desc = GetNumberDescByType(*region_metadata, type);
+  if (desc && desc->has_example_number()) {
+    ErrorType success = Parse(desc->example_number(), region_code, number);
+    if (success == NO_PARSING_ERROR) {
+      return true;
+    } else {
+      LOG(ERROR) << "Error parsing example number ("
+                 << static_cast<int>(success) << ")";
+    }
+  }
+  return false;
+}
+
+bool PhoneNumberUtil::GetExampleNumberForNonGeoEntity(
+    int country_calling_code, PhoneNumber* number) const {
+  DCHECK(number);
+  const PhoneMetadata* metadata =
+      GetMetadataForNonGeographicalRegion(country_calling_code);
+  if (metadata) {
+    const PhoneNumberDesc& desc = metadata->general_desc();
+    if (desc.has_example_number()) {
+      ErrorType success = Parse(StrCat(kPlusSign,
+                                       SimpleItoa(country_calling_code),
+                                       desc.example_number()),
+                                RegionCode::ZZ(), number);
+      if (success == NO_PARSING_ERROR) {
+        return true;
+      } else {
+        LOG(ERROR) << "Error parsing example number ("
+                   << static_cast<int>(success) << ")";
+      }
+    }
+  } else {
+    LOG(WARNING) << "Invalid or unknown country calling code provided: "
+                 << country_calling_code;
   }
   return false;
 }
@@ -1453,14 +1722,72 @@ bool PhoneNumberUtil::CheckRegionForParsing(
     const string& default_region) const {
   if (!IsValidRegionCode(default_region) && !number_to_parse.empty()) {
     const scoped_ptr<RegExpInput> number(
-        regexp_factory->CreateInput(number_to_parse));
-    if (!plus_chars_pattern->Consume(number.get())) {
+        reg_exps_->regexp_factory_->CreateInput(number_to_parse));
+    if (!reg_exps_->plus_chars_pattern_->Consume(number.get())) {
       return false;
     }
   }
   return true;
 }
 
+// Converts number_to_parse to a form that we can parse and write it to
+// national_number if it is written in RFC3966; otherwise extract a possible
+// number out of it and write to national_number.
+void PhoneNumberUtil::BuildNationalNumberForParsing(
+    const string& number_to_parse, string* national_number) const {
+  size_t index_of_phone_context = number_to_parse.find(kRfc3966PhoneContext);
+  if (index_of_phone_context != string::npos) {
+    int phone_context_start =
+        index_of_phone_context + strlen(kRfc3966PhoneContext);
+    // If the phone context contains a phone number prefix, we need to capture
+    // it, whereas domains will be ignored.
+    if (number_to_parse.at(phone_context_start) == kPlusSign[0]) {
+      // Additional parameters might follow the phone context. If so, we will
+      // remove them here because the parameters after phone context are not
+      // important for parsing the phone number.
+      size_t phone_context_end = number_to_parse.find(';', phone_context_start);
+      if (phone_context_end != string::npos) {
+        StrAppend(
+            national_number, number_to_parse.substr(
+                phone_context_start, phone_context_end - phone_context_start));
+      } else {
+        StrAppend(national_number, number_to_parse.substr(phone_context_start));
+      }
+    }
+
+    // Now append everything between the "tel:" prefix and the phone-context.
+    // This should include the national number, an optional extension or
+    // isdn-subaddress component. Note we also handle the case when "tel:" is
+    // missing, as we have seen in some of the phone number inputs. In that
+    // case, we append everything from the beginning.
+    size_t index_of_rfc_prefix = number_to_parse.find(kRfc3966Prefix);
+    int index_of_national_number = (index_of_rfc_prefix != string::npos) ?
+        index_of_rfc_prefix + strlen(kRfc3966Prefix) : 0;
+    StrAppend(
+        national_number,
+        number_to_parse.substr(
+            index_of_national_number,
+            index_of_phone_context - index_of_national_number));
+  } else {
+    // Extract a possible number from the string passed in (this strips leading
+    // characters that could not be the start of a phone number.)
+    ExtractPossibleNumber(number_to_parse, national_number);
+  }
+
+  // Delete the isdn-subaddress and everything after it if it is present. Note
+  // extension won't appear at the same time with isdn-subaddress according to
+  // paragraph 5.3 of the RFC3966 spec.
+  size_t index_of_isdn = national_number->find(kRfc3966IsdnSubaddress);
+  if (index_of_isdn != string::npos) {
+    national_number->erase(index_of_isdn);
+  }
+  // If both phone context and isdn-subaddress are absent but other parameters
+  // are present, the parameters are left in nationalNumber. This is because
+  // we are concerned about deleting content from a potential number string
+  // when there is no strong evidence that the number is actually written in
+  // RFC3966.
+}
+
 PhoneNumberUtil::ErrorType PhoneNumberUtil::ParseHelper(
     const string& number_to_parse,
     const string& default_region,
@@ -1468,10 +1795,10 @@ PhoneNumberUtil::ErrorType PhoneNumberUtil::ParseHelper(
     bool check_region,
     PhoneNumber* phone_number) const {
   DCHECK(phone_number);
-  // Extract a possible number from the string passed in (this strips leading
-  // characters that could not be the start of a phone number.)
+
   string national_number;
-  ExtractPossibleNumber(number_to_parse, &national_number);
+  BuildNationalNumberForParsing(number_to_parse, &national_number);
+
   if (!IsViablePhoneNumber(national_number)) {
     VLOG(2) << "The string supplied did not seem to be a phone number.";
     return NOT_A_NUMBER;
@@ -1502,9 +1829,9 @@ PhoneNumberUtil::ErrorType PhoneNumberUtil::ParseHelper(
                               &normalized_national_number, &temp_number);
   if (country_code_error != NO_PARSING_ERROR) {
      const scoped_ptr<RegExpInput> number_string_piece(
-        regexp_factory->CreateInput(national_number));
+        reg_exps_->regexp_factory_->CreateInput(national_number));
     if ((country_code_error == INVALID_COUNTRY_CODE_ERROR) &&
-        (plus_chars_pattern->Consume(number_string_piece.get()))) {
+        (reg_exps_->plus_chars_pattern_->Consume(number_string_piece.get()))) {
       normalized_national_number.assign(number_string_piece->ToString());
       // Strip the plus-char, and try again.
       MaybeExtractCountryCode(country_metadata,
@@ -1523,7 +1850,8 @@ PhoneNumberUtil::ErrorType PhoneNumberUtil::ParseHelper(
     string phone_number_region;
     GetRegionCodeForCountryCode(country_code, &phone_number_region);
     if (phone_number_region != default_region) {
-      country_metadata = GetMetadataForRegion(phone_number_region);
+      country_metadata =
+          GetMetadataForRegionOrCallingCode(country_code, phone_number_region);
     }
   } else if (country_metadata) {
     // If no extracted country calling code, use the region supplied instead.
@@ -1536,11 +1864,22 @@ PhoneNumberUtil::ErrorType PhoneNumberUtil::ParseHelper(
     return TOO_SHORT_NSN;
   }
   if (country_metadata) {
-    string* carrier_code = keep_raw_input ?
-        temp_number.mutable_preferred_domestic_carrier_code() : NULL;
+    string carrier_code;
+    string potential_national_number(normalized_national_number);
     MaybeStripNationalPrefixAndCarrierCode(*country_metadata,
-                                           &normalized_national_number,
-                                           carrier_code);
+                                           &potential_national_number,
+                                           &carrier_code);
+    // We require that the NSN remaining after stripping the national prefix
+    // and carrier code be of a possible length for the region. Otherwise, we
+    // don't do the stripping, since the original number could be a valid short
+    // number.
+    if (!IsShorterThanPossibleNormalNumber(country_metadata,
+        potential_national_number)) {
+      normalized_national_number.assign(potential_national_number);
+      if (keep_raw_input) {
+        temp_number.set_preferred_domestic_carrier_code(carrier_code);
+      }
+    }
   }
   size_t normalized_national_number_length =
       normalized_national_number.length();
@@ -1553,13 +1892,12 @@ PhoneNumberUtil::ErrorType PhoneNumberUtil::ParseHelper(
     return TOO_LONG_NSN;
   }
   temp_number.set_country_code(country_code);
-  if (normalized_national_number[0] == '0') {
-    temp_number.set_italian_leading_zero(true);
-  }
+  SetItalianLeadingZerosForPhoneNumber(normalized_national_number,
+      &temp_number);
   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);
+  phone_number->Swap(&temp_number);
   return NO_PARSING_ERROR;
 }
 
@@ -1585,7 +1923,7 @@ void PhoneNumberUtil::ExtractPossibleNumber(const string& number,
   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->FullMatch(current_char)) {
+    if (reg_exps_->valid_start_char_pattern_->FullMatch(current_char)) {
       break;
     }
   }
@@ -1608,8 +1946,8 @@ void PhoneNumberUtil::ExtractPossibleNumber(const string& number,
           << *extracted_number;
 
   // Now remove any extra numbers at the end.
-  capture_up_to_second_number_start_pattern->PartialMatch(*extracted_number,
-                                                          extracted_number);
+  reg_exps_->capture_up_to_second_number_start_pattern_->
+      PartialMatch(*extracted_number, extracted_number);
 }
 
 bool PhoneNumberUtil::IsPossibleNumber(const PhoneNumber& number) const {
@@ -1637,26 +1975,16 @@ PhoneNumberUtil::ValidationResult PhoneNumberUtil::IsPossibleNumberWithReason(
   // 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, &region_code);
-  if (!HasValidRegionCode(region_code, country_code, national_number)) {
+  if (!HasValidCountryCallingCode(country_code)) {
     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;
-    }
-  }
-  const RegExp& possible_number_pattern = regexp_cache->GetRegExp(
-      StrCat("(", general_num_desc.possible_number_pattern(), ")"));
+  string region_code;
+  GetRegionCodeForCountryCode(country_code, &region_code);
+  // Metadata cannot be NULL because the country calling code is valid.
+  const PhoneMetadata* metadata =
+      GetMetadataForRegionOrCallingCode(country_code, region_code);
+  const RegExp& possible_number_pattern = reg_exps_->regexp_cache_->GetRegExp(
+      StrCat("(", metadata->general_desc().possible_number_pattern(), ")"));
   return TestNumberLengthAgainstPattern(possible_number_pattern,
                                         national_number);
 }
@@ -1683,61 +2011,167 @@ PhoneNumberUtil::PhoneNumberType PhoneNumberUtil::GetNumberType(
     const PhoneNumber& number) const {
   string region_code;
   GetRegionCodeForNumber(number, &region_code);
-  if (!IsValidRegionCode(region_code)) {
+  const PhoneMetadata* metadata =
+      GetMetadataForRegionOrCallingCode(number.country_code(), region_code);
+  if (!metadata) {
     return UNKNOWN;
   }
   string national_significant_number;
   GetNationalSignificantNumber(number, &national_significant_number);
-  return GetNumberTypeHelper(national_significant_number,
-                             *GetMetadataForRegion(region_code));
+  return GetNumberTypeHelper(national_significant_number, *metadata);
 }
 
 bool PhoneNumberUtil::IsValidNumber(const PhoneNumber& number) const {
   string region_code;
   GetRegionCodeForNumber(number, &region_code);
-  return IsValidRegionCode(region_code) &&
-      IsValidNumberForRegion(number, region_code);
+  return IsValidNumberForRegion(number, region_code);
 }
 
 bool PhoneNumberUtil::IsValidNumberForRegion(const PhoneNumber& number,
                                              const string& region_code) const {
-  if (number.country_code() != GetCountryCodeForRegion(region_code)) {
+  int country_code = number.country_code();
+  const PhoneMetadata* metadata =
+      GetMetadataForRegionOrCallingCode(country_code, region_code);
+  if (!metadata ||
+      ((kRegionCodeForNonGeoEntity != region_code) &&
+       country_code != GetCountryCodeForValidRegion(region_code))) {
+    // Either the region code was invalid, or the country calling code for this
+    // number does not match that of the region code.
     return false;
   }
-  const 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()) {
-    VLOG(3) << "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::IsNumberGeographical(
+    const PhoneNumber& phone_number) const {
+  PhoneNumberType number_type = GetNumberType(phone_number);
+  // TODO: Include mobile phone numbers from countries like
+  // Indonesia, which has some mobile numbers that are geographical.
+  return number_type == PhoneNumberUtil::FIXED_LINE ||
+      number_type == PhoneNumberUtil::FIXED_LINE_OR_MOBILE;
+}
+
 bool PhoneNumberUtil::IsLeadingZeroPossible(int country_calling_code) const {
   string region_code;
   GetRegionCodeForCountryCode(country_calling_code, &region_code);
   const PhoneMetadata* main_metadata_for_calling_code =
-      GetMetadataForRegion(region_code);
+      GetMetadataForRegionOrCallingCode(country_calling_code, region_code);
   if (!main_metadata_for_calling_code) return false;
   return main_metadata_for_calling_code->leading_zero_possible();
 }
 
+// A helper function to set the values related to leading zeros in a
+// PhoneNumber.
+void PhoneNumberUtil::SetItalianLeadingZerosForPhoneNumber(
+    const string& national_number, PhoneNumber* phone_number) const {
+  if (national_number.length() > 1 && national_number[0] == '0') {
+    phone_number->set_italian_leading_zero(true);
+    size_t number_of_leading_zeros = 1;
+    // Note that if the national number is all "0"s, the last "0" is not
+    // counted as a leading zero.
+    while (number_of_leading_zeros < national_number.length() - 1 &&
+        national_number[number_of_leading_zeros] == '0') {
+      number_of_leading_zeros++;
+    }
+    if (number_of_leading_zeros != 1) {
+      phone_number->set_number_of_leading_zeros(number_of_leading_zeros);
+    }
+  }
+}
+
+bool PhoneNumberUtil::IsNumberPossibleForDesc(
+    const string& national_number, const PhoneNumberDesc& number_desc) const {
+  return reg_exps_->regexp_cache_.get()->
+             GetRegExp(number_desc.possible_number_pattern())
+             .FullMatch(national_number);
+}
+
+bool PhoneNumberUtil::IsNumberMatchingDesc(
+    const string& national_number, const PhoneNumberDesc& number_desc) const {
+  return IsNumberPossibleForDesc(national_number, number_desc) &&
+         reg_exps_->regexp_cache_.get()->
+             GetRegExp(number_desc.national_number_pattern())
+             .FullMatch(national_number);
+}
+
+PhoneNumberUtil::PhoneNumberType PhoneNumberUtil::GetNumberTypeHelper(
+    const string& national_number, const PhoneMetadata& metadata) const {
+  if (!IsNumberMatchingDesc(national_number, metadata.general_desc())) {
+    VLOG(4) << "Number type unknown - doesn't match general national number"
+            << " pattern.";
+    return PhoneNumberUtil::UNKNOWN;
+  }
+  if (IsNumberMatchingDesc(national_number, metadata.premium_rate())) {
+    VLOG(4) << "Number is a premium number.";
+    return PhoneNumberUtil::PREMIUM_RATE;
+  }
+  if (IsNumberMatchingDesc(national_number, metadata.toll_free())) {
+    VLOG(4) << "Number is a toll-free number.";
+    return PhoneNumberUtil::TOLL_FREE;
+  }
+  if (IsNumberMatchingDesc(national_number, metadata.shared_cost())) {
+    VLOG(4) << "Number is a shared cost number.";
+    return PhoneNumberUtil::SHARED_COST;
+  }
+  if (IsNumberMatchingDesc(national_number, metadata.voip())) {
+    VLOG(4) << "Number is a VOIP (Voice over IP) number.";
+    return PhoneNumberUtil::VOIP;
+  }
+  if (IsNumberMatchingDesc(national_number, metadata.personal_number())) {
+    VLOG(4) << "Number is a personal number.";
+    return PhoneNumberUtil::PERSONAL_NUMBER;
+  }
+  if (IsNumberMatchingDesc(national_number, metadata.pager())) {
+    VLOG(4) << "Number is a pager number.";
+    return PhoneNumberUtil::PAGER;
+  }
+  if (IsNumberMatchingDesc(national_number, metadata.uan())) {
+    VLOG(4) << "Number is a UAN.";
+    return PhoneNumberUtil::UAN;
+  }
+  if (IsNumberMatchingDesc(national_number, metadata.voicemail())) {
+    VLOG(4) << "Number is a voicemail number.";
+    return PhoneNumberUtil::VOICEMAIL;
+  }
+
+  bool is_fixed_line =
+      IsNumberMatchingDesc(national_number, metadata.fixed_line());
+  if (is_fixed_line) {
+    if (metadata.same_mobile_and_fixed_line_pattern()) {
+      VLOG(4) << "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())) {
+      VLOG(4) << "Fixed-line and mobile patterns differ, but number is "
+              << "still fixed-line or mobile";
+      return PhoneNumberUtil::FIXED_LINE_OR_MOBILE;
+    }
+    VLOG(4) << "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())) {
+    VLOG(4) << "Number is a mobile number.";
+    return PhoneNumberUtil::MOBILE;
+  }
+  VLOG(4) << "Number type unknown - doesn\'t match any specific number type"
+          << " pattern.";
+  return PhoneNumberUtil::UNKNOWN;
+}
+
 void PhoneNumberUtil::GetNationalSignificantNumber(
     const PhoneNumber& number,
     string* national_number) const {
   DCHECK(national_number);
-  // If a leading zero has been set, we prefix this now. Note this is not a
+  // If leading zero(s) have been set, we prefix this now. Note this is not a
   // national prefix.
-  StrAppend(national_number, number.italian_leading_zero() ? "0" : "");
+  StrAppend(national_number, number.italian_leading_zero() ?
+      string(number.number_of_leading_zeros(), '0') : "");
   StrAppend(national_number, number.national_number());
 }
 
@@ -1745,21 +2179,18 @@ int PhoneNumberUtil::GetLengthOfGeographicalAreaCode(
     const PhoneNumber& number) const {
   string region_code;
   GetRegionCodeForNumber(number, &region_code);
-  if (!IsValidRegionCode(region_code)) {
+  const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
+  if (!metadata) {
     return 0;
   }
-  const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
-  DCHECK(metadata);
-  if (!metadata->has_national_prefix()) {
+  // If a country doesn't use a national prefix, and this number doesn't have an
+  // Italian leading zero, we assume it is a closed dialling plan with no area
+  // codes.
+  if (!metadata->has_national_prefix() && !number.italian_leading_zero()) {
     return 0;
   }
 
-  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) {
+  if (!IsNumberGeographical(number)) {
     return 0;
   }
 
@@ -1777,13 +2208,13 @@ int PhoneNumberUtil::GetLengthOfNationalDestinationCode(
   string formatted_number;
   Format(copied_proto, INTERNATIONAL, &formatted_number);
   const scoped_ptr<RegExpInput> i18n_number(
-      regexp_factory->CreateInput(formatted_number));
+      reg_exps_->regexp_factory_->CreateInput(formatted_number));
   string digit_group;
   string ndc;
   string third_group;
   for (int i = 0; i < 3; ++i) {
-    if (!capturing_ascii_digits_pattern->FindAndConsume(i18n_number.get(),
-                                                        &digit_group)) {
+    if (!reg_exps_->capturing_ascii_digits_pattern_->FindAndConsume(
+            i18n_number.get(), &digit_group)) {
       // We should find at least three groups.
       return 0;
     }
@@ -1793,22 +2224,38 @@ int PhoneNumberUtil::GetLengthOfNationalDestinationCode(
       third_group = digit_group;
     }
   }
-  string region_code;
-  GetRegionCodeForNumber(number, &region_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;
+
+  if (GetNumberType(number) == MOBILE) {
+    // For example 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 the length of the
+    // mobile token, which also forms part of the national significant number.
+    // This assumes that the mobile token is always formatted separately from
+    // the rest of the phone number.
+    string mobile_token;
+    GetCountryMobileToken(number.country_code(), &mobile_token);
+    if (!mobile_token.empty()) {
+      return third_group.size() + mobile_token.size();
+    }
   }
   return ndc.size();
 }
 
+void PhoneNumberUtil::GetCountryMobileToken(int country_calling_code,
+                                            string* mobile_token) const {
+  DCHECK(mobile_token);
+  map<int, char>::iterator it = reg_exps_->mobile_token_mappings_.find(
+      country_calling_code);
+  if (it != reg_exps_->mobile_token_mappings_.end()) {
+    *mobile_token = it->second;
+  } else {
+    mobile_token->assign("");
+  }
+}
+
 void PhoneNumberUtil::NormalizeDigitsOnly(string* number) const {
   DCHECK(number);
-  const RegExp& non_digits_pattern = regexp_cache->GetRegExp(
+  const RegExp& non_digits_pattern = reg_exps_->regexp_cache_->GetRegExp(
       StrCat("[^", kDigits, "]"));
   // Delete everything that isn't valid digits.
   non_digits_pattern.GlobalReplace(number, "");
@@ -1816,6 +2263,12 @@ void PhoneNumberUtil::NormalizeDigitsOnly(string* number) const {
   number->assign(NormalizeUTF8::NormalizeDecimalDigits(*number));
 }
 
+void PhoneNumberUtil::NormalizeDiallableCharsOnly(string* number) const {
+  DCHECK(number);
+  NormalizeHelper(reg_exps_->diallable_char_mappings_,
+                  true /* remove non matches */, number);
+}
+
 bool PhoneNumberUtil::IsAlphaNumber(const string& number) const {
   if (!IsViablePhoneNumber(number)) {
     // Number is too short, or doesn't match the basic phone number pattern.
@@ -1825,12 +2278,12 @@ bool PhoneNumberUtil::IsAlphaNumber(const string& number) const {
   string number_copy(number);
   string extension;
   MaybeStripExtension(&number_copy, &extension);
-  return valid_alpha_phone_pattern->FullMatch(number_copy);
+  return reg_exps_->valid_alpha_phone_pattern_->FullMatch(number_copy);
 }
 
 void PhoneNumberUtil::ConvertAlphaCharactersInNumber(string* number) const {
   DCHECK(number);
-  NormalizeHelper(*alpha_phone_mappings, false, number);
+  NormalizeHelper(reg_exps_->alpha_phone_mappings_, false, number);
 }
 
 // Normalizes a string of characters representing a phone number. This performs
@@ -1847,8 +2300,8 @@ void PhoneNumberUtil::ConvertAlphaCharactersInNumber(string* number) const {
 //   - Spurious alpha characters are stripped.
 void PhoneNumberUtil::Normalize(string* number) const {
   DCHECK(number);
-  if (valid_alpha_phone_pattern->PartialMatch(*number)) {
-    NormalizeHelper(*alpha_phone_mappings, true, number);
+  if (reg_exps_->valid_alpha_phone_pattern_->PartialMatch(*number)) {
+    NormalizeHelper(reg_exps_->alpha_phone_mappings_, true, number);
   }
   NormalizeDigitsOnly(number);
 }
@@ -1864,7 +2317,7 @@ bool PhoneNumberUtil::IsViablePhoneNumber(const string& number) const {
     VLOG(2) << "Number too short to be viable:" << number;
     return false;
   }
-  return valid_phone_number_pattern->FullMatch(number);
+  return reg_exps_->valid_phone_number_pattern_->FullMatch(number);
 }
 
 // Strips the IDD from the start of the number if present. Helper function used
@@ -1873,15 +2326,15 @@ bool PhoneNumberUtil::ParsePrefixAsIdd(const RegExp& idd_pattern,
                                        string* number) const {
   DCHECK(number);
   const scoped_ptr<RegExpInput> number_copy(
-      regexp_factory->CreateInput(*number));
+      reg_exps_->regexp_factory_->CreateInput(*number));
   // 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())) {
     // 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->PartialMatch(number_copy->ToString(),
-                                              &extracted_digit)) {
+    if (reg_exps_->capturing_digit_pattern_->PartialMatch(
+            number_copy->ToString(), &extracted_digit)) {
       NormalizeDigitsOnly(&extracted_digit);
       if (extracted_digit == "0") {
         return false;
@@ -1911,8 +2364,8 @@ PhoneNumberUtil::MaybeStripInternationalPrefixAndNormalize(
     return PhoneNumber::FROM_DEFAULT_COUNTRY;
   }
   const scoped_ptr<RegExpInput> number_string_piece(
-      regexp_factory->CreateInput(*number));
-  if (plus_chars_pattern->Consume(number_string_piece.get())) {
+      reg_exps_->regexp_factory_->CreateInput(*number));
+  if (reg_exps_->plus_chars_pattern_->Consume(number_string_piece.get())) {
     number->assign(number_string_piece->ToString());
     // Can now normalize the rest of the number since we've consumed the "+"
     // sign at the start.
@@ -1920,7 +2373,8 @@ PhoneNumberUtil::MaybeStripInternationalPrefixAndNormalize(
     return PhoneNumber::FROM_NUMBER_WITH_PLUS_SIGN;
   }
   // Attempt to parse the first digits as an international prefix.
-  const RegExp& idd_pattern = regexp_cache->GetRegExp(possible_idd_prefix);
+  const RegExp& idd_pattern =
+      reg_exps_->regexp_cache_->GetRegExp(possible_idd_prefix);
   Normalize(number);
   return ParsePrefixAsIdd(idd_pattern, number)
       ? PhoneNumber::FROM_NUMBER_WITH_IDD
@@ -1930,8 +2384,9 @@ PhoneNumberUtil::MaybeStripInternationalPrefixAndNormalize(
 // 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.
-void PhoneNumberUtil::MaybeStripNationalPrefixAndCarrierCode(
+// region that we think this number is from. Returns true if a national prefix
+// and/or carrier code was stripped.
+bool PhoneNumberUtil::MaybeStripNationalPrefixAndCarrierCode(
     const PhoneMetadata& metadata,
     string* number,
     string* carrier_code) const {
@@ -1942,17 +2397,17 @@ void PhoneNumberUtil::MaybeStripNationalPrefixAndCarrierCode(
   if (number->empty() || possible_national_prefix.empty()) {
     // Early return for numbers of zero length or with no national prefix
     // possible.
-    return;
+    return false;
   }
   // We use two copies here since Consume modifies the phone number, and if the
   // first if-clause fails the number will already be changed.
   const scoped_ptr<RegExpInput> number_copy(
-      regexp_factory->CreateInput(*number));
+      reg_exps_->regexp_factory_->CreateInput(*number));
   const scoped_ptr<RegExpInput> number_copy_without_transform(
-      regexp_factory->CreateInput(*number));
+      reg_exps_->regexp_factory_->CreateInput(*number));
   string number_string_copy(*number);
   string captured_part_of_prefix;
-  const RegExp& national_number_rule = regexp_cache->GetRegExp(
+  const RegExp& national_number_rule = reg_exps_->regexp_cache_->GetRegExp(
       metadata.general_desc().national_number_pattern());
   // Check if the original number is viable.
   bool is_viable_original_number = national_number_rule.FullMatch(*number);
@@ -1960,7 +2415,7 @@ void PhoneNumberUtil::MaybeStripNationalPrefixAndCarrierCode(
   // copy so that we can revert to the original string if necessary.
   const string& transform_rule = metadata.national_prefix_transform_rule();
   const RegExp& possible_national_prefix_pattern =
-      regexp_cache->GetRegExp(possible_national_prefix);
+      reg_exps_->regexp_cache_->GetRegExp(possible_national_prefix);
   if (!transform_rule.empty() &&
       (possible_national_prefix_pattern.Consume(
           number_copy.get(), &carrier_code_temp, &captured_part_of_prefix) ||
@@ -1975,7 +2430,7 @@ void PhoneNumberUtil::MaybeStripNationalPrefixAndCarrierCode(
                                              transform_rule);
     if (is_viable_original_number &&
         !national_number_rule.FullMatch(number_string_copy)) {
-      return;
+      return false;
     }
     number->assign(number_string_copy);
     if (carrier_code) {
@@ -1993,15 +2448,17 @@ void PhoneNumberUtil::MaybeStripNationalPrefixAndCarrierCode(
         number_copy_without_transform->ToString();
     if (is_viable_original_number &&
         !national_number_rule.FullMatch(number_copy_as_string)) {
-      return;
+      return false;
     }
     number->assign(number_copy_as_string);
     if (carrier_code) {
       carrier_code->assign(carrier_code_temp);
     }
   } else {
+    return false;
     VLOG(4) << "The first digits did not match the national prefix.";
   }
+  return true;
 }
 
 // Strips any extension (as in, the part of the number dialled after the call is
@@ -2017,14 +2474,14 @@ bool PhoneNumberUtil::MaybeStripExtension(string* number, string* extension)
   string possible_extension_three;
   string number_copy(*number);
   const scoped_ptr<RegExpInput> number_copy_as_regexp_input(
-      regexp_factory->CreateInput(number_copy));
-  if (extn_pattern->Consume(number_copy_as_regexp_input.get(),
+      reg_exps_->regexp_factory_->CreateInput(number_copy));
+  if (reg_exps_->extn_pattern_->Consume(number_copy_as_regexp_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, "");
+    reg_exps_->extn_pattern_->Replace(&number_copy, "");
     VLOG(4) << "Found an extension. Possible extension one: "
             << possible_extension_one
             << ". Possible extension two: " << possible_extension_two
@@ -2111,7 +2568,7 @@ PhoneNumberUtil::ErrorType PhoneNumberUtil::MaybeExtractCountryCode(
     phone_number->set_country_code_source(country_code_source);
   }
   if (country_code_source != PhoneNumber::FROM_DEFAULT_COUNTRY) {
-    if (national_number->length() < kMinLengthForNsn) {
+    if (national_number->length() <= kMinLengthForNsn) {
       VLOG(2) << "Phone number had an IDD, but after this was not "
               << "long enough to be a viable phone number.";
       return TOO_SHORT_AFTER_IDD;
@@ -2138,14 +2595,16 @@ PhoneNumberUtil::ErrorType PhoneNumberUtil::MaybeExtractCountryCode(
       const PhoneNumberDesc& general_num_desc =
           default_region_metadata->general_desc();
       const RegExp& valid_number_pattern =
-          regexp_cache->GetRegExp(general_num_desc.national_number_pattern());
+          reg_exps_->regexp_cache_->GetRegExp(
+              general_num_desc.national_number_pattern());
       MaybeStripNationalPrefixAndCarrierCode(*default_region_metadata,
                                              &potential_national_number,
                                              NULL);
       VLOG(4) << "Number without country calling code prefix: "
               << potential_national_number;
-      const RegExp& possible_number_pattern = regexp_cache->GetRegExp(
-          StrCat("(", general_num_desc.possible_number_pattern(), ")"));
+      const RegExp& possible_number_pattern =
+          reg_exps_->regexp_cache_->GetRegExp(
+              StrCat("(", general_num_desc.possible_number_pattern(), ")"));
       // 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.
@@ -2308,17 +2767,27 @@ AsYouTypeFormatter* PhoneNumberUtil::GetAsYouTypeFormatter(
   return new AsYouTypeFormatter(region_code);
 }
 
+bool PhoneNumberUtil::IsShorterThanPossibleNormalNumber(
+    const PhoneMetadata* country_metadata, const string& number) const {
+  const RegExp& possible_number_pattern =
+      reg_exps_->regexp_cache_->GetRegExp(StrCat("(",
+          country_metadata->general_desc().possible_number_pattern(), ")"));
+  return TestNumberLengthAgainstPattern(possible_number_pattern, number) ==
+      PhoneNumberUtil::TOO_SHORT;
+}
+
 bool PhoneNumberUtil::CanBeInternationallyDialled(
     const PhoneNumber& number) const {
   string region_code;
   GetRegionCodeForNumber(number, &region_code);
-  string national_significant_number;
-  GetNationalSignificantNumber(number, &national_significant_number);
-  if (!HasValidRegionCode(region_code, number.country_code(),
-                          national_significant_number)) {
+  const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
+  if (!metadata) {
+    // Note numbers belonging to non-geographical entities (e.g. +800 numbers)
+    // are always internationally diallable, and will be caught here.
     return true;
   }
-  const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
+  string national_significant_number;
+  GetNationalSignificantNumber(number, &national_significant_number);
   return !IsNumberMatchingDesc(
       national_significant_number, metadata->no_international_dialling());
 }