Support the little endian floats and doubles by ByteBuf

Motivation:
`ByteBuf` does not have the little endian variant of float/double access methods.

Modifications:
Add support for little endian floats and doubles into `ByteBuf`.

Result:
`ByteBuf` has get/read/set/writeFloatLE() and get/read/set/writeDoubleLE() methods. Fixes [#6576].
This commit is contained in:
Nikolay Fedorovskikh 2017-08-13 00:42:44 +05:00 committed by Norman Maurer
parent 4875a2aad4
commit 0774c91456
2 changed files with 168 additions and 6 deletions

View File

@ -757,6 +757,20 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
*/
public abstract float getFloat(int index);
/**
* Gets a 32-bit floating point number at the specified absolute
* {@code index} in this buffer in Little Endian Byte Order.
* This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 4} is greater than {@code this.capacity}
*/
public float getFloatLE(int index) {
return Float.intBitsToFloat(getIntLE(index));
}
/**
* Gets a 64-bit floating point number at the specified absolute
* {@code index} in this buffer. This method does not modify
@ -768,6 +782,20 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
*/
public abstract double getDouble(int index);
/**
* Gets a 64-bit floating point number at the specified absolute
* {@code index} in this buffer in Little Endian Byte Order.
* This method does not modify {@code readerIndex} or
* {@code writerIndex} of this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 8} is greater than {@code this.capacity}
*/
public double getDoubleLE(int index) {
return Double.longBitsToDouble(getLongLE(index));
}
/**
* Transfers this buffer's data to the specified destination starting at
* the specified absolute {@code index} until the destination becomes
@ -1089,6 +1117,20 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
*/
public abstract ByteBuf setFloat(int index, float value);
/**
* Sets the specified 32-bit floating-point number at the specified
* absolute {@code index} in this buffer in Little Endian Byte Order.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 4} is greater than {@code this.capacity}
*/
public ByteBuf setFloatLE(int index, float value) {
return setIntLE(index, Float.floatToRawIntBits(value));
}
/**
* Sets the specified 64-bit floating-point number at the specified
* absolute {@code index} in this buffer.
@ -1101,6 +1143,20 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
*/
public abstract ByteBuf setDouble(int index, double value);
/**
* Sets the specified 64-bit floating-point number at the specified
* absolute {@code index} in this buffer in Little Endian Byte Order.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* {@code index + 8} is greater than {@code this.capacity}
*/
public ByteBuf setDoubleLE(int index, double value) {
return setLongLE(index, Double.doubleToRawLongBits(value));
}
/**
* Transfers the specified source buffer's data to this buffer starting at
* the specified absolute {@code index} until the source buffer becomes
@ -1463,6 +1519,18 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
*/
public abstract float readFloat();
/**
* Gets a 32-bit floating point number at the current {@code readerIndex}
* in Little Endian Byte Order and increases the {@code readerIndex}
* by {@code 4} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 4}
*/
public float readFloatLE() {
return Float.intBitsToFloat(readIntLE());
}
/**
* Gets a 64-bit floating point number at the current {@code readerIndex}
* and increases the {@code readerIndex} by {@code 8} in this buffer.
@ -1472,6 +1540,18 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
*/
public abstract double readDouble();
/**
* Gets a 64-bit floating point number at the current {@code readerIndex}
* in Little Endian Byte Order and increases the {@code readerIndex}
* by {@code 8} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.readableBytes} is less than {@code 8}
*/
public double readDoubleLE() {
return Double.longBitsToDouble(readLongLE());
}
/**
* Transfers this buffer's data to a newly created buffer starting at
* the current {@code readerIndex} and increases the {@code readerIndex}
@ -1794,6 +1874,18 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
*/
public abstract ByteBuf writeFloat(float value);
/**
* Sets the specified 32-bit floating point number at the current
* {@code writerIndex} in Little Endian Byte Order and increases
* the {@code writerIndex} by {@code 4} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.writableBytes} is less than {@code 4}
*/
public ByteBuf writeFloatLE(float value) {
return writeIntLE(Float.floatToRawIntBits(value));
}
/**
* Sets the specified 64-bit floating point number at the current
* {@code writerIndex} and increases the {@code writerIndex} by {@code 8}
@ -1804,6 +1896,18 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
*/
public abstract ByteBuf writeDouble(double value);
/**
* Sets the specified 64-bit floating point number at the current
* {@code writerIndex} in Little Endian Byte Order and increases
* the {@code writerIndex} by {@code 8} in this buffer.
*
* @throws IndexOutOfBoundsException
* if {@code this.writableBytes} is less than {@code 8}
*/
public ByteBuf writeDoubleLE(double value) {
return writeLongLE(Double.doubleToRawLongBits(value));
}
/**
* Transfers the specified source buffer's data to this buffer starting at
* the current {@code writerIndex} until the source buffer becomes

View File

@ -786,29 +786,57 @@ public abstract class AbstractByteBufTest {
@Test
public void testRandomFloatAccess() {
testRandomFloatAccess(true);
}
@Test
public void testRandomFloatLEAccess() {
testRandomFloatAccess(false);
}
private void testRandomFloatAccess(boolean testBigEndian) {
for (int i = 0; i < buffer.capacity() - 7; i += 8) {
float value = random.nextFloat();
buffer.setFloat(i, value);
if (testBigEndian) {
buffer.setFloat(i, value);
} else {
buffer.setFloatLE(i, value);
}
}
random.setSeed(seed);
for (int i = 0; i < buffer.capacity() - 7; i += 8) {
float value = random.nextFloat();
assertEquals(value, buffer.getFloat(i), 0.01);
float expected = random.nextFloat();
float actual = testBigEndian? buffer.getFloat(i) : buffer.getFloatLE(i);
assertEquals(expected, actual, 0.01);
}
}
@Test
public void testRandomDoubleAccess() {
testRandomDoubleAccess(true);
}
@Test
public void testRandomDoubleLEAccess() {
testRandomDoubleAccess(false);
}
private void testRandomDoubleAccess(boolean testBigEndian) {
for (int i = 0; i < buffer.capacity() - 7; i += 8) {
double value = random.nextDouble();
buffer.setDouble(i, value);
if (testBigEndian) {
buffer.setDouble(i, value);
} else {
buffer.setDoubleLE(i, value);
}
}
random.setSeed(seed);
for (int i = 0; i < buffer.capacity() - 7; i += 8) {
double value = random.nextDouble();
assertEquals(value, buffer.getDouble(i), 0.01);
double expected = random.nextDouble();
double actual = testBigEndian? buffer.getDouble(i) : buffer.getDoubleLE(i);
assertEquals(expected, actual, 0.01);
}
}
@ -2615,11 +2643,21 @@ public abstract class AbstractByteBufTest {
releasedBuffer().getFloat(0);
}
@Test(expected = IllegalReferenceCountException.class)
public void testGetFloatLEAfterRelease() {
releasedBuffer().getFloatLE(0);
}
@Test(expected = IllegalReferenceCountException.class)
public void testGetDoubleAfterRelease() {
releasedBuffer().getDouble(0);
}
@Test(expected = IllegalReferenceCountException.class)
public void testGetDoubleLEAfterRelease() {
releasedBuffer().getDoubleLE(0);
}
@Test(expected = IllegalReferenceCountException.class)
public void testGetBytesAfterRelease() {
ByteBuf buffer = buffer(8);
@ -2919,11 +2957,21 @@ public abstract class AbstractByteBufTest {
releasedBuffer().readFloat();
}
@Test(expected = IllegalReferenceCountException.class)
public void testReadFloatLEAfterRelease() {
releasedBuffer().readFloatLE();
}
@Test(expected = IllegalReferenceCountException.class)
public void testReadDoubleAfterRelease() {
releasedBuffer().readDouble();
}
@Test(expected = IllegalReferenceCountException.class)
public void testReadDoubleLEAfterRelease() {
releasedBuffer().readDoubleLE();
}
@Test(expected = IllegalReferenceCountException.class)
public void testReadBytesAfterRelease() {
releasedBuffer().readBytes(1);
@ -3049,11 +3097,21 @@ public abstract class AbstractByteBufTest {
releasedBuffer().writeFloat(1);
}
@Test(expected = IllegalReferenceCountException.class)
public void testWriteFloatLEAfterRelease() {
releasedBuffer().writeFloatLE(1);
}
@Test(expected = IllegalReferenceCountException.class)
public void testWriteDoubleAfterRelease() {
releasedBuffer().writeDouble(1);
}
@Test(expected = IllegalReferenceCountException.class)
public void testWriteDoubleLEAfterRelease() {
releasedBuffer().writeDoubleLE(1);
}
@Test(expected = IllegalReferenceCountException.class)
public void testWriteBytesAfterRelease() {
ByteBuf buffer = buffer(8);