Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions csharp/PhoneNumbers/PhoneNumberUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,26 @@ public static bool IsViablePhoneNumber(string number)
return ValidPhoneNumber().IsMatch(number);
}

/// <summary>
/// Whether the rule matches everything from <paramref name="start"/> onwards. Both of these
/// only ever fed a slice to a regex, so on targets with span matching the slice never becomes
/// a string.
/// </summary>
private static bool IsMatchAllFrom(PhoneRegex rule, string value, int start) =>
#if NET7_0_OR_GREATER
rule.IsMatchAll(value.AsSpan(start));
#else
rule.IsMatchAll(value.Substring(start));
#endif

/// <summary>Whether the first <paramref name="length"/> characters look like a phone number.</summary>
private static bool IsViablePhoneNumberPrefix(string number, int length) =>
#if NET7_0_OR_GREATER
length >= MIN_LENGTH_FOR_NSN && ValidPhoneNumber().IsMatch(number.AsSpan(0, length));
#else
IsViablePhoneNumber(number.Substring(0, length));
#endif

private static void Normalize(StringBuilder number)
{
if (IsValidAlphaPhone(number))
Expand Down Expand Up @@ -2540,7 +2560,7 @@ internal bool MaybeStripNationalPrefixAndCarrierCode(StringBuilder number, strin
{
// If the original number was viable, and the resultant number is not, we return.
if (isViableOriginalNumber &&
!nationalNumberRule.IsMatchAll(numberString.Substring(prefixMatch.Length)))
!IsMatchAllFrom(nationalNumberRule, numberString, prefixMatch.Length))
return false;
if (getCarrier && numOfGroups > 1 && prefixMatch.Groups[numOfGroups - 1].Success)
carrierCode = prefixMatch.Groups[1].Value;
Expand Down Expand Up @@ -2577,7 +2597,7 @@ static string MaybeStripExtension(StringBuilder number, string numberString)
var m = ExtnPattern().Match(numberString);
// If we find a potential extension, and the number preceding this is a viable number, we assume
// it is an extension.
if (m.Success && IsViablePhoneNumber(numberString.Substring(0, m.Index)))
if (m.Success && IsViablePhoneNumberPrefix(numberString, m.Index))
{
// The numbers are captured into groups in the regular expression.
for (int i = 1, length = m.Groups.Count; i < length; i++)
Expand Down
9 changes: 9 additions & 0 deletions csharp/PhoneNumbers/PhoneRegex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ public PhoneRegex(string pattern, RegexOptions options)
public string Replace(string value, string replacement) => regex.Value.Replace(value, replacement);

public bool IsMatchAll(string value) => allRegex.Value.IsMatch(value);

#if NET7_0_OR_GREATER
/// <summary>
/// Lets callers test a slice without materialising it. Internal because a public member here
/// would exist on the net8.0 and net10.0 assets but not on netstandard2.0. At a major version
/// the string overloads should become span overloads outright - see issue #375.
/// </summary>
internal bool IsMatchAll(ReadOnlySpan<char> value) => allRegex.Value.IsMatch(value);
#endif
public Match MatchAll(string value) => allRegex.Value.Match(value);

public bool IsMatchBeginning(string value) => beginRegex.Value.IsMatch(value);
Expand Down