package the8472.utils; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; public class Arrays { private static final java.lang.invoke.MethodHandle compareImpl; private static final java.lang.invoke.MethodHandle mismatchImpl; static { MethodHandle compU = null; MethodHandle mism = null; try { compU = MethodHandles.lookup().findStatic(java.util.Arrays.class, "compareUnsigned", MethodType.methodType(int.class, byte[].class, byte[].class)); mism = MethodHandles.lookup().findStatic(java.util.Arrays.class, "mismatch", MethodType.methodType(int.class, byte[].class, byte[].class)); } catch (NoSuchMethodException | IllegalAccessException e) { // no java9 } if(compU == null) { try { compU = MethodHandles.lookup().findStatic(Arrays.class, "compareUnsignedFallback", MethodType.methodType(int.class, byte[].class, byte[].class)); mism = MethodHandles.lookup().findStatic(Arrays.class, "mismatchFallback", MethodType.methodType(int.class, byte[].class, byte[].class)); } catch (NoSuchMethodException | IllegalAccessException e) { throw new Error("should not happen"); } } compareImpl = compU; mismatchImpl = mism; } public static int compareUnsigned(byte[] a, byte[] b) { try { return (int) compareImpl.invokeExact(a, b); } catch(RuntimeException e) { throw e; } catch(Throwable e) { throw new Error("should not happen", e); } } public static int mismatch(byte[] a, byte[] b) { try { return (int) mismatchImpl.invokeExact(a, b); } catch(RuntimeException e) { throw e; } catch(Throwable e) { throw new Error("should not happen", e); } } @SuppressWarnings("unused") private static int compareUnsignedFallback(byte[] a, byte[] b) { int minLength = Math.min(a.length, b.length); for(int i=0;i+7<minLength;i+=8) { long la = Byte.toUnsignedLong(a[i]) << 56 | Byte.toUnsignedLong(a[i+1]) << 48 | Byte.toUnsignedLong(a[i+2]) << 40 | Byte.toUnsignedLong(a[i+3]) << 32 | Byte.toUnsignedLong(a[i+4]) << 24 | Byte.toUnsignedLong(a[i+5]) << 16 | Byte.toUnsignedLong(a[i+6]) << 8 | Byte.toUnsignedLong(a[i+7]) << 0; long lb = Byte.toUnsignedLong(b[i]) << 56 | Byte.toUnsignedLong(b[i+1]) << 48 | Byte.toUnsignedLong(b[i+2]) << 40 | Byte.toUnsignedLong(b[i+3]) << 32 | Byte.toUnsignedLong(b[i+4]) << 24 | Byte.toUnsignedLong(b[i+5]) << 16 | Byte.toUnsignedLong(b[i+6]) << 8 | Byte.toUnsignedLong(b[i+7]) << 0; if(la != lb) return Long.compareUnsigned(la, lb); } int offset = minLength - minLength & 0x7; for(int i=offset;i<minLength;i++) { int ia = Byte.toUnsignedInt(a[i]); int ib = Byte.toUnsignedInt(b[i]); if(ia != ib) return Integer.compare(ia, ib); } return a.length - b.length; } @SuppressWarnings("unused") private static int mismatchFallback(byte[] a, byte[] b) { int min = Math.min(a.length, b.length); for(int i=0;i<min;i++) { if(a[i] != b[i]) return i; } return a.length == b.length ? -1 : min; } }