UnsafeByteBufUtil errors and simplification
Motiviation: UnsafeByteBufUtil has some bugs related to using an incorrect index, and also omitting the array paramter when dealing with byte[] objects. There is also some simplification possible with respect to type casting, and minor formatting consistentcy issues. Modifications: - Ensure indexing is correct when dealing with native memory - Fix the native access and endianness for the medium/unsigned medium methods - Ensure array is used when dealing with heap memory - Remove unecessary casts when using long - Fix formating and alignment Result: UnsafeByteBufUtil is more correct and won't access direct memory when heap arrays are used.
This commit is contained in:
parent
5b72acb59a
commit
99c2d1e303
@ -50,16 +50,13 @@ final class UnsafeByteBufUtil {
|
||||
|
||||
static int getUnsignedMedium(long address) {
|
||||
if (UNALIGNED) {
|
||||
if (BIG_ENDIAN_NATIVE_ORDER) {
|
||||
return (PlatformDependent.getByte(address) & 0xff) |
|
||||
(PlatformDependent.getShort(address + 1) & 0xffff) << 8;
|
||||
}
|
||||
return (Short.reverseBytes(PlatformDependent.getShort(address)) & 0xffff) << 8 |
|
||||
PlatformDependent.getByte(address + 2) & 0xff;
|
||||
return (PlatformDependent.getByte(address) & 0xff) << 16 |
|
||||
(BIG_ENDIAN_NATIVE_ORDER ? PlatformDependent.getShort(address + 1)
|
||||
: Short.reverseBytes(PlatformDependent.getShort(address + 1))) & 0xffff;
|
||||
}
|
||||
return (PlatformDependent.getByte(address) & 0xff) << 16 |
|
||||
(PlatformDependent.getByte(address + 1) & 0xff) << 8 |
|
||||
PlatformDependent.getByte(address + 2) & 0xff;
|
||||
return (PlatformDependent.getByte(address) & 0xff) << 16 |
|
||||
(PlatformDependent.getByte(address + 1) & 0xff) << 8 |
|
||||
PlatformDependent.getByte(address + 2) & 0xff;
|
||||
}
|
||||
|
||||
static int getInt(long address) {
|
||||
@ -70,7 +67,7 @@ final class UnsafeByteBufUtil {
|
||||
return PlatformDependent.getByte(address) << 24 |
|
||||
(PlatformDependent.getByte(address + 1) & 0xff) << 16 |
|
||||
(PlatformDependent.getByte(address + 2) & 0xff) << 8 |
|
||||
PlatformDependent.getByte(address + 3) & 0xff;
|
||||
PlatformDependent.getByte(address + 3) & 0xff;
|
||||
}
|
||||
|
||||
static long getLong(long address) {
|
||||
@ -78,14 +75,14 @@ final class UnsafeByteBufUtil {
|
||||
long v = PlatformDependent.getLong(address);
|
||||
return BIG_ENDIAN_NATIVE_ORDER ? v : Long.reverseBytes(v);
|
||||
}
|
||||
return (long) PlatformDependent.getByte(address) << 56 |
|
||||
((long) PlatformDependent.getByte(address + 1) & 0xff) << 48 |
|
||||
((long) PlatformDependent.getByte(address + 2) & 0xff) << 40 |
|
||||
((long) PlatformDependent.getByte(address + 3) & 0xff) << 32 |
|
||||
((long) PlatformDependent.getByte(address + 4) & 0xff) << 24 |
|
||||
((long) PlatformDependent.getByte(address + 5) & 0xff) << 16 |
|
||||
((long) PlatformDependent.getByte(address + 6) & 0xff) << 8 |
|
||||
(long) PlatformDependent.getByte(address + 7) & 0xff;
|
||||
return ((long) PlatformDependent.getByte(address)) << 56 |
|
||||
(PlatformDependent.getByte(address + 1) & 0xffL) << 48 |
|
||||
(PlatformDependent.getByte(address + 2) & 0xffL) << 40 |
|
||||
(PlatformDependent.getByte(address + 3) & 0xffL) << 32 |
|
||||
(PlatformDependent.getByte(address + 4) & 0xffL) << 24 |
|
||||
(PlatformDependent.getByte(address + 5) & 0xffL) << 16 |
|
||||
(PlatformDependent.getByte(address + 6) & 0xffL) << 8 |
|
||||
(PlatformDependent.getByte(address + 7)) & 0xffL;
|
||||
}
|
||||
|
||||
static void setByte(long address, int value) {
|
||||
@ -103,16 +100,11 @@ final class UnsafeByteBufUtil {
|
||||
}
|
||||
|
||||
static void setMedium(long address, int value) {
|
||||
PlatformDependent.putByte(address, (byte) (value >>> 16));
|
||||
if (UNALIGNED) {
|
||||
if (BIG_ENDIAN_NATIVE_ORDER) {
|
||||
PlatformDependent.putByte(address, (byte) value);
|
||||
PlatformDependent.putShort(address + 1, (short) (value >>> 8));
|
||||
} else {
|
||||
PlatformDependent.putShort(address, Short.reverseBytes((short) (value >>> 8)));
|
||||
PlatformDependent.putByte(address + 2, (byte) value);
|
||||
}
|
||||
PlatformDependent.putShort(address + 1, BIG_ENDIAN_NATIVE_ORDER ? (short) value
|
||||
: Short.reverseBytes((short) value));
|
||||
} else {
|
||||
PlatformDependent.putByte(address, (byte) (value >>> 16));
|
||||
PlatformDependent.putByte(address + 1, (byte) (value >>> 8));
|
||||
PlatformDependent.putByte(address + 2, (byte) value);
|
||||
}
|
||||
@ -154,21 +146,19 @@ final class UnsafeByteBufUtil {
|
||||
return BIG_ENDIAN_NATIVE_ORDER ? v : Short.reverseBytes(v);
|
||||
}
|
||||
return (short) (PlatformDependent.getByte(array, index) << 8 |
|
||||
PlatformDependent.getByte(array, index + 1) & 0xff);
|
||||
PlatformDependent.getByte(array, index + 1) & 0xff);
|
||||
}
|
||||
|
||||
static int getUnsignedMedium(byte[] array, int index) {
|
||||
if (UNALIGNED) {
|
||||
if (BIG_ENDIAN_NATIVE_ORDER) {
|
||||
return (PlatformDependent.getByte(array, index) & 0xff) |
|
||||
(PlatformDependent.getShort(array, index + 1) & 0xffff) << 8;
|
||||
}
|
||||
return (Short.reverseBytes(PlatformDependent.getShort(array, index)) & 0xffff) << 8 |
|
||||
PlatformDependent.getByte(array, index + 2) & 0xff;
|
||||
return (PlatformDependent.getByte(array, index) & 0xff) << 16 |
|
||||
(BIG_ENDIAN_NATIVE_ORDER ? PlatformDependent.getShort(array, index + 1)
|
||||
: Short.reverseBytes(PlatformDependent.getShort(array, index + 1)))
|
||||
& 0xffff;
|
||||
}
|
||||
return (PlatformDependent.getByte(array, index) & 0xff) << 16 |
|
||||
(PlatformDependent.getByte(array, index + 1) & 0xff) << 8 |
|
||||
PlatformDependent.getByte(array, index + 2) & 0xff;
|
||||
return (PlatformDependent.getByte(array, index) & 0xff) << 16 |
|
||||
(PlatformDependent.getByte(array, index + 1) & 0xff) << 8 |
|
||||
PlatformDependent.getByte(array, index + 2) & 0xff;
|
||||
}
|
||||
|
||||
static int getInt(byte[] array, int index) {
|
||||
@ -177,9 +167,9 @@ final class UnsafeByteBufUtil {
|
||||
return BIG_ENDIAN_NATIVE_ORDER ? v : Integer.reverseBytes(v);
|
||||
}
|
||||
return PlatformDependent.getByte(array, index) << 24 |
|
||||
(PlatformDependent.getByte(array, index + 1) & 0xff) << 16 |
|
||||
(PlatformDependent.getByte(array, index + 2) & 0xff) << 8 |
|
||||
PlatformDependent.getByte(array, index + 3) & 0xff;
|
||||
(PlatformDependent.getByte(array, index + 1) & 0xff) << 16 |
|
||||
(PlatformDependent.getByte(array, index + 2) & 0xff) << 8 |
|
||||
PlatformDependent.getByte(array, index + 3) & 0xff;
|
||||
}
|
||||
|
||||
static long getLong(byte[] array, int index) {
|
||||
@ -187,14 +177,14 @@ final class UnsafeByteBufUtil {
|
||||
long v = PlatformDependent.getLong(array, index);
|
||||
return BIG_ENDIAN_NATIVE_ORDER ? v : Long.reverseBytes(v);
|
||||
}
|
||||
return (long) PlatformDependent.getByte(array, index) << 56 |
|
||||
((long) PlatformDependent.getByte(array, index + 1) & 0xff) << 48 |
|
||||
((long) PlatformDependent.getByte(array, index + 2) & 0xff) << 40 |
|
||||
((long) PlatformDependent.getByte(array, index + 3) & 0xff) << 32 |
|
||||
((long) PlatformDependent.getByte(array, index + 4) & 0xff) << 24 |
|
||||
((long) PlatformDependent.getByte(array, index + 5) & 0xff) << 16 |
|
||||
((long) PlatformDependent.getByte(array, index + 6) & 0xff) << 8 |
|
||||
(long) PlatformDependent.getByte(array, index + 7) & 0xff;
|
||||
return ((long) PlatformDependent.getByte(array, index)) << 56 |
|
||||
(PlatformDependent.getByte(array, index + 1) & 0xffL) << 48 |
|
||||
(PlatformDependent.getByte(array, index + 2) & 0xffL) << 40 |
|
||||
(PlatformDependent.getByte(array, index + 3) & 0xffL) << 32 |
|
||||
(PlatformDependent.getByte(array, index + 4) & 0xffL) << 24 |
|
||||
(PlatformDependent.getByte(array, index + 5) & 0xffL) << 16 |
|
||||
(PlatformDependent.getByte(array, index + 6) & 0xffL) << 8 |
|
||||
(PlatformDependent.getByte(array, index + 7)) & 0xffL;
|
||||
}
|
||||
|
||||
static void setByte(byte[] array, int index, int value) {
|
||||
@ -203,31 +193,27 @@ final class UnsafeByteBufUtil {
|
||||
|
||||
static void setShort(byte[] array, int index, int value) {
|
||||
if (UNALIGNED) {
|
||||
PlatformDependent.putShort(
|
||||
array, index, BIG_ENDIAN_NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value));
|
||||
PlatformDependent.putShort(array, index,
|
||||
BIG_ENDIAN_NATIVE_ORDER ? (short) value : Short.reverseBytes((short) value));
|
||||
} else {
|
||||
PlatformDependent.putByte(array, index, (byte) (value >>> 8));
|
||||
PlatformDependent.putByte(array, index + 1, (byte) value);
|
||||
}
|
||||
}
|
||||
|
||||
static void setMedium(byte[] array, int index, int value) {
|
||||
static void setMedium(byte[] array, int index, int value) {
|
||||
PlatformDependent.putByte(array, index, (byte) (value >>> 16));
|
||||
if (UNALIGNED) {
|
||||
if (BIG_ENDIAN_NATIVE_ORDER) {
|
||||
PlatformDependent.putByte(array, index, (byte) value);
|
||||
PlatformDependent.putShort(array, index + 1, (short) (value >>> 8));
|
||||
} else {
|
||||
PlatformDependent.putShort(array, index, Short.reverseBytes((short) (value >>> 8)));
|
||||
PlatformDependent.putByte(array, index + 2, (byte) value);
|
||||
}
|
||||
PlatformDependent.putShort(array, index + 1,
|
||||
BIG_ENDIAN_NATIVE_ORDER ? (short) value
|
||||
: Short.reverseBytes((short) value));
|
||||
} else {
|
||||
PlatformDependent.putByte(array, index, (byte) (value >>> 16));
|
||||
PlatformDependent.putByte(array, index + 1, (byte) (value >>> 8));
|
||||
PlatformDependent.putByte(array, index + 2, (byte) value);
|
||||
}
|
||||
}
|
||||
|
||||
static void setInt(byte[] array, int index, int value) {
|
||||
static void setInt(byte[] array, int index, int value) {
|
||||
if (UNALIGNED) {
|
||||
PlatformDependent.putInt(array, index, BIG_ENDIAN_NATIVE_ORDER ? value : Integer.reverseBytes(value));
|
||||
} else {
|
||||
@ -238,7 +224,7 @@ final class UnsafeByteBufUtil {
|
||||
}
|
||||
}
|
||||
|
||||
static void setLong(byte[] array, int index, long value) {
|
||||
static void setLong(byte[] array, int index, long value) {
|
||||
if (UNALIGNED) {
|
||||
PlatformDependent.putLong(array, index, BIG_ENDIAN_NATIVE_ORDER ? value : Long.reverseBytes(value));
|
||||
} else {
|
||||
|
@ -57,7 +57,6 @@ import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assume.assumeFalse;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
/**
|
||||
@ -67,6 +66,7 @@ public abstract class AbstractByteBufTest {
|
||||
|
||||
private static final int CAPACITY = 4096; // Must be even
|
||||
private static final int BLOCK_SIZE = 128;
|
||||
private static final int JAVA_BYTEBUFFER_CONSISTENCY_ITERATIONS = 100;
|
||||
|
||||
private long seed;
|
||||
private Random random;
|
||||
@ -437,6 +437,38 @@ public abstract class AbstractByteBufTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShortConsistentWithByteBuffer() {
|
||||
testShortConsistentWithByteBuffer(true, true);
|
||||
testShortConsistentWithByteBuffer(true, false);
|
||||
testShortConsistentWithByteBuffer(false, true);
|
||||
testShortConsistentWithByteBuffer(false, false);
|
||||
}
|
||||
|
||||
private void testShortConsistentWithByteBuffer(boolean direct, boolean testBigEndian) {
|
||||
for (int i = 0; i < JAVA_BYTEBUFFER_CONSISTENCY_ITERATIONS; ++i) {
|
||||
ByteBuffer javaBuffer = direct ? ByteBuffer.allocateDirect(buffer.capacity())
|
||||
: ByteBuffer.allocate(buffer.capacity());
|
||||
if (!testBigEndian) {
|
||||
javaBuffer = javaBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
short expected = (short) (random.nextInt() & 0xFFFF);
|
||||
javaBuffer.putShort(expected);
|
||||
|
||||
final int bufferIndex = buffer.capacity() - 2;
|
||||
if (!testBigEndian) {
|
||||
buffer = buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
buffer.setShort(bufferIndex, expected);
|
||||
javaBuffer.flip();
|
||||
|
||||
short javaActual = javaBuffer.getShort();
|
||||
assertEquals(expected, javaActual);
|
||||
assertEquals(javaActual, buffer.getShort(bufferIndex));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRandomUnsignedShortAccess() {
|
||||
for (int i = 0; i < buffer.capacity() - 1; i += 2) {
|
||||
@ -479,6 +511,38 @@ public abstract class AbstractByteBufTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMediumConsistentWithByteBuffer() {
|
||||
testMediumConsistentWithByteBuffer(true, true);
|
||||
testMediumConsistentWithByteBuffer(true, false);
|
||||
testMediumConsistentWithByteBuffer(false, true);
|
||||
testMediumConsistentWithByteBuffer(false, false);
|
||||
}
|
||||
|
||||
private void testMediumConsistentWithByteBuffer(boolean direct, boolean testBigEndian) {
|
||||
for (int i = 0; i < JAVA_BYTEBUFFER_CONSISTENCY_ITERATIONS; ++i) {
|
||||
ByteBuffer javaBuffer = direct ? ByteBuffer.allocateDirect(buffer.capacity())
|
||||
: ByteBuffer.allocate(buffer.capacity());
|
||||
if (!testBigEndian) {
|
||||
javaBuffer = javaBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
int expected = random.nextInt() & 0x00FFFFFF;
|
||||
javaBuffer.putInt(expected);
|
||||
|
||||
final int bufferIndex = buffer.capacity() - 3;
|
||||
if (testBigEndian) {
|
||||
buffer = buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
buffer.setMedium(bufferIndex, expected);
|
||||
javaBuffer.flip();
|
||||
|
||||
int javaActual = javaBuffer.getInt();
|
||||
assertEquals(expected, javaActual);
|
||||
assertEquals(javaActual, buffer.getUnsignedMedium(bufferIndex));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRandomIntAccess() {
|
||||
for (int i = 0; i < buffer.capacity() - 3; i += 4) {
|
||||
@ -493,6 +557,38 @@ public abstract class AbstractByteBufTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntConsistentWithByteBuffer() {
|
||||
testIntConsistentWithByteBuffer(true, true);
|
||||
testIntConsistentWithByteBuffer(true, false);
|
||||
testIntConsistentWithByteBuffer(false, true);
|
||||
testIntConsistentWithByteBuffer(false, false);
|
||||
}
|
||||
|
||||
private void testIntConsistentWithByteBuffer(boolean direct, boolean testBigEndian) {
|
||||
for (int i = 0; i < JAVA_BYTEBUFFER_CONSISTENCY_ITERATIONS; ++i) {
|
||||
ByteBuffer javaBuffer = direct ? ByteBuffer.allocateDirect(buffer.capacity())
|
||||
: ByteBuffer.allocate(buffer.capacity());
|
||||
if (!testBigEndian) {
|
||||
javaBuffer = javaBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
int expected = random.nextInt();
|
||||
javaBuffer.putInt(expected);
|
||||
|
||||
final int bufferIndex = buffer.capacity() - 4;
|
||||
if (testBigEndian) {
|
||||
buffer = buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
buffer.setInt(bufferIndex, expected);
|
||||
javaBuffer.flip();
|
||||
|
||||
int javaActual = javaBuffer.getInt();
|
||||
assertEquals(expected, javaActual);
|
||||
assertEquals(javaActual, buffer.getInt(bufferIndex));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRandomUnsignedIntAccess() {
|
||||
for (int i = 0; i < buffer.capacity() - 3; i += 4) {
|
||||
|
Loading…
Reference in New Issue
Block a user