提交 b796adb9 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Add additional methods to Bits for double and LE byte order

上级 88fa4120
...@@ -18,16 +18,45 @@ import java.util.UUID; ...@@ -18,16 +18,45 @@ import java.util.UUID;
public final class Bits { public final class Bits {
/** /**
* VarHandle giving access to elements of a byte[] array viewed as if it were a * VarHandle giving access to elements of a byte[] array viewed as if it
* int[] array on big-endian system. * were a int[] array on big-endian system.
*/ */
private static final VarHandle INT_VH = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN); private static final VarHandle INT_VH_BE = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN);
/** /**
* VarHandle giving access to elements of a byte[] array viewed as if it were a * VarHandle giving access to elements of a byte[] array viewed as if it
* long[] array on big-endian system. * were a int[] array on little-endian system.
*/ */
private static final VarHandle LONG_VH = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.BIG_ENDIAN); private static final VarHandle INT_VH_LE = MethodHandles.byteArrayViewVarHandle(int[].class,
ByteOrder.LITTLE_ENDIAN);
/**
* VarHandle giving access to elements of a byte[] array viewed as if it
* were a long[] array on big-endian system.
*/
private static final VarHandle LONG_VH_BE = MethodHandles.byteArrayViewVarHandle(long[].class,
ByteOrder.BIG_ENDIAN);
/**
* VarHandle giving access to elements of a byte[] array viewed as if it
* were a long[] array on little-endian system.
*/
private static final VarHandle LONG_VH_LE = MethodHandles.byteArrayViewVarHandle(long[].class,
ByteOrder.LITTLE_ENDIAN);
/**
* VarHandle giving access to elements of a byte[] array viewed as if it
* were a double[] array on big-endian system.
*/
private static final VarHandle DOUBLE_VH_BE = MethodHandles.byteArrayViewVarHandle(double[].class,
ByteOrder.BIG_ENDIAN);
/**
* VarHandle giving access to elements of a byte[] array viewed as if it
* were a double[] array on little-endian system.
*/
private static final VarHandle DOUBLE_VH_LE = MethodHandles.byteArrayViewVarHandle(double[].class,
ByteOrder.LITTLE_ENDIAN);
/** /**
* Compare the contents of two char arrays. If the content or length of the * Compare the contents of two char arrays. If the content or length of the
...@@ -96,12 +125,26 @@ public final class Bits { ...@@ -96,12 +125,26 @@ public final class Bits {
* @return the value * @return the value
*/ */
public static int readInt(byte[] buff, int pos) { public static int readInt(byte[] buff, int pos) {
return (int) INT_VH.get(buff, pos); return (int) INT_VH_BE.get(buff, pos);
} }
/** /**
* Reads a long value from the byte array at the given position in big-endian * Reads a int value from the byte array at the given position in
* order. * little-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @return the value
*/
public static int readIntLE(byte[] buff, int pos) {
return (int) INT_VH_LE.get(buff, pos);
}
/**
* Reads a long value from the byte array at the given position in
* big-endian order.
* *
* @param buff * @param buff
* the byte array * the byte array
...@@ -110,7 +153,49 @@ public final class Bits { ...@@ -110,7 +153,49 @@ public final class Bits {
* @return the value * @return the value
*/ */
public static long readLong(byte[] buff, int pos) { public static long readLong(byte[] buff, int pos) {
return (long) LONG_VH.get(buff, pos); return (long) LONG_VH_BE.get(buff, pos);
}
/**
* Reads a long value from the byte array at the given position in
* little-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @return the value
*/
public static long readLongLE(byte[] buff, int pos) {
return (long) LONG_VH_LE.get(buff, pos);
}
/**
* Reads a double value from the byte array at the given position in
* big-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @return the value
*/
public static double readDouble(byte[] buff, int pos) {
return (double) DOUBLE_VH_BE.get(buff, pos);
}
/**
* Reads a double value from the byte array at the given position in
* little-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @return the value
*/
public static double readDoubleLE(byte[] buff, int pos) {
return (double) DOUBLE_VH_LE.get(buff, pos);
} }
/** /**
...@@ -124,8 +209,8 @@ public final class Bits { ...@@ -124,8 +209,8 @@ public final class Bits {
*/ */
public static byte[] uuidToBytes(long msb, long lsb) { public static byte[] uuidToBytes(long msb, long lsb) {
byte[] buff = new byte[16]; byte[] buff = new byte[16];
LONG_VH.set(buff, 0, msb); LONG_VH_BE.set(buff, 0, msb);
LONG_VH.set(buff, 8, lsb); LONG_VH_BE.set(buff, 8, lsb);
return buff; return buff;
} }
...@@ -152,7 +237,22 @@ public final class Bits { ...@@ -152,7 +237,22 @@ public final class Bits {
* the value to write * the value to write
*/ */
public static void writeInt(byte[] buff, int pos, int x) { public static void writeInt(byte[] buff, int pos, int x) {
INT_VH.set(buff, pos, x); INT_VH_BE.set(buff, pos, x);
}
/**
* Writes a int value to the byte array at the given position in
* little-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @param x
* the value to write
*/
public static void writeIntLE(byte[] buff, int pos, int x) {
INT_VH_LE.set(buff, pos, x);
} }
/** /**
...@@ -167,7 +267,52 @@ public final class Bits { ...@@ -167,7 +267,52 @@ public final class Bits {
* the value to write * the value to write
*/ */
public static void writeLong(byte[] buff, int pos, long x) { public static void writeLong(byte[] buff, int pos, long x) {
LONG_VH.set(buff, pos, x); LONG_VH_BE.set(buff, pos, x);
}
/**
* Writes a long value to the byte array at the given position in
* little-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @param x
* the value to write
*/
public static void writeLongLE(byte[] buff, int pos, long x) {
LONG_VH_LE.set(buff, pos, x);
}
/**
* Writes a double value to the byte array at the given position in
* big-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @param x
* the value to write
*/
public static void writeDouble(byte[] buff, int pos, double x) {
DOUBLE_VH_BE.set(buff, pos, x);
}
/**
* Writes a double value to the byte array at the given position in
* little-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @param x
* the value to write
*/
public static void writeDoubleLE(byte[] buff, int pos, double x) {
DOUBLE_VH_LE.set(buff, pos, x);
} }
private Bits() { private Bits() {
......
...@@ -124,8 +124,22 @@ public final class Bits { ...@@ -124,8 +124,22 @@ public final class Bits {
} }
/** /**
* Reads a long value from the byte array at the given position in big-endian * Reads a int value from the byte array at the given position in
* order. * little-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @return the value
*/
public static int readIntLE(byte[] buff, int pos) {
return (buff[pos++] & 0xff) + ((buff[pos++] & 0xff) << 8) + ((buff[pos++] & 0xff) << 16) + (buff[pos] << 24);
}
/**
* Reads a long value from the byte array at the given position in
* big-endian order.
* *
* @param buff * @param buff
* the byte array * the byte array
...@@ -134,7 +148,49 @@ public final class Bits { ...@@ -134,7 +148,49 @@ public final class Bits {
* @return the value * @return the value
*/ */
public static long readLong(byte[] buff, int pos) { public static long readLong(byte[] buff, int pos) {
return (((long) readInt(buff, pos)) << 32) + (readInt(buff, pos + 4) & 0xffffffffL); return (((long) readInt(buff, pos)) << 32) + (readInt(buff, pos + 4) & 0xffff_ffffL);
}
/**
* Reads a long value from the byte array at the given position in
* little-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @return the value
*/
public static long readLongLE(byte[] buff, int pos) {
return (readIntLE(buff, pos) & 0xffff_ffffL) + (((long) readIntLE(buff, pos + 4)) << 32);
}
/**
* Reads a double value from the byte array at the given position in
* big-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @return the value
*/
public static double readDouble(byte[] buff, int pos) {
return Double.longBitsToDouble(readLong(buff, pos));
}
/**
* Reads a double value from the byte array at the given position in
* little-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @return the value
*/
public static double readDoubleLE(byte[] buff, int pos) {
return Double.longBitsToDouble(readLongLE(buff, pos));
} }
/** /**
...@@ -184,6 +240,24 @@ public final class Bits { ...@@ -184,6 +240,24 @@ public final class Bits {
buff[pos] = (byte) x; buff[pos] = (byte) x;
} }
/**
* Writes a int value to the byte array at the given position in
* little-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @param x
* the value to write
*/
public static void writeIntLE(byte[] buff, int pos, int x) {
buff[pos++] = (byte) x;
buff[pos++] = (byte) (x >> 8);
buff[pos++] = (byte) (x >> 16);
buff[pos] = (byte) (x >> 24);
}
/** /**
* Writes a long value to the byte array at the given position in big-endian * Writes a long value to the byte array at the given position in big-endian
* order. * order.
...@@ -200,6 +274,52 @@ public final class Bits { ...@@ -200,6 +274,52 @@ public final class Bits {
writeInt(buff, pos + 4, (int) x); writeInt(buff, pos + 4, (int) x);
} }
/**
* Writes a long value to the byte array at the given position in
* little-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @param x
* the value to write
*/
public static void writeLongLE(byte[] buff, int pos, long x) {
writeIntLE(buff, pos, (int) x);
writeIntLE(buff, pos + 4, (int) (x >> 32));
}
/**
* Writes a double value to the byte array at the given position in
* big-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @param x
* the value to write
*/
public static void writeDouble(byte[] buff, int pos, double x) {
writeLong(buff, pos, Double.doubleToRawLongBits(x));
}
/**
* Writes a double value to the byte array at the given position in
* little-endian order.
*
* @param buff
* the byte array
* @param pos
* the position
* @param x
* the value to write
*/
public static void writeDoubleLE(byte[] buff, int pos, double x) {
writeLongLE(buff, pos, Double.doubleToRawLongBits(x));
}
private Bits() { private Bits() {
} }
} }
...@@ -47,6 +47,7 @@ public class TestUtils extends TestBase { ...@@ -47,6 +47,7 @@ public class TestUtils extends TestBase {
testIOUtils(); testIOUtils();
testSortTopN(); testSortTopN();
testSortTopNRandom(); testSortTopNRandom();
testWriteReadInt();
testWriteReadLong(); testWriteReadLong();
testGetNonPrimitiveClass(); testGetNonPrimitiveClass();
testGetNonPrimitiveClass(); testGetNonPrimitiveClass();
...@@ -94,23 +95,62 @@ public class TestUtils extends TestBase { ...@@ -94,23 +95,62 @@ public class TestUtils extends TestBase {
} }
} }
private void testWriteReadInt() {
byte[] buff = new byte[4];
for (int x : new int[]{Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 1, -1,
Short.MIN_VALUE, Short.MAX_VALUE}) {
testIntImpl1(buff, x);
}
Random r = new Random(1);
for (int i = 0; i < 1000; i++) {
testIntImpl1(buff, r.nextInt());
}
}
private void testIntImpl1(byte[] buff, int x) {
int r = Integer.reverseBytes(x);
Bits.writeInt(buff, 0, x);
testIntImpl2(buff, x, r);
Bits.writeIntLE(buff, 0, x);
testIntImpl2(buff, r, x);
}
private void testIntImpl2(byte[] buff, int x, int r) {
assertEquals(x, Bits.readInt(buff, 0));
assertEquals(r, Bits.readIntLE(buff, 0));
}
private void testWriteReadLong() { private void testWriteReadLong() {
byte[] buff = new byte[8]; byte[] buff = new byte[8];
for (long x : new long[]{Long.MIN_VALUE, Long.MAX_VALUE, 0, 1, -1, for (long x : new long[]{Long.MIN_VALUE, Long.MAX_VALUE, 0, 1, -1,
Integer.MIN_VALUE, Integer.MAX_VALUE}) { Integer.MIN_VALUE, Integer.MAX_VALUE}) {
Bits.writeLong(buff, 0, x); testLongImpl1(buff, x);
long y = Bits.readLong(buff, 0);
assertEquals(x, y);
} }
Random r = new Random(1); Random r = new Random(1);
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
long x = r.nextLong(); testLongImpl1(buff, r.nextLong());
Bits.writeLong(buff, 0, x);
long y = Bits.readLong(buff, 0);
assertEquals(x, y);
} }
} }
private void testLongImpl1(byte[] buff, long x) {
long r = Long.reverseBytes(x);
Bits.writeLong(buff, 0, x);
testLongImpl2(buff, x, r);
Bits.writeLongLE(buff, 0, x);
testLongImpl2(buff, r, x);
Bits.writeDouble(buff, 0, Double.longBitsToDouble(x));
testLongImpl2(buff, x, r);
Bits.writeDoubleLE(buff, 0, Double.longBitsToDouble(x));
testLongImpl2(buff, r, x);
}
private void testLongImpl2(byte[] buff, long x, long r) {
assertEquals(x, Bits.readLong(buff, 0));
assertEquals(r, Bits.readLongLE(buff, 0));
assertEquals(Double.longBitsToDouble(x), Bits.readDouble(buff, 0));
assertEquals(Double.longBitsToDouble(r), Bits.readDoubleLE(buff, 0));
}
private void testSortTopN() { private void testSortTopN() {
Comparator<Integer> comp = new Comparator<Integer>() { Comparator<Integer> comp = new Comparator<Integer>() {
@Override @Override
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论