Skip to content

Commit

Permalink
Implement Span overloads for IPAddress class
Browse files Browse the repository at this point in the history
See issue #22607
This adds
public IPAddress(ReadOnlySpan<byte> address)
public IPAddress(ReadOnlySpan<byte> address, long scopeid)
public bool TryWriteBytes(Span<byte> destination, out int bytesWritten)
public static IPAddress Parse(ReadOnlySpan<char> ipSpan)
public static bool TryParse(ReadOnlySpan<char> ipSpan, out IPAddress address)
public static bool TryFormat(Span<char> destination, out int bytesWritten)
  • Loading branch information
Paxxi authored and stephentoub committed Aug 21, 2017
1 parent 7a67354 commit 0029b32
Show file tree
Hide file tree
Showing 16 changed files with 915 additions and 352 deletions.
6 changes: 6 additions & 0 deletions src/System.Net.Primitives/ref/System.Net.Primitives.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,9 @@ public partial class IPAddress
public static readonly System.Net.IPAddress Loopback;
public static readonly System.Net.IPAddress None;
public IPAddress(byte[] address) { }
public IPAddress(ReadOnlySpan<byte> address) { }
public IPAddress(byte[] address, long scopeid) { }
public IPAddress(ReadOnlySpan<byte> address, long scopeid) { }
public IPAddress(long newAddress) { }
public System.Net.Sockets.AddressFamily AddressFamily { get { throw null; } }
public bool IsIPv4MappedToIPv6 { get { throw null; } }
Expand All @@ -202,6 +204,7 @@ public IPAddress(long newAddress) { }
public long ScopeId { get { throw null; } set { } }
public override bool Equals(object comparand) { throw null; }
public byte[] GetAddressBytes() { throw null; }
public bool TryWriteBytes(Span<byte> destination, out int bytesWritten) { throw null; }
public override int GetHashCode() { throw null; }
public static short HostToNetworkOrder(short host) { throw null; }
public static int HostToNetworkOrder(int host) { throw null; }
Expand All @@ -213,8 +216,11 @@ public IPAddress(long newAddress) { }
public static int NetworkToHostOrder(int network) { throw null; }
public static long NetworkToHostOrder(long network) { throw null; }
public static System.Net.IPAddress Parse(string ipString) { throw null; }
public static System.Net.IPAddress Parse(ReadOnlySpan<char> ipString) { throw null; }
public override string ToString() { throw null; }
public bool TryFormat(Span<char> destination, out int charsWritten) { throw null; }
public static bool TryParse(string ipString, out System.Net.IPAddress address) { throw null; }
public static bool TryParse(ReadOnlySpan<char> ipString, out System.Net.IPAddress address) { throw null; }
[Obsolete("This property has been deprecated. It is address family dependent. Please use IPAddress.Equals method to perform comparisons. http://go.microsoft.com/fwlink/?linkid=14202")]
public long Address { get { throw null; } set { } }
}
Expand Down
3 changes: 2 additions & 1 deletion src/System.Net.Primitives/ref/System.Net.Primitives.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Microsoft.Win32.Primitives\ref\Microsoft.Win32.Primitives.csproj" />
<ProjectReference Include="..\..\System.Memory\ref\System.Memory.csproj" />
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
<ProjectReference Include="..\..\System.Runtime.InteropServices\ref\System.Runtime.InteropServices.csproj" />
<ProjectReference Include="..\..\System.Runtime.Handles\ref\System.Runtime.Handles.csproj" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
</Project>
1 change: 1 addition & 0 deletions src/System.Net.Primitives/src/System.Net.Primitives.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@
<Reference Include="System.Diagnostics.Debug" />
<Reference Include="System.Diagnostics.Tracing" />
<Reference Include="System.Resources.ResourceManager" />
<Reference Include="System.Memory" />
<Reference Include="System.Runtime" />
<Reference Include="System.Runtime.Extensions" />
<Reference Include="System.Runtime.InteropServices" />
Expand Down
115 changes: 87 additions & 28 deletions src/System.Net.Primitives/src/System/Net/IPAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,13 @@ public IPAddress(long newAddress)
/// Constructor for an IPv6 Address with a specified Scope.
/// </para>
/// </devdoc>
public IPAddress(byte[] address, long scopeid)
public IPAddress(byte[] address, long scopeid) :
this(new ReadOnlySpan<byte>(address ?? throw new ArgumentNullException(nameof(address))), scopeid)
{
if (address == null)
{
throw new ArgumentNullException(nameof(address));
}
}

