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 0a040d7cb..8e629405e 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 @@ -199,6 +199,14 @@ public abstract class TByteBuffer extends TBuffer implements TComparable= limit) { + throw new TBufferUnderflowException(); + } + int a = array[start + position] & 0xFF; + int b = array[start + position + 1] & 0xFF; + position += 2; + if (order == TByteOrder.BIG_ENDIAN) { + return (char)(a << 8 | b); + } else { + return (char)(b << 8 | a); + } + } + + @Override + public TByteBuffer putChar(char value) { + if (readOnly) { + throw new TReadOnlyBufferException(); + } + if (position + 1 >= limit) { + throw new TBufferOverflowException(); + } + if (order == TByteOrder.BIG_ENDIAN) { + array[start + position++] = (byte)(value >> 8); + array[start + position++] = (byte)value; + } else { + array[start + position++] = (byte)value; + array[start + position++] = (byte)(value >> 8); + } + return this; + } + + @Override + public char getChar(int index) { + if (index < 0 || index + 1 >= limit) { + throw new IndexOutOfBoundsException("Index " + index + " is outside of range [0;" + (limit - 1) + ")"); + } + int a = array[start + index] & 0xFF; + int b = array[start + index + 1] & 0xFF; + if (order == TByteOrder.BIG_ENDIAN) { + return (char)(a << 8 | b); + } else { + return (char)(b << 8 | a); + } + } + + @Override + public TByteBuffer putChar(int index, char value) { + if (readOnly) { + throw new TReadOnlyBufferException(); + } + if (index < 0 || index + 1 >= limit) { + throw new IndexOutOfBoundsException("Index " + index + " is outside of range [0;" + (limit - 1) + ")"); + } + if (order == TByteOrder.BIG_ENDIAN) { + array[start + index] = (byte)(value >> 8); + array[start + index + 1] = (byte)value; + } else { + array[start + index] = (byte)value; + array[start + index + 1] = (byte)(value >> 8); + } + return this; + } + @Override public TCharBuffer asCharBuffer() { int sz = remaining() / 2; @@ -147,4 +212,13 @@ class TByteBufferImpl extends TByteBuffer { result.byteOrder = order; return result; } + + @Override + public TDoubleBuffer asDoubleBuffer() { + int sz = remaining() / 8; + TDoubleBufferOverByteBuffer result = new TDoubleBufferOverByteBuffer(start + position, sz, this, 0, sz, + isReadOnly()); + result.byteOrder = order; + return result; + } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TCharBufferOverByteBuffer.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TCharBufferOverByteBuffer.java index 4a8747ac8..695c44980 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TCharBufferOverByteBuffer.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TCharBufferOverByteBuffer.java @@ -45,9 +45,11 @@ class TCharBufferOverByteBuffer extends TCharBufferImpl { char getChar(int index) { int value; if (byteOrder == TByteOrder.BIG_ENDIAN) { - value = (byteByffer.array[start + index * 2] << 8) | (byteByffer.array[start + index * 2 + 1]); + value = ((byteByffer.array[start + index * 2] & 0xFF) << 8) | + (byteByffer.array[start + index * 2 + 1] & 0xFF); } else { - value = (byteByffer.array[start + index * 2 + 1] << 8) | (byteByffer.array[start + index * 2]); + value = ((byteByffer.array[start + index * 2 + 1] & 0xFF) << 8) | + (byteByffer.array[start + index * 2] & 0xFF); } return (char)value; } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TDoubleBuffer.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TDoubleBuffer.java index ff5c81074..9a22a30df 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TDoubleBuffer.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TDoubleBuffer.java @@ -20,13 +20,8 @@ package org.teavm.classlib.java.nio; * @author Alexey Andreev */ public abstract class TDoubleBuffer extends TBuffer implements Comparable { - int start; - double[] array; - - TDoubleBuffer(int start, int capacity, double[] array, int position, int limit) { + TDoubleBuffer(int capacity, int position, int limit) { super(capacity); - this.start = start; - this.array = array; this.position = position; this.limit = limit; } @@ -35,11 +30,11 @@ public abstract class TDoubleBuffer extends TBuffer implements Comparable= dst.length) { throw new IndexOutOfBoundsException("Offset " + offset + " is outside of range [0;" + dst.length + ")"); @@ -74,9 +73,9 @@ public abstract class TDoubleBuffer extends TBuffer implements Comparable>> 32); + long elem = Double.doubleToLongBits(getElement(pos++)); + hashCode = 31 * hashCode + (int)elem + (int)(elem >>> 32); } return hashCode; } @@ -169,10 +187,10 @@ public abstract class TDoubleBuffer extends TBuffer implements Comparable */ -class TDoubleBufferImpl extends TDoubleBuffer { - private boolean readOnly; - - public TDoubleBufferImpl(int capacity) { - this(0, capacity, new double[capacity], 0, capacity, false); - } - - public TDoubleBufferImpl(int start, int capacity, double[] array, int position, int limit, boolean readOnly) { - super(start, capacity, array, position, limit); - this.readOnly = readOnly; +abstract class TDoubleBufferImpl extends TDoubleBuffer { + public TDoubleBufferImpl(int capacity, int position, int limit) { + super(capacity, position, limit); } @Override public TDoubleBuffer slice() { - return new TDoubleBufferImpl(position, limit - position, array, 0, limit - position, readOnly); + return duplicate(position, limit - position, 0, limit - position, isReadOnly()); } @Override public TDoubleBuffer duplicate() { - return new TDoubleBufferImpl(start, capacity, array, position, limit, readOnly); + return duplicate(0, capacity, position, limit, isReadOnly()); } @Override public TDoubleBuffer asReadOnlyBuffer() { - return new TDoubleBufferImpl(start, capacity, array, position, limit, true); + return duplicate(0, capacity, position, limit, true); } + abstract TDoubleBuffer duplicate(int start, int capacity, int position, int limit, boolean readOnly); + @Override public double get() { if (position >= limit) { throw new TBufferUnderflowException(); } - return array[start + position++]; + return getElement(position++); } @Override public TDoubleBuffer put(double b) { - if (readOnly) { + if (isReadOnly()) { throw new TReadOnlyBufferException(); } if (position >= limit) { throw new TBufferOverflowException(); } - array[start + position++] = b; + putElement(position++, b); return this; } @@ -71,32 +66,31 @@ class TDoubleBufferImpl extends TDoubleBuffer { if (index < 0 || index >= limit) { throw new IndexOutOfBoundsException("Index " + index + " is outside of range [0;" + limit + ")"); } - return array[start + index]; + return getElement(index); } @Override public TDoubleBuffer put(int index, double b) { - if (readOnly) { + if (isReadOnly()) { throw new TReadOnlyBufferException(); } if (index < 0 || index >= limit) { throw new IndexOutOfBoundsException("Index " + index + " is outside of range [0;" + limit + ")"); } - array[start + index] = b; + putElement(index, b); return this; } @Override public TDoubleBuffer compact() { - if (readOnly) { + if (isReadOnly()) { throw new TReadOnlyBufferException(); } if (position > 0) { int sz = remaining(); - int dst = start; - int src = start + position; + int src = position; for (int i = 0; i < sz; ++i) { - array[dst++] = array[src++]; + putElement(i, getElement(src++)); } position = sz; } @@ -112,6 +106,8 @@ class TDoubleBufferImpl extends TDoubleBuffer { @Override public boolean isReadOnly() { - return readOnly; + return readOnly(); } + + abstract boolean readOnly(); } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TDoubleBufferOverArray.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TDoubleBufferOverArray.java new file mode 100644 index 000000000..95acba240 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TDoubleBufferOverArray.java @@ -0,0 +1,77 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.nio; + +/** + * + * @author Alexey Andreev + */ +class TDoubleBufferOverArray extends TDoubleBufferImpl { + boolean readOnly; + int start; + double[] array; + + public TDoubleBufferOverArray(int capacity) { + this(0, capacity, new double[capacity], 0, capacity, false); + } + + public TDoubleBufferOverArray(int start, int capacity, double[] array, int position, int limit, boolean readOnly) { + super(capacity, position, limit); + this.start = start; + this.readOnly = readOnly; + this.array = array; + } + + @Override + TDoubleBuffer duplicate(int start, int capacity, int position, int limit, boolean readOnly) { + return new TDoubleBufferOverArray(this.start + start, capacity, array, position, limit, readOnly); + } + + @Override + double getElement(int index) { + return array[index + start]; + } + + @Override + void putElement(int index, double value) { + array[index + start] = value; + } + + @Override + boolean isArrayPresent() { + return true; + } + + @Override + double[] getArray() { + return array; + } + + @Override + int getArrayOffset() { + return start; + } + + @Override + boolean readOnly() { + return readOnly; + } + + @Override + public TByteOrder order() { + return TByteOrder.BIG_ENDIAN; + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TDoubleBufferOverByteBuffer.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TDoubleBufferOverByteBuffer.java new file mode 100644 index 000000000..2d78c4f79 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TDoubleBufferOverByteBuffer.java @@ -0,0 +1,117 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.nio; + +/** + * + * @author Alexey Andreev + */ +class TDoubleBufferOverByteBuffer extends TDoubleBufferImpl { + private TByteBufferImpl byteByffer; + TByteOrder byteOrder = TByteOrder.BIG_ENDIAN; + boolean readOnly; + private int start; + + public TDoubleBufferOverByteBuffer(int start, int capacity, TByteBufferImpl byteBuffer, int position, int limit, + boolean readOnly) { + super(capacity, position, limit); + this.start = start; + this.byteByffer = byteBuffer; + this.readOnly = readOnly; + } + + @Override + TDoubleBuffer duplicate(int start, int capacity, int position, int limit, boolean readOnly) { + TDoubleBufferOverByteBuffer result = new TDoubleBufferOverByteBuffer(this.start + start * 2, capacity, + byteByffer, position, limit, readOnly); + result.byteOrder = byteOrder; + return result; + } + + @Override + double getElement(int index) { + long value; + if (byteOrder == TByteOrder.BIG_ENDIAN) { + value = (((long)byteByffer.array[start + index * 8] & 0xFF) << 56) | + (((long)byteByffer.array[start + index * 8 + 1] & 0xFF) << 48) | + (((long)byteByffer.array[start + index * 8 + 2] & 0xFF) << 40) | + (((long)byteByffer.array[start + index * 8 + 3] & 0xFF) << 32) | + (((long)byteByffer.array[start + index * 8 + 4] & 0xFF) << 24) | + (((long)byteByffer.array[start + index * 8 + 5] & 0xFF) << 16) | + (((long)byteByffer.array[start + index * 8 + 6] & 0xFF) << 8) | + (byteByffer.array[start + index * 8 + 7] & 0xFF); + } else { + value = (byteByffer.array[start + index * 8] & 0xFF) | + (((long)byteByffer.array[start + index * 8 + 1] & 0xFF) << 8) | + (((long)byteByffer.array[start + index * 8 + 2] & 0xFF) << 16) | + (((long)byteByffer.array[start + index * 8 + 3] & 0xFF) << 24) | + (((long)byteByffer.array[start + index * 8 + 4] & 0xFF) << 32) | + (((long)byteByffer.array[start + index * 8 + 5] & 0xFF) << 40) | + (((long)byteByffer.array[start + index * 8 + 6] & 0xFF) << 48) | + (((long)byteByffer.array[start + index * 8 + 7] & 0xFF) << 56); + } + return Double.longBitsToDouble(value); + } + + @Override + void putElement(int index, double d) { + long value = Double.doubleToLongBits(d); + if (byteOrder == TByteOrder.BIG_ENDIAN) { + byteByffer.array[start + index * 8] = (byte)(value >> 56); + byteByffer.array[start + index * 8 + 1] = (byte)(value >> 48); + byteByffer.array[start + index * 8 + 2] = (byte)(value >> 40); + byteByffer.array[start + index * 8 + 3] = (byte)(value >> 32); + byteByffer.array[start + index * 8 + 4] = (byte)(value >> 24); + byteByffer.array[start + index * 8 + 5] = (byte)(value >> 16); + byteByffer.array[start + index * 8 + 6] = (byte)(value >> 8); + byteByffer.array[start + index * 8 + 7] = (byte)value; + } else { + byteByffer.array[start + index * 8] = (byte)value; + byteByffer.array[start + index * 8 + 1] = (byte)(value >> 8); + byteByffer.array[start + index * 8 + 2] = (byte)(value >> 16); + byteByffer.array[start + index * 8 + 3] = (byte)(value >> 24); + byteByffer.array[start + index * 8 + 4] = (byte)(value >> 32); + byteByffer.array[start + index * 8 + 5] = (byte)(value >> 40); + byteByffer.array[start + index * 8 + 6] = (byte)(value >> 48); + byteByffer.array[start + index * 8 + 7] = (byte)(value >> 56); + } + } + + @Override + boolean isArrayPresent() { + return false; + } + + @Override + double[] getArray() { + throw new UnsupportedOperationException(); + } + + @Override + int getArrayOffset() { + throw new UnsupportedOperationException(); + } + + @Override + boolean readOnly() { + return readOnly; + } + + @Override + public TByteOrder order() { + return byteOrder; + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TFloatBufferOverByteBuffer.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TFloatBufferOverByteBuffer.java index 18ce83ef9..d46635e51 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TFloatBufferOverByteBuffer.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TFloatBufferOverByteBuffer.java @@ -45,15 +45,15 @@ class TFloatBufferOverByteBuffer extends TFloatBufferImpl { float getElement(int index) { int value; if (byteOrder == TByteOrder.BIG_ENDIAN) { - value = (byteByffer.array[start + index * 4] << 24) | - (byteByffer.array[start + index * 4 + 1] << 16) | - (byteByffer.array[start + index * 4 + 2] << 8) | - (byteByffer.array[start + index * 4 + 3]); + value = ((byteByffer.array[start + index * 4] & 0xFF) << 24) | + ((byteByffer.array[start + index * 4 + 1] & 0xFF) << 16) | + ((byteByffer.array[start + index * 4 + 2] & 0xFF) << 8) | + (byteByffer.array[start + index * 4 + 3] & 0xFF); } else { - value = (byteByffer.array[start + index * 4]) | - (byteByffer.array[start + index * 4 + 1] << 8) | - (byteByffer.array[start + index * 4 + 2] << 16) | - (byteByffer.array[start + index * 4 + 3] << 24); + value = (byteByffer.array[start + index * 4] & 0xFF) | + ((byteByffer.array[start + index * 4 + 1] & 0xFF) << 8) | + ((byteByffer.array[start + index * 4 + 2] & 0xFF) << 16) | + ((byteByffer.array[start + index * 4 + 3] & 0xFF) << 24); } return Float.intBitsToFloat(value); } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TIntBufferOverByteBuffer.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TIntBufferOverByteBuffer.java index 1c8f82835..733d89068 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TIntBufferOverByteBuffer.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TIntBufferOverByteBuffer.java @@ -45,15 +45,15 @@ public class TIntBufferOverByteBuffer extends TIntBufferImpl { int getElement(int index) { int value; if (byteOrder == TByteOrder.BIG_ENDIAN) { - value = (byteByffer.array[start + index * 4] << 24) | - (byteByffer.array[start + index * 4 + 1] << 16) | - (byteByffer.array[start + index * 4 + 2] << 8) | - (byteByffer.array[start + index * 4 + 3]); + value = ((byteByffer.array[start + index * 4] & 0xFF) << 24) | + ((byteByffer.array[start + index * 4 + 1] & 0xFF) << 16) | + ((byteByffer.array[start + index * 4 + 2] & 0xFF) << 8) | + (byteByffer.array[start + index * 4 + 3] & 0xFF); } else { - value = (byteByffer.array[start + index * 4]) | - (byteByffer.array[start + index * 4 + 1] << 8) | - (byteByffer.array[start + index * 4 + 2] << 16) | - (byteByffer.array[start + index * 4 + 3] << 24); + value = (byteByffer.array[start + index * 4] & 0xFF) | + ((byteByffer.array[start + index * 4 + 1] & 0xFF) << 8) | + ((byteByffer.array[start + index * 4 + 2] & 0xFF) << 16) | + ((byteByffer.array[start + index * 4 + 3] & 0xFF) << 24); } return value; } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TLongBufferOverByteBuffer.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TLongBufferOverByteBuffer.java index 53410ce75..eedc34c66 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TLongBufferOverByteBuffer.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TLongBufferOverByteBuffer.java @@ -45,23 +45,23 @@ class TLongBufferOverByteBuffer extends TLongBufferImpl { long getElement(int index) { long value; if (byteOrder == TByteOrder.BIG_ENDIAN) { - value = ((long)byteByffer.array[start + index * 8] << 56) | - ((long)byteByffer.array[start + index * 8 + 1] << 48) | - ((long)byteByffer.array[start + index * 8 + 2] << 40) | - ((long)byteByffer.array[start + index * 8 + 3] << 32) | - ((long)byteByffer.array[start + index * 8 + 4] << 24) | - ((long)byteByffer.array[start + index * 8 + 5] << 16) | - ((long)byteByffer.array[start + index * 8 + 6] << 8) | - byteByffer.array[start + index * 8 + 7]; + value = (((long)byteByffer.array[start + index * 8] & 0xFF) << 56) | + (((long)byteByffer.array[start + index * 8 + 1] & 0xFF) << 48) | + (((long)byteByffer.array[start + index * 8 + 2] & 0xFF) << 40) | + (((long)byteByffer.array[start + index * 8 + 3] & 0xFF) << 32) | + (((long)byteByffer.array[start + index * 8 + 4] & 0xFF) << 24) | + (((long)byteByffer.array[start + index * 8 + 5] & 0xFF) << 16) | + (((long)byteByffer.array[start + index * 8 + 6] & 0xFF) << 8) | + (byteByffer.array[start + index * 8 + 7] & 0xFF); } else { - value = byteByffer.array[start + index * 8] | - ((long)byteByffer.array[start + index * 8 + 1] << 8) | - ((long)byteByffer.array[start + index * 8 + 2] << 16) | - ((long)byteByffer.array[start + index * 8 + 3] << 24) | - ((long)byteByffer.array[start + index * 8 + 4] << 32) | - ((long)byteByffer.array[start + index * 8 + 5] << 40) | - ((long)byteByffer.array[start + index * 8 + 6] << 48) | - ((long)byteByffer.array[start + index * 8 + 7] << 56); + value = (byteByffer.array[start + index * 8] & 0xFF) | + (((long)byteByffer.array[start + index * 8 + 1] & 0xFF) << 8) | + (((long)byteByffer.array[start + index * 8 + 2] & 0xFF) << 16) | + (((long)byteByffer.array[start + index * 8 + 3] & 0xFF) << 24) | + (((long)byteByffer.array[start + index * 8 + 4] & 0xFF) << 32) | + (((long)byteByffer.array[start + index * 8 + 5] & 0xFF) << 40) | + (((long)byteByffer.array[start + index * 8 + 6] & 0xFF) << 48) | + (((long)byteByffer.array[start + index * 8 + 7] & 0xFF) << 56); } return value; } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TShortBufferOverByteBuffer.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TShortBufferOverByteBuffer.java index f5c1e3020..516e1ceb8 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TShortBufferOverByteBuffer.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/nio/TShortBufferOverByteBuffer.java @@ -45,9 +45,11 @@ class TShortBufferOverByteBuffer extends TShortBufferImpl { short getElement(int index) { int value; if (byteOrder == TByteOrder.BIG_ENDIAN) { - value = (byteByffer.array[start + index * 2] << 8) | (byteByffer.array[start + index * 2 + 1]); + value = ((byteByffer.array[start + index * 2] & 0xFF) << 8) | + (byteByffer.array[start + index * 2 + 1] & 0xFF); } else { - value = (byteByffer.array[start + index * 2 + 1] << 8) | (byteByffer.array[start + index * 2]); + value = ((byteByffer.array[start + index * 2 + 1] & 0xFF) << 8) | + (byteByffer.array[start + index * 2] & 0xFF); } return (short)value; }