package com.oracle.truffle.js.runtime.array;
import static com.oracle.truffle.js.runtime.builtins.JSArrayBufferView.typedArrayGetByteArray;
import static com.oracle.truffle.js.runtime.builtins.JSArrayBufferView.typedArrayGetByteBuffer;
import static com.oracle.truffle.js.runtime.builtins.JSArrayBufferView.typedArrayGetLength;
import static com.oracle.truffle.js.runtime.builtins.JSArrayBufferView.typedArrayGetOffset;
import java.nio.ByteBuffer;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.js.runtime.BigInt;
import com.oracle.truffle.js.runtime.Errors;
import com.oracle.truffle.js.runtime.JSContext;
import com.oracle.truffle.js.runtime.JSRuntime;
import com.oracle.truffle.js.runtime.builtins.JSArrayBuffer;
import com.oracle.truffle.js.runtime.objects.Undefined;
public abstract class TypedArray extends ScriptArray {
private final boolean offset;
private final int bytesPerElement;
private final String name;
private final TypedArrayFactory factory;
protected TypedArray(TypedArrayFactory factory, boolean offset) {
this.offset = offset;
this.bytesPerElement = factory.getBytesPerElement();
this.name = factory.getName();
this.factory = factory;
}
@Override
public final long length(DynamicObject object) {
return lengthInt(object);
}
@Override
public final int lengthInt(DynamicObject object) {
return typedArrayGetLength(object);
}
@Override
public final TypedArray setLengthImpl(DynamicObject object, long len, ProfileHolder profile) {
return this;
}
@Override
public final long firstElementIndex(DynamicObject object) {
return 0;
}
@Override
public final long lastElementIndex(DynamicObject object) {
return length(object) - 1;
}
@Override
public final long nextElementIndex(DynamicObject object, long index) {
return index + 1;
}
@Override
public final long previousElementIndex(DynamicObject object, long index) {
return index - 1;
}
@Override
public final Object[] toArray(DynamicObject object) {
int length = lengthInt(object);
Object[] result = new Object[length];
for (int i = 0; i < length; i++) {
result[i] = getElement(object, i);
}
return result;
}
@Override
public final ScriptArray deleteElementImpl(DynamicObject object, long index, boolean strict) {
return this;
}
@Override
public final boolean hasElement(DynamicObject object, long index) {
return 0 <= index && index < length(object);
}
protected static byte[] getByteArray(DynamicObject object) {
return typedArrayGetByteArray(object);
}
protected static ByteBuffer getByteBuffer(DynamicObject object) {
return typedArrayGetByteBuffer(object);
}
public final Object getBufferFromTypedArray(DynamicObject object) {
return isDirect() ? getByteBuffer(object) : getByteArray(object);
}
protected final int getOffset(DynamicObject object) {
if (offset) {
return typedArrayGetOffset(object);
} else {
return 0;
}
}
public final TypedArrayFactory getFactory() {
return factory;
}
public final int bytesPerElement() {
return bytesPerElement;
}
public final String getName() {
return name;
}
@Override
public boolean isHolesType() {
return false;
}
@Override
public boolean hasHoles(DynamicObject object) {
return false;
}
@Override
public ScriptArray removeRangeImpl(DynamicObject object, long start, long end) {
throw Errors.unsupported("cannot removeRange() on TypedArray");
}
@Override
public ScriptArray addRangeImpl(DynamicObject object, long atOffset, int size) {
throw Errors.unsupported("cannot addRange() on TypedArray");
}
@Override
public boolean isSealed() {
return false;
}
@Override
public boolean isFrozen() {
return false;
}
@Override
public boolean isLengthNotWritable() {
return false;
}
@Override
public ScriptArray seal() {
return this;
}
@Override
public ScriptArray freeze() {
return this;
}
@Override
public ScriptArray setLengthNotWritable() {
return this;
}
@Override
public ScriptArray preventExtensions() {
return this;
}
@Override
public final boolean isStatelessType() {
return true;
}
public boolean isDirect() {
return false;
}
public final boolean hasOffset() {
return offset;
}
public abstract Object getBufferElement(DynamicObject buffer, int index, boolean littleEndian);
public abstract void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value);
public static TypedArrayFactory[] factories(JSContext context) {
if (context.getContextOptions().isBigInt()) {
return TypedArrayFactory.FACTORIES;
} else {
return TypedArrayFactory.getNoBigIntFactories();
}
}
public abstract static class TypedIntArray<T> extends TypedArray {
protected TypedIntArray(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public Object getElement(DynamicObject object, long index) {
if (hasElement(object, index)) {
return getInt(object, (int) index);
} else {
return Undefined.instance;
}
}
@Override
public Object getElementInBounds(DynamicObject object, long index) {
assert hasElement(object, index);
return getInt(object, (int) index);
}
@Override
public TypedIntArray<T> setElementImpl(DynamicObject object, long index, Object value, boolean strict) {
if (hasElement(object, index)) {
setInt(object, (int) index, JSRuntime.toInt32(value));
}
return this;
}
public final int getInt(DynamicObject object, int index) {
return getIntImpl(getBufferFromTypedArrayT(object), getOffset(object), index);
}
public final void setInt(DynamicObject object, int index, int value) {
setIntImpl(getBufferFromTypedArrayT(object), getOffset(object), index, value);
}
@SuppressWarnings("unchecked")
private T getBufferFromTypedArrayT(DynamicObject object) {
return (T) super.getBufferFromTypedArray(object);
}
public abstract int getIntImpl(T buffer, int offset, int index);
public abstract void setIntImpl(T buffer, int offset, int index, int value);
}
static final int INT8_BYTES_PER_ELEMENT = 1;
public static final class Int8Array extends TypedIntArray<byte[]> {
Int8Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public int getIntImpl(byte[] array, int offset, int index) {
return ByteArrayAccess.nativeOrder().getInt8(array, offset + index * INT8_BYTES_PER_ELEMENT);
}
@Override
public void setIntImpl(byte[] array, int offset, int index, int value) {
ByteArrayAccess.nativeOrder().putInt8(array, offset + index * INT8_BYTES_PER_ELEMENT, value);
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return ByteArrayAccess.forOrder(littleEndian).getInt8(JSArrayBuffer.getByteArray(buffer), index);
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteArrayAccess.forOrder(littleEndian).putInt8(JSArrayBuffer.getByteArray(buffer), index, JSRuntime.toInt32((Number) value));
}
}
public static final class DirectInt8Array extends TypedIntArray<ByteBuffer> {
DirectInt8Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public int getIntImpl(ByteBuffer buffer, int offset, int index) {
return buffer.get(offset + index * INT8_BYTES_PER_ELEMENT);
}
@Override
public void setIntImpl(ByteBuffer buffer, int offset, int index, int value) {
buffer.put(offset + index * INT8_BYTES_PER_ELEMENT, (byte) value);
}
@Override
public boolean isDirect() {
return true;
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return (int) JSArrayBuffer.getDirectByteBuffer(buffer).get(index);
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
JSArrayBuffer.getDirectByteBuffer(buffer).put(index, (byte) JSRuntime.toInt32((Number) value));
}
}
static final int UINT8_BYTES_PER_ELEMENT = 1;
public static final class Uint8Array extends TypedIntArray<byte[]> {
Uint8Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public int getIntImpl(byte[] array, int offset, int index) {
return ByteArrayAccess.nativeOrder().getUint8(array, offset + index * UINT8_BYTES_PER_ELEMENT);
}
@Override
public void setIntImpl(byte[] array, int offset, int index, int value) {
ByteArrayAccess.nativeOrder().putInt8(array, offset + index * UINT8_BYTES_PER_ELEMENT, value);
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return ByteArrayAccess.forOrder(littleEndian).getUint8(JSArrayBuffer.getByteArray(buffer), index);
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteArrayAccess.forOrder(littleEndian).putInt8(JSArrayBuffer.getByteArray(buffer), index, JSRuntime.toInt32((Number) value));
}
}
public static final class DirectUint8Array extends TypedIntArray<ByteBuffer> {
DirectUint8Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public int getIntImpl(ByteBuffer buffer, int offset, int index) {
return buffer.get(offset + index * UINT8_BYTES_PER_ELEMENT) & 0xff;
}
@Override
public void setIntImpl(ByteBuffer buffer, int offset, int index, int value) {
buffer.put(offset + index * UINT8_BYTES_PER_ELEMENT, (byte) value);
}
@Override
public boolean isDirect() {
return true;
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return JSArrayBuffer.getDirectByteBuffer(buffer).get(index) & 0xff;
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
JSArrayBuffer.getDirectByteBuffer(buffer).put(index, (byte) JSRuntime.toInt32((Number) value));
}
}
public abstract static class AbstractUint8ClampedArray<T> extends TypedIntArray<T> {
private AbstractUint8ClampedArray(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public TypedIntArray<T> setElementImpl(DynamicObject object, long index, Object value, boolean strict) {
if (hasElement(object, index)) {
setInt(object, (int) index, toInt(JSRuntime.toDouble(value)));
}
return this;
}
protected static int uint8Clamp(int value) {
return value < 0 ? 0 : (value > 0xff ? 0xff : value);
}
public static int toInt(double value) {
return (int) JSRuntime.mathRint(value);
}
}
public static final class Uint8ClampedArray extends AbstractUint8ClampedArray<byte[]> {
Uint8ClampedArray(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public int getIntImpl(byte[] array, int offset, int index) {
return ByteArrayAccess.nativeOrder().getUint8(array, offset + index * UINT8_BYTES_PER_ELEMENT);
}
@Override
public void setIntImpl(byte[] array, int offset, int index, int value) {
ByteArrayAccess.nativeOrder().putInt8(array, offset + index * UINT8_BYTES_PER_ELEMENT, uint8Clamp(value));
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return ByteArrayAccess.forOrder(littleEndian).getUint8(JSArrayBuffer.getByteArray(buffer), index);
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteArrayAccess.forOrder(littleEndian).putInt8(JSArrayBuffer.getByteArray(buffer), index, uint8Clamp(toInt(JSRuntime.toDouble((Number) value))));
}
}
public static final class DirectUint8ClampedArray extends AbstractUint8ClampedArray<ByteBuffer> {
DirectUint8ClampedArray(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public int getIntImpl(ByteBuffer buffer, int offset, int index) {
return buffer.get(offset + index * UINT8_BYTES_PER_ELEMENT) & 0xff;
}
@Override
public void setIntImpl(ByteBuffer buffer, int offset, int index, int value) {
buffer.put(offset + index * UINT8_BYTES_PER_ELEMENT, (byte) uint8Clamp(value));
}
@Override
public boolean isDirect() {
return true;
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return JSArrayBuffer.getDirectByteBuffer(buffer).get(index) & 0xff;
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
JSArrayBuffer.getDirectByteBuffer(buffer).put(index, (byte) uint8Clamp(toInt(JSRuntime.toDouble((Number) value))));
}
}
static final int INT16_BYTES_PER_ELEMENT = 2;
public static final class Int16Array extends TypedIntArray<byte[]> {
Int16Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public int getIntImpl(byte[] array, int offset, int index) {
return ByteArrayAccess.nativeOrder().getInt16(array, offset + index * INT16_BYTES_PER_ELEMENT);
}
@Override
public void setIntImpl(byte[] array, int offset, int index, int value) {
ByteArrayAccess.nativeOrder().putInt16(array, offset + index * INT16_BYTES_PER_ELEMENT, value);
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return ByteArrayAccess.forOrder(littleEndian).getInt16(JSArrayBuffer.getByteArray(buffer), index);
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteArrayAccess.forOrder(littleEndian).putInt16(JSArrayBuffer.getByteArray(buffer), index, JSRuntime.toInt32((Number) value));
}
}
public static final class DirectInt16Array extends TypedIntArray<ByteBuffer> {
DirectInt16Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public int getIntImpl(ByteBuffer buffer, int offset, int index) {
return ByteBufferAccess.nativeOrder().getInt16(buffer, offset + index * INT16_BYTES_PER_ELEMENT);
}
@Override
public void setIntImpl(ByteBuffer buffer, int offset, int index, int value) {
ByteBufferAccess.nativeOrder().putInt16(buffer, offset + index * INT16_BYTES_PER_ELEMENT, (short) value);
}
@Override
public boolean isDirect() {
return true;
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return (int) ByteBufferAccess.forOrder(littleEndian).getInt16(JSArrayBuffer.getDirectByteBuffer(buffer), index);
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteBufferAccess.forOrder(littleEndian).putInt16(JSArrayBuffer.getDirectByteBuffer(buffer), index, (short) JSRuntime.toInt32((Number) value));
}
}
static final int UINT16_BYTES_PER_ELEMENT = 2;
public static final class Uint16Array extends TypedIntArray<byte[]> {
Uint16Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public int getIntImpl(byte[] array, int offset, int index) {
return ByteArrayAccess.nativeOrder().getUint16(array, offset + index * UINT16_BYTES_PER_ELEMENT);
}
@Override
public void setIntImpl(byte[] array, int offset, int index, int value) {
ByteArrayAccess.nativeOrder().putInt16(array, offset + index * UINT16_BYTES_PER_ELEMENT, value);
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return ByteArrayAccess.forOrder(littleEndian).getUint16(JSArrayBuffer.getByteArray(buffer), index);
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteArrayAccess.forOrder(littleEndian).putInt16(JSArrayBuffer.getByteArray(buffer), index, JSRuntime.toInt32((Number) value));
}
}
public static final class DirectUint16Array extends TypedIntArray<ByteBuffer> {
DirectUint16Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public int getIntImpl(ByteBuffer buffer, int offset, int index) {
return ByteBufferAccess.nativeOrder().getUint16(buffer, offset + index * UINT16_BYTES_PER_ELEMENT);
}
@Override
public void setIntImpl(ByteBuffer buffer, int offset, int index, int value) {
ByteBufferAccess.nativeOrder().putInt16(buffer, offset + index * UINT16_BYTES_PER_ELEMENT, (char) value);
}
@Override
public boolean isDirect() {
return true;
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return (int) ByteBufferAccess.forOrder(littleEndian).getUint16(JSArrayBuffer.getDirectByteBuffer(buffer), index);
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteBufferAccess.forOrder(littleEndian).putInt16(JSArrayBuffer.getDirectByteBuffer(buffer), index, (char) JSRuntime.toInt32((Number) value));
}
}
static final int INT32_BYTES_PER_ELEMENT = 4;
public static final class Int32Array extends TypedIntArray<byte[]> {
Int32Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public int getIntImpl(byte[] array, int offset, int index) {
return ByteArrayAccess.nativeOrder().getInt32(array, offset + index * INT32_BYTES_PER_ELEMENT);
}
@Override
public void setIntImpl(byte[] array, int offset, int index, int value) {
ByteArrayAccess.nativeOrder().putInt32(array, offset + index * INT32_BYTES_PER_ELEMENT, value);
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return ByteArrayAccess.forOrder(littleEndian).getInt32(JSArrayBuffer.getByteArray(buffer), index);
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteArrayAccess.forOrder(littleEndian).putInt32(JSArrayBuffer.getByteArray(buffer), index, JSRuntime.toInt32((Number) value));
}
}
public static final class DirectInt32Array extends TypedIntArray<ByteBuffer> {
DirectInt32Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public int getIntImpl(ByteBuffer buffer, int offset, int index) {
return ByteBufferAccess.nativeOrder().getInt32(buffer, offset + index * INT32_BYTES_PER_ELEMENT);
}
@Override
public void setIntImpl(ByteBuffer buffer, int offset, int index, int value) {
ByteBufferAccess.nativeOrder().putInt32(buffer, offset + index * INT32_BYTES_PER_ELEMENT, value);
}
@Override
public boolean isDirect() {
return true;
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return ByteBufferAccess.forOrder(littleEndian).getInt32(JSArrayBuffer.getDirectByteBuffer(buffer), index);
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteBufferAccess.forOrder(littleEndian).putInt32(JSArrayBuffer.getDirectByteBuffer(buffer), index, JSRuntime.toInt32((Number) value));
}
}
static final int UINT32_BYTES_PER_ELEMENT = 4;
public abstract static class AbstractUint32Array<T> extends TypedIntArray<T> {
private AbstractUint32Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public Object getElement(DynamicObject object, long index) {
if (hasElement(object, index)) {
int value = getInt(object, (int) index);
return toUint32(value);
} else {
return Undefined.instance;
}
}
protected static Number toUint32(int value) {
if (value >= 0) {
return value;
} else {
return (double) (value & 0xFFFFFFFFL);
}
}
@Override
public Object getElementInBounds(DynamicObject object, long index) {
assert hasElement(object, index);
return toUint32(getInt(object, (int) index));
}
}
public static final class Uint32Array extends AbstractUint32Array<byte[]> {
Uint32Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public int getIntImpl(byte[] array, int offset, int index) {
return ByteArrayAccess.nativeOrder().getInt32(array, offset + index * UINT32_BYTES_PER_ELEMENT);
}
@Override
public void setIntImpl(byte[] array, int offset, int index, int value) {
ByteArrayAccess.nativeOrder().putInt32(array, offset + index * UINT32_BYTES_PER_ELEMENT, value);
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return toUint32((int) ByteArrayAccess.forOrder(littleEndian).getUint32(JSArrayBuffer.getByteArray(buffer), index));
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteArrayAccess.forOrder(littleEndian).putInt32(JSArrayBuffer.getByteArray(buffer), index, JSRuntime.toInt32((Number) value));
}
}
public static final class DirectUint32Array extends AbstractUint32Array<ByteBuffer> {
DirectUint32Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public int getIntImpl(ByteBuffer buffer, int offset, int index) {
return ByteBufferAccess.nativeOrder().getInt32(buffer, offset + index * UINT32_BYTES_PER_ELEMENT);
}
@Override
public void setIntImpl(ByteBuffer buffer, int offset, int index, int value) {
ByteBufferAccess.nativeOrder().putInt32(buffer, offset + index * UINT32_BYTES_PER_ELEMENT, value);
}
@Override
public boolean isDirect() {
return true;
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return toUint32(ByteBufferAccess.forOrder(littleEndian).getInt32(JSArrayBuffer.getDirectByteBuffer(buffer), index));
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteBufferAccess.forOrder(littleEndian).putInt32(JSArrayBuffer.getDirectByteBuffer(buffer), index, JSRuntime.toInt32((Number) value));
}
}
public abstract static class TypedBigIntArray<T> extends TypedArray {
protected TypedBigIntArray(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public Object getElement(DynamicObject object, long index) {
if (hasElement(object, index)) {
return getBigInt(object, (int) index);
} else {
return Undefined.instance;
}
}
@Override
public Object getElementInBounds(DynamicObject object, long index) {
assert hasElement(object, index);
return getBigInt(object, (int) index);
}
@Override
public TypedBigIntArray<T> setElementImpl(DynamicObject object, long index, Object value, boolean strict) {
if (hasElement(object, index)) {
setBigInt(object, (int) index, JSRuntime.toBigInt(value));
}
return this;
}
public final BigInt getBigInt(DynamicObject object, int index) {
return getBigIntImpl(getBufferFromTypedArrayT(object), getOffset(object), index);
}
public final void setBigInt(DynamicObject object, int index, BigInt value) {
setBigIntImpl(getBufferFromTypedArrayT(object), getOffset(object), index, value);
}
@SuppressWarnings("unchecked")
private T getBufferFromTypedArrayT(DynamicObject object) {
return (T) super.getBufferFromTypedArray(object);
}
public abstract BigInt getBigIntImpl(T buffer, int offset, int index);
public abstract void setBigIntImpl(T buffer, int offset, int index, BigInt value);
}
static final int BIGINT64_BYTES_PER_ELEMENT = 8;
public static final class BigInt64Array extends TypedBigIntArray<byte[]> {
BigInt64Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public BigInt getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return BigInt.valueOf(ByteArrayAccess.forOrder(littleEndian).getInt64(JSArrayBuffer.getByteArray(buffer), index));
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteArrayAccess.forOrder(littleEndian).putInt64(JSArrayBuffer.getByteArray(buffer), index, JSRuntime.toBigInt(value).longValue());
}
@Override
public BigInt getBigIntImpl(byte[] buffer, int offset, int index) {
return BigInt.valueOf(ByteArrayAccess.nativeOrder().getInt64(buffer, offset + index * BIGINT64_BYTES_PER_ELEMENT));
}
@Override
public void setBigIntImpl(byte[] buffer, int offset, int index, BigInt value) {
ByteArrayAccess.nativeOrder().putInt64(buffer, offset + index * BIGINT64_BYTES_PER_ELEMENT, value.longValue());
}
}
public static final class DirectBigInt64Array extends TypedBigIntArray<ByteBuffer> {
DirectBigInt64Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public boolean isDirect() {
return true;
}
@Override
public BigInt getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return BigInt.valueOf(ByteBufferAccess.forOrder(littleEndian).getInt64(JSArrayBuffer.getDirectByteBuffer(buffer), index));
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteBufferAccess.forOrder(littleEndian).putInt64(JSArrayBuffer.getDirectByteBuffer(buffer), index, JSRuntime.toBigInt(value).longValue());
}
@Override
public BigInt getBigIntImpl(ByteBuffer buffer, int offset, int index) {
return BigInt.valueOf(ByteBufferAccess.nativeOrder().getInt64(buffer, offset + index * BIGINT64_BYTES_PER_ELEMENT));
}
@Override
public void setBigIntImpl(ByteBuffer buffer, int offset, int index, BigInt value) {
ByteBufferAccess.nativeOrder().putInt64(buffer, offset + index * BIGINT64_BYTES_PER_ELEMENT, value.longValue());
}
}
static final int BIGUINT64_BYTES_PER_ELEMENT = 8;
public static final class BigUint64Array extends TypedBigIntArray<byte[]> {
BigUint64Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public BigInt getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return BigInt.valueOfUnsigned(ByteArrayAccess.forOrder(littleEndian).getInt64(JSArrayBuffer.getByteArray(buffer), index));
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteArrayAccess.forOrder(littleEndian).putInt64(JSArrayBuffer.getByteArray(buffer), index, JSRuntime.toBigInt(value).longValue());
}
@Override
public BigInt getBigIntImpl(byte[] buffer, int offset, int index) {
return BigInt.valueOfUnsigned(ByteArrayAccess.nativeOrder().getInt64(buffer, offset + index * BIGUINT64_BYTES_PER_ELEMENT));
}
@Override
public void setBigIntImpl(byte[] buffer, int offset, int index, BigInt value) {
ByteArrayAccess.nativeOrder().putInt64(buffer, offset + index * BIGUINT64_BYTES_PER_ELEMENT, value.longValue());
}
}
public static final class DirectBigUint64Array extends TypedBigIntArray<ByteBuffer> {
DirectBigUint64Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public boolean isDirect() {
return true;
}
@Override
public BigInt getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return BigInt.valueOfUnsigned(ByteBufferAccess.forOrder(littleEndian).getInt64(JSArrayBuffer.getDirectByteBuffer(buffer), index));
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteBufferAccess.forOrder(littleEndian).putInt64(JSArrayBuffer.getDirectByteBuffer(buffer), index, JSRuntime.toBigInt(value).longValue());
}
@Override
public BigInt getBigIntImpl(ByteBuffer buffer, int offset, int index) {
return BigInt.valueOfUnsigned(ByteBufferAccess.nativeOrder().getInt64(buffer, offset + index * BIGUINT64_BYTES_PER_ELEMENT));
}
@Override
public void setBigIntImpl(ByteBuffer buffer, int offset, int index, BigInt value) {
ByteBufferAccess.nativeOrder().putInt64(buffer, offset + index * BIGUINT64_BYTES_PER_ELEMENT, value.longValue());
}
}
public abstract static class TypedFloatArray<T> extends TypedArray {
protected TypedFloatArray(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public final Object getElement(DynamicObject object, long index) {
if (hasElement(object, index)) {
return getDouble(object, (int) index);
} else {
return Undefined.instance;
}
}
@Override
public Object getElementInBounds(DynamicObject object, long index) {
assert hasElement(object, index);
return getDouble(object, (int) index);
}
@Override
public final TypedFloatArray<T> setElementImpl(DynamicObject object, long index, Object value, boolean strict) {
if (hasElement(object, index)) {
setDouble(object, (int) index, JSRuntime.toDouble(value));
}
return this;
}
@SuppressWarnings("unchecked")
private T getBufferFromTypedArrayT(DynamicObject object) {
return (T) super.getBufferFromTypedArray(object);
}
public final double getDouble(DynamicObject object, int index) {
return getDoubleImpl(getBufferFromTypedArrayT(object), getOffset(object), index);
}
public final void setDouble(DynamicObject object, int index, double value) {
setDoubleImpl(getBufferFromTypedArrayT(object), getOffset(object), index, value);
}
public abstract double getDoubleImpl(T buffer, int offset, int index);
public abstract void setDoubleImpl(T buffer, int offset, int index, double value);
}
static final int FLOAT32_BYTES_PER_ELEMENT = 4;
public static final class Float32Array extends TypedFloatArray<byte[]> {
Float32Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public double getDoubleImpl(byte[] array, int offset, int index) {
return ByteArrayAccess.nativeOrder().getFloat(array, offset + index * FLOAT32_BYTES_PER_ELEMENT);
}
@Override
public void setDoubleImpl(byte[] array, int offset, int index, double value) {
ByteArrayAccess.nativeOrder().putFloat(array, offset + index * FLOAT32_BYTES_PER_ELEMENT, (float) value);
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return (double) ByteArrayAccess.forOrder(littleEndian).getFloat(JSArrayBuffer.getByteArray(buffer), index);
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteArrayAccess.forOrder(littleEndian).putFloat(JSArrayBuffer.getByteArray(buffer), index, JSRuntime.floatValue((Number) value));
}
}
public static final class DirectFloat32Array extends TypedFloatArray<ByteBuffer> {
DirectFloat32Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public double getDoubleImpl(ByteBuffer buffer, int offset, int index) {
return ByteBufferAccess.nativeOrder().getFloat(buffer, offset + index * FLOAT32_BYTES_PER_ELEMENT);
}
@Override
public void setDoubleImpl(ByteBuffer buffer, int offset, int index, double value) {
ByteBufferAccess.nativeOrder().putFloat(buffer, offset + index * FLOAT32_BYTES_PER_ELEMENT, (float) value);
}
@Override
public boolean isDirect() {
return true;
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return (double) ByteBufferAccess.forOrder(littleEndian).getFloat(JSArrayBuffer.getDirectByteBuffer(buffer), index);
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteBufferAccess.forOrder(littleEndian).putFloat(JSArrayBuffer.getDirectByteBuffer(buffer), index, JSRuntime.floatValue((Number) value));
}
}
static final int FLOAT64_BYTES_PER_ELEMENT = 8;
public static final class Float64Array extends TypedFloatArray<byte[]> {
Float64Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public double getDoubleImpl(byte[] array, int offset, int index) {
return ByteArrayAccess.nativeOrder().getDouble(array, offset + index * FLOAT64_BYTES_PER_ELEMENT);
}
@Override
public void setDoubleImpl(byte[] array, int offset, int index, double value) {
ByteArrayAccess.nativeOrder().putDouble(array, offset + index * FLOAT64_BYTES_PER_ELEMENT, value);
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return ByteArrayAccess.forOrder(littleEndian).getDouble(JSArrayBuffer.getByteArray(buffer), index);
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteArrayAccess.forOrder(littleEndian).putDouble(JSArrayBuffer.getByteArray(buffer), index, JSRuntime.doubleValue((Number) value));
}
}
public static final class DirectFloat64Array extends TypedFloatArray<ByteBuffer> {
DirectFloat64Array(TypedArrayFactory factory, boolean offset) {
super(factory, offset);
}
@Override
public double getDoubleImpl(ByteBuffer buffer, int offset, int index) {
return ByteBufferAccess.nativeOrder().getDouble(buffer, offset + index * FLOAT64_BYTES_PER_ELEMENT);
}
@Override
public void setDoubleImpl(ByteBuffer buffer, int offset, int index, double value) {
ByteBufferAccess.nativeOrder().putDouble(buffer, offset + index * FLOAT64_BYTES_PER_ELEMENT, value);
}
@Override
public boolean isDirect() {
return true;
}
@Override
public Number getBufferElement(DynamicObject buffer, int index, boolean littleEndian) {
return ByteBufferAccess.forOrder(littleEndian).getDouble(JSArrayBuffer.getDirectByteBuffer(buffer), index);
}
@Override
public void setBufferElement(DynamicObject buffer, int index, boolean littleEndian, Object value) {
ByteBufferAccess.forOrder(littleEndian).putDouble(JSArrayBuffer.getDirectByteBuffer(buffer), index, JSRuntime.doubleValue((Number) value));
}
}
}