Skip to content

Commit eddba62

Browse files
committed
Chore: Migrate regex to generatedRegex
1 parent 20bd604 commit eddba62

File tree

11 files changed

+76
-48
lines changed

11 files changed

+76
-48
lines changed

Source/NETworkManager.Converters/ValidateSubnetCalculatorSubnettingConverter.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Globalization;
33
using System.Net;
44
using System.Net.Sockets;
5-
using System.Text.RegularExpressions;
65
using System.Windows.Data;
76
using NETworkManager.Models.Network;
87
using NETworkManager.Utilities;
@@ -40,7 +39,7 @@ public object Convert(object[] values, Type targetType, object parameter, Cultur
4039
};
4140

4241
// Support subnetmask like 255.255.255.0
43-
int newCidr = Regex.IsMatch(newSubnetmaskOrCidr, RegexHelper.SubnetmaskRegex)
42+
int newCidr = RegexHelper.SubnetmaskRegex().IsMatch(newSubnetmaskOrCidr)
4443
? System.Convert.ToByte(Subnetmask.ConvertSubnetmaskToCidr(IPAddress.Parse(newSubnetmaskOrCidr)))
4544
: System.Convert.ToByte(newSubnetmaskOrCidr.TrimStart('/'));
4645

Source/NETworkManager.Models/Network/HostRangeHelper.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ private static (List<(IPAddress ipAddress, string hostname)> hosts, List<string>
5555
break;
5656

5757
// 192.168.0.0/24
58-
case var _ when Regex.IsMatch(host, RegexHelper.IPv4AddressCidrRegex):
58+
case var _ when RegexHelper.IPv4AddressCidrRegex().IsMatch(host):
5959
// 192.168.0.0/255.255.255.0
60-
case var _ when Regex.IsMatch(host, RegexHelper.IPv4AddressSubnetmaskRegex):
60+
case var _ when RegexHelper.IPv4AddressSubnetmaskRegex().IsMatch(host):
6161
var network = IPNetwork2.Parse(host);
6262

6363
Parallel.For(IPv4Address.ToInt32(network.Network), IPv4Address.ToInt32(network.Broadcast) + 1,
@@ -87,7 +87,7 @@ private static (List<(IPAddress ipAddress, string hostname)> hosts, List<string>
8787
break;
8888

8989
// 192.168.[50-100].1
90-
case var _ when Regex.IsMatch(host, RegexHelper.IPv4AddressSpecialRangeRegex):
90+
case var _ when RegexHelper.IPv4AddressSpecialRangeRegex().IsMatch(host):
9191
var octets = host.Split('.');
9292

9393
var list = new List<ConcurrentBag<int>>();

Source/NETworkManager.Utilities/RegexHelper.cs

Lines changed: 60 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,22 @@ namespace NETworkManager.Utilities;
55
public static partial class RegexHelper
66
{
77
/// <summary>
8-
/// Match an IPv4-Address like 192.168.178.1
9-
/// </summary>
10-
// ReSharper disable once InconsistentNaming
8+
/// Represents a regular expression pattern that matches valid IPv4 address values.
9+
/// </summary>
1110
private const string IPv4AddressValues =
1211
@"((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)";
1312

13+
/// <summary>
14+
/// Represents a regular expression pattern that matches valid IPv4 subnet mask values.
15+
/// </summary>
16+
private const string SubnetmaskValues =
17+
@"(((255\.){3}(255|254|252|248|240|224|192|128|0+))|((255\.){2}(255|254|252|248|240|224|192|128|0+)\.0)|((255\.)(255|254|252|248|240|224|192|128|0+)(\.0+){2})|((255|254|252|248|240|224|192|128|0+)(\.0+){3}))";
18+
19+
/// <summary>
20+
/// Represents the regular expression pattern used to validate CIDR notation values for IPv4 subnet masks.
21+
/// </summary>
22+
private const string CidrRegexValues = @"([1-9]|[1-2][0-9]|3[0-2])";
23+
1424
/// <summary>
1525
/// Provides a compiled regular expression that matches valid IPv4 addresses in dot-decimal notation.
1626
/// </summary>
@@ -43,31 +53,59 @@ public static partial class RegexHelper
4353
[GeneratedRegex($"^{IPv4AddressValues}-{IPv4AddressValues}$")]
4454
public static partial Regex IPv4AddressRangeRegex();
4555

56+
/// <summary>
57+
/// Provides a compiled regular expression that matches valid IPv4 subnet mask values.
58+
/// </summary>
59+
/// <remarks>The returned regular expression is generated at compile time and is optimized for
60+
/// performance. Use this regex to validate or parse subnet mask strings in IPv4 networking scenarios.</remarks>
61+
/// <returns>A <see cref="Regex"/> instance that matches strings representing valid IPv4 subnet masks.</returns>
62+
[GeneratedRegex($"^{SubnetmaskValues}$")]
63+
public static partial Regex SubnetmaskRegex();
64+
65+
/// <summary>
66+
/// Provides a compiled regular expression that matches IPv4 addresses with subnet masks in CIDR notation, such as
67+
/// "192.168.178.0/255.255.255.0".
68+
/// </summary>
69+
/// <remarks>The returned regular expression validates both the IPv4 address and the subnet mask
70+
/// components. Use this regex to verify input strings representing IPv4 subnets in formats like
71+
/// "address/mask".</remarks>
72+
/// <returns>A <see cref="Regex"/> instance that matches strings containing an IPv4 address followed by a subnet mask,
73+
/// separated by a forward slash.</returns>
74+
[GeneratedRegex($@"^{IPv4AddressValues}\/{SubnetmaskValues}$")]
75+
public static partial Regex IPv4AddressSubnetmaskRegex();
76+
77+
/// <summary>
78+
/// Provides a compiled regular expression that matches an IPv4 address in CIDR notation, such as
79+
/// "192.168.178.0/24".
80+
/// </summary>
81+
/// <remarks>The returned regular expression can be used to validate or extract IPv4 addresses with CIDR
82+
/// notation, such as "192.168.1.0/24". The pattern enforces correct formatting for both the address and the prefix
83+
/// length.</remarks>
84+
/// <returns>A <see cref="Regex"/> instance that matches strings containing an IPv4 address followed by a slash and a valid
85+
/// CIDR prefix length.</returns>
86+
[GeneratedRegex($@"^{IPv4AddressValues}\/{CidrRegexValues}$")]
87+
public static partial Regex IPv4AddressCidrRegex();
88+
89+
/// <summary>
90+
/// Creates a regular expression that matches IPv4 addresses, allowing for a special range in one or more octets.
91+
/// </summary>
92+
/// <remarks>The returned regular expression matches standard IPv4 addresses and addresses where one or
93+
/// more octets are defined by a custom range pattern. This is useful for validating or parsing addresses such as
94+
/// "192.168.[50-100].1" where a range is specified in place of an octet. The format and behavior of the special
95+
/// range are determined by the <c>SpecialRangeRegex</c> value.</remarks>
96+
/// <returns>A <see cref="Regex"/> instance that matches IPv4 addresses with support for custom special ranges as defined by
97+
/// <c>SpecialRangeRegex</c>.</returns>
98+
[GeneratedRegex($@"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|{SpecialRangeRegex})\.){{3}}((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|{SpecialRangeRegex})$")]
99+
public static partial Regex IPv4AddressSpecialRangeRegex();
100+
46101
// Match a MAC-Address 000000000000 00:00:00:00:00:00, 00-00-00-00-00-00-00 or 0000.0000.0000
47102
public const string MACAddressRegex =
48103
@"^^[A-Fa-f0-9]{12}$|^[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}$|^[A-Fa-f0-9]{4}.[A-Fa-f0-9]{4}.[A-Fa-f0-9]{4}$$";
49104

50105
// Match the first 3 bytes of a MAC-Address 000000, 00:00:00, 00-00-00
51106
public const string MACAddressFirst3BytesRegex =
52107
@"^[A-Fa-f0-9]{6}$|^[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}$|^[A-Fa-f0-9]{4}.[A-Fa-f0-9]{2}$";
53-
54-
// Private subnetmask / cidr values
55-
private const string SubnetmaskValues =
56-
@"(((255\.){3}(255|254|252|248|240|224|192|128|0+))|((255\.){2}(255|254|252|248|240|224|192|128|0+)\.0)|((255\.)(255|254|252|248|240|224|192|128|0+)(\.0+){2})|((255|254|252|248|240|224|192|128|0+)(\.0+){3}))";
57-
58-
private const string CidrRegex = @"([1-9]|[1-2][0-9]|3[0-2])";
59-
60-
// Match a Subnetmask like 255.255.255.0
61-
public const string SubnetmaskRegex = @"^" + SubnetmaskValues + @"$";
62-
63-
// Match a subnet from 192.168.178.0/1 to 192.168.178.0/32
64-
// ReSharper disable once InconsistentNaming
65-
public const string IPv4AddressCidrRegex = $@"^{IPv4AddressValues}\/{CidrRegex}$";
66-
67-
// Match a subnet from 192.168.178.0/192.0.0.0 to 192.168.178.0/255.255.255.255
68-
// ReSharper disable once InconsistentNaming
69-
public const string IPv4AddressSubnetmaskRegex = $@"^{IPv4AddressValues}\/{SubnetmaskValues}$";
70-
108+
71109
// Match IPv6 address like ::1
72110
// ReSharper disable once InconsistentNaming
73111
public const string IPv6AddressRegex =
@@ -82,11 +120,6 @@ public static partial class RegexHelper
82120
public const string SpecialRangeRegex =
83121
@"\[((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)-(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)))([,]((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)-(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))))*\]";
84122

85-
// Match a IPv4-Address like 192.168.[50-100].1
86-
// ReSharper disable once InconsistentNaming
87-
public const string IPv4AddressSpecialRangeRegex =
88-
$@"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|{SpecialRangeRegex})\.){{3}}((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)|{SpecialRangeRegex})$";
89-
90123
// Private hostname values
91124
private const string HostnameOrDomainValues =
92125
@"(?=.{1,255}$)(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\.[A-Za-z0-9-]{1,63})*\.?";
@@ -95,7 +128,7 @@ public static partial class RegexHelper
95128
public const string HostnameOrDomainRegex = $@"^{HostnameOrDomainValues}$";
96129

97130
// Match a hostname with cidr like server-01.example.com/24
98-
public const string HostnameOrDomainWithCidrRegex = $@"^{HostnameOrDomainValues}\/{CidrRegex}$";
131+
public const string HostnameOrDomainWithCidrRegex = $@"^{HostnameOrDomainValues}\/{CidrRegexValues}$";
99132

100133
// Match a hostname with subnetmask like server-01.example.com/255.255.255.0
101134
public const string HostnameOrDomainWithSubnetmaskRegex = $@"^{HostnameOrDomainValues}\/{SubnetmaskValues}$";

Source/NETworkManager.Validators/IPv4IPv6SubnetValidator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ public override ValidationResult Validate(object value, CultureInfo cultureInfo)
1616
return new ValidationResult(false, Strings.EnterValidSubnet);
1717

1818
// Check if it is a IPv4 address with a cidr like 192.168.0.0/24
19-
if (Regex.IsMatch(subnet, RegexHelper.IPv4AddressCidrRegex))
19+
if (RegexHelper.IPv4AddressCidrRegex().IsMatch(subnet))
2020
return ValidationResult.ValidResult;
2121

2222
// Check if it is a IPv4 address with a subnetmask like 255.255.255.0
23-
if (Regex.IsMatch(subnet, RegexHelper.IPv4AddressSubnetmaskRegex))
23+
if (RegexHelper.IPv4AddressSubnetmaskRegex().IsMatch(subnet))
2424
return ValidationResult.ValidResult;
2525

2626
// check if it is a IPv6 address with a cidr like ::1/64

Source/NETworkManager.Validators/IPv4IPv6SubnetmaskOrCIDRValidator.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Globalization;
2-
using System.Text.RegularExpressions;
32
using System.Windows.Controls;
43
using NETworkManager.Localization.Resources;
54
using NETworkManager.Utilities;
@@ -16,7 +15,7 @@ public override ValidationResult Validate(object value, CultureInfo cultureInfo)
1615
return new ValidationResult(false, Strings.EnterValidSubnetmaskOrCIDR);
1716

1817
// Check if it is a subnetmask like 255.255.255.0
19-
if (Regex.IsMatch(subnetmaskOrCidr, RegexHelper.SubnetmaskRegex))
18+
if (RegexHelper.SubnetmaskRegex().IsMatch(subnetmaskOrCidr))
2019
return ValidationResult.ValidResult;
2120

2221
// Check if it is a CIDR like /24

Source/NETworkManager.Validators/IPv4SubnetValidator.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Globalization;
2-
using System.Text.RegularExpressions;
32
using System.Windows.Controls;
43
using NETworkManager.Localization.Resources;
54
using NETworkManager.Utilities;
@@ -15,10 +14,10 @@ public override ValidationResult Validate(object value, CultureInfo cultureInfo)
1514
if (string.IsNullOrEmpty(subnet))
1615
return new ValidationResult(false, Strings.EnterValidSubnet);
1716

18-
if (Regex.IsMatch(subnet, RegexHelper.IPv4AddressCidrRegex))
17+
if (RegexHelper.IPv4AddressCidrRegex().IsMatch(subnet))
1918
return ValidationResult.ValidResult;
2019

21-
if (Regex.IsMatch(subnet, RegexHelper.IPv4AddressSubnetmaskRegex))
20+
if (RegexHelper.IPv4AddressSubnetmaskRegex().IsMatch(subnet))
2221
return ValidationResult.ValidResult;
2322

2423
return new ValidationResult(false, Strings.EnterValidSubnet);

Source/NETworkManager.Validators/IPv4SubnetmaskOrCIDRValidator.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Globalization;
2-
using System.Text.RegularExpressions;
32
using System.Windows.Controls;
43
using NETworkManager.Localization.Resources;
54
using NETworkManager.Utilities;
@@ -16,7 +15,7 @@ public override ValidationResult Validate(object value, CultureInfo cultureInfo)
1615
return new ValidationResult(false, Strings.EnterValidSubnetmaskOrCIDR);
1716

1817

19-
if (Regex.IsMatch(subnetmaskOrCidr, RegexHelper.SubnetmaskRegex))
18+
if (RegexHelper.SubnetmaskRegex().IsMatch(subnetmaskOrCidr))
2019
return ValidationResult.ValidResult;
2120

2221
if (int.TryParse(subnetmaskOrCidr.TrimStart('/'), out var cidr))

Source/NETworkManager.Validators/MultipleHostsRangeValidator.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ public override ValidationResult Validate(object value, CultureInfo cultureInfo)
2424
continue;
2525

2626
// 192.168.0.0/24
27-
if (Regex.IsMatch(ipHostOrRange, RegexHelper.IPv4AddressCidrRegex))
27+
if (RegexHelper.IPv4AddressCidrRegex().IsMatch(ipHostOrRange))
2828
continue;
2929

3030
// 192.168.0.0/255.255.255.0
31-
if (Regex.IsMatch(ipHostOrRange, RegexHelper.IPv4AddressSubnetmaskRegex))
31+
if (RegexHelper.IPv4AddressSubnetmaskRegex().IsMatch(ipHostOrRange))
3232
continue;
3333

3434
// 192.168.0.0 - 192.168.0.100
@@ -43,7 +43,7 @@ public override ValidationResult Validate(object value, CultureInfo cultureInfo)
4343
}
4444

4545
// 192.168.[50-100].1
46-
if (Regex.IsMatch(ipHostOrRange, RegexHelper.IPv4AddressSpecialRangeRegex))
46+
if (RegexHelper.IPv4AddressSpecialRangeRegex().IsMatch(ipHostOrRange))
4747
{
4848
var octets = ipHostOrRange.Split('.');
4949

Source/NETworkManager.Validators/SubnetmaskValidator.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Globalization;
2-
using System.Text.RegularExpressions;
32
using System.Windows.Controls;
43
using NETworkManager.Localization.Resources;
54
using NETworkManager.Utilities;
@@ -10,7 +9,7 @@ public class SubnetmaskValidator : ValidationRule
109
{
1110
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
1211
{
13-
return value != null && Regex.IsMatch((string)value, RegexHelper.SubnetmaskRegex)
12+
return value != null && RegexHelper.SubnetmaskRegex().IsMatch((string)value)
1413
? ValidationResult.ValidResult
1514
: new ValidationResult(false, Strings.EnterValidSubnetmask);
1615
}

Source/NETworkManager/ViewModels/SubnetCalculatorSubnettingViewModel.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
using System.Linq;
1616
using System.Net;
1717
using System.Net.Sockets;
18-
using System.Text.RegularExpressions;
1918
using System.Threading.Tasks;
2019
using System.Windows;
2120
using System.Windows.Data;
@@ -249,7 +248,7 @@ private async Task Calculate()
249248

250249
var newCidr =
251250
// Support subnetmask like 255.255.255.0
252-
Regex.IsMatch(newSubnetmaskOrCidr, RegexHelper.SubnetmaskRegex)
251+
RegexHelper.SubnetmaskRegex().IsMatch(newSubnetmaskOrCidr)
253252
? Convert.ToByte(Subnetmask.ConvertSubnetmaskToCidr(IPAddress.Parse(newSubnetmaskOrCidr)))
254253
: Convert.ToByte(newSubnetmaskOrCidr.TrimStart('/'));
255254

0 commit comments

Comments
 (0)