public IPAddress(ReadOnlySpan<byte> address, long scopeid)
{
if (address.Length != IPAddressParserStatics.IPv6AddressBytes)
{
throw new ArgumentException(SR.dns_bad_ip_address, nameof(address));
Expand Down Expand Up @@ -200,12 +200,13 @@ private IPAddress(ushort[] numbers, uint scopeid)
/// Constructor for IPv4 and IPv6 Address.
/// </para>
/// </devdoc>
public IPAddress(byte[] address)
public IPAddress(byte[] address) :
this(new ReadOnlySpan<byte>(address ?? throw new ArgumentNullException(nameof(address))))
{
}

public IPAddress(ReadOnlySpan<byte> address)
{
if (address == null)
{
throw new ArgumentNullException(nameof(address));
}
if (address.Length != IPAddressParserStatics.IPv4AddressBytes && address.Length != IPAddressParserStatics.IPv6AddressBytes)
{
throw new ArgumentException(SR.dns_bad_ip_address, nameof(address));
Expand Down Expand Up @@ -262,48 +263,99 @@ internal IPAddress(int newAddress)
/// </devdoc>
public static bool TryParse(string ipString, out IPAddress address)
{
address = IPAddressParser.Parse(ipString, true);
if (ipString == null)
{
address = null;
return false;
}

address = IPAddressParser.Parse(ipString, tryParse: true);
return (address != null);
}

public static bool TryParse(ReadOnlySpan<char> ipSpan, out IPAddress address)
{
address = IPAddressParser.Parse(ipSpan, tryParse: true);
return (address != null);
}

public static IPAddress Parse(string ipString)
{
return IPAddressParser.Parse(ipString, false);
if (ipString == null)
{
throw new ArgumentNullException(nameof(ipString));
}

return IPAddressParser.Parse(ipString, tryParse: false);
}

/// <devdoc>
/// <para>
/// Provides a copy of the IPAddress internals as an array of bytes.
/// </para>
/// </devdoc>
public byte[] GetAddressBytes()
public static IPAddress Parse(ReadOnlySpan<char> ipSpan)
{
return IPAddressParser.Parse(ipSpan, tryParse: false);
}

public bool TryWriteBytes(Span<byte> destination, out int bytesWritten)
{
byte[] bytes;
if (IsIPv6)
{
Debug.Assert(_numbers != null && _numbers.Length == NumberOfLabels);

bytes = new byte[IPAddressParserStatics.IPv6AddressBytes];
if (destination.Length < IPAddressParserStatics.IPv6AddressBytes)
{
bytesWritten = 0;
return false;
}

int j = 0;
for (int i = 0; i < NumberOfLabels; i++)
{
bytes[j++] = (byte)((_numbers[i] >> 8) & 0xFF);
bytes[j++] = (byte)((_numbers[i]) & 0xFF);
destination[j++] = (byte)((_numbers[i] >> 8) & 0xFF);
destination[j++] = (byte)((_numbers[i]) & 0xFF);
}

bytesWritten = IPAddressParserStatics.IPv6AddressBytes;
}
else
{
uint address = PrivateAddress;
bytes = new byte[IPAddressParserStatics.IPv4AddressBytes];
if (destination.Length < IPAddressParserStatics.IPv4AddressBytes)
{
bytesWritten = 0;
return false;
}

uint address = PrivateAddress;
unchecked
{
bytes[0] = (byte)(address);
bytes[1] = (byte)(address >> 8);
bytes[2] = (byte)(address >> 16);
bytes[3] = (byte)(address >> 24);
destination[0] = (byte)(address);
destination[1] = (byte)(address >> 8);
destination[2] = (byte)(address >> 16);
destination[3] = (byte)(address >> 24);
}

bytesWritten = IPAddressParserStatics.IPv4AddressBytes;
}

return true;
}
/// <devdoc>
/// <para>
/// Provides a copy of the IPAddress internals as an array of bytes.
/// </para>
/// </devdoc>
public byte[] GetAddressBytes()
{
if (IsIPv6)
{
Debug.Assert(_numbers != null && _numbers.Length == NumberOfLabels);
}

int length = IsIPv6 ? IPAddressParserStatics.IPv6AddressBytes : IPAddressParserStatics.IPv4AddressBytes;
var bytes = new byte[length];

bool result = TryWriteBytes(new Span<byte>(bytes), out int bytesWritten);

Debug.Assert(result);

return bytes;
}

Expand Down Expand Up @@ -369,6 +421,13 @@ public override string ToString()
return _toString;
}

public bool TryFormat(Span<char> destination, out int charsWritten)
{
return IsIPv4 ?
IPAddressParser.IPv4AddressToString(PrivateAddress, destination, out charsWritten) :
IPAddressParser.IPv6AddressToString(_numbers, PrivateScopeId, destination, out charsWritten);
}

public static long HostToNetworkOrder(long host)
{
#if BIGENDIAN
Expand Down
Loading

0 comments on commit 0029b32

Please sign in to comment.