From 814c8f80d51dd3b128fba906bfcb746a697c555f Mon Sep 17 00:00:00 2001 From: Mike Poindexter Date: Mon, 20 Jul 2015 18:09:50 -0700 Subject: [PATCH 1/2] Various fixes to ByteBuffer -Fix exception when put()'ing a zero byte array -Fix getInt() methods returning a short value -Fix relative get() using the index instead of the supplied position -Add long put/get --- .../teavm/classlib/java/nio/TByteBuffer.java | 11 ++ .../classlib/java/nio/TByteBufferImpl.java | 118 ++++++++++++++++-- 2 files changed, 121 insertions(+), 8 deletions(-) diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TByteBuffer.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TByteBuffer.java index ddadfb53a..a7338fef4 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TByteBuffer.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TByteBuffer.java @@ -86,6 +86,9 @@ public abstract class TByteBuffer extends TBuffer implements TComparable= limit) { throw new IndexOutOfBoundsException("Index " + index + " is outside of range [0;" + (limit - 3) + ")"); } - int a = array[start + position] & 0xFF; - int b = array[start + position + 1] & 0xFF; - int c = array[start + position + 2] & 0xFF; - int d = array[start + position + 3] & 0xFF; + int a = array[start + index] & 0xFF; + int b = array[start + index + 1] & 0xFF; + int c = array[start + index + 2] & 0xFF; + int d = array[start + index + 3] & 0xFF; if (order == TByteOrder.BIG_ENDIAN) { - return (short)((a << 24) | (b << 16) | (c << 8) | d); + return (int)((a << 24) | (b << 16) | (c << 8) | d); } else { - return (short)((d << 24) | (c << 16) | (b << 8) | a); + return (int)((d << 24) | (c << 16) | (b << 8) | a); } } @@ -340,6 +340,108 @@ class TByteBufferImpl extends TByteBuffer { } } + @Override + public long getLong() { + if (position + 7 >= limit) { + throw new TBufferUnderflowException(); + } + long a = array[start + position] & 0xFF; + long b = array[start + position + 1] & 0xFF; + long c = array[start + position + 2] & 0xFF; + long d = array[start + position + 3] & 0xFF; + long e = array[start + position + 4] & 0xFF; + long f = array[start + position + 5] & 0xFF; + long g = array[start + position + 6] & 0xFF; + long h = array[start + position + 7] & 0xFF; + position += 8; + if (order == TByteOrder.BIG_ENDIAN) { + return (long)((a << 56) | (b << 48) | (c << 40) | (d << 32) | (e << 24) | (f << 16) | (g << 8) | h); + } else { + return (long)((h << 56) | (g << 48) | (f << 40) | (e << 32) | (d << 24) | (c << 16) | (b << 8) | a); + } + } + + @Override + public TByteBuffer putLong(long value) { + if (readOnly) { + throw new TReadOnlyBufferException(); + } + if (position + 7 >= limit) { + throw new TBufferOverflowException(); + } + if (order == TByteOrder.BIG_ENDIAN) { + array[start + position++] = (byte)(value >> 56); + array[start + position++] = (byte)(value >> 48); + array[start + position++] = (byte)(value >> 40); + array[start + position++] = (byte)(value >> 32); + array[start + position++] = (byte)(value >> 24); + array[start + position++] = (byte)(value >> 16); + array[start + position++] = (byte)(value >> 8); + array[start + position++] = (byte)value; + } else { + array[start + position++] = (byte)value; + array[start + position++] = (byte)(value >> 8); + array[start + position++] = (byte)(value >> 16); + array[start + position++] = (byte)(value >> 24); + array[start + position++] = (byte)(value >> 32); + array[start + position++] = (byte)(value >> 40); + array[start + position++] = (byte)(value >> 48); + array[start + position++] = (byte)(value >> 56); + } + return this; + } + + @Override + public long getLong(int index) { + if (index < 0 || index + 7 >= limit) { + throw new IndexOutOfBoundsException("Index " + index + " is outside of range [0;" + (limit - 7) + ")"); + } + long a = array[start + index] & 0xFF; + long b = array[start + index + 1] & 0xFF; + long c = array[start + index + 2] & 0xFF; + long d = array[start + index + 3] & 0xFF; + long e = array[start + index + 4] & 0xFF; + long f = array[start + index + 5] & 0xFF; + long g = array[start + index + 6] & 0xFF; + long h = array[start + index + 7] & 0xFF; + position += 8; + if (order == TByteOrder.BIG_ENDIAN) { + return (long)((a << 56) | (b << 48) | (c << 40) | (d << 32) | (e << 24) | (f << 16) | (g << 8) | h); + } else { + return (long)((h << 56) | (g << 48) | (f << 40) | (e << 32) | (d << 24) | (c << 16) | (b << 8) | a); + } + } + + @Override + public TByteBuffer putLong(int index, long value) { + if (readOnly) { + throw new TReadOnlyBufferException(); + } + if (index < 0 || index + 3 >= limit) { + throw new IndexOutOfBoundsException("Index " + index + " is outside of range [0;" + (limit - 3) + ")"); + } + if (order == TByteOrder.BIG_ENDIAN) { + array[start + index + 0] = (byte)(value >> 56); + array[start + index + 1] = (byte)(value >> 48); + array[start + index + 2] = (byte)(value >> 40); + array[start + index + 3] = (byte)(value >> 32); + array[start + index + 4] = (byte)(value >> 24); + array[start + index + 5] = (byte)(value >> 16); + array[start + index + 6] = (byte)(value >> 8); + array[start + index + 7] = (byte)value; + } else { + array[start + index + 0] = (byte)value; + array[start + index + 1] = (byte)(value >> 8); + array[start + index + 2] = (byte)(value >> 16); + array[start + index + 3] = (byte)(value >> 24); + array[start + index + 4] = (byte)(value >> 24); + array[start + index + 5] = (byte)(value >> 24); + array[start + index + 6] = (byte)(value >> 24); + array[start + index + 7] = (byte)(value >> 24); + } + return this; + } + @Override public TLongBuffer asLongBuffer() { int sz = remaining() / 8; From cdedbd0de5a7af00c99843c3179972d45a56ef17 Mon Sep 17 00:00:00 2001 From: Mike Poindexter Date: Mon, 20 Jul 2015 23:33:59 -0700 Subject: [PATCH 2/2] Add tests --- .../classlib/java/nio/ByteBufferTest.java | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/teavm-tests/src/test/java/org/teavm/classlib/java/nio/ByteBufferTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/nio/ByteBufferTest.java index 846351a7b..41572cc87 100644 --- a/teavm-tests/src/test/java/org/teavm/classlib/java/nio/ByteBufferTest.java +++ b/teavm-tests/src/test/java/org/teavm/classlib/java/nio/ByteBufferTest.java @@ -345,6 +345,17 @@ public class ByteBufferTest { assertThat(array, is(new byte[] {0, 2, 3, 0 })); } + @Test + public void putsBytesWithZeroLengthArray() { + byte[] array = new byte[4]; + ByteBuffer buffer = ByteBuffer.wrap(array); + buffer.get(); + byte[] data = { }; + buffer.put(data, 0, 0); + assertThat(buffer.position(), is(1)); + assertThat(array, is(new byte[] {0, 0, 0, 0 })); + } + @Test public void compacts() { byte[] array = { 2, 3, 5, 7 }; @@ -498,4 +509,99 @@ public class ByteBufferTest { // expected } } + + @Test + public void getsInt() { + byte[] array = { 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30 }; + ByteBuffer buffer = ByteBuffer.wrap(array); + assertThat(buffer.getInt(), is(0x23242526)); + assertThat(buffer.getInt(), is(0x27282930)); + try { + buffer.getInt(); + fail("Exception expected"); + } catch (BufferUnderflowException e) { + // expected + } + buffer.position(7); + try { + buffer.getInt(); + fail("Exception expected"); + } catch (BufferUnderflowException e) { + // expected + } + assertThat(buffer.getInt(0), is(0x23242526)); + assertThat(buffer.getInt(4), is(0x27282930)); + try { + buffer.getInt(7); + fail("Exception expected"); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + @Test + public void getsLong() { + byte[] array = { 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 }; + ByteBuffer buffer = ByteBuffer.wrap(array); + assertThat(buffer.getLong(), is(0x2324252627282930L)); + assertThat(buffer.getLong(), is(0x3132333435363738L)); + try { + buffer.getLong(); + fail("Exception expected"); + } catch (BufferUnderflowException e) { + // expected + } + buffer.position(15); + try { + buffer.getLong(); + fail("Exception expected"); + } catch (BufferUnderflowException e) { + // expected + } + assertThat(buffer.getLong(0), is(0x2324252627282930L)); + assertThat(buffer.getLong(8), is(0x3132333435363738L)); + try { + buffer.getLong(16); + fail("Exception expected"); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + @Test + public void putsLong() { + byte[] array = new byte[16]; + ByteBuffer buffer = ByteBuffer.wrap(array); + buffer.putLong(0x2324252627282930L); + buffer.putLong(0x3132333435363738L); + try { + buffer.putLong(0L); + fail("Exception expected"); + } catch (BufferOverflowException e) { + // expected + } + buffer.position(15); + try { + buffer.putLong(0L); + fail("Exception expected"); + } catch (BufferOverflowException e) { + // expected + } + assertThat(buffer.get(0), is((byte)0x23)); + assertThat(buffer.get(1), is((byte)0x24)); + assertThat(buffer.get(2), is((byte)0x25)); + assertThat(buffer.get(3), is((byte)0x26)); + assertThat(buffer.get(4), is((byte)0x27)); + assertThat(buffer.get(5), is((byte)0x28)); + assertThat(buffer.get(6), is((byte)0x29)); + assertThat(buffer.get(7), is((byte)0x30)); + buffer.putLong(0, 0xAABBCCDDEEFF0000L); + assertThat(buffer.get(1), is((byte)0xBB)); + try { + buffer.putLong(15, 0x0L); + fail("Exception expected"); + } catch (IndexOutOfBoundsException e) { + // expected + } + } }