-
-
Save rumikotakahashi/dfdb4c526fcc3c097770f17602a4c675 to your computer and use it in GitHub Desktop.
byte array comparer(inspired by Messagepack-CSharp and System.Span<T>)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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