OLD | NEW |
(Empty) | |
| 1 // Copyright (C) 2009 Google Inc. |
| 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at |
| 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. |
| 14 |
| 15 // Author: Shaopeng Jia |
| 16 // Open-sourced by: Philippe Liard |
| 17 |
| 18 #include "phonenumberutil.h" |
| 19 |
| 20 #include <algorithm> |
| 21 #include <fstream> |
| 22 #include <iostream> |
| 23 #include <map> |
| 24 #include <sstream> |
| 25 #include <vector> |
| 26 |
| 27 #include <google/protobuf/message_lite.h> |
| 28 #include <unicode/errorcode.h> |
| 29 #include <unicode/translit.h> |
| 30 |
| 31 #include "base/logging.h" |
| 32 #include "base/singleton.h" |
| 33 #include "default_logger.h" |
| 34 #include "logger_adapter.h" |
| 35 #include "metadata.h" |
| 36 #include "phonemetadata.pb.h" |
| 37 #include "phonenumber.h" |
| 38 #include "phonenumber.pb.h" |
| 39 #include "regexp_adapter.h" |
| 40 #include "stringutil.h" |
| 41 #include "utf/unicodetext.h" |
| 42 #include "utf/utf.h" |
| 43 |
| 44 namespace i18n { |
| 45 namespace phonenumbers { |
| 46 |
| 47 using std::cerr; |
| 48 using std::endl; |
| 49 using std::ifstream; |
| 50 using std::make_pair; |
| 51 using std::sort; |
| 52 using std::stringstream; |
| 53 |
| 54 using google::protobuf::RepeatedPtrField; |
| 55 |
| 56 namespace { |
| 57 |
| 58 scoped_ptr<LoggerAdapter> logger; |
| 59 |
| 60 // These objects are created in the function InitializeStaticMapsAndSets. |
| 61 |
| 62 // These mappings map a character (key) to a specific digit that should replace |
| 63 // it for normalization purposes. |
| 64 scoped_ptr<map<char32, char> > alpha_mappings; |
| 65 // For performance reasons, amalgamate both into one map. |
| 66 scoped_ptr<map<char32, char> > all_normalization_mappings; |
| 67 // Separate map of all symbols that we wish to retain when formatting alpha |
| 68 // numbers. This includes digits, ascii letters and number grouping symbols such |
| 69 // as "-" and " ". |
| 70 scoped_ptr<map<char32, char> > all_plus_number_grouping_symbols; |
| 71 |
| 72 // The kPlusSign signifies the international prefix. |
| 73 const char kPlusSign[] = "+"; |
| 74 |
| 75 const char kPlusChars[] = "++"; |
| 76 scoped_ptr<const reg_exp::RegularExpression> plus_chars_pattern; |
| 77 |
| 78 const char kRfc3966ExtnPrefix[] = ";ext="; |
| 79 |
| 80 // Pattern that makes it easy to distinguish whether a region has a unique |
| 81 // international dialing prefix or not. If a region has a unique international |
| 82 // prefix (e.g. 011 in USA), it will be represented as a string that contains a |
| 83 // sequence of ASCII digits. If there are multiple available international |
| 84 // prefixes in a region, they will be represented as a regex string that always |
| 85 // contains character(s) other than ASCII digits. |
| 86 // Note this regex also includes tilde, which signals waiting for the tone. |
| 87 scoped_ptr<const reg_exp::RegularExpression> unique_international_prefix; |
| 88 |
| 89 // Digits accepted in phone numbers. |
| 90 // Both Arabic-Indic and Eastern Arabic-Indic are supported. |
| 91 const char kValidDigits[] = "0-90-9٠-٩۰-۹"; |
| 92 // We accept alpha characters in phone numbers, ASCII only. We store lower-case |
| 93 // here only since our regular expressions are case-insensitive. |
| 94 const char kValidAlpha[] = "a-z"; |
| 95 scoped_ptr<const reg_exp::RegularExpression> capturing_digit_pattern; |
| 96 scoped_ptr<const reg_exp::RegularExpression> capturing_ascii_digits_pattern; |
| 97 |
| 98 // Regular expression of acceptable characters that may start a phone number |
| 99 // for the purposes of parsing. This allows us to strip away meaningless |
| 100 // prefixes to phone numbers that may be mistakenly given to us. This |
| 101 // consists of digits, the plus symbol and arabic-indic digits. This does |
| 102 // not contain alpha characters, although they may be used later in the |
| 103 // number. It also does not include other punctuation, as this will be |
| 104 // stripped later during parsing and is of no information value when parsing |
| 105 // a number. The string starting with this valid character is captured. |
| 106 // This corresponds to VALID_START_CHAR in the java version. |
| 107 scoped_ptr<const string> valid_start_char; |
| 108 scoped_ptr<const reg_exp::RegularExpression> valid_start_char_pattern; |
| 109 |
| 110 // Regular expression of characters typically used to start a second phone |
| 111 // number for the purposes of parsing. This allows us to strip off parts of |
| 112 // the number that are actually the start of another number, such as for: |
| 113 // (530) 583-6985 x302/x2303 -> the second extension here makes this actually |
| 114 // two phone numbers, (530) 583-6985 x302 and (530) 583-6985 x2303. We remove |
| 115 // the second extension so that the first number is parsed correctly. The string |
| 116 // preceding this is captured. |
| 117 // This corresponds to SECOND_NUMBER_START in the java version. |
| 118 const char kCaptureUpToSecondNumberStart[] = "(.*)[\\\\/] *x"; |
| 119 scoped_ptr<const reg_exp::RegularExpression> |
| 120 capture_up_to_second_number_start_pattern; |
| 121 |
| 122 // Regular expression of trailing characters that we want to remove. We remove |
| 123 // all characters that are not alpha or numerical characters. The hash |
| 124 // character is retained here, as it may signify the previous block was an |
| 125 // extension. Note the capturing block at the start to capture the rest of the |
| 126 // number if this was a match. |
| 127 // This corresponds to UNWANTED_END_CHARS in the java version. |
| 128 const char kUnwantedEndChar[] = "[^\\p{N}\\p{L}#]"; |
| 129 scoped_ptr<const reg_exp::RegularExpression> unwanted_end_char_pattern; |
| 130 |
| 131 // Regular expression of acceptable punctuation found in phone numbers. This |
| 132 // excludes punctuation found as a leading character only. This consists of |
| 133 // dash characters, white space characters, full stops, slashes, square |
| 134 // brackets, parentheses and tildes. It also includes the letter 'x' as that is |
| 135 // found as a placeholder for carrier information in some phone numbers. |
| 136 // Full-width variants are also present. |
| 137 // To find out the unicode code-point of the characters below in vim, highlight |
| 138 // the character and type 'ga'. Note that the - is used to express ranges of |
| 139 // full-width punctuation below, as well as being present in the expression |
| 140 // itself. In emacs, you can use M-x unicode-what to query information about the |
| 141 // unicode character. |
| 142 const char kValidPunctuation[] = |
| 143 "-x‐-―−ー--/ ()()[].\\[\\]/~⁓∼~"; |
| 144 |
| 145 // Regular expression of viable phone numbers. This is location independent. |
| 146 // Checks we have at least three leading digits, and only valid punctuation, |
| 147 // alpha characters and digits in the phone number. Does not include extension |
| 148 // data. The symbol 'x' is allowed here as valid punctuation since it is often |
| 149 // used as a placeholder for carrier codes, for example in Brazilian phone |
| 150 // numbers. We also allow multiple plus-signs at the start. |
| 151 // Corresponds to the following: |
| 152 // plus_sign*([punctuation]*[digits]){3,}([punctuation]|[digits]|[alpha])* |
| 153 scoped_ptr<const string> valid_phone_number; |
| 154 |
| 155 // Default extension prefix to use when formatting. This will be put in front of |
| 156 // any extension component of the number, after the main national number is |
| 157 // formatted. For example, if you wish the default extension formatting to be " |
| 158 // extn: 3456", then you should specify " extn: " here as the default extension |
| 159 // prefix. This can be overridden by region-specific preferences. |
| 160 const char kDefaultExtnPrefix[] = " ext. "; |
| 161 |
| 162 // Regexp of all possible ways to write extensions, for use when parsing. This |
| 163 // will be run as a case-insensitive regexp match. Wide character versions are |
| 164 // also provided after each ascii version. There are three regular expressions |
| 165 // here. The first covers RFC 3966 format, where the extension is added using |
| 166 // ";ext=". The second more generic one starts with optional white space and |
| 167 // ends with an optional full stop (.), followed by zero or more spaces/tabs and |
| 168 // then the numbers themselves. The third one covers the special case of |
| 169 // American numbers where the extension is written with a hash at the end, such |
| 170 // as "- 503#". |
| 171 // Note that the only capturing groups should be around the digits that you want |
| 172 // to capture as part of the extension, or else parsing will fail! |
| 173 scoped_ptr<const string> known_extn_patterns; |
| 174 // Regexp of all known extension prefixes used by different regions followed |
| 175 // by 1 or more valid digits, for use when parsing. |
| 176 scoped_ptr<const reg_exp::RegularExpression> extn_pattern; |
| 177 |
| 178 // We append optionally the extension pattern to the end here, as a valid phone |
| 179 // number may have an extension prefix appended, followed by 1 or more digits. |
| 180 scoped_ptr<const reg_exp::RegularExpression> valid_phone_number_pattern; |
| 181 |
| 182 // We use this pattern to check if the phone number has at least three letters |
| 183 // in it - if so, then we treat it as a number where some phone-number digits |
| 184 // are represented by letters. |
| 185 scoped_ptr<const reg_exp::RegularExpression> valid_alpha_phone_pattern; |
| 186 |
| 187 scoped_ptr<const reg_exp::RegularExpression> first_group_capturing_pattern; |
| 188 |
| 189 scoped_ptr<const reg_exp::RegularExpression> carrier_code_pattern; |
| 190 |
| 191 void TransformRegularExpressionToRE2Syntax(string* regex) { |
| 192 DCHECK(regex); |
| 193 StripString(regex, "$", '\\'); |
| 194 } |
| 195 |
| 196 // Returns a pointer to the description inside the metadata of the appropriate |
| 197 // type. |
| 198 const PhoneNumberDesc* GetNumberDescByType( |
| 199 const PhoneMetadata& metadata, |
| 200 PhoneNumberUtil::PhoneNumberType type) { |
| 201 switch (type) { |
| 202 case PhoneNumberUtil::PREMIUM_RATE: |
| 203 return &metadata.premium_rate(); |
| 204 case PhoneNumberUtil::TOLL_FREE: |
| 205 return &metadata.toll_free(); |
| 206 case PhoneNumberUtil::MOBILE: |
| 207 return &metadata.mobile(); |
| 208 case PhoneNumberUtil::FIXED_LINE: |
| 209 case PhoneNumberUtil::FIXED_LINE_OR_MOBILE: |
| 210 return &metadata.fixed_line(); |
| 211 case PhoneNumberUtil::SHARED_COST: |
| 212 return &metadata.shared_cost(); |
| 213 case PhoneNumberUtil::VOIP: |
| 214 return &metadata.voip(); |
| 215 case PhoneNumberUtil::PERSONAL_NUMBER: |
| 216 return &metadata.personal_number(); |
| 217 case PhoneNumberUtil::PAGER: |
| 218 return &metadata.pager(); |
| 219 case PhoneNumberUtil::UAN: |
| 220 return &metadata.uan(); |
| 221 default: |
| 222 return &metadata.general_desc(); |
| 223 } |
| 224 } |
| 225 |
| 226 // A helper function that is used by Format and FormatByPattern. |
| 227 void FormatNumberByFormat(int country_calling_code, |
| 228 PhoneNumberUtil::PhoneNumberFormat number_format, |
| 229 const string& formatted_national_number, |
| 230 const string& formatted_extension, |
| 231 string* formatted_number) { |
| 232 switch (number_format) { |
| 233 case PhoneNumberUtil::E164: |
| 234 formatted_number->assign(StrCat(kPlusSign, |
| 235 SimpleItoa(country_calling_code), |
| 236 formatted_national_number, |
| 237 formatted_extension)); |
| 238 return; |
| 239 case PhoneNumberUtil::INTERNATIONAL: |
| 240 formatted_number->assign(StrCat(kPlusSign, |
| 241 SimpleItoa(country_calling_code), |
| 242 " ", |
| 243 formatted_national_number, |
| 244 formatted_extension)); |
| 245 return; |
| 246 case PhoneNumberUtil::RFC3966: |
| 247 formatted_number->assign(StrCat(kPlusSign, |
| 248 SimpleItoa(country_calling_code), |
| 249 "-", |
| 250 formatted_national_number, |
| 251 formatted_extension)); |
| 252 return; |
| 253 case PhoneNumberUtil::NATIONAL: |
| 254 default: |
| 255 formatted_number->assign(StrCat(formatted_national_number, |
| 256 formatted_extension)); |
| 257 } |
| 258 } |
| 259 |
| 260 // The number_for_leading_digits_match is a separate parameter, because for |
| 261 // alpha numbers we want to pass in the numeric version to select the right |
| 262 // formatting rule, but then we actually apply the formatting pattern to the |
| 263 // national_number (which in this case has alpha characters in it). |
| 264 // |
| 265 // Note that carrier_code is optional - if an empty string, no carrier code |
| 266 // replacement will take place. |
| 267 void FormatAccordingToFormatsWithCarrier( |
| 268 const string& number_for_leading_digits_match, |
| 269 const RepeatedPtrField<NumberFormat>& available_formats, |
| 270 PhoneNumberUtil::PhoneNumberFormat number_format, |
| 271 const string& national_number, |
| 272 const string& carrier_code, |
| 273 string* formatted_number) { |
| 274 DCHECK(formatted_number); |
| 275 for (RepeatedPtrField<NumberFormat>::const_iterator |
| 276 it = available_formats.begin(); it != available_formats.end(); ++it) { |
| 277 int size = it->leading_digits_pattern_size(); |
| 278 if (size > 0) { |
| 279 scoped_ptr<reg_exp::RegularExpressionInput> |
| 280 number_copy(reg_exp::CreateRegularExpressionInput( |
| 281 number_for_leading_digits_match.c_str())); |
| 282 // We always use the last leading_digits_pattern, as it is the most |
| 283 // detailed. |
| 284 if (!number_copy->ConsumeRegExp(it->leading_digits_pattern(size - 1), |
| 285 true, NULL, NULL)) { |
| 286 continue; |
| 287 } |
| 288 } |
| 289 scoped_ptr<reg_exp::RegularExpression> pattern_to_match( |
| 290 reg_exp::CreateRegularExpression(it->pattern().c_str())); |
| 291 if (pattern_to_match->Match(national_number.c_str(), true, NULL)) { |
| 292 string formatting_pattern(it->format()); |
| 293 if (number_format == PhoneNumberUtil::NATIONAL && |
| 294 carrier_code.length() > 0 && |
| 295 it->domestic_carrier_code_formatting_rule().length() > 0) { |
| 296 // Replace the $CC in the formatting rule with the desired carrier code. |
| 297 string carrier_code_formatting_rule = |
| 298 it->domestic_carrier_code_formatting_rule(); |
| 299 carrier_code_pattern->Replace(&carrier_code_formatting_rule, |
| 300 false, carrier_code.c_str()); |
| 301 TransformRegularExpressionToRE2Syntax(&carrier_code_formatting_rule); |
| 302 first_group_capturing_pattern->Replace(&formatting_pattern, |
| 303 false, |
| 304 carrier_code_formatting_rule.c_str()); |
| 305 } else { |
| 306 // Use the national prefix formatting rule instead. |
| 307 string national_prefix_formatting_rule = |
| 308 it->national_prefix_formatting_rule(); |
| 309 if (number_format == PhoneNumberUtil::NATIONAL && |
| 310 national_prefix_formatting_rule.length() > 0) { |
| 311 // Apply the national_prefix_formatting_rule as the formatting_pattern |
| 312 // contains only information on how the national significant number |
| 313 // should be formatted at this point. |
| 314 TransformRegularExpressionToRE2Syntax( |
| 315 &national_prefix_formatting_rule); |
| 316 first_group_capturing_pattern->Replace(&formatting_pattern, |
| 317 false, |
| 318 national_prefix_formatting_rule.c_str()); |
| 319 } |
| 320 } |
| 321 TransformRegularExpressionToRE2Syntax(&formatting_pattern); |
| 322 formatted_number->assign(national_number); |
| 323 pattern_to_match->Replace(formatted_number, true, |
| 324 formatting_pattern.c_str()); |
| 325 return; |
| 326 } |
| 327 } |
| 328 // If no pattern above is matched, we format the number as a whole. |
| 329 formatted_number->assign(national_number); |
| 330 } |
| 331 |
| 332 // Simple wrapper of FormatAccordingToFormatsWithCarrier for the common case of |
| 333 // no carrier code. |
| 334 void FormatAccordingToFormats( |
| 335 const string& number_for_leading_digits_match, |
| 336 const RepeatedPtrField<NumberFormat>& available_formats, |
| 337 PhoneNumberUtil::PhoneNumberFormat number_format, |
| 338 const string& national_number, |
| 339 string* formatted_number) { |
| 340 DCHECK(formatted_number); |
| 341 FormatAccordingToFormatsWithCarrier(number_for_leading_digits_match, |
| 342 available_formats, number_format, |
| 343 national_number, "", formatted_number); |
| 344 } |
| 345 |
| 346 // Returns true when one national number is the suffix of the other or both are |
| 347 // the same. |
| 348 bool IsNationalNumberSuffixOfTheOther(const PhoneNumber& first_number, |
| 349 const PhoneNumber& second_number) { |
| 350 const string& first_number_national_number = |
| 351 SimpleItoa(first_number.national_number()); |
| 352 const string& second_number_national_number = |
| 353 SimpleItoa(second_number.national_number()); |
| 354 // Note that HasSuffixString returns true if the numbers are equal. |
| 355 return HasSuffixString(first_number_national_number, |
| 356 second_number_national_number) || |
| 357 HasSuffixString(second_number_national_number, |
| 358 first_number_national_number); |
| 359 } |
| 360 |
| 361 bool IsNumberMatchingDesc(const string& national_number, |
| 362 const PhoneNumberDesc& number_desc) { |
| 363 scoped_ptr<const reg_exp::RegularExpression> |
| 364 possible_pattern(reg_exp::CreateRegularExpression( |
| 365 number_desc.possible_number_pattern().c_str())); |
| 366 scoped_ptr<const reg_exp::RegularExpression> |
| 367 national_pattern(reg_exp::CreateRegularExpression( |
| 368 number_desc.national_number_pattern().c_str())); |
| 369 return (possible_pattern->Match(national_number.c_str(), true, NULL) && |
| 370 national_pattern->Match(national_number.c_str(), true, NULL)); |
| 371 } |
| 372 |
| 373 PhoneNumberUtil::PhoneNumberType GetNumberTypeHelper( |
| 374 const string& national_number, const PhoneMetadata& metadata) { |
| 375 const PhoneNumberDesc& general_desc = metadata.general_desc(); |
| 376 if (!general_desc.has_national_number_pattern() || |
| 377 !IsNumberMatchingDesc(national_number, general_desc)) { |
| 378 logger->Debug("Number type unknown - " |
| 379 "doesn't match general national number pattern."); |
| 380 return PhoneNumberUtil::UNKNOWN; |
| 381 } |
| 382 if (IsNumberMatchingDesc(national_number, metadata.premium_rate())) { |
| 383 logger->Debug("Number is a premium number."); |
| 384 return PhoneNumberUtil::PREMIUM_RATE; |
| 385 } |
| 386 if (IsNumberMatchingDesc(national_number, metadata.toll_free())) { |
| 387 logger->Debug("Number is a toll-free number."); |
| 388 return PhoneNumberUtil::TOLL_FREE; |
| 389 } |
| 390 if (IsNumberMatchingDesc(national_number, metadata.shared_cost())) { |
| 391 logger->Debug("Number is a shared cost number."); |
| 392 return PhoneNumberUtil::SHARED_COST; |
| 393 } |
| 394 if (IsNumberMatchingDesc(national_number, metadata.voip())) { |
| 395 logger->Debug("Number is a VOIP (Voice over IP) number."); |
| 396 return PhoneNumberUtil::VOIP; |
| 397 } |
| 398 if (IsNumberMatchingDesc(national_number, metadata.personal_number())) { |
| 399 logger->Debug("Number is a personal number."); |
| 400 return PhoneNumberUtil::PERSONAL_NUMBER; |
| 401 } |
| 402 if (IsNumberMatchingDesc(national_number, metadata.pager())) { |
| 403 logger->Debug("Number is a pager number."); |
| 404 return PhoneNumberUtil::PAGER; |
| 405 } |
| 406 if (IsNumberMatchingDesc(national_number, metadata.uan())) { |
| 407 logger->Debug("Number is a UAN."); |
| 408 return PhoneNumberUtil::UAN; |
| 409 } |
| 410 |
| 411 bool is_fixed_line = |
| 412 IsNumberMatchingDesc(national_number, metadata.fixed_line()); |
| 413 if (is_fixed_line) { |
| 414 if (metadata.same_mobile_and_fixed_line_pattern()) { |
| 415 logger->Debug("Fixed-line and mobile patterns equal, " |
| 416 "number is fixed-line or mobile"); |
| 417 return PhoneNumberUtil::FIXED_LINE_OR_MOBILE; |
| 418 } else if (IsNumberMatchingDesc(national_number, metadata.mobile())) { |
| 419 logger->Debug("Fixed-line and mobile patterns differ, but number is " |
| 420 "still fixed-line or mobile"); |
| 421 return PhoneNumberUtil::FIXED_LINE_OR_MOBILE; |
| 422 } |
| 423 logger->Debug("Number is a fixed line number."); |
| 424 return PhoneNumberUtil::FIXED_LINE; |
| 425 } |
| 426 // Otherwise, test to see if the number is mobile. Only do this if certain |
| 427 // that the patterns for mobile and fixed line aren't the same. |
| 428 if (!metadata.same_mobile_and_fixed_line_pattern() && |
| 429 IsNumberMatchingDesc(national_number, metadata.mobile())) { |
| 430 logger->Debug("Number is a mobile number."); |
| 431 return PhoneNumberUtil::MOBILE; |
| 432 } |
| 433 logger->Debug("Number type unknown - doesn't match any specific number type" |
| 434 " pattern."); |
| 435 return PhoneNumberUtil::UNKNOWN; |
| 436 } |
| 437 |
| 438 int DecodeUTF8Char(const char* in, char32* out) { |
| 439 Rune r; |
| 440 int len = chartorune(&r, in); |
| 441 *out = r; |
| 442 |
| 443 return len; |
| 444 } |
| 445 |
| 446 char32 ToUnicodeCodepoint(const char* unicode_char) { |
| 447 char32 codepoint; |
| 448 DecodeUTF8Char(unicode_char, &codepoint); |
| 449 |
| 450 return codepoint; |
| 451 } |
| 452 |
| 453 // Initialisation helper function used to populate the regular expressions in a |
| 454 // defined order. |
| 455 void CreateRegularExpressions() { |
| 456 unique_international_prefix.reset( |
| 457 reg_exp::CreateRegularExpression("[\\d]+(?:[~⁓∼~][\\d]+)?")); |
| 458 first_group_capturing_pattern.reset( |
| 459 reg_exp::CreateRegularExpression("(\\$1)")); |
| 460 carrier_code_pattern.reset( |
| 461 reg_exp::CreateRegularExpression("\\$CC")); |
| 462 capturing_digit_pattern.reset( |
| 463 reg_exp::CreateRegularExpression( |
| 464 StrCat("([", kValidDigits, "])").c_str())); |
| 465 capturing_ascii_digits_pattern.reset( |
| 466 reg_exp::CreateRegularExpression("(\\d+)")); |
| 467 valid_start_char.reset(new string(StrCat( |
| 468 "[", kPlusChars, kValidDigits, "]"))); |
| 469 valid_start_char_pattern.reset( |
| 470 reg_exp::CreateRegularExpression(valid_start_char->c_str())); |
| 471 capture_up_to_second_number_start_pattern.reset( |
| 472 reg_exp::CreateRegularExpression(kCaptureUpToSecondNumberStart)); |
| 473 unwanted_end_char_pattern.reset( |
| 474 reg_exp::CreateRegularExpression(kUnwantedEndChar)); |
| 475 valid_phone_number.reset(new string( |
| 476 StrCat("[", kPlusChars, "]*(?:[", kValidPunctuation, "]*[", kValidDigits, |
| 477 "]){3,}[", kValidAlpha, kValidPunctuation, kValidDigits, "]*"))); |
| 478 // Canonical-equivalence doesn't seem to be an option with RE2, so we allow |
| 479 // two options for representing the ó - the character itself, and one in the |
| 480 // unicode decomposed form with the combining acute accent. Note that there |
| 481 // are currently three capturing groups for the extension itself - if this |
| 482 // number is changed, MaybeStripExtension needs to be updated. |
| 483 const string capturing_extn_digits = StrCat("([", kValidDigits, "]{1,7})"); |
| 484 known_extn_patterns.reset(new string( |
| 485 StrCat(kRfc3966ExtnPrefix, capturing_extn_digits, "|" |
| 486 "[ \\t,]*(?:ext(?:ensi(?:ó?|ó))?n?|extn?|[,xx##~~]|" |
| 487 "int|int|anexo)" |
| 488 "[:\\..]?[ \\t,-]*", capturing_extn_digits, "#?|" |
| 489 "[- ]+([", kValidDigits, "]{1,5})#"))); |
| 490 extn_pattern.reset(reg_exp::CreateRegularExpression( |
| 491 StrCat("(?i)(?:", *known_extn_patterns, ")$").c_str())); |
| 492 valid_phone_number_pattern.reset(reg_exp::CreateRegularExpression( |
| 493 StrCat("(?i)", *valid_phone_number, "(?:", *known_extn_patterns, |
| 494 ")?").c_str())); |
| 495 valid_alpha_phone_pattern.reset(reg_exp::CreateRegularExpression( |
| 496 StrCat("(?i)(?:.*?[", kValidAlpha, "]){3}").c_str())); |
| 497 plus_chars_pattern.reset(reg_exp::CreateRegularExpression( |
| 498 StrCat("[", kPlusChars, "]+").c_str())); |
| 499 } |
| 500 |
| 501 void InitializeStaticMapsAndSets() { |
| 502 // Create global objects. |
| 503 all_plus_number_grouping_symbols.reset(new map<char32, char>); |
| 504 alpha_mappings.reset(new map<char32, char>); |
| 505 all_normalization_mappings.reset(new map<char32, char>); |
| 506 |
| 507 // Punctuation that we wish to respect in alpha numbers, as they show number |
| 508 // groupings are mapped here. |
| 509 all_plus_number_grouping_symbols->insert( |
| 510 make_pair(ToUnicodeCodepoint("-"), '-')); |
| 511 all_plus_number_grouping_symbols->insert( |
| 512 make_pair(ToUnicodeCodepoint("-"), '-')); |
| 513 all_plus_number_grouping_symbols->insert( |
| 514 make_pair(ToUnicodeCodepoint("‐"), '-')); |
| 515 all_plus_number_grouping_symbols->insert( |
| 516 make_pair(ToUnicodeCodepoint("‑"), '-')); |
| 517 all_plus_number_grouping_symbols->insert( |
| 518 make_pair(ToUnicodeCodepoint("‒"), '-')); |
| 519 all_plus_number_grouping_symbols->insert( |
| 520 make_pair(ToUnicodeCodepoint("–"), '-')); |
| 521 all_plus_number_grouping_symbols->insert( |
| 522 make_pair(ToUnicodeCodepoint("—"), '-')); |
| 523 all_plus_number_grouping_symbols->insert( |
| 524 make_pair(ToUnicodeCodepoint("―"), '-')); |
| 525 all_plus_number_grouping_symbols->insert( |
| 526 make_pair(ToUnicodeCodepoint("−"), '-')); |
| 527 all_plus_number_grouping_symbols->insert( |
| 528 make_pair(ToUnicodeCodepoint("/"), '/')); |
| 529 all_plus_number_grouping_symbols->insert( |
| 530 make_pair(ToUnicodeCodepoint("/"), '/')); |
| 531 all_plus_number_grouping_symbols->insert( |
| 532 make_pair(ToUnicodeCodepoint(" "), ' ')); |
| 533 all_plus_number_grouping_symbols->insert( |
| 534 make_pair(ToUnicodeCodepoint(" "), ' ')); |
| 535 all_plus_number_grouping_symbols->insert( |
| 536 make_pair(ToUnicodeCodepoint(""), ' ')); |
| 537 all_plus_number_grouping_symbols->insert( |
| 538 make_pair(ToUnicodeCodepoint("."), '.')); |
| 539 all_plus_number_grouping_symbols->insert( |
| 540 make_pair(ToUnicodeCodepoint("."), '.')); |
| 541 // Only the upper-case letters are added here - the lower-case versions are |
| 542 // added programmatically. |
| 543 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("A"), '2')); |
| 544 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("B"), '2')); |
| 545 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("C"), '2')); |
| 546 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("D"), '3')); |
| 547 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("E"), '3')); |
| 548 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("F"), '3')); |
| 549 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("G"), '4')); |
| 550 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("H"), '4')); |
| 551 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("I"), '4')); |
| 552 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("J"), '5')); |
| 553 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("K"), '5')); |
| 554 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("L"), '5')); |
| 555 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("M"), '6')); |
| 556 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("N"), '6')); |
| 557 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("O"), '6')); |
| 558 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("P"), '7')); |
| 559 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("Q"), '7')); |
| 560 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("R"), '7')); |
| 561 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("S"), '7')); |
| 562 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("T"), '8')); |
| 563 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("U"), '8')); |
| 564 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("V"), '8')); |
| 565 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("W"), '9')); |
| 566 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("X"), '9')); |
| 567 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("Y"), '9')); |
| 568 alpha_mappings->insert(make_pair(ToUnicodeCodepoint("Z"), '9')); |
| 569 map<char32, char> lower_case_mappings; |
| 570 map<char32, char> alpha_letters; |
| 571 for (map<char32, char>::const_iterator it = alpha_mappings->begin(); |
| 572 it != alpha_mappings->end(); |
| 573 ++it) { |
| 574 // Convert all the upper-case ASCII letters to lower-case. |
| 575 if (it->first < 128) { |
| 576 char letter_as_upper = static_cast<char>(it->first); |
| 577 char32 letter_as_lower = static_cast<char32>(tolower(letter_as_upper)); |
| 578 lower_case_mappings.insert(make_pair(letter_as_lower, it->second)); |
| 579 // Add the letters in both variants to the alpha_letters map. This just |
| 580 // pairs each letter with its upper-case representation so that it can be |
| 581 // retained when normalising alpha numbers. |
| 582 alpha_letters.insert(make_pair(letter_as_lower, letter_as_upper)); |
| 583 alpha_letters.insert(make_pair(it->first, letter_as_upper)); |
| 584 } |
| 585 } |
| 586 // In the Java version we don't insert the lower-case mappings in the map, |
| 587 // because we convert to upper case on the fly. Doing this here would involve |
| 588 // pulling in all of ICU, which we don't want to do if we don't have to. |
| 589 alpha_mappings->insert(lower_case_mappings.begin(), |
| 590 lower_case_mappings.end()); |
| 591 all_normalization_mappings->insert(alpha_mappings->begin(), |
| 592 alpha_mappings->end()); |
| 593 all_plus_number_grouping_symbols->insert(alpha_letters.begin(), |
| 594 alpha_letters.end()); |
| 595 // Add the ASCII digits so that they don't get deleted by NormalizeHelper(). |
| 596 for (char c = '0'; c <= '9'; ++c) { |
| 597 all_normalization_mappings->insert(make_pair(c, c)); |
| 598 all_plus_number_grouping_symbols->insert(make_pair(c, c)); |
| 599 } |
| 600 CreateRegularExpressions(); |
| 601 } |
| 602 |
| 603 // Normalizes a string of characters representing a phone number by replacing |
| 604 // all characters found in the accompanying map with the values therein, and |
| 605 // stripping all other characters if remove_non_matches is true. |
| 606 // Parameters: |
| 607 // number - a pointer to a string of characters representing a phone number to |
| 608 // be normalized. |
| 609 // normalization_replacements - a mapping of characters to what they should be |
| 610 // replaced by in the normalized version of the phone number |
| 611 // remove_non_matches - indicates whether characters that are not able to be |
| 612 // replaced should be stripped from the number. If this is false, they will be |
| 613 // left unchanged in the number. |
| 614 void NormalizeHelper(const map<char32, char>& normalization_replacements, |
| 615 bool remove_non_matches, |
| 616 string* number) { |
| 617 DCHECK(number); |
| 618 UnicodeText number_as_unicode; |
| 619 number_as_unicode.PointToUTF8(number->data(), number->size()); |
| 620 string normalized_number; |
| 621 for (UnicodeText::const_iterator it = number_as_unicode.begin(); |
| 622 it != number_as_unicode.end(); |
| 623 ++it) { |
| 624 map<char32, char>::const_iterator found_glyph_pair = |
| 625 normalization_replacements.find(*it); |
| 626 if (found_glyph_pair != normalization_replacements.end()) { |
| 627 normalized_number.push_back(found_glyph_pair->second); |
| 628 } else if (!remove_non_matches) { |
| 629 normalized_number.append(it.utf8_data()); |
| 630 } |
| 631 // If neither of the above are true, we remove this character. |
| 632 } |
| 633 number->assign(normalized_number); |
| 634 } |
| 635 |
| 636 // Strips the IDD from the start of the number if present. Helper function used |
| 637 // by MaybeStripInternationalPrefixAndNormalize. |
| 638 bool ParsePrefixAsIdd(const reg_exp::RegularExpression* idd_pattern, |
| 639 string* number) { |
| 640 DCHECK(number); |
| 641 scoped_ptr<reg_exp::RegularExpressionInput> number_copy( |
| 642 reg_exp::CreateRegularExpressionInput(number->c_str())); |
| 643 // First attempt to strip the idd_pattern at the start, if present. We make a |
| 644 // copy so that we can revert to the original string if necessary. |
| 645 if (idd_pattern->Consume(number_copy.get(), true, NULL, NULL)) { |
| 646 // Only strip this if the first digit after the match is not a 0, since |
| 647 // country calling codes cannot begin with 0. |
| 648 string extracted_digit; |
| 649 if (capturing_digit_pattern->Match(number_copy->ToString().c_str(), false, |
| 650 &extracted_digit)) { |
| 651 PhoneNumberUtil::NormalizeDigitsOnly(&extracted_digit); |
| 652 if (extracted_digit == "0") { |
| 653 return false; |
| 654 } |
| 655 } |
| 656 number->assign(number_copy->ToString()); |
| 657 return true; |
| 658 } |
| 659 return false; |
| 660 } |
| 661 |
| 662 PhoneNumberUtil::ValidationResult TestNumberLengthAgainstPattern( |
| 663 const reg_exp::RegularExpression* number_pattern, const string& number) { |
| 664 string extracted_number; |
| 665 if (number_pattern->Match(number.c_str(), true, &extracted_number)) { |
| 666 return PhoneNumberUtil::IS_POSSIBLE; |
| 667 } |
| 668 if (number_pattern->Match(number.c_str(), false, &extracted_number)) { |
| 669 return PhoneNumberUtil::TOO_LONG; |
| 670 } else { |
| 671 return PhoneNumberUtil::TOO_SHORT; |
| 672 } |
| 673 } |
| 674 |
| 675 } // namespace |
| 676 |
| 677 // Fetch the metadata which are actually already available in the address space |
| 678 // (embedded). |
| 679 class DefaultMetadataProvider : public PhoneNumberUtil::MetadataProvider { |
| 680 public: |
| 681 virtual ~DefaultMetadataProvider() {} |
| 682 |
| 683 virtual pair<const void*, unsigned> operator()() { |
| 684 return make_pair(metadata_get(), metadata_size()); |
| 685 } |
| 686 }; |
| 687 |
| 688 bool PhoneNumberUtil::LoadMetadata(PhoneMetadataCollection* metadata, |
| 689 MetadataProvider& provider) { |
| 690 |
| 691 pair<const void*, unsigned> p = provider(); |
| 692 const void* metadata_start = p.first; |
| 693 unsigned size = p.second; |
| 694 |
| 695 if (!metadata->ParseFromArray(metadata_start, size)) { |
| 696 cerr << "Could not parse binary data." << endl; |
| 697 return false; |
| 698 } |
| 699 return true; |
| 700 } |
| 701 |
| 702 void PhoneNumberUtil::SetLoggerAdapter(LoggerAdapter* logger_adapter) { |
| 703 logger.reset(logger_adapter); |
| 704 } |
| 705 |
| 706 // Private constructor. Also takes care of initialisation. |
| 707 PhoneNumberUtil::PhoneNumberUtil(MetadataProvider* provider) |
| 708 : country_calling_code_to_region_code_map_(new vector<IntRegionsPair>()), |
| 709 nanpa_regions_(new set<string>()), |
| 710 region_to_metadata_map_(new map<string, PhoneMetadata>()) { |
| 711 |
| 712 if (logger == NULL) { |
| 713 SetLoggerAdapter(new DefaultLogger()); |
| 714 } |
| 715 PhoneMetadataCollection metadata_collection; |
| 716 DefaultMetadataProvider default_provider; |
| 717 |
| 718 if (!LoadMetadata(&metadata_collection, provider ? *provider |
| 719 : default_provider)) { |
| 720 logger->Fatal("Could not load metadata"); |
| 721 return; |
| 722 } |
| 723 // Storing data in a temporary map to make it easier to find other regions |
| 724 // that share a country calling code when inserting data. |
| 725 map<int, list<string>* > country_calling_code_to_region_map; |
| 726 for (RepeatedPtrField<PhoneMetadata>::const_iterator it = |
| 727 metadata_collection.metadata().begin(); |
| 728 it != metadata_collection.metadata().end(); |
| 729 ++it) { |
| 730 const PhoneMetadata& phone_metadata = *it; |
| 731 const string& region_code = phone_metadata.id(); |
| 732 region_to_metadata_map_->insert(make_pair(region_code, *it)); |
| 733 int country_calling_code = it->country_code(); |
| 734 map<int, list<string>*>::iterator calling_code_in_map = |
| 735 country_calling_code_to_region_map.find(country_calling_code); |
| 736 if (calling_code_in_map != country_calling_code_to_region_map.end()) { |
| 737 if (it->main_country_for_code()) { |
| 738 calling_code_in_map->second->push_front(region_code); |
| 739 } else { |
| 740 calling_code_in_map->second->push_back(region_code); |
| 741 } |
| 742 } else { |
| 743 // For most country calling codes, there will be only one region code. |
| 744 list<string>* list_with_region_code = new list<string>(); |
| 745 list_with_region_code->push_back(region_code); |
| 746 country_calling_code_to_region_map.insert( |
| 747 make_pair(country_calling_code, list_with_region_code)); |
| 748 } |
| 749 if (country_calling_code == kNanpaCountryCode) { |
| 750 nanpa_regions_->insert(region_code); |
| 751 } |
| 752 } |
| 753 |
| 754 country_calling_code_to_region_code_map_->insert( |
| 755 country_calling_code_to_region_code_map_->begin(), |
| 756 country_calling_code_to_region_map.begin(), |
| 757 country_calling_code_to_region_map.end()); |
| 758 // Sort all the pairs in ascending order according to country calling code. |
| 759 sort(country_calling_code_to_region_code_map_->begin(), |
| 760 country_calling_code_to_region_code_map_->end(), |
| 761 CompareFirst()); |
| 762 |
| 763 InitializeStaticMapsAndSets(); |
| 764 } |
| 765 |
| 766 PhoneNumberUtil::~PhoneNumberUtil() { |
| 767 for (vector<IntRegionsPair>::const_iterator it = |
| 768 country_calling_code_to_region_code_map_->begin(); |
| 769 it != country_calling_code_to_region_code_map_->end(); |
| 770 ++it) { |
| 771 delete it->second; |
| 772 } |
| 773 } |
| 774 |
| 775 // Public wrapper function to get a PhoneNumberUtil instance with the default |
| 776 // metadata file. |
| 777 // static |
| 778 PhoneNumberUtil* PhoneNumberUtil::GetInstance() { |
| 779 return Singleton<PhoneNumberUtil>::get(); |
| 780 } |
| 781 |
| 782 void PhoneNumberUtil::GetSupportedRegions(set<string>* regions) const { |
| 783 DCHECK(regions); |
| 784 for (map<string, PhoneMetadata>::const_iterator it = |
| 785 region_to_metadata_map_->begin(); it != region_to_metadata_map_->end(); |
| 786 ++it) { |
| 787 regions->insert(it->first); |
| 788 } |
| 789 } |
| 790 |
| 791 void PhoneNumberUtil::GetNddPrefixForRegion(const string& region_code, |
| 792 bool strip_non_digits, |
| 793 string* national_prefix) const { |
| 794 DCHECK(national_prefix); |
| 795 if (!IsValidRegionCode(region_code)) { |
| 796 logger->Error("Invalid region code provided."); |
| 797 return; |
| 798 } |
| 799 const PhoneMetadata* metadata = GetMetadataForRegion(region_code); |
| 800 national_prefix->assign(metadata->national_prefix()); |
| 801 if (strip_non_digits) { |
| 802 // Note: if any other non-numeric symbols are ever used in national |
| 803 // prefixes, these would have to be removed here as well. |
| 804 strrmm(national_prefix, "~"); |
| 805 } |
| 806 } |
| 807 |
| 808 bool PhoneNumberUtil::IsValidRegionCode(const string& region_code) const { |
| 809 return (region_to_metadata_map_->find(region_code) != |
| 810 region_to_metadata_map_->end()); |
| 811 } |
| 812 |
| 813 bool PhoneNumberUtil::HasValidRegionCode(const string& region_code, |
| 814 int country_code, |
| 815 const string& number) const { |
| 816 if (!IsValidRegionCode(region_code)) { |
| 817 logger->Info(string("Number ") + number + |
| 818 " has invalid or missing country code (" + country_code + ")"); |
| 819 return false; |
| 820 } |
| 821 return true; |
| 822 } |
| 823 |
| 824 // Returns a pointer to the phone metadata for the appropriate region. |
| 825 const PhoneMetadata* PhoneNumberUtil::GetMetadataForRegion( |
| 826 const string& region_code) const { |
| 827 map<string, PhoneMetadata>::const_iterator it = |
| 828 region_to_metadata_map_->find(region_code); |
| 829 if (it != region_to_metadata_map_->end()) { |
| 830 return &it->second; |
| 831 } |
| 832 return NULL; |
| 833 } |
| 834 |
| 835 void PhoneNumberUtil::Format(const PhoneNumber& number, |
| 836 PhoneNumberFormat number_format, |
| 837 string* formatted_number) const { |
| 838 DCHECK(formatted_number); |
| 839 int country_calling_code = number.country_code(); |
| 840 string national_significant_number; |
| 841 GetNationalSignificantNumber(number, &national_significant_number); |
| 842 if (number_format == E164) { |
| 843 // Early exit for E164 case since no formatting of the national number needs |
| 844 // to be applied. Extensions are not formatted. |
| 845 FormatNumberByFormat(country_calling_code, E164, |
| 846 national_significant_number, "", formatted_number); |
| 847 return; |
| 848 } |
| 849 // Note here that all NANPA formatting rules are contained by US, so we use |
| 850 // that to format NANPA numbers. The same applies to Russian Fed regions - |
| 851 // rules are contained by Russia. French Indian Ocean country rules are |
| 852 // contained by Réunion. |
| 853 string region_code; |
| 854 GetRegionCodeForCountryCode(country_calling_code, ®ion_code); |
| 855 if (!HasValidRegionCode(region_code, country_calling_code, |
| 856 national_significant_number)) { |
| 857 formatted_number->assign(national_significant_number); |
| 858 return; |
| 859 } |
| 860 string formatted_extension; |
| 861 MaybeGetFormattedExtension(number, region_code, number_format, |
| 862 &formatted_extension); |
| 863 string formatted_national_number; |
| 864 FormatNationalNumber(national_significant_number, region_code, number_format, |
| 865 &formatted_national_number); |
| 866 FormatNumberByFormat(country_calling_code, number_format, |
| 867 formatted_national_number, |
| 868 formatted_extension, formatted_number); |
| 869 } |
| 870 |
| 871 void PhoneNumberUtil::FormatByPattern( |
| 872 const PhoneNumber& number, |
| 873 PhoneNumberFormat number_format, |
| 874 const RepeatedPtrField<NumberFormat>& user_defined_formats, |
| 875 string* formatted_number) const { |
| 876 static scoped_ptr<const reg_exp::RegularExpression> |
| 877 national_prefix_pattern(reg_exp::CreateRegularExpression("\\$NP")); |
| 878 static scoped_ptr<const reg_exp::RegularExpression> |
| 879 first_group_pattern(reg_exp::CreateRegularExpression("\\$FG")); |
| 880 DCHECK(formatted_number); |
| 881 int country_calling_code = number.country_code(); |
| 882 // Note GetRegionCodeForCountryCode() is used because formatting information |
| 883 // for regions which share a country calling code is contained by only one |
| 884 // region for performance reasons. For example, for NANPA regions it will be |
| 885 // contained in the metadata for US. |
| 886 string region_code; |
| 887 GetRegionCodeForCountryCode(country_calling_code, ®ion_code); |
| 888 string national_significant_number; |
| 889 GetNationalSignificantNumber(number, &national_significant_number); |
| 890 if (!HasValidRegionCode(region_code, country_calling_code, |
| 891 national_significant_number)) { |
| 892 formatted_number->assign(national_significant_number); |
| 893 return; |
| 894 } |
| 895 RepeatedPtrField<NumberFormat> user_defined_formats_copy; |
| 896 for (RepeatedPtrField<NumberFormat>::const_iterator it = |
| 897 user_defined_formats.begin(); |
| 898 it != user_defined_formats.end(); |
| 899 ++it) { |
| 900 string national_prefix_formatting_rule( |
| 901 it->national_prefix_formatting_rule()); |
| 902 if (!national_prefix_formatting_rule.empty()) { |
| 903 const string& national_prefix = |
| 904 GetMetadataForRegion(region_code)->national_prefix(); |
| 905 NumberFormat* num_format_copy = user_defined_formats_copy.Add(); |
| 906 num_format_copy->MergeFrom(*it); |
| 907 if (!national_prefix.empty()) { |
| 908 // Replace $NP with national prefix and $FG with the first group ($1). |
| 909 national_prefix_pattern->Replace(&national_prefix_formatting_rule, |
| 910 false, |
| 911 national_prefix.c_str()); |
| 912 first_group_pattern->Replace(&national_prefix_formatting_rule, |
| 913 false, |
| 914 "$1"); |
| 915 num_format_copy->set_national_prefix_formatting_rule( |
| 916 national_prefix_formatting_rule); |
| 917 } else { |
| 918 // We don't want to have a rule for how to format the national prefix if |
| 919 // there isn't one. |
| 920 num_format_copy->clear_national_prefix_formatting_rule(); |
| 921 } |
| 922 } else { |
| 923 user_defined_formats_copy.Add()->MergeFrom(*it); |
| 924 } |
| 925 } |
| 926 |
| 927 string formatted_number_without_extension; |
| 928 FormatAccordingToFormats(national_significant_number, |
| 929 user_defined_formats_copy, |
| 930 number_format, national_significant_number, |
| 931 &formatted_number_without_extension); |
| 932 string formatted_extension; |
| 933 MaybeGetFormattedExtension(number, region_code, NATIONAL, |
| 934 &formatted_extension); |
| 935 FormatNumberByFormat(country_calling_code, number_format, |
| 936 formatted_number_without_extension, formatted_extension, |
| 937 formatted_number); |
| 938 } |
| 939 |
| 940 void PhoneNumberUtil::FormatNationalNumberWithCarrierCode( |
| 941 const PhoneNumber& number, |
| 942 const string& carrier_code, |
| 943 string* formatted_number) const { |
| 944 int country_calling_code = number.country_code(); |
| 945 string national_significant_number; |
| 946 GetNationalSignificantNumber(number, &national_significant_number); |
| 947 // Note GetRegionCodeForCountryCode() is used because formatting information |
| 948 // for regions which share a country calling code is contained by only one |
| 949 // region for performance reasons. For example, for NANPA regions it will be |
| 950 // contained in the metadata for US. |
| 951 string region_code; |
| 952 GetRegionCodeForCountryCode(country_calling_code, ®ion_code); |
| 953 if (!HasValidRegionCode(region_code, country_calling_code, |
| 954 national_significant_number)) { |
| 955 formatted_number->assign(national_significant_number); |
| 956 } |
| 957 string formatted_extension; |
| 958 MaybeGetFormattedExtension(number, region_code, NATIONAL, |
| 959 &formatted_extension); |
| 960 string formatted_national_number; |
| 961 FormatNationalNumberWithCarrier(national_significant_number, region_code, |
| 962 NATIONAL, carrier_code, |
| 963 &formatted_national_number); |
| 964 FormatNumberByFormat(country_calling_code, NATIONAL, |
| 965 formatted_national_number, formatted_extension, |
| 966 formatted_number); |
| 967 } |
| 968 |
| 969 void PhoneNumberUtil::FormatNationalNumberWithPreferredCarrierCode( |
| 970 const PhoneNumber& number, |
| 971 const string& fallback_carrier_code, |
| 972 string* formatted_number) const { |
| 973 FormatNationalNumberWithCarrierCode( |
| 974 number, |
| 975 number.has_preferred_domestic_carrier_code() |
| 976 ? number.preferred_domestic_carrier_code() |
| 977 : fallback_carrier_code, |
| 978 formatted_number); |
| 979 } |
| 980 |
| 981 void PhoneNumberUtil::FormatOutOfCountryCallingNumber( |
| 982 const PhoneNumber& number, |
| 983 const string& calling_from, |
| 984 string* formatted_number) const { |
| 985 DCHECK(formatted_number); |
| 986 if (!IsValidRegionCode(calling_from)) { |
| 987 logger->Info("Trying to format number from invalid region. International" |
| 988 " formatting applied."); |
| 989 Format(number, INTERNATIONAL, formatted_number); |
| 990 return; |
| 991 } |
| 992 int country_code = number.country_code(); |
| 993 string region_code; |
| 994 GetRegionCodeForCountryCode(country_code, ®ion_code); |
| 995 string national_significant_number; |
| 996 GetNationalSignificantNumber(number, &national_significant_number); |
| 997 if (!HasValidRegionCode(region_code, country_code, |
| 998 national_significant_number)) { |
| 999 formatted_number->assign(national_significant_number); |
| 1000 return; |
| 1001 } |
| 1002 if (country_code == kNanpaCountryCode) { |
| 1003 if (IsNANPACountry(calling_from)) { |
| 1004 // For NANPA regions, return the national format for these regions but |
| 1005 // prefix it with the country calling code. |
| 1006 string national_number; |
| 1007 Format(number, NATIONAL, &national_number); |
| 1008 formatted_number->assign(StrCat(country_code, " ", national_number)); |
| 1009 return; |
| 1010 } |
| 1011 } else if (country_code == GetCountryCodeForRegion(calling_from)) { |
| 1012 // If neither region is a NANPA region, then we check to see if the |
| 1013 // country calling code of the number and the country calling code of the |
| 1014 // region we are calling from are the same. |
| 1015 // For regions that share a country calling code, the country calling code |
| 1016 // need not be dialled. This also applies when dialling within a region, so |
| 1017 // this if clause covers both these cases. |
| 1018 // Technically this is the case for dialling from la Réunion to other |
| 1019 // overseas departments of France (French Guiana, Martinique, Guadeloupe), |
| 1020 // but not vice versa - so we don't cover this edge case for now and for |
| 1021 // those cases return the version including country calling code. |
| 1022 // Details here: |
| 1023 // http://www.petitfute.com/voyage/225-info-pratiques-reunion |
| 1024 Format(number, NATIONAL, formatted_number); |
| 1025 return; |
| 1026 } |
| 1027 string formatted_national_number; |
| 1028 FormatNationalNumber(national_significant_number, region_code, INTERNATIONAL, |
| 1029 &formatted_national_number); |
| 1030 const PhoneMetadata* metadata = GetMetadataForRegion(calling_from); |
| 1031 const string& international_prefix = metadata->international_prefix(); |
| 1032 string formatted_extension; |
| 1033 MaybeGetFormattedExtension(number, region_code, INTERNATIONAL, |
| 1034 &formatted_extension); |
| 1035 // For regions that have multiple international prefixes, the international |
| 1036 // format of the number is returned, unless there is a preferred international |
| 1037 // prefix. |
| 1038 string international_prefix_for_formatting( |
| 1039 unique_international_prefix->Match(international_prefix.c_str(), |
| 1040 true, NULL) |
| 1041 ? international_prefix |
| 1042 : metadata->preferred_international_prefix()); |
| 1043 if (!international_prefix_for_formatting.empty()) { |
| 1044 formatted_number->assign( |
| 1045 StrCat(international_prefix_for_formatting, " ", country_code, " ", |
| 1046 formatted_national_number, formatted_extension)); |
| 1047 } else { |
| 1048 FormatNumberByFormat(country_code, INTERNATIONAL, formatted_national_number, |
| 1049 formatted_extension, formatted_number); |
| 1050 } |
| 1051 } |
| 1052 |
| 1053 void PhoneNumberUtil::FormatInOriginalFormat(const PhoneNumber& number, |
| 1054 const string& region_calling_from, |
| 1055 string* formatted_number) const { |
| 1056 DCHECK(formatted_number); |
| 1057 |
| 1058 if (!number.has_country_code_source()) { |
| 1059 Format(number, NATIONAL, formatted_number); |
| 1060 return; |
| 1061 } |
| 1062 switch (number.country_code_source()) { |
| 1063 case PhoneNumber::FROM_NUMBER_WITH_PLUS_SIGN: |
| 1064 Format(number, INTERNATIONAL, formatted_number); |
| 1065 return; |
| 1066 case PhoneNumber::FROM_NUMBER_WITH_IDD: |
| 1067 FormatOutOfCountryCallingNumber(number, region_calling_from, |
| 1068 formatted_number); |
| 1069 return; |
| 1070 case PhoneNumber::FROM_NUMBER_WITHOUT_PLUS_SIGN: |
| 1071 Format(number, INTERNATIONAL, formatted_number); |
| 1072 formatted_number->erase(formatted_number->begin()); |
| 1073 return; |
| 1074 case PhoneNumber::FROM_DEFAULT_COUNTRY: |
| 1075 default: |
| 1076 Format(number, NATIONAL, formatted_number); |
| 1077 } |
| 1078 } |
| 1079 |
| 1080 void PhoneNumberUtil::FormatOutOfCountryKeepingAlphaChars( |
| 1081 const PhoneNumber& number, |
| 1082 const string& calling_from, |
| 1083 string* formatted_number) const { |
| 1084 // If there is no raw input, then we can't keep alpha characters because there |
| 1085 // aren't any. In this case, we return FormatOutOfCountryCallingNumber. |
| 1086 if (number.raw_input().empty()) { |
| 1087 FormatOutOfCountryCallingNumber(number, calling_from, formatted_number); |
| 1088 return; |
| 1089 } |
| 1090 string region_code; |
| 1091 GetRegionCodeForCountryCode(number.country_code(), ®ion_code); |
| 1092 if (!HasValidRegionCode(region_code, number.country_code(), |
| 1093 number.raw_input())) { |
| 1094 formatted_number->assign(number.raw_input()); |
| 1095 return; |
| 1096 } |
| 1097 // Strip any prefix such as country calling code, IDD, that was present. We do |
| 1098 // this by comparing the number in raw_input with the parsed number. |
| 1099 string raw_input_copy(number.raw_input()); |
| 1100 // Normalize punctuation. We retain number grouping symbols such as " " only. |
| 1101 NormalizeHelper(*all_plus_number_grouping_symbols, true, &raw_input_copy); |
| 1102 // Now we trim everything before the first three digits in the parsed number. |
| 1103 // We choose three because all valid alpha numbers have 3 digits at the start |
| 1104 // - if it does not, then we don't trim anything at all. Similarly, if the |
| 1105 // national number was less than three digits, we don't trim anything at all. |
| 1106 string national_number; |
| 1107 GetNationalSignificantNumber(number, &national_number); |
| 1108 if (national_number.length() > 3) { |
| 1109 size_t first_national_number_digit = |
| 1110 raw_input_copy.find(national_number.substr(0, 3)); |
| 1111 if (first_national_number_digit != string::npos) { |
| 1112 raw_input_copy = raw_input_copy.substr(first_national_number_digit); |
| 1113 } |
| 1114 } |
| 1115 const PhoneMetadata* metadata = GetMetadataForRegion(calling_from); |
| 1116 if (number.country_code() == kNanpaCountryCode) { |
| 1117 if (IsNANPACountry(calling_from)) { |
| 1118 formatted_number->assign(StrCat(number.country_code(), " ", |
| 1119 raw_input_copy)); |
| 1120 return; |
| 1121 } |
| 1122 } else if (number.country_code() == GetCountryCodeForRegion(calling_from)) { |
| 1123 // Here we copy the formatting rules so we can modify the pattern we expect |
| 1124 // to match against. |
| 1125 RepeatedPtrField<NumberFormat> available_formats = metadata->number_format()
; |
| 1126 for (RepeatedPtrField<NumberFormat>::iterator |
| 1127 it = available_formats.begin(); it != available_formats.end(); ++it) { |
| 1128 // The first group is the first group of digits that the user determined. |
| 1129 it->set_pattern("(\\d+)(.*)"); |
| 1130 // Here we just concatenate them back together after the national prefix |
| 1131 // has been fixed. |
| 1132 it->set_format("$1$2"); |
| 1133 } |
| 1134 // Now we format using these patterns instead of the default pattern, but |
| 1135 // with the national prefix prefixed if necessary, by choosing the format |
| 1136 // rule based on the leading digits present in the unformatted national |
| 1137 // number. |
| 1138 // This will not work in the cases where the pattern (and not the |
| 1139 // leading digits) decide whether a national prefix needs to be used, since |
| 1140 // we have overridden the pattern to match anything, but that is not the |
| 1141 // case in the metadata to date. |
| 1142 FormatAccordingToFormats(national_number, available_formats, |
| 1143 NATIONAL, raw_input_copy, formatted_number); |
| 1144 return; |
| 1145 } |
| 1146 |
| 1147 const string& international_prefix = metadata->international_prefix(); |
| 1148 // For regions that have multiple international prefixes, the international |
| 1149 // format of the number is returned, unless there is a preferred international |
| 1150 // prefix. |
| 1151 string international_prefix_for_formatting( |
| 1152 unique_international_prefix->Match(international_prefix.c_str(), |
| 1153 true, NULL) |
| 1154 ? international_prefix |
| 1155 : metadata->preferred_international_prefix()); |
| 1156 if (!international_prefix_for_formatting.empty()) { |
| 1157 formatted_number->assign( |
| 1158 StrCat(international_prefix_for_formatting, " ", number.country_code(), |
| 1159 " ", raw_input_copy)); |
| 1160 } else { |
| 1161 FormatNumberByFormat(number.country_code(), INTERNATIONAL, raw_input_copy, |
| 1162 "", formatted_number); |
| 1163 } |
| 1164 } |
| 1165 |
| 1166 void PhoneNumberUtil::FormatNationalNumber( |
| 1167 const string& number, |
| 1168 const string& region_code, |
| 1169 PhoneNumberFormat number_format, |
| 1170 string* formatted_number) const { |
| 1171 DCHECK(formatted_number); |
| 1172 FormatNationalNumberWithCarrier(number, region_code, number_format, "", |
| 1173 formatted_number); |
| 1174 } |
| 1175 |
| 1176 // Note in some regions, the national number can be written in two completely |
| 1177 // different ways depending on whether it forms part of the NATIONAL format or |
| 1178 // INTERNATIONAL format. The number_format parameter here is used to specify |
| 1179 // which format to use for those cases. If a carrier_code is specified, this |
| 1180 // will be inserted into the formatted string to replace $CC. |
| 1181 void PhoneNumberUtil::FormatNationalNumberWithCarrier( |
| 1182 const string& number, |
| 1183 const string& region_code, |
| 1184 PhoneNumberFormat number_format, |
| 1185 const string& carrier_code, |
| 1186 string* formatted_number) const { |
| 1187 DCHECK(formatted_number); |
| 1188 const PhoneMetadata* metadata = GetMetadataForRegion(region_code); |
| 1189 // When the intl_number_formats exists, we use that to format national number |
| 1190 // for the INTERNATIONAL format instead of using the number_formats. |
| 1191 const RepeatedPtrField<NumberFormat> available_formats = |
| 1192 (metadata->intl_number_format_size() == 0 || number_format == NATIONAL) |
| 1193 ? metadata->number_format() |
| 1194 : metadata->intl_number_format(); |
| 1195 FormatAccordingToFormatsWithCarrier(number, available_formats, number_format, |
| 1196 number, carrier_code, formatted_number); |
| 1197 if (number_format == RFC3966) { |
| 1198 // Replace all separators with a "-". |
| 1199 scoped_ptr<const reg_exp::RegularExpression> separator_pattern( |
| 1200 reg_exp::CreateRegularExpression( |
| 1201 StrCat("[", kValidPunctuation, "]+").c_str())); |
| 1202 separator_pattern->Replace(formatted_number, true, "-"); |
| 1203 } |
| 1204 } |
| 1205 |
| 1206 // Gets the formatted extension of a phone number, if the phone number had an |
| 1207 // extension specified. If not, it returns an empty string. |
| 1208 void PhoneNumberUtil::MaybeGetFormattedExtension( |
| 1209 const PhoneNumber& number, |
| 1210 const string& region_code, |
| 1211 PhoneNumberFormat number_format, |
| 1212 string* extension) const { |
| 1213 DCHECK(extension); |
| 1214 if (!number.has_extension() || number.extension().length() == 0) { |
| 1215 extension->assign(""); |
| 1216 } else { |
| 1217 if (number_format == RFC3966) { |
| 1218 StrAppend(extension, kRfc3966ExtnPrefix, number.extension()); |
| 1219 return; |
| 1220 } |
| 1221 FormatExtension(number.extension(), region_code, extension); |
| 1222 } |
| 1223 } |
| 1224 |
| 1225 // Formats the extension part of the phone number by prefixing it with the |
| 1226 // appropriate extension prefix. This will be the default extension prefix, |
| 1227 // unless overridden by a preferred extension prefix for this region. |
| 1228 void PhoneNumberUtil::FormatExtension(const string& extension_digits, |
| 1229 const string& region_code, |
| 1230 string* extension) const { |
| 1231 DCHECK(extension); |
| 1232 const PhoneMetadata* metadata = GetMetadataForRegion(region_code); |
| 1233 if (metadata->has_preferred_extn_prefix()) { |
| 1234 extension->assign(StrCat(metadata->preferred_extn_prefix(), |
| 1235 extension_digits)); |
| 1236 } else { |
| 1237 extension->assign(StrCat(kDefaultExtnPrefix, extension_digits)); |
| 1238 } |
| 1239 } |
| 1240 |
| 1241 bool PhoneNumberUtil::IsNANPACountry(const string& region_code) const { |
| 1242 return nanpa_regions_->find(region_code) != nanpa_regions_->end(); |
| 1243 } |
| 1244 |
| 1245 // Returns the region codes that matches the specific country calling code. In |
| 1246 // the case of no region code being found, region_codes will be left empty. |
| 1247 void PhoneNumberUtil::GetRegionCodesForCountryCallingCode( |
| 1248 int country_calling_code, |
| 1249 list<string>* region_codes) const { |
| 1250 DCHECK(region_codes); |
| 1251 // Create a IntRegionsPair with the country_code passed in, and use it to |
| 1252 // locate the pair with the same country_code in the sorted vector. |
| 1253 IntRegionsPair target_pair; |
| 1254 target_pair.first = country_calling_code; |
| 1255 typedef vector<IntRegionsPair>::const_iterator ConstIterator; |
| 1256 pair<ConstIterator, ConstIterator> range = equal_range( |
| 1257 country_calling_code_to_region_code_map_->begin(), |
| 1258 country_calling_code_to_region_code_map_->end(), |
| 1259 target_pair, CompareFirst()); |
| 1260 if (range.first != range.second) { |
| 1261 region_codes->insert(region_codes->begin(), |
| 1262 range.first->second->begin(), |
| 1263 range.first->second->end()); |
| 1264 } |
| 1265 } |
| 1266 |
| 1267 // Returns the region code that matches the specific country calling code. In |
| 1268 // the case of no region code being found, ZZ will be returned. |
| 1269 void PhoneNumberUtil::GetRegionCodeForCountryCode( |
| 1270 int country_calling_code, |
| 1271 string* region_code) const { |
| 1272 DCHECK(region_code); |
| 1273 list<string> region_codes; |
| 1274 |
| 1275 GetRegionCodesForCountryCallingCode(country_calling_code, ®ion_codes); |
| 1276 *region_code = region_codes.size() != 0 ? region_codes.front() : "ZZ"; |
| 1277 } |
| 1278 |
| 1279 void PhoneNumberUtil::GetRegionCodeForNumber(const PhoneNumber& number, |
| 1280 string* region_code) const { |
| 1281 DCHECK(region_code); |
| 1282 int country_calling_code = number.country_code(); |
| 1283 list<string> region_codes; |
| 1284 GetRegionCodesForCountryCallingCode(country_calling_code, ®ion_codes); |
| 1285 if (region_codes.size() == 0) { |
| 1286 string number_string; |
| 1287 GetNationalSignificantNumber(number, &number_string); |
| 1288 logger->Warning(string("Missing/invalid country code (") + |
| 1289 SimpleItoa(country_calling_code) + ") for number " + number_string); |
| 1290 *region_code = "ZZ"; |
| 1291 return; |
| 1292 } |
| 1293 if (region_codes.size() == 1) { |
| 1294 *region_code = region_codes.front(); |
| 1295 } else { |
| 1296 GetRegionCodeForNumberFromRegionList(number, region_codes, region_code); |
| 1297 } |
| 1298 } |
| 1299 |
| 1300 void PhoneNumberUtil::GetRegionCodeForNumberFromRegionList( |
| 1301 const PhoneNumber& number, const list<string>& region_codes, |
| 1302 string* region_code) const { |
| 1303 DCHECK(region_code); |
| 1304 string national_number; |
| 1305 GetNationalSignificantNumber(number, &national_number); |
| 1306 for (list<string>::const_iterator it = region_codes.begin(); |
| 1307 it != region_codes.end(); ++it) { |
| 1308 const PhoneMetadata* metadata = GetMetadataForRegion(*it); |
| 1309 if (metadata->has_leading_digits()) { |
| 1310 scoped_ptr<reg_exp::RegularExpressionInput> number( |
| 1311 reg_exp::CreateRegularExpressionInput(national_number.c_str())); |
| 1312 if (number->ConsumeRegExp(metadata->leading_digits(), true, NULL, NULL)) { |
| 1313 *region_code = *it; |
| 1314 return; |
| 1315 } |
| 1316 } else if (GetNumberTypeHelper(national_number, *metadata) != UNKNOWN) { |
| 1317 *region_code = *it; |
| 1318 return; |
| 1319 } |
| 1320 } |
| 1321 *region_code = "ZZ"; |
| 1322 } |
| 1323 |
| 1324 int PhoneNumberUtil::GetCountryCodeForRegion(const string& region_code) const { |
| 1325 if (!IsValidRegionCode(region_code)) { |
| 1326 logger->Info("Invalid or unknown country code provided."); |
| 1327 return 0; |
| 1328 } |
| 1329 const PhoneMetadata* metadata = GetMetadataForRegion(region_code); |
| 1330 if (!metadata) { |
| 1331 logger->Error("Unsupported country code provided."); |
| 1332 return 0; |
| 1333 } |
| 1334 return metadata->country_code(); |
| 1335 } |
| 1336 |
| 1337 // Gets a valid fixed-line number for the specified region_code. Returns false |
| 1338 // if the country was unknown or if no number exists. |
| 1339 bool PhoneNumberUtil::GetExampleNumber(const string& region_code, |
| 1340 PhoneNumber* number) const { |
| 1341 DCHECK(number); |
| 1342 return GetExampleNumberForType(region_code, |
| 1343 FIXED_LINE, |
| 1344 number); |
| 1345 } |
| 1346 |
| 1347 // Gets a valid number for the specified region_code and type. Returns false if |
| 1348 // the country was unknown or if no number exists. |
| 1349 bool PhoneNumberUtil::GetExampleNumberForType( |
| 1350 const string& region_code, |
| 1351 PhoneNumberUtil::PhoneNumberType type, |
| 1352 PhoneNumber* number) const { |
| 1353 DCHECK(number); |
| 1354 const PhoneMetadata* region_metadata = GetMetadataForRegion(region_code); |
| 1355 const PhoneNumberDesc* description = |
| 1356 GetNumberDescByType(*region_metadata, type); |
| 1357 if (description && description->has_example_number()) { |
| 1358 return (Parse(description->example_number(), |
| 1359 region_code, |
| 1360 number) == NO_PARSING_ERROR); |
| 1361 } |
| 1362 return false; |
| 1363 } |
| 1364 |
| 1365 PhoneNumberUtil::ErrorType PhoneNumberUtil::Parse(const string& number_to_parse, |
| 1366 const string& default_region, |
| 1367 PhoneNumber* number) const { |
| 1368 DCHECK(number); |
| 1369 return ParseHelper(number_to_parse, default_region, false, true, number); |
| 1370 } |
| 1371 |
| 1372 PhoneNumberUtil::ErrorType PhoneNumberUtil::ParseAndKeepRawInput( |
| 1373 const string& number_to_parse, |
| 1374 const string& default_region, |
| 1375 PhoneNumber* number) const { |
| 1376 DCHECK(number); |
| 1377 return ParseHelper(number_to_parse, default_region, true, true, number); |
| 1378 } |
| 1379 |
| 1380 // Checks to see that the region code used is valid, or if it is not valid, that |
| 1381 // the number to parse starts with a + symbol so that we can attempt to infer |
| 1382 // the country from the number. Returns false if it cannot use the region |
| 1383 // provided and the region cannot be inferred. |
| 1384 bool PhoneNumberUtil::CheckRegionForParsing( |
| 1385 const string& number_to_parse, |
| 1386 const string& default_region) const { |
| 1387 if (!IsValidRegionCode(default_region) && !number_to_parse.empty()) { |
| 1388 scoped_ptr<reg_exp::RegularExpressionInput> number_as_string_piece( |
| 1389 reg_exp::CreateRegularExpressionInput(number_to_parse.c_str())); |
| 1390 if (!plus_chars_pattern->Consume(number_as_string_piece.get(), |
| 1391 true, NULL, NULL)) { |
| 1392 return false; |
| 1393 } |
| 1394 } |
| 1395 return true; |
| 1396 } |
| 1397 |
| 1398 PhoneNumberUtil::ErrorType PhoneNumberUtil::ParseHelper( |
| 1399 const string& number_to_parse, |
| 1400 const string& default_region, |
| 1401 bool keep_raw_input, |
| 1402 bool check_region, |
| 1403 PhoneNumber* phone_number) const { |
| 1404 DCHECK(phone_number); |
| 1405 // Extract a possible number from the string passed in (this strips leading |
| 1406 // characters that could not be the start of a phone number.) |
| 1407 string national_number; |
| 1408 ExtractPossibleNumber(number_to_parse, &national_number); |
| 1409 if (!IsViablePhoneNumber(national_number)) { |
| 1410 logger->Debug("The string supplied did not seem to be a phone number."); |
| 1411 return NOT_A_NUMBER; |
| 1412 } |
| 1413 |
| 1414 if (check_region && |
| 1415 !CheckRegionForParsing(national_number, default_region)) { |
| 1416 logger->Info("Missing or invalid default country."); |
| 1417 return INVALID_COUNTRY_CODE_ERROR; |
| 1418 } |
| 1419 PhoneNumber temp_number; |
| 1420 if (keep_raw_input) { |
| 1421 temp_number.set_raw_input(number_to_parse); |
| 1422 } |
| 1423 // Attempt to parse extension first, since it doesn't require country-specific |
| 1424 // data and we want to have the non-normalised number here. |
| 1425 string extension; |
| 1426 MaybeStripExtension(&national_number, &extension); |
| 1427 if (!extension.empty()) { |
| 1428 temp_number.set_extension(extension); |
| 1429 } |
| 1430 const PhoneMetadata* country_metadata = GetMetadataForRegion(default_region); |
| 1431 // Check to see if the number is given in international format so we know |
| 1432 // whether this number is from the default country or not. |
| 1433 string normalized_national_number(national_number); |
| 1434 ErrorType country_code_error = |
| 1435 MaybeExtractCountryCode(country_metadata, keep_raw_input, |
| 1436 &normalized_national_number, &temp_number); |
| 1437 int country_code = temp_number.country_code(); |
| 1438 if (country_code_error != NO_PARSING_ERROR) { |
| 1439 return country_code_error; |
| 1440 } |
| 1441 if (country_code != 0) { |
| 1442 string phone_number_region; |
| 1443 GetRegionCodeForCountryCode(country_code, &phone_number_region); |
| 1444 if (phone_number_region != default_region) { |
| 1445 country_metadata = GetMetadataForRegion(phone_number_region); |
| 1446 } |
| 1447 } else if (country_metadata) { |
| 1448 // If no extracted country calling code, use the region supplied instead. |
| 1449 // Note that the national number was already normalized by |
| 1450 // MaybeExtractCountryCode. |
| 1451 country_code = country_metadata->country_code(); |
| 1452 } |
| 1453 if (normalized_national_number.length() < kMinLengthForNsn) { |
| 1454 logger->Debug("The string supplied is too short to be a phone number."); |
| 1455 return TOO_SHORT_NSN; |
| 1456 } |
| 1457 if (country_metadata) { |
| 1458 string* carrier_code = keep_raw_input ? |
| 1459 temp_number.mutable_preferred_domestic_carrier_code() : NULL; |
| 1460 MaybeStripNationalPrefixAndCarrierCode(*country_metadata, |
| 1461 &normalized_national_number, |
| 1462 carrier_code); |
| 1463 } |
| 1464 size_t normalized_national_number_length = |
| 1465 normalized_national_number.length(); |
| 1466 if (normalized_national_number_length < kMinLengthForNsn) { |
| 1467 logger->Debug("The string supplied is too short to be a phone number."); |
| 1468 return TOO_SHORT_NSN; |
| 1469 } |
| 1470 if (normalized_national_number_length > kMaxLengthForNsn) { |
| 1471 logger->Debug("The string supplied is too long to be a phone number."); |
| 1472 return TOO_LONG_NSN; |
| 1473 } |
| 1474 temp_number.set_country_code(country_code); |
| 1475 if (country_metadata && |
| 1476 country_metadata->leading_zero_possible() && |
| 1477 normalized_national_number[0] == '0') { |
| 1478 temp_number.set_italian_leading_zero(true); |
| 1479 } |
| 1480 uint64 number_as_int; |
| 1481 safe_strtou64(normalized_national_number, &number_as_int); |
| 1482 temp_number.set_national_number(number_as_int); |
| 1483 phone_number->MergeFrom(temp_number); |
| 1484 return NO_PARSING_ERROR; |
| 1485 } |
| 1486 |
| 1487 // Attempts to extract a possible number from the string passed in. This |
| 1488 // currently strips all leading characters that could not be used to start a |
| 1489 // phone number. Characters that can be used to start a phone number are |
| 1490 // defined in the valid_start_char_pattern. If none of these characters are |
| 1491 // found in the number passed in, an empty string is returned. This function |
| 1492 // also attempts to strip off any alternative extensions or endings if two or |
| 1493 // more are present, such as in the case of: (530) 583-6985 x302/x2303. The |
| 1494 // second extension here makes this actually two phone numbers, (530) 583-6985 |
| 1495 // x302 and (530) 583-6985 x2303. We remove the second extension so that the |
| 1496 // first number is parsed correctly. |
| 1497 // static |
| 1498 void PhoneNumberUtil::ExtractPossibleNumber(const string& number, |
| 1499 string* extracted_number) { |
| 1500 DCHECK(extracted_number); |
| 1501 |
| 1502 UnicodeText number_as_unicode; |
| 1503 number_as_unicode.PointToUTF8(number.data(), number.size()); |
| 1504 char current_char[5]; |
| 1505 int len; |
| 1506 UnicodeText::const_iterator it; |
| 1507 for (it = number_as_unicode.begin(); it != number_as_unicode.end(); ++it) { |
| 1508 len = it.get_utf8(current_char); |
| 1509 current_char[len] = '\0'; |
| 1510 if (valid_start_char_pattern->Match(current_char, true, NULL)) { |
| 1511 break; |
| 1512 } |
| 1513 } |
| 1514 |
| 1515 if (it == number_as_unicode.end()) { |
| 1516 // No valid start character was found. extracted_number should be set to |
| 1517 // empty string. |
| 1518 extracted_number->assign(""); |
| 1519 return; |
| 1520 } |
| 1521 |
| 1522 UnicodeText::const_reverse_iterator reverse_it(number_as_unicode.end()); |
| 1523 for (; reverse_it.base() != it; ++reverse_it) { |
| 1524 len = reverse_it.get_utf8(current_char); |
| 1525 current_char[len] = '\0'; |
| 1526 if (!unwanted_end_char_pattern->Match(current_char, true, NULL)) { |
| 1527 break; |
| 1528 } |
| 1529 } |
| 1530 |
| 1531 if (reverse_it.base() == it) { |
| 1532 extracted_number->assign(""); |
| 1533 return; |
| 1534 } |
| 1535 |
| 1536 extracted_number->assign(UnicodeText::UTF8Substring(it, reverse_it.base())); |
| 1537 |
| 1538 logger->Debug("After stripping starting and trailing characters," |
| 1539 " left with: " + *extracted_number); |
| 1540 |
| 1541 // Now remove any extra numbers at the end. |
| 1542 capture_up_to_second_number_start_pattern->Match(extracted_number->c_str(), |
| 1543 false, |
| 1544 extracted_number); |
| 1545 } |
| 1546 |
| 1547 bool PhoneNumberUtil::IsPossibleNumber(const PhoneNumber& number) const { |
| 1548 return IsPossibleNumberWithReason(number) == IS_POSSIBLE; |
| 1549 } |
| 1550 |
| 1551 bool PhoneNumberUtil::IsPossibleNumberForString( |
| 1552 const string& number, |
| 1553 const string& region_dialing_from) const { |
| 1554 PhoneNumber number_proto; |
| 1555 if (Parse(number, region_dialing_from, &number_proto) == NO_PARSING_ERROR) { |
| 1556 return IsPossibleNumber(number_proto); |
| 1557 } else { |
| 1558 return false; |
| 1559 } |
| 1560 } |
| 1561 |
| 1562 PhoneNumberUtil::ValidationResult PhoneNumberUtil::IsPossibleNumberWithReason( |
| 1563 const PhoneNumber& number) const { |
| 1564 string national_number; |
| 1565 GetNationalSignificantNumber(number, &national_number); |
| 1566 int country_code = number.country_code(); |
| 1567 // Note: For Russian Fed and NANPA numbers, we just use the rules from the |
| 1568 // default region (US or Russia) since the GetRegionCodeForNumber will not |
| 1569 // work if the number is possible but not valid. This would need to be |
| 1570 // revisited if the possible number pattern ever differed between various |
| 1571 // regions within those plans. |
| 1572 string region_code; |
| 1573 GetRegionCodeForCountryCode(country_code, ®ion_code); |
| 1574 if (!HasValidRegionCode(region_code, country_code, national_number)) { |
| 1575 return INVALID_COUNTRY_CODE; |
| 1576 } |
| 1577 const PhoneNumberDesc& general_num_desc = |
| 1578 GetMetadataForRegion(region_code)->general_desc(); |
| 1579 // Handling case of numbers with no metadata. |
| 1580 if (!general_num_desc.has_national_number_pattern()) { |
| 1581 size_t number_length = national_number.length(); |
| 1582 if (number_length < kMinLengthForNsn) { |
| 1583 return TOO_SHORT; |
| 1584 } else if (number_length > kMaxLengthForNsn) { |
| 1585 return TOO_LONG; |
| 1586 } else { |
| 1587 return IS_POSSIBLE; |
| 1588 } |
| 1589 } |
| 1590 scoped_ptr<reg_exp::RegularExpression> possible_number_pattern( |
| 1591 reg_exp::CreateRegularExpression( |
| 1592 StrCat("(", general_num_desc.possible_number_pattern(), ")").c_str())); |
| 1593 return TestNumberLengthAgainstPattern(possible_number_pattern.get(), |
| 1594 national_number); |
| 1595 } |
| 1596 |
| 1597 bool PhoneNumberUtil::TruncateTooLongNumber(PhoneNumber* number) const { |
| 1598 if (IsValidNumber(*number)) { |
| 1599 return true; |
| 1600 } |
| 1601 PhoneNumber number_copy(*number); |
| 1602 uint64 national_number = number->national_number(); |
| 1603 do { |
| 1604 national_number /= 10; |
| 1605 number_copy.set_national_number(national_number); |
| 1606 if (IsPossibleNumberWithReason(number_copy) == TOO_SHORT || |
| 1607 national_number == 0) { |
| 1608 return false; |
| 1609 } |
| 1610 } while (!IsValidNumber(number_copy)); |
| 1611 number->set_national_number(national_number); |
| 1612 return true; |
| 1613 } |
| 1614 |
| 1615 PhoneNumberUtil::PhoneNumberType PhoneNumberUtil::GetNumberType( |
| 1616 const PhoneNumber& number) const { |
| 1617 string region_code; |
| 1618 GetRegionCodeForNumber(number, ®ion_code); |
| 1619 if (!IsValidRegionCode(region_code)) { |
| 1620 return UNKNOWN; |
| 1621 } |
| 1622 string national_significant_number; |
| 1623 GetNationalSignificantNumber(number, &national_significant_number); |
| 1624 return GetNumberTypeHelper(national_significant_number, |
| 1625 *GetMetadataForRegion(region_code)); |
| 1626 } |
| 1627 |
| 1628 bool PhoneNumberUtil::IsValidNumber(const PhoneNumber& number) const { |
| 1629 string region_code; |
| 1630 GetRegionCodeForNumber(number, ®ion_code); |
| 1631 return IsValidRegionCode(region_code) && |
| 1632 IsValidNumberForRegion(number, region_code); |
| 1633 } |
| 1634 |
| 1635 bool PhoneNumberUtil::IsValidNumberForRegion(const PhoneNumber& number, |
| 1636 const string& region_code) const { |
| 1637 if (number.country_code() != GetCountryCodeForRegion(region_code)) { |
| 1638 return false; |
| 1639 } |
| 1640 const PhoneMetadata* metadata = GetMetadataForRegion(region_code); |
| 1641 const PhoneNumberDesc& general_desc = metadata->general_desc(); |
| 1642 string national_number; |
| 1643 GetNationalSignificantNumber(number, &national_number); |
| 1644 |
| 1645 // For regions where we don't have metadata for PhoneNumberDesc, we treat |
| 1646 // any number passed in as a valid number if its national significant number |
| 1647 // is between the minimum and maximum lengths defined by ITU for a national |
| 1648 // significant number. |
| 1649 if (!general_desc.has_national_number_pattern()) { |
| 1650 logger->Info("Validating number with incomplete metadata."); |
| 1651 size_t number_length = national_number.length(); |
| 1652 return number_length > kMinLengthForNsn && |
| 1653 number_length <= kMaxLengthForNsn; |
| 1654 } |
| 1655 return GetNumberTypeHelper(national_number, *metadata) != UNKNOWN; |
| 1656 } |
| 1657 |
| 1658 bool PhoneNumberUtil::IsLeadingZeroPossible(int country_calling_code) const { |
| 1659 string region_code; |
| 1660 GetRegionCodeForCountryCode(country_calling_code, ®ion_code); |
| 1661 const PhoneMetadata* main_metadata_for_calling_code = |
| 1662 GetMetadataForRegion(region_code); |
| 1663 if (!main_metadata_for_calling_code) return false; |
| 1664 return main_metadata_for_calling_code->leading_zero_possible(); |
| 1665 } |
| 1666 |
| 1667 void PhoneNumberUtil::GetNationalSignificantNumber( |
| 1668 const PhoneNumber& number, |
| 1669 string* national_number) const { |
| 1670 // The leading zero in the national (significant) number of an Italian phone |
| 1671 // number has a special meaning. Unlike the rest of the world, it indicates |
| 1672 // the number is a landline number. There have been plans to migrate landline |
| 1673 // numbers to start with the digit two since December 2000, but it has not yet |
| 1674 // happened. |
| 1675 // See http://en.wikipedia.org/wiki/%2B39 for more details. |
| 1676 // Other regions such as Cote d'Ivoire and Gabon use this for their mobile |
| 1677 // numbers. |
| 1678 DCHECK(national_number); |
| 1679 StrAppend(national_number, |
| 1680 (IsLeadingZeroPossible(number.country_code()) && |
| 1681 number.has_italian_leading_zero() && |
| 1682 number.italian_leading_zero()) |
| 1683 ? "0" |
| 1684 : ""); |
| 1685 StrAppend(national_number, number.national_number()); |
| 1686 } |
| 1687 |
| 1688 int PhoneNumberUtil::GetLengthOfGeographicalAreaCode( |
| 1689 const PhoneNumber& number) const { |
| 1690 string region_code; |
| 1691 GetRegionCodeForNumber(number, ®ion_code); |
| 1692 if (!IsValidRegionCode(region_code)) { |
| 1693 return 0; |
| 1694 } |
| 1695 const PhoneMetadata* metadata = GetMetadataForRegion(region_code); |
| 1696 DCHECK(metadata); |
| 1697 if (!metadata->has_national_prefix()) { |
| 1698 return 0; |
| 1699 } |
| 1700 |
| 1701 string national_significant_number; |
| 1702 GetNationalSignificantNumber(number, &national_significant_number); |
| 1703 PhoneNumberType type = GetNumberTypeHelper(national_significant_number, |
| 1704 *metadata); |
| 1705 // Most numbers other than the two types below have to be dialled in full. |
| 1706 if (type != FIXED_LINE && type != FIXED_LINE_OR_MOBILE) { |
| 1707 return 0; |
| 1708 } |
| 1709 |
| 1710 return GetLengthOfNationalDestinationCode(number); |
| 1711 } |
| 1712 |
| 1713 int PhoneNumberUtil::GetLengthOfNationalDestinationCode( |
| 1714 const PhoneNumber& number) const { |
| 1715 PhoneNumber copied_proto(number); |
| 1716 if (number.has_extension()) { |
| 1717 // Clear the extension so it's not included when formatting. |
| 1718 copied_proto.clear_extension(); |
| 1719 } |
| 1720 |
| 1721 string formatted_number; |
| 1722 Format(copied_proto, INTERNATIONAL, &formatted_number); |
| 1723 scoped_ptr<reg_exp::RegularExpressionInput> i18n_number( |
| 1724 reg_exp::CreateRegularExpressionInput(formatted_number.c_str())); |
| 1725 string digit_group; |
| 1726 string ndc; |
| 1727 string third_group; |
| 1728 for (int i = 0; i < 3; ++i) { |
| 1729 if (!capturing_ascii_digits_pattern->Consume(i18n_number.get(), |
| 1730 false, |
| 1731 &digit_group, |
| 1732 NULL)) { |
| 1733 // We should find at least three groups. |
| 1734 return 0; |
| 1735 } |
| 1736 if (i == 1) { |
| 1737 ndc = digit_group; |
| 1738 } else if (i == 2) { |
| 1739 third_group = digit_group; |
| 1740 } |
| 1741 } |
| 1742 string region_code; |
| 1743 GetRegionCodeForNumber(number, ®ion_code); |
| 1744 if (region_code == "AR" && |
| 1745 GetNumberType(number) == MOBILE) { |
| 1746 // Argentinian mobile numbers, when formatted in the international format, |
| 1747 // are in the form of +54 9 NDC XXXX.... As a result, we take the length of |
| 1748 // the third group (NDC) and add 1 for the digit 9, which also forms part of |
| 1749 // the national significant number. |
| 1750 return third_group.size() + 1; |
| 1751 } |
| 1752 return ndc.size(); |
| 1753 } |
| 1754 |
| 1755 // static |
| 1756 void PhoneNumberUtil::NormalizeDigitsOnly(string* number) { |
| 1757 DCHECK(number); |
| 1758 // Delete everything that isn't valid digits. |
| 1759 static scoped_ptr<reg_exp::RegularExpression> invalid_digits_pattern( |
| 1760 reg_exp::CreateRegularExpression(StrCat("[^", kValidDigits, |
| 1761 "]").c_str())); |
| 1762 static const char *empty = ""; |
| 1763 invalid_digits_pattern->Replace(number, true, empty); |
| 1764 // Normalize all decimal digits to ASCII digits. |
| 1765 UParseError error; |
| 1766 icu::ErrorCode status; |
| 1767 |
| 1768 scoped_ptr<icu::Transliterator> transliterator( |
| 1769 icu::Transliterator::createFromRules( |
| 1770 "NormalizeDecimalDigits", |
| 1771 "[[:nv=0:]-[0]-[:^nt=de:]]>0;" |
| 1772 "[[:nv=1:]-[1]-[:^nt=de:]]>1;" |
| 1773 "[[:nv=2:]-[2]-[:^nt=de:]]>2;" |
| 1774 "[[:nv=3:]-[3]-[:^nt=de:]]>3;" |
| 1775 "[[:nv=4:]-[4]-[:^nt=de:]]>4;" |
| 1776 "[[:nv=5:]-[5]-[:^nt=de:]]>5;" |
| 1777 "[[:nv=6:]-[6]-[:^nt=de:]]>6;" |
| 1778 "[[:nv=7:]-[7]-[:^nt=de:]]>7;" |
| 1779 "[[:nv=8:]-[8]-[:^nt=de:]]>8;" |
| 1780 "[[:nv=9:]-[9]-[:^nt=de:]]>9;", |
| 1781 UTRANS_FORWARD, |
| 1782 error, |
| 1783 status |
| 1784 ) |
| 1785 ); |
| 1786 if (!status.isSuccess()) { |
| 1787 logger->Error("Error creating ICU Transliterator"); |
| 1788 return; |
| 1789 } |
| 1790 icu::UnicodeString utf16(icu::UnicodeString::fromUTF8(number->c_str())); |
| 1791 transliterator->transliterate(utf16); |
| 1792 number->clear(); |
| 1793 utf16.toUTF8String(*number); |
| 1794 } |
| 1795 |
| 1796 bool PhoneNumberUtil::IsAlphaNumber(const string& number) const { |
| 1797 if (!IsViablePhoneNumber(number)) { |
| 1798 // Number is too short, or doesn't match the basic phone number pattern. |
| 1799 return false; |
| 1800 } |
| 1801 // Copy the number, since we are going to try and strip the extension from it. |
| 1802 string number_copy(number); |
| 1803 string extension; |
| 1804 MaybeStripExtension(&number_copy, &extension); |
| 1805 return valid_alpha_phone_pattern->Match(number_copy.c_str(), true, NULL); |
| 1806 } |
| 1807 |
| 1808 void PhoneNumberUtil::ConvertAlphaCharactersInNumber(string* number) const { |
| 1809 DCHECK(number); |
| 1810 NormalizeHelper(*all_normalization_mappings, false, number); |
| 1811 } |
| 1812 |
| 1813 // Normalizes a string of characters representing a phone number. This performs |
| 1814 // the following conversions: |
| 1815 // - Wide-ascii digits are converted to normal ASCII (European) digits. |
| 1816 // - Letters are converted to their numeric representation on a telephone |
| 1817 // keypad. The keypad used here is the one defined in ITU Recommendation |
| 1818 // E.161. This is only done if there are 3 or more letters in the number, to |
| 1819 // lessen the risk that such letters are typos - otherwise alpha characters |
| 1820 // are stripped. |
| 1821 // - Punctuation is stripped. |
| 1822 // - Arabic-Indic numerals are converted to European numerals. |
| 1823 void PhoneNumberUtil::Normalize(string* number) const { |
| 1824 DCHECK(number); |
| 1825 if (valid_alpha_phone_pattern->Match(number->c_str(), false, NULL)) { |
| 1826 NormalizeHelper(*all_normalization_mappings, true, number); |
| 1827 } |
| 1828 NormalizeDigitsOnly(number); |
| 1829 } |
| 1830 |
| 1831 // Checks to see if the string of characters could possibly be a phone number at |
| 1832 // all. At the moment, checks to see that the string begins with at least 3 |
| 1833 // digits, ignoring any punctuation commonly found in phone numbers. This |
| 1834 // method does not require the number to be normalized in advance - but does |
| 1835 // assume that leading non-number symbols have been removed, such as by the |
| 1836 // method ExtractPossibleNumber. |
| 1837 // static |
| 1838 bool PhoneNumberUtil::IsViablePhoneNumber(const string& number) { |
| 1839 if (number.length() < kMinLengthForNsn) { |
| 1840 logger->Debug("Number too short to be viable:" + number); |
| 1841 return false; |
| 1842 } |
| 1843 return valid_phone_number_pattern->Match(number.c_str(), true, NULL); |
| 1844 } |
| 1845 |
| 1846 // Strips any international prefix (such as +, 00, 011) present in the number |
| 1847 // provided, normalizes the resulting number, and indicates if an international |
| 1848 // prefix was present. |
| 1849 // |
| 1850 // possible_idd_prefix represents the international direct dialing prefix from |
| 1851 // the region we think this number may be dialed in. |
| 1852 // Returns true if an international dialing prefix could be removed from the |
| 1853 // number, otherwise false if the number did not seem to be in international |
| 1854 // format. |
| 1855 PhoneNumber::CountryCodeSource |
| 1856 PhoneNumberUtil::MaybeStripInternationalPrefixAndNormalize( |
| 1857 const string& possible_idd_prefix, |
| 1858 string* number) const { |
| 1859 DCHECK(number); |
| 1860 if (number->empty()) { |
| 1861 return PhoneNumber::FROM_DEFAULT_COUNTRY; |
| 1862 } |
| 1863 scoped_ptr<reg_exp::RegularExpressionInput> number_string_piece( |
| 1864 reg_exp::CreateRegularExpressionInput(number->c_str())); |
| 1865 if (plus_chars_pattern->Consume(number_string_piece.get(), true, |
| 1866 NULL, NULL)) { |
| 1867 number->assign(number_string_piece->ToString()); |
| 1868 // Can now normalize the rest of the number since we've consumed the "+" |
| 1869 // sign at the start. |
| 1870 Normalize(number); |
| 1871 return PhoneNumber::FROM_NUMBER_WITH_PLUS_SIGN; |
| 1872 } |
| 1873 // Attempt to parse the first digits as an international prefix. |
| 1874 scoped_ptr<reg_exp::RegularExpression> idd_pattern( |
| 1875 reg_exp::CreateRegularExpression(possible_idd_prefix.c_str())); |
| 1876 if (ParsePrefixAsIdd(idd_pattern.get(), number)) { |
| 1877 Normalize(number); |
| 1878 return PhoneNumber::FROM_NUMBER_WITH_IDD; |
| 1879 } |
| 1880 // If still not found, then try and normalize the number and then try again. |
| 1881 // This shouldn't be done before, since non-numeric characters (+ and ~) may |
| 1882 // legally be in the international prefix. |
| 1883 Normalize(number); |
| 1884 return ParsePrefixAsIdd(idd_pattern.get(), number) |
| 1885 ? PhoneNumber::FROM_NUMBER_WITH_IDD |
| 1886 : PhoneNumber::FROM_DEFAULT_COUNTRY; |
| 1887 } |
| 1888 |
| 1889 // Strips any national prefix (such as 0, 1) present in the number provided. |
| 1890 // The number passed in should be the normalized telephone number that we wish |
| 1891 // to strip any national dialing prefix from. The metadata should be for the |
| 1892 // region that we think this number is from. |
| 1893 // static |
| 1894 void PhoneNumberUtil::MaybeStripNationalPrefixAndCarrierCode( |
| 1895 const PhoneMetadata& metadata, |
| 1896 string* number, |
| 1897 string* carrier_code) { |
| 1898 DCHECK(number); |
| 1899 string carrier_code_temp; |
| 1900 const string& possible_national_prefix = |
| 1901 metadata.national_prefix_for_parsing(); |
| 1902 if (number->empty() || possible_national_prefix.empty()) { |
| 1903 // Early return for numbers of zero length or with no national prefix |
| 1904 // possible. |
| 1905 return; |
| 1906 } |
| 1907 // We use two copies here since Consume modifies the phone number, and if the |
| 1908 // first if-clause fails the number will already be changed. |
| 1909 scoped_ptr<reg_exp::RegularExpressionInput> number_copy( |
| 1910 reg_exp::CreateRegularExpressionInput(number->c_str())); |
| 1911 scoped_ptr<reg_exp::RegularExpressionInput> number_copy_without_transform( |
| 1912 reg_exp::CreateRegularExpressionInput(number->c_str())); |
| 1913 |
| 1914 string number_string_copy(*number); |
| 1915 string captured_part_of_prefix; |
| 1916 scoped_ptr<reg_exp::RegularExpression> national_number_rule( |
| 1917 reg_exp::CreateRegularExpression( |
| 1918 metadata.general_desc().national_number_pattern().c_str())); |
| 1919 // Attempt to parse the first digits as a national prefix. We make a |
| 1920 // copy so that we can revert to the original string if necessary. |
| 1921 const string& transform_rule = metadata.national_prefix_transform_rule(); |
| 1922 if (!transform_rule.empty() && |
| 1923 (number_copy->ConsumeRegExp(possible_national_prefix, true, |
| 1924 &carrier_code_temp, |
| 1925 &captured_part_of_prefix) || |
| 1926 number_copy->ConsumeRegExp(possible_national_prefix, true, |
| 1927 &captured_part_of_prefix, NULL)) && |
| 1928 !captured_part_of_prefix.empty()) { |
| 1929 string re2_transform_rule(transform_rule); |
| 1930 TransformRegularExpressionToRE2Syntax(&re2_transform_rule); |
| 1931 // If this succeeded, then we must have had a transform rule and there must |
| 1932 // have been some part of the prefix that we captured. |
| 1933 // We make the transformation and check that the resultant number is viable. |
| 1934 // If so, replace the number and return. |
| 1935 scoped_ptr<reg_exp::RegularExpression> possible_national_prefix_rule( |
| 1936 reg_exp::CreateRegularExpression(possible_national_prefix.c_str())); |
| 1937 possible_national_prefix_rule->Replace(&number_string_copy, false, |
| 1938 re2_transform_rule.c_str()); |
| 1939 if (national_number_rule->Match(number_string_copy.c_str(), true, NULL)) { |
| 1940 number->assign(number_string_copy); |
| 1941 if (carrier_code) { |
| 1942 carrier_code->assign(carrier_code_temp); |
| 1943 } |
| 1944 } |
| 1945 } else if (number_copy_without_transform->ConsumeRegExp( |
| 1946 possible_national_prefix, true, &carrier_code_temp, NULL) || |
| 1947 number_copy_without_transform->ConsumeRegExp( |
| 1948 possible_national_prefix, true, NULL, NULL)) { |
| 1949 logger->Debug("Parsed the first digits as a national prefix."); |
| 1950 string unconsumed_part(number_copy_without_transform->ToString()); |
| 1951 // If captured_part_of_prefix is empty, this implies nothing was captured by |
| 1952 // the capturing groups in possible_national_prefix; therefore, no |
| 1953 // transformation is necessary, and we just remove the national prefix. |
| 1954 if (national_number_rule->Match(unconsumed_part.c_str(), true, NULL)) { |
| 1955 number->assign(unconsumed_part); |
| 1956 if (carrier_code) { |
| 1957 carrier_code->assign(carrier_code_temp); |
| 1958 } |
| 1959 } |
| 1960 } else { |
| 1961 logger->Debug("The first digits did not match the national prefix."); |
| 1962 } |
| 1963 } |
| 1964 |
| 1965 // Strips any extension (as in, the part of the number dialled after the call is |
| 1966 // connected, usually indicated with extn, ext, x or similar) from the end of |
| 1967 // the number, and returns it. The number passed in should be non-normalized. |
| 1968 // static |
| 1969 bool PhoneNumberUtil::MaybeStripExtension(string* number, string* extension) { |
| 1970 DCHECK(number); |
| 1971 DCHECK(extension); |
| 1972 // There are three extension capturing groups in the regular expression. |
| 1973 string possible_extension_one; |
| 1974 string possible_extension_two; |
| 1975 string possible_extension_three; |
| 1976 string number_copy(*number); |
| 1977 scoped_ptr<reg_exp::RegularExpressionInput> number_copy_regex_input( |
| 1978 reg_exp::CreateRegularExpressionInput(number_copy.c_str())); |
| 1979 if (extn_pattern->Consume(number_copy_regex_input.get(), false, |
| 1980 &possible_extension_one, &possible_extension_two, |
| 1981 &possible_extension_three)) { |
| 1982 // Replace the extensions in the original string here. |
| 1983 extn_pattern->Replace(&number_copy, false, ""); |
| 1984 logger->Debug("Found an extension. Possible extension one: " |
| 1985 + possible_extension_one |
| 1986 + ". Possible extension two: " + possible_extension_two |
| 1987 + ". Remaining number: " + number_copy); |
| 1988 // If we find a potential extension, and the number preceding this is a |
| 1989 // viable number, we assume it is an extension. |
| 1990 if ((!possible_extension_one.empty() || !possible_extension_two.empty() || |
| 1991 !possible_extension_three.empty()) && |
| 1992 IsViablePhoneNumber(number_copy)) { |
| 1993 number->assign(number_copy); |
| 1994 if (!possible_extension_one.empty()) { |
| 1995 extension->assign(possible_extension_one); |
| 1996 } else if (!possible_extension_two.empty()) { |
| 1997 extension->assign(possible_extension_two); |
| 1998 } else if (!possible_extension_three.empty()) { |
| 1999 extension->assign(possible_extension_three); |
| 2000 } |
| 2001 return true; |
| 2002 } |
| 2003 } |
| 2004 return false; |
| 2005 } |
| 2006 |
| 2007 // Extracts country calling code from national_number, and returns it. It |
| 2008 // assumes that the leading plus sign or IDD has already been removed. Returns 0 |
| 2009 // if national_number doesn't start with a valid country calling code, and |
| 2010 // leaves national_number unmodified. Assumes the national_number is at least 3 |
| 2011 // characters long. |
| 2012 int PhoneNumberUtil::ExtractCountryCode(string* national_number) const { |
| 2013 int potential_country_code; |
| 2014 for (int i = 1; i <= 3; ++i) { |
| 2015 safe_strto32(national_number->substr(0, i), &potential_country_code); |
| 2016 string region_code; |
| 2017 GetRegionCodeForCountryCode(potential_country_code, ®ion_code); |
| 2018 if (region_code != "ZZ") { |
| 2019 national_number->erase(0, i); |
| 2020 return potential_country_code; |
| 2021 } |
| 2022 } |
| 2023 return 0; |
| 2024 } |
| 2025 |
| 2026 // Tries to extract a country calling code from a number. Country calling codes |
| 2027 // are extracted in the following ways: |
| 2028 // - by stripping the international dialing prefix of the region the person |
| 2029 // is dialing from, if this is present in the number, and looking at the next |
| 2030 // digits |
| 2031 // - by stripping the '+' sign if present and then looking at the next digits |
| 2032 // - by comparing the start of the number and the country calling code of the |
| 2033 // default region. If the number is not considered possible for the numbering |
| 2034 // plan of the default region initially, but starts with the country calling |
| 2035 // code of this region, validation will be reattempted after stripping this |
| 2036 // country calling code. If this number is considered a possible number, then |
| 2037 // the first digits will be considered the country calling code and removed as |
| 2038 // such. |
| 2039 // |
| 2040 // Returns NO_PARSING_ERROR if a country calling code was successfully |
| 2041 // extracted or none was present, or the appropriate error otherwise, such as |
| 2042 // if a + was present but it was not followed by a valid country calling code. |
| 2043 // If NO_PARSING_ERROR is returned, the national_number without the country |
| 2044 // calling code is populated, and the country_code passed in is set to the |
| 2045 // country calling code if found, otherwise to 0. |
| 2046 PhoneNumberUtil::ErrorType PhoneNumberUtil::MaybeExtractCountryCode( |
| 2047 const PhoneMetadata* default_region_metadata, |
| 2048 bool keep_raw_input, |
| 2049 string* national_number, |
| 2050 PhoneNumber* phone_number) const { |
| 2051 DCHECK(national_number); |
| 2052 DCHECK(phone_number); |
| 2053 // Set the default prefix to be something that will never match if there is no |
| 2054 // default region. |
| 2055 string possible_country_idd_prefix = default_region_metadata |
| 2056 ? default_region_metadata->international_prefix() |
| 2057 : "NonMatch"; |
| 2058 PhoneNumber::CountryCodeSource country_code_source = |
| 2059 MaybeStripInternationalPrefixAndNormalize(possible_country_idd_prefix, |
| 2060 national_number); |
| 2061 if (keep_raw_input) { |
| 2062 phone_number->set_country_code_source(country_code_source); |
| 2063 } |
| 2064 if (country_code_source != PhoneNumber::FROM_DEFAULT_COUNTRY) { |
| 2065 if (national_number->length() < kMinLengthForNsn) { |
| 2066 logger->Debug("Phone number had an IDD, but after this was not " |
| 2067 "long enough to be a viable phone number."); |
| 2068 return TOO_SHORT_AFTER_IDD; |
| 2069 } |
| 2070 int potential_country_code = ExtractCountryCode(national_number); |
| 2071 if (potential_country_code != 0) { |
| 2072 phone_number->set_country_code(potential_country_code); |
| 2073 return NO_PARSING_ERROR; |
| 2074 } |
| 2075 // If this fails, they must be using a strange country calling code that we |
| 2076 // don't recognize, or that doesn't exist. |
| 2077 return INVALID_COUNTRY_CODE_ERROR; |
| 2078 } else if (default_region_metadata) { |
| 2079 // Check to see if the number starts with the country calling code for the |
| 2080 // default region. If so, we remove the country calling code, and do some |
| 2081 // checks on the validity of the number before and after. |
| 2082 int default_country_code = default_region_metadata->country_code(); |
| 2083 string default_country_code_string(SimpleItoa(default_country_code)); |
| 2084 logger->Debug("Possible country code: " + default_country_code_string); |
| 2085 string potential_national_number; |
| 2086 if (TryStripPrefixString(*national_number, |
| 2087 default_country_code_string, |
| 2088 &potential_national_number)) { |
| 2089 const PhoneNumberDesc& general_num_desc = |
| 2090 default_region_metadata->general_desc(); |
| 2091 scoped_ptr<reg_exp::RegularExpression> valid_number_pattern( |
| 2092 reg_exp::CreateRegularExpression( |
| 2093 general_num_desc.national_number_pattern().c_str())); |
| 2094 |
| 2095 MaybeStripNationalPrefixAndCarrierCode(*default_region_metadata, |
| 2096 &potential_national_number, |
| 2097 NULL); |
| 2098 logger->Debug("Number without country code prefix: " |
| 2099 + potential_national_number); |
| 2100 string extracted_number; |
| 2101 scoped_ptr<reg_exp::RegularExpression> possible_number_pattern( |
| 2102 reg_exp::CreateRegularExpression( |
| 2103 StrCat("(", general_num_desc.possible_number_pattern(), |
| 2104 ")").c_str())); |
| 2105 // If the number was not valid before but is valid now, or if it was too |
| 2106 // long before, we consider the number with the country code stripped to |
| 2107 // be a better result and keep that instead. |
| 2108 if ((!valid_number_pattern->Match(national_number->c_str(), |
| 2109 true, NULL) && |
| 2110 valid_number_pattern->Match(potential_national_number.c_str(), |
| 2111 true, NULL)) || |
| 2112 TestNumberLengthAgainstPattern(possible_number_pattern.get(), |
| 2113 *national_number) |
| 2114 == TOO_LONG) { |
| 2115 national_number->assign(potential_national_number); |
| 2116 if (keep_raw_input) { |
| 2117 phone_number->set_country_code_source( |
| 2118 PhoneNumber::FROM_NUMBER_WITHOUT_PLUS_SIGN); |
| 2119 } |
| 2120 phone_number->set_country_code(default_country_code); |
| 2121 return NO_PARSING_ERROR; |
| 2122 } |
| 2123 } |
| 2124 } |
| 2125 // No country calling code present. Set the country_code to 0. |
| 2126 phone_number->set_country_code(0); |
| 2127 return NO_PARSING_ERROR; |
| 2128 } |
| 2129 |
| 2130 PhoneNumberUtil::MatchType PhoneNumberUtil::IsNumberMatch( |
| 2131 const PhoneNumber& first_number_in, |
| 2132 const PhoneNumber& second_number_in) const { |
| 2133 // Make copies of the phone number so that the numbers passed in are not |
| 2134 // edited. |
| 2135 PhoneNumber first_number(first_number_in); |
| 2136 PhoneNumber second_number(second_number_in); |
| 2137 // First clear raw_input and country_code_source and |
| 2138 // preferred_domestic_carrier_code fields and any empty-string extensions so |
| 2139 // that we can use the proto-buffer equality method. |
| 2140 first_number.clear_raw_input(); |
| 2141 first_number.clear_country_code_source(); |
| 2142 first_number.clear_preferred_domestic_carrier_code(); |
| 2143 second_number.clear_raw_input(); |
| 2144 second_number.clear_country_code_source(); |
| 2145 second_number.clear_preferred_domestic_carrier_code(); |
| 2146 if (first_number.extension().empty()) { |
| 2147 first_number.clear_extension(); |
| 2148 } |
| 2149 if (second_number.extension().empty()) { |
| 2150 second_number.clear_extension(); |
| 2151 } |
| 2152 // Early exit if both had extensions and these are different. |
| 2153 if (first_number.has_extension() && second_number.has_extension() && |
| 2154 first_number.extension() != second_number.extension()) { |
| 2155 return NO_MATCH; |
| 2156 } |
| 2157 int first_number_country_code = first_number.country_code(); |
| 2158 int second_number_country_code = second_number.country_code(); |
| 2159 // Both had country calling code specified. |
| 2160 if (first_number_country_code != 0 && second_number_country_code != 0) { |
| 2161 if (ExactlySameAs(first_number, second_number)) { |
| 2162 return EXACT_MATCH; |
| 2163 } else if (first_number_country_code == second_number_country_code && |
| 2164 IsNationalNumberSuffixOfTheOther(first_number, second_number)) { |
| 2165 // A SHORT_NSN_MATCH occurs if there is a difference because of the |
| 2166 // presence or absence of an 'Italian leading zero', the presence or |
| 2167 // absence of an extension, or one NSN being a shorter variant of the |
| 2168 // other. |
| 2169 return SHORT_NSN_MATCH; |
| 2170 } |
| 2171 // This is not a match. |
| 2172 return NO_MATCH; |
| 2173 } |
| 2174 // Checks cases where one or both country calling codes were not specified. To |
| 2175 // make equality checks easier, we first set the country_code fields to be |
| 2176 // equal. |
| 2177 first_number.set_country_code(second_number_country_code); |
| 2178 // If all else was the same, then this is an NSN_MATCH. |
| 2179 if (ExactlySameAs(first_number, second_number)) { |
| 2180 return NSN_MATCH; |
| 2181 } |
| 2182 if (IsNationalNumberSuffixOfTheOther(first_number, second_number)) { |
| 2183 return SHORT_NSN_MATCH; |
| 2184 } |
| 2185 return NO_MATCH; |
| 2186 } |
| 2187 |
| 2188 PhoneNumberUtil::MatchType PhoneNumberUtil::IsNumberMatchWithTwoStrings( |
| 2189 const string& first_number, |
| 2190 const string& second_number) const { |
| 2191 PhoneNumber first_number_as_proto; |
| 2192 ErrorType error_type = |
| 2193 Parse(first_number, "ZZ", &first_number_as_proto); |
| 2194 if (error_type == NO_PARSING_ERROR) { |
| 2195 return IsNumberMatchWithOneString(first_number_as_proto, second_number); |
| 2196 } |
| 2197 if (error_type == INVALID_COUNTRY_CODE_ERROR) { |
| 2198 PhoneNumber second_number_as_proto; |
| 2199 ErrorType error_type = Parse(second_number, "ZZ", |
| 2200 &second_number_as_proto); |
| 2201 if (error_type == NO_PARSING_ERROR) { |
| 2202 return IsNumberMatchWithOneString(second_number_as_proto, first_number); |
| 2203 } |
| 2204 if (error_type == INVALID_COUNTRY_CODE_ERROR) { |
| 2205 error_type = ParseHelper(first_number, "ZZ", false, false, |
| 2206 &first_number_as_proto); |
| 2207 if (error_type == NO_PARSING_ERROR) { |
| 2208 error_type = ParseHelper(second_number, "ZZ", false, false, |
| 2209 &second_number_as_proto); |
| 2210 if (error_type == NO_PARSING_ERROR) { |
| 2211 return IsNumberMatch(first_number_as_proto, second_number_as_proto); |
| 2212 } |
| 2213 } |
| 2214 } |
| 2215 } |
| 2216 // One or more of the phone numbers we are trying to match is not a viable |
| 2217 // phone number. |
| 2218 return INVALID_NUMBER; |
| 2219 } |
| 2220 |
| 2221 PhoneNumberUtil::MatchType PhoneNumberUtil::IsNumberMatchWithOneString( |
| 2222 const PhoneNumber& first_number, |
| 2223 const string& second_number) const { |
| 2224 // First see if the second number has an implicit country calling code, by |
| 2225 // attempting to parse it. |
| 2226 PhoneNumber second_number_as_proto; |
| 2227 ErrorType error_type = |
| 2228 Parse(second_number, "ZZ", &second_number_as_proto); |
| 2229 if (error_type == NO_PARSING_ERROR) { |
| 2230 return IsNumberMatch(first_number, second_number_as_proto); |
| 2231 } |
| 2232 if (error_type == INVALID_COUNTRY_CODE_ERROR) { |
| 2233 // The second number has no country calling code. EXACT_MATCH is no longer |
| 2234 // possible. We parse it as if the region was the same as that for the |
| 2235 // first number, and if EXACT_MATCH is returned, we replace this with |
| 2236 // NSN_MATCH. |
| 2237 string first_number_region; |
| 2238 GetRegionCodeForCountryCode(first_number.country_code(), |
| 2239 &first_number_region); |
| 2240 if (first_number_region != "ZZ") { |
| 2241 PhoneNumber second_number_with_first_number_region; |
| 2242 Parse(second_number, first_number_region, |
| 2243 &second_number_with_first_number_region); |
| 2244 MatchType match = IsNumberMatch(first_number, |
| 2245 second_number_with_first_number_region); |
| 2246 if (match == EXACT_MATCH) { |
| 2247 return NSN_MATCH; |
| 2248 } |
| 2249 return match; |
| 2250 } else { |
| 2251 // If the first number didn't have a valid country calling code, then we |
| 2252 // parse the second number without one as well. |
| 2253 error_type = ParseHelper(second_number, "ZZ", false, false, |
| 2254 &second_number_as_proto); |
| 2255 if (error_type == NO_PARSING_ERROR) { |
| 2256 return IsNumberMatch(first_number, second_number_as_proto); |
| 2257 } |
| 2258 } |
| 2259 } |
| 2260 // One or more of the phone numbers we are trying to match is not a viable |
| 2261 // phone number. |
| 2262 return INVALID_NUMBER; |
| 2263 } |
| 2264 |
| 2265 } // namespace phonenumbers |
| 2266 } // namespace i18n |
OLD | NEW |