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