blob: bf42937c7aef3c4887131af09fa3a20672e41c84 [file] [log] [blame] [edit]
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// ignore_for_file: unnecessary_cast, overridden_fields
part of 'types.dart';
final class JArrayType<E> extends JObjType<JArray<E>> {
final JArrayElementType<E> elementType;
const JArrayType(this.elementType);
@override
String get signature => '[${elementType.signature}';
@override
JArray<E> fromReference(JReference reference) =>
JArray.fromReference(elementType, reference);
@override
JObjType get superType => const JObjectType();
@override
final int superCount = 1;
@override
int get hashCode => Object.hash(JArrayType, elementType);
@override
bool operator ==(Object other) {
return other.runtimeType == (JArrayType<E>) &&
other is JArrayType<E> &&
elementType == other.elementType;
}
}
class JArray<E> extends JObject {
final JArrayElementType<E> elementType;
@override
late final JArrayType<E> $type = type(elementType) as JArrayType<E>;
/// The type which includes information such as the signature of this class.
static JObjType<JArray<T>> type<T>(JArrayElementType<T> innerType) =>
JArrayType(innerType);
/// Construct a new [JArray] with [reference] as its underlying reference.
JArray.fromReference(this.elementType, JReference reference)
: super.fromReference(reference);
/// Creates a [JArray] of the given length from the given [elementType].
///
/// The [length] must be a non-negative integer.
factory JArray(JArrayElementType<E> elementType, int length) {
return elementType._newArray(length);
}
/// Creates a [JArray] of the given length with [fill] at each position.
///
/// The [length] must be a non-negative integer.
static JArray<$E> filled<$E extends JObject>(int length, $E fill,
{JObjType<$E>? E}) {
RangeError.checkNotNegative(length);
E ??= fill.$type as JObjType<$E>;
return E._newArray(length, fill);
}
int? _length;
/// The number of elements in this array.
int get length {
return _length ??= Jni.env.GetArrayLength(reference.pointer);
}
}
extension NativeArray<E extends JPrimitive> on JArray<E> {
void _allocate<T extends NativeType>(
int byteCount,
void Function(Pointer<T> ptr) use,
) {
using((arena) {
final ptr = arena.allocate<T>(byteCount);
use(ptr);
}, malloc);
}
}
extension on Allocator {
Pointer<NativeFinalizerFunction>? get _nativeFree {
return switch (this) {
malloc => malloc.nativeFree,
calloc => calloc.nativeFree,
_ => null,
};
}
}
extension BoolArray on JArray<jboolean> {
bool operator [](int index) {
RangeError.checkValidIndex(index, this);
return Jni.env.GetBooleanArrayElement(reference.pointer, index);
}
void operator []=(int index, bool value) {
RangeError.checkValidIndex(index, this);
Jni.env.SetBooleanArrayElement(reference.pointer, index, value);
}
Uint8List getRange(int start, int end, {Allocator allocator = malloc}) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
final buffer = allocator<JBooleanMarker>(rangeLength);
Jni.env
.GetBooleanArrayRegion(reference.pointer, start, rangeLength, buffer);
return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree);
}
void setRange(int start, int end, Iterable<bool> iterable,
[int skipCount = 0]) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
_allocate<JBooleanMarker>(sizeOf<JBooleanMarker>() * rangeLength, (ptr) {
ptr
.asTypedList(rangeLength)
.setRange(0, rangeLength, iterable.map((e) => e ? 1 : 0), skipCount);
Jni.env.SetBooleanArrayRegion(reference.pointer, start, rangeLength, ptr);
});
}
}
extension ByteArray on JArray<jbyte> {
int operator [](int index) {
RangeError.checkValidIndex(index, this);
return Jni.env.GetByteArrayElement(reference.pointer, index);
}
void operator []=(int index, int value) {
RangeError.checkValidIndex(index, this);
Jni.env.SetByteArrayElement(reference.pointer, index, value);
}
Int8List getRange(int start, int end, {Allocator allocator = malloc}) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
final buffer = allocator<JByteMarker>(rangeLength);
Jni.env.GetByteArrayRegion(reference.pointer, start, rangeLength, buffer);
return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree);
}
void setRange(int start, int end, Iterable<int> iterable,
[int skipCount = 0]) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
_allocate<JByteMarker>(sizeOf<JByteMarker>() * rangeLength, (ptr) {
ptr
.asTypedList(rangeLength)
.setRange(0, rangeLength, iterable, skipCount);
Jni.env.SetByteArrayRegion(reference.pointer, start, rangeLength, ptr);
});
}
}
/// `JArray<jchar>` is a 16-bit integer array.
///
/// Due to variable length encoding, the number of code units is not equal to
/// the number of characters.
extension CharArray on JArray<jchar> {
int operator [](int index) {
RangeError.checkValidIndex(index, this);
return Jni.env.GetCharArrayElement(reference.pointer, index);
}
void operator []=(int index, int value) {
RangeError.checkValidIndex(index, this);
Jni.env.SetCharArrayElement(reference.pointer, index, value);
}
Uint16List getRange(int start, int end, {Allocator allocator = malloc}) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
final buffer = allocator<JCharMarker>(rangeLength);
Jni.env.GetCharArrayRegion(reference.pointer, start, rangeLength, buffer);
return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree);
}
void setRange(int start, int end, Iterable<int> iterable,
[int skipCount = 0]) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
_allocate<JCharMarker>(sizeOf<JCharMarker>() * rangeLength, (ptr) {
ptr
.asTypedList(rangeLength)
.setRange(0, rangeLength, iterable, skipCount);
Jni.env.SetCharArrayRegion(reference.pointer, start, rangeLength, ptr);
});
}
}
extension ShortArray on JArray<jshort> {
int operator [](int index) {
RangeError.checkValidIndex(index, this);
return Jni.env.GetShortArrayElement(reference.pointer, index);
}
void operator []=(int index, int value) {
RangeError.checkValidIndex(index, this);
Jni.env.SetShortArrayElement(reference.pointer, index, value);
}
Int16List getRange(int start, int end, {Allocator allocator = malloc}) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
final buffer = allocator<JShortMarker>(rangeLength);
Jni.env.GetShortArrayRegion(reference.pointer, start, rangeLength, buffer);
return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree);
}
void setRange(int start, int end, Iterable<int> iterable,
[int skipCount = 0]) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
_allocate<JShortMarker>(sizeOf<JShortMarker>() * rangeLength, (ptr) {
ptr
.asTypedList(rangeLength)
.setRange(0, rangeLength, iterable, skipCount);
Jni.env.SetShortArrayRegion(reference.pointer, start, rangeLength, ptr);
});
}
}
extension IntArray on JArray<jint> {
int operator [](int index) {
RangeError.checkValidIndex(index, this);
return Jni.env.GetIntArrayElement(reference.pointer, index);
}
void operator []=(int index, int value) {
RangeError.checkValidIndex(index, this);
Jni.env.SetIntArrayElement(reference.pointer, index, value);
}
Int32List getRange(int start, int end, {Allocator allocator = malloc}) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
final buffer = allocator<JIntMarker>(rangeLength);
Jni.env.GetIntArrayRegion(reference.pointer, start, rangeLength, buffer);
return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree);
}
void setRange(int start, int end, Iterable<int> iterable,
[int skipCount = 0]) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
_allocate<JIntMarker>(sizeOf<JIntMarker>() * rangeLength, (ptr) {
ptr
.asTypedList(rangeLength)
.setRange(0, rangeLength, iterable, skipCount);
Jni.env.SetIntArrayRegion(reference.pointer, start, rangeLength, ptr);
});
}
}
extension LongArray on JArray<jlong> {
int operator [](int index) {
RangeError.checkValidIndex(index, this);
return Jni.env.GetLongArrayElement(reference.pointer, index);
}
void operator []=(int index, int value) {
RangeError.checkValidIndex(index, this);
Jni.env.SetLongArrayElement(reference.pointer, index, value);
}
Int64List getRange(int start, int end, {Allocator allocator = malloc}) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
final buffer = allocator<JLongMarker>(rangeLength);
Jni.env.GetLongArrayRegion(reference.pointer, start, rangeLength, buffer);
return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree);
}
void setRange(int start, int end, Iterable<int> iterable,
[int skipCount = 0]) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
_allocate<JLongMarker>(sizeOf<JLongMarker>() * rangeLength, (ptr) {
ptr
.asTypedList(rangeLength)
.setRange(0, rangeLength, iterable, skipCount);
Jni.env.SetLongArrayRegion(reference.pointer, start, rangeLength, ptr);
});
}
}
extension FloatArray on JArray<jfloat> {
double operator [](int index) {
RangeError.checkValidIndex(index, this);
return Jni.env.GetFloatArrayElement(reference.pointer, index);
}
void operator []=(int index, double value) {
RangeError.checkValidIndex(index, this);
Jni.env.SetFloatArrayElement(reference.pointer, index, value);
}
Float32List getRange(int start, int end, {Allocator allocator = malloc}) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
final buffer = allocator<JFloatMarker>(rangeLength);
Jni.env.GetFloatArrayRegion(reference.pointer, start, rangeLength, buffer);
return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree);
}
void setRange(int start, int end, Iterable<double> iterable,
[int skipCount = 0]) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
_allocate<JFloatMarker>(sizeOf<JFloatMarker>() * rangeLength, (ptr) {
ptr
.asTypedList(rangeLength)
.setRange(0, rangeLength, iterable, skipCount);
Jni.env.SetFloatArrayRegion(reference.pointer, start, rangeLength, ptr);
});
}
}
extension DoubleArray on JArray<jdouble> {
double operator [](int index) {
RangeError.checkValidIndex(index, this);
return Jni.env.GetDoubleArrayElement(reference.pointer, index);
}
void operator []=(int index, double value) {
RangeError.checkValidIndex(index, this);
Jni.env.SetDoubleArrayElement(reference.pointer, index, value);
}
Float64List getRange(int start, int end, {Allocator allocator = malloc}) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
final buffer = allocator<JDoubleMarker>(rangeLength);
Jni.env.GetDoubleArrayRegion(reference.pointer, start, rangeLength, buffer);
return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree);
}
void setRange(int start, int end, Iterable<double> iterable,
[int skipCount = 0]) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
_allocate<JDoubleMarker>(sizeOf<JDoubleMarker>() * rangeLength, (ptr) {
ptr
.asTypedList(rangeLength)
.setRange(0, rangeLength, iterable, skipCount);
Jni.env.SetDoubleArrayRegion(reference.pointer, start, rangeLength, ptr);
});
}
}
extension ObjectArray<T extends JObject> on JArray<T> {
T operator [](int index) {
RangeError.checkValidIndex(index, this);
return (elementType as JObjType<T>).fromReference(JGlobalReference(
Jni.env.GetObjectArrayElement(reference.pointer, index)));
}
void operator []=(int index, T value) {
RangeError.checkValidIndex(index, this);
Jni.env.SetObjectArrayElement(
reference.pointer, index, value.reference.pointer);
}
void setRange(int start, int end, Iterable<T> iterable, [int skipCount = 0]) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
final it = iterable.skip(skipCount).take(rangeLength);
it.forEachIndexed((index, element) {
this[index] = element;
});
}
}