Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: third_party/libphonenumber/cpp/src/phonenumberutil.cc

Issue 6803005: Autofill phone number enhancements and integration of Phone Number Util Library: part 1 (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(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, &region_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, &region_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, &region_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, &region_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(), &region_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, &region_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, &region_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, &region_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, &region_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, &region_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, &region_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, &region_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, &region_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, &region_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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698