Skip to content

Instantly share code, notes, and snippets.

@rumikotakahashi
Forked from itn3000/ByteComparer.cs
Created August 29, 2017 05:32
Show Gist options
  • Select an option

  • Save rumikotakahashi/dfdb4c526fcc3c097770f17602a4c675 to your computer and use it in GitHub Desktop.

Select an option

Save rumikotakahashi/dfdb4c526fcc3c097770f17602a4c675 to your computer and use it in GitHub Desktop.
byte array comparer(inspired by Messagepack-CSharp and System.Span<T>)
using System;
static class Util
{
public static bool AreSameSpan(byte[] b1, byte[] b2)
{
var span = new Span<byte>(b1);
var span2 = new Span<byte>(b2);
return span.SequenceEqual(span2);
}
public static unsafe bool AreSameBytePtr(byte[] xs, int xsOffset, int xsCount, byte[] ys, int ysOffset, int ysCount)
{
if (xs == null || ys == null || xsCount != ysCount)
{
return false;
}
fixed (byte* p1 = xs)
fixed (byte* p2 = ys)
{
var x1 = p1 + xsOffset;
var x2 = p2 + ysOffset;
var length = xsCount;
var loooCount = length / 8;
for (var i = 0; i < loooCount; i++, x1 += 8, x2 += 8)
{
if (*(long*)x1 != *(long*)x2)
{
return false;
}
}
if ((length & 4) != 0)
{
if (*(int*)x1 != *(int*)x2)
{
return false;
}
x1 += 4;
x2 += 4;
}
if ((length & 2) != 0)
{
if (*(short*)x1 != *(short*)x2)
{
return false;
}
x1 += 2;
x2 += 2;
}
if ((length & 1) != 0)
{
if (*x1 != *x2)
{
return false;
}
}
return true;
}
}
public static unsafe bool AreSameByteWithOffset(byte[] xs, int xsOffset, int xsCount, byte[] ys, int ysOffset, int ysCount)
{
if (xs == null || ys == null || xsCount != ysCount)
{
return false;
}
fixed (byte* p1 = xs)
fixed (byte* p2 = ys)
{
// when length >= System.Numerics.Vector<byte>.Count, it will be faster if using System.Numerics.Vector<byte>
var length = xsCount;
// It is most efficient
if (length >= 8)
{
var x1 = p1 + xsOffset;
var x2 = p2 + ysOffset;
// calculate the end loop offset.
var endxptr = x1 + xsCount - 8;
var endyptr = x2 + xsCount - 8;
// compare bytes per sizeof(UIntPtr)
while (x1 < endxptr)
{
if (*(long*)x1 != *(long*)x2)
{
return false;
}
x1 += 8;
x2 += 8;
}
// compare last sizeof(UIntPtr) bytes.
// the most loss of duplicated comparison when xsCount % sizeof(UIntPtr) == sizeof(UIntPtr) - 1
return *(long*)endxptr == *(long*)endyptr;
}
else if (length >= 4)
{
var x1 = p1 + xsOffset;
var x2 = p2 + ysOffset;
// calculate the end loop offset.
var endxptr = x1 + xsCount - 4;
var endyptr = x2 + xsCount - 4;
// compare bytes per sizeof(UIntPtr)
while (x1 < endxptr)
{
if (*(int*)x1 != *(int*)x2)
{
return false;
}
x1 += 4;
x2 += 4;
}
// compare last sizeof(UIntPtr) bytes.
// the most loss of duplicated comparison when xsCount % sizeof(UIntPtr) == sizeof(UIntPtr) - 1
return *(int*)endxptr == *(int*)endyptr;
}
else
{
var x1 = p1 + xsOffset;
var x2 = p2 + ysOffset;
var endptr = x1 + xsCount;
for (; x1 < endptr; x1++, x2++)
{
if (*x1 != *x2)
{
return false;
}
}
return true;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment