public static PhysicalAddress Parse(string address)
{
- int validCount = 0;
- bool hasDashes = false;
- byte[] buffer = null;
+ int validSegmentLength;
+ char? delimiter = null;
+ byte[] buffer;
if (address == null)
{
- return PhysicalAddress.None;
+ return None;
}
- // Has dashes?
if (address.Contains('-'))
{
- hasDashes = true;
- buffer = new byte[(address.Length + 1) / 3];
-
if ((address.Length + 1) % 3 != 0)
{
- throw new FormatException(SR.Format(SR.net_bad_mac_address, address));
+ ThrowBadAddressException(address);
+ }
+
+ delimiter = '-';
+ buffer = new byte[(address.Length + 1) / 3]; // allow any length that's a multiple of 3
+ validSegmentLength = 2;
+ }
+ else if (address.Contains(':'))
+ {
+ delimiter = ':';
+ validSegmentLength = GetValidSegmentLength(address, ':');
+ if (validSegmentLength != 2 && validSegmentLength != 4)
+ {
+ ThrowBadAddressException(address);
+ }
+ buffer = new byte[6];
+ }
+ else if (address.Contains('.'))
+ {
+ delimiter = '.';
+ validSegmentLength = GetValidSegmentLength(address, '.');
+ if (validSegmentLength != 4)
+ {
+ ThrowBadAddressException(address);
}
+ buffer = new byte[6];
}
else
{
if (address.Length % 2 > 0)
{
- throw new FormatException(SR.Format(SR.net_bad_mac_address, address));
+ ThrowBadAddressException(address);
}
+ validSegmentLength = address.Length;
buffer = new byte[address.Length / 2];
}
+ int validCount = 0;
int j = 0;
for (int i = 0; i < address.Length; i++)
{
- int value = (int)address[i];
+ int value = address[i];
- if (value >= 0x30 && value <= 0x39)
+ if (value >= '0' && value <= '9')
+ {
+ value -= '0';
+ }
+ else if (value >= 'A' && value <= 'F')
{
- value -= 0x30;
+ value -= ('A' - 10);
}
- else if (value >= 0x41 && value <= 0x46)
+ else if (value >= 'a' && value <= 'f')
{
- value -= 0x37;
+ value -= ('a' - 10);
}
- else if (value == (int)'-')
+ else
{
- if (validCount == 2)
+ if (delimiter == value && validCount == validSegmentLength)
{
validCount = 0;
continue;
}
- else
- {
- throw new FormatException(SR.Format(SR.net_bad_mac_address, address));
- }
- }
- else
- {
- throw new FormatException(SR.Format(SR.net_bad_mac_address, address));
+
+ ThrowBadAddressException(address);
}
- // we had too many characters after the last dash
- if (hasDashes && validCount >= 2)
+ // we had too many characters after the last delimiter
+ if (validCount >= validSegmentLength)
{
- throw new FormatException(SR.Format(SR.net_bad_mac_address, address));
+ ThrowBadAddressException(address);
}
if (validCount % 2 == 0)
validCount++;
}
- // we too few characters after the last dash
- if (validCount < 2)
+ // we had too few characters after the last delimiter
+ if (validCount < validSegmentLength)
{
- throw new FormatException(SR.Format(SR.net_bad_mac_address, address));
+ ThrowBadAddressException(address);
}
return new PhysicalAddress(buffer);
+
+ static void ThrowBadAddressException(string address) =>
+ throw new FormatException(SR.Format(SR.net_bad_mac_address, address));
+ }
+
+ private static int GetValidSegmentLength(string address, char delimiter)
+ {
+ int segments = 1;
+ int validSegmentLength = 0;
+ for (int i = 0; i < address.Length; i++)
+ {
+ if (address[i] == delimiter)
+ {
+ if (validSegmentLength == 0)
+ {
+ validSegmentLength = i;
+ }
+ else if ((i - (segments - 1)) % validSegmentLength != 0)
+ {
+ // segments - 1 = num of delimeters. Throw if new segment isn't the validSegmentLength
+ throw new FormatException(SR.Format(SR.net_bad_mac_address, address));
+ }
+
+ segments++;
+ }
+ }
+
+ if (segments * validSegmentLength != 12)
+ {
+ throw new FormatException(SR.Format(SR.net_bad_mac_address, address));
+ }
+
+ return validSegmentLength;
}
}
}
yield return new object[] { "47-FB-74-41-3B", new byte[] { 0x47, 0xfb, 0x74, 0x41, 0x3B } };
yield return new object[] { "00-11-22-33-44-55", new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 } };
yield return new object[] { "F0-E1-D2-C3-B4-A5", new byte[] { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5 } };
+ yield return new object[] { "f0-e1-d2-c3-b4-a5", new byte[] { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5 } };
yield return new object[] { "54-0C-C4-7E-66-54", new byte[] { 0x54, 0x0c, 0xc4, 0x7e, 0x66, 0x54 } };
yield return new object[] { "001122334455", new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 } };
+ yield return new object[] { "00:11:22:33:44:55", new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 } };
+ yield return new object[] { "0011:2233:4455", new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 } };
+ yield return new object[] { "0011.2233.4455", new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 } };
yield return new object[]
{
"00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-14-15-16-17-18-19-1A-1B-1C-1D-1E-1F-" +
[InlineData("D2-C3-")]
[InlineData("D2-A33")]
[InlineData("B4-A5-F01")]
- [InlineData("f0-e1-d2-c3-b4-a5")]
- [InlineData("47:FB:74:41:66:3B")]
- [InlineData("de84.1251.1c9d")]
- [InlineData("AE88.D6EC.A720")]
+ [InlineData("00:111:22:33:44:55")]
+ [InlineData("0:1:22:33:44:55")]
+ [InlineData("0:0:1:1:22:33:44:55")]
+ [InlineData(":::00112233444")]
+ [InlineData("0011:2233")]
+ [InlineData("0011:2233:4455:6677")]
+ [InlineData("0011:2233:4455:6677:8899:0011")]
+ [InlineData("001:12233:4455")]
+ [InlineData("0011:2233:")]
+ [InlineData("0011:2233:44555")]
+ [InlineData("001.12233.4455")]
+ [InlineData("0011.2233.")]
+ [InlineData("0011.2233.44555")]
+ [InlineData("00.111.22.33.44.55")]
+ [InlineData("001.122.334.455")]
+
public void Parse_Invalid_ThrowsFormatException(string address)
{
FormatException ex = Assert.Throws<FormatException>(() => PhysicalAddress.Parse(address));
[MemberData(nameof(RoundtripParseToString_String_Bytes))]
public void ToString_ExpectedResult(string expectedAddress, byte[] inputBytes)
{
- Assert.Equal(expectedAddress.Replace("-", ""), new PhysicalAddress(inputBytes).ToString());
+ Assert.Equal(expectedAddress.Replace("-", "").Replace(":", "").Replace(".", "").ToUpper(), new PhysicalAddress(inputBytes).ToString());
}
[Theory]