|
|
|
using System; |
|
static class ByteComparer |
|
{ |
|
public static bool AreSameSpan(byte[] b1, byte[] b2) |
|
{ |
|
var span = new Span<byte>(b1); |
|
var span2 = new Span<byte>(b2); |
|
return span.SequenceEqual(span2); |
|
} |
|
// similar to MessagePack-CSharp's implementation |
|
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; |
|
} |
|
} |
|
// similar to System.Span<byte>'s implementation |
|
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, comparison 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(long) |
|
while (x1 < endxptr) |
|
{ |
|
if (*(long*)x1 != *(long*)x2) |
|
{ |
|
return false; |
|
} |
|
x1 += 8; |
|
x2 += 8; |
|
} |
|
// compare last sizeof(long) bytes. |
|
// the most loss of duplicated comparison when xsCount % sizeof(long) == 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(int) |
|
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(int) == sizeof(int) - 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; |
|
} |
|
} |
|
} |
|
} |