/// <summary> /// Returns an iterable over all {@link PhoneNumberMatch PhoneNumberMatches} in {@code text}. /// </summary> /// <param name="text">the text to search for phone numbers, null for no text</param> /// <param name="defaultRegion">region that we are expecting the number to be from. This is only used /// if the number being parsed is not written in international format. The /// country_code for the number in this case would be stored as that of /// the default region supplied. May be null if only international /// numbers are expected.</param> /// <param name="leniency">the leniency to use when evaluating candidate phone numbers</param> /// <param name="maxTries">the maximum number of invalid numbers to try before giving up on the /// text. This is to cover degenerate cases where the text has a lot of /// false positives in it. Must be {@code >= 0}.</param> /// <returns></returns> public IEnumerable<PhoneNumberMatch> FindNumbers(string text, string defaultRegion, Leniency leniency, long maxTries) { _PhoneNumberUtil.Leniency temp; switch (leniency) { case Leniency.POSSIBLE: temp = _Leniency.POSSIBLE; break; case Leniency.VALID: temp = _Leniency.VALID; break; case Leniency.STRICT_GROUPING: temp = _Leniency.STRICT_GROUPING; break; case Leniency.EXACT_GROUPING: temp = _Leniency.EXACT_GROUPING; break; default: throw new NotSupportedException(); } foreach (var item in phoneNumberUtil.findNumbers(text, defaultRegion, temp, maxTries)) { yield return item; } }
/** * Returns an iterable over all {@link PhoneNumberMatch PhoneNumberMatches} in {@code text}. * * @param text the text to search for phone numbers, null for no text * @param defaultRegion region that we are expecting the number to be from. This is only used * if the number being parsed is not written in international format. The * country_code for the number in this case would be stored as that of * the default region supplied. May be null if only international * numbers are expected. * @param leniency the leniency to use when evaluating candidate phone numbers * @param maxTries the maximum number of invalid numbers to try before giving up on the * text. This is to cover degenerate cases where the text has a lot of * false positives in it. Must be {@code >= 0}. */ public IEnumerable<PhoneNumberMatch> FindNumbers(String text, String defaultRegion, Leniency leniency, long maxTries) { return new EnumerableFromConstructor<PhoneNumberMatch>(() => { return new PhoneNumberMatcher(this, text, defaultRegion, leniency, maxTries); }); }
public bool Verify(Leniency leniency, PhoneNumber number, String candidate, PhoneNumberUtil util) { switch (leniency) { case Leniency.POSSIBLE: return IsPossibleNumber(number); case Leniency.VALID: { if (!util.IsValidNumber(number) || !PhoneNumberUtil.ContainsOnlyValidXChars(number, candidate, util)) return false; return PhoneNumberUtil.IsNationalPrefixPresentIfRequired(number, util); } case Leniency.STRICT_GROUPING: { if (!util.IsValidNumber(number) || !PhoneNumberUtil.ContainsOnlyValidXChars(number, candidate, util) || PhoneNumberUtil.ContainsMoreThanOneSlash(candidate) || !PhoneNumberUtil.IsNationalPrefixPresentIfRequired(number, util)) { return false; } // TODO: Evaluate how this works for other locales (testing has been // limited to NANPA regions) and optimise if necessary. String[] formattedNumberGroups = PhoneNumberUtil.GetNationalNumberGroups(util, number); StringBuilder normalizedCandidate = PhoneNumberUtil.NormalizeDigits(candidate, true /* keep strip non-digits */); int fromIndex = 0; // Check each group of consecutive digits are not broken into separate groups in the // {@code candidate} string. for (int i = 0; i < formattedNumberGroups.Length; i++) { // Fails if the substring of {@code candidate} starting from {@code fromIndex} doesn't // contain the consecutive digits in formattedNumberGroups[i]. fromIndex = normalizedCandidate.ToString().IndexOf(formattedNumberGroups[i], fromIndex); if (fromIndex < 0) { return false; } // Moves {@code fromIndex} forward. fromIndex += formattedNumberGroups[i].Length; if (i == 0 && fromIndex < normalizedCandidate.Length) { // We are at the position right after the NDC. if (char.IsDigit(normalizedCandidate[fromIndex])) { // This means there is no formatting symbol after the NDC. In this case, we only // accept the number if there is no formatting symbol at all in the number, except // for extensions. String nationalSignificantNumber = util.GetNationalSignificantNumber(number); return normalizedCandidate.ToString().Substring(fromIndex - formattedNumberGroups[i].Length) .StartsWith(nationalSignificantNumber); } } } // The check here makes sure that we haven't mistakenly already used the extension to // match the last group of the subscriber number. Note the extension cannot have // formatting in-between digits. return normalizedCandidate.ToString().Substring(fromIndex).Contains(number.Extension); } case Leniency.EXACT_GROUPING: default: { if (!util.IsValidNumber(number) || !ContainsOnlyValidXChars(number, candidate, util) || ContainsMoreThanOneSlash(candidate) || !IsNationalPrefixPresentIfRequired(number, util)) { return false; } // TODO: Evaluate how this works for other locales (testing has been // limited to NANPA regions) and optimise if necessary. StringBuilder normalizedCandidate = PhoneNumberUtil.NormalizeDigits(candidate, true /* keep strip non-digits */); String[] candidateGroups = NON_DIGITS_PATTERN.Split(normalizedCandidate.ToString()); // Set this to the last group, skipping it if the number has an extension. int candidateNumberGroupIndex = number.HasExtension ? candidateGroups.Length - 2 : candidateGroups.Length - 1; // First we check if the national significant number is formatted as a block. // We use contains and not equals, since the national significant number may be present with // a prefix such as a national number prefix, or the country code itself. if (candidateGroups.Length == 1 || candidateGroups[candidateNumberGroupIndex].Contains( util.GetNationalSignificantNumber(number))) { return true; } String[] formattedNumberGroups = PhoneNumberUtil.GetNationalNumberGroups(util, number); // Starting from the end, go through in reverse, excluding the first group, and check the // candidate and number groups are the same. for (int formattedNumberGroupIndex = (formattedNumberGroups.Length - 1); formattedNumberGroupIndex > 0 && candidateNumberGroupIndex >= 0; formattedNumberGroupIndex--, candidateNumberGroupIndex--) { if (!candidateGroups[candidateNumberGroupIndex].Equals( formattedNumberGroups[formattedNumberGroupIndex])) { return false; } } // Now check the first group. There may be a national prefix at the start, so we only check // that the candidate group ends with the formatted number group. return (candidateNumberGroupIndex >= 0 && candidateGroups[candidateNumberGroupIndex].EndsWith(formattedNumberGroups[0])); } } }
public bool Verify(Leniency leniency, PhoneNumber number, String candidate, PhoneNumberUtil util) { switch (leniency) { case Leniency.POSSIBLE: return IsPossibleNumber(number); case Leniency.VALID: { if (!util.IsValidNumber(number) || !PhoneNumberMatcher.ContainsOnlyValidXChars(number, candidate, util)) return false; return PhoneNumberMatcher.IsNationalPrefixPresentIfRequired(number, util); } case Leniency.STRICT_GROUPING: { if (!util.IsValidNumber(number) || !PhoneNumberMatcher.ContainsOnlyValidXChars(number, candidate, util) || PhoneNumberMatcher.ContainsMoreThanOneSlash(candidate) || !PhoneNumberMatcher.IsNationalPrefixPresentIfRequired(number, util)) { return false; } return PhoneNumberMatcher.CheckNumberGroupingIsValid( number, candidate, util, (PhoneNumberUtil u, PhoneNumber n, StringBuilder nc, String[] eg) => { return PhoneNumberMatcher.AllNumberGroupsRemainGrouped(u, n, nc, eg); } ); } case Leniency.EXACT_GROUPING: default: { if (!util.IsValidNumber(number) || !PhoneNumberMatcher.ContainsOnlyValidXChars(number, candidate, util) || PhoneNumberMatcher.ContainsMoreThanOneSlash(candidate) || !PhoneNumberMatcher.IsNationalPrefixPresentIfRequired(number, util)) { return false; } return PhoneNumberMatcher.CheckNumberGroupingIsValid( number, candidate, util, (PhoneNumberUtil u, PhoneNumber n, StringBuilder normalizedCandidate, String[] expectedNumberGroups) => { return PhoneNumberMatcher.AllNumberGroupsAreExactlyPresent( u, n, normalizedCandidate, expectedNumberGroups); } ); } } }
/// <summary> /// Returns an iterable over all {@link PhoneNumberMatch PhoneNumberMatches} in {@code text}. /// </summary> /// <param name="text">the text to search for phone numbers, null for no text</param> /// <param name="defaultRegion">region that we are expecting the number to be from. This is only used /// if the number being parsed is not written in international format. The /// country_code for the number in this case would be stored as that of /// the default region supplied. May be null if only international /// numbers are expected.</param> /// <param name="leniency">the leniency to use when evaluating candidate phone numbers</param> /// <param name="maxTries">the maximum number of invalid numbers to try before giving up on the /// text. This is to cover degenerate cases where the text has a lot of /// false positives in it. Must be {@code >= 0}.</param> /// <returns></returns> public IEnumerable <PhoneNumberMatch> FindNumbers(string text, string defaultRegion, Leniency leniency, long maxTries) { _PhoneNumberUtil.Leniency temp; switch (leniency) { case Leniency.POSSIBLE: temp = _Leniency.POSSIBLE; break; case Leniency.VALID: temp = _Leniency.VALID; break; case Leniency.STRICT_GROUPING: temp = _Leniency.STRICT_GROUPING; break; case Leniency.EXACT_GROUPING: temp = _Leniency.EXACT_GROUPING; break; default: throw new NotSupportedException(); } foreach (var item in phoneNumberUtil.findNumbers(text, defaultRegion, temp, maxTries)) { yield return(item); } }