blob: 9779032a75b76b4c2b2cd14f9f34a9c3cba44521 [file] [log] [blame] [edit]
// Copyright (c) 2023, 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.
import 'dart:collection';
import 'dart:ffi';
import 'package:jni/src/util/jset.dart';
import '../accessors.dart';
import '../jni.dart';
import '../jobject.dart';
import '../jvalues.dart';
import '../third_party/generated_bindings.dart';
import '../types.dart';
import 'jiterator.dart';
final class JListType<$E extends JObject> extends JObjType<JList<$E>> {
final JObjType<$E> E;
const JListType(
this.E,
);
@override
String get signature => r"Ljava/util/List;";
@override
JList<$E> fromRef(JObjectPtr ref) => JList.fromRef(E, ref);
@override
JObjType get superType => const JObjectType();
@override
final superCount = 1;
@override
int get hashCode => Object.hash(JListType, E);
@override
bool operator ==(Object other) {
return other.runtimeType == JListType && other is JListType && E == other.E;
}
}
class JList<$E extends JObject> extends JObject with ListMixin<$E> {
@override
// ignore: overridden_fields
late final JObjType<JList> $type = type(E);
final JObjType<$E> E;
JList.fromRef(
this.E,
JObjectPtr ref,
) : super.fromRef(ref);
static final _class = Jni.findJClass(r"java/util/List");
/// The type which includes information such as the signature of this class.
static JListType<$E> type<$E extends JObject>(
JObjType<$E> E,
) {
return JListType(
E,
);
}
static final _arrayListClassRef = Jni.findJClass(r"java/util/ArrayList");
static final _ctorId = Jni.accessors
.getMethodIDOf(_arrayListClassRef.reference, r"<init>", r"()V");
JList.array(this.E)
: super.fromRef(Jni.accessors.newObjectWithArgs(
_arrayListClassRef.reference, _ctorId, []).object);
static final _sizeId =
Jni.accessors.getMethodIDOf(_class.reference, r"size", r"()I");
@override
int get length => Jni.accessors
.callMethodWithArgs(reference, _sizeId, JniCallType.intType, []).integer;
@override
set length(int newLength) {
RangeError.checkNotNegative(newLength);
while (length < newLength) {
add(E.fromRef(nullptr));
}
while (newLength < length) {
removeAt(length - 1);
}
}
static final _getId = Jni.accessors
.getMethodIDOf(_class.reference, r"get", r"(I)Ljava/lang/Object;");
@override
$E operator [](int index) {
RangeError.checkValidIndex(index, this);
return E.fromRef(Jni.accessors.callMethodWithArgs(
reference, _getId, JniCallType.objectType, [JValueInt(index)]).object);
}
static final _setId = Jni.accessors.getMethodIDOf(
_class.reference, r"set", r"(ILjava/lang/Object;)Ljava/lang/Object;");
@override
void operator []=(int index, $E value) {
RangeError.checkValidIndex(index, this);
E.fromRef(Jni.accessors.callMethodWithArgs(reference, _setId,
JniCallType.objectType, [JValueInt(index), value.reference]).object);
}
static final _addId = Jni.accessors
.getMethodIDOf(_class.reference, r"add", r"(Ljava/lang/Object;)Z");
@override
void add($E element) {
Jni.accessors.callMethodWithArgs(reference, _addId, JniCallType.booleanType,
[element.reference]).check();
}
static final _collectionClass = Jni.findJClass("java/util/Collection");
static final _addAllId = Jni.accessors
.getMethodIDOf(_class.reference, r"addAll", r"(Ljava/util/Collection;)Z");
@override
void addAll(Iterable<$E> iterable) {
if (iterable is JObject &&
Jni.env.IsInstanceOf(
(iterable as JObject).reference, _collectionClass.reference)) {
Jni.accessors.callMethodWithArgs(reference, _addAllId,
JniCallType.booleanType, [(iterable as JObject).reference]).boolean;
return;
}
return super.addAll(iterable);
}
static final _clearId =
Jni.accessors.getMethodIDOf(_class.reference, r"clear", r"()V");
@override
void clear() {
Jni.accessors.callMethodWithArgs(
reference, _clearId, JniCallType.voidType, []).check();
}
static final _containsId = Jni.accessors
.getMethodIDOf(_class.reference, r"contains", r"(Ljava/lang/Object;)Z");
@override
bool contains(Object? element) {
if (element is! JObject) return false;
return Jni.accessors.callMethodWithArgs(reference, _containsId,
JniCallType.booleanType, [element.reference]).boolean;
}
static final _getRangeId = Jni.accessors
.getMethodIDOf(_class.reference, r"subList", r"(II)Ljava/util/List;");
@override
JList<$E> getRange(int start, int end) {
RangeError.checkValidRange(start, end, this.length);
return JListType(E).fromRef(
Jni.accessors.callMethodWithArgs(reference, _getRangeId,
JniCallType.objectType, [JValueInt(start), JValueInt(end)]).object,
);
}
static final _indexOfId = Jni.accessors
.getMethodIDOf(_class.reference, r"indexOf", r"(Ljava/lang/Object;)I");
@override
int indexOf(Object? element, [int start = 0]) {
if (element is! JObject) return -1;
if (start < 0) start = 0;
if (start == 0) {
return Jni.accessors.callMethodWithArgs(reference, _indexOfId,
JniCallType.intType, [element.reference]).integer;
}
return Jni.accessors.callMethodWithArgs(
getRange(start, length).reference,
_indexOfId,
JniCallType.intType,
[element.reference],
).integer;
}
static final _insertId = Jni.accessors
.getMethodIDOf(_class.reference, r"add", r"(ILjava/lang/Object;)V");
@override
void insert(int index, $E element) {
Jni.accessors.callMethodWithArgs(reference, _insertId, JniCallType.voidType,
[JValueInt(index), element.reference]).check();
}
static final _insertAllId = Jni.accessors.getMethodIDOf(
_class.reference, r"addAll", r"(ILjava/util/Collection;)Z");
@override
void insertAll(int index, Iterable<$E> iterable) {
if (iterable is JObject &&
Jni.env.IsInstanceOf(
(iterable as JObject).reference, _collectionClass.reference)) {
Jni.accessors.callMethodWithArgs(
reference,
_insertAllId,
JniCallType.booleanType,
[JValueInt(index), (iterable as JObject).reference],
).boolean;
return;
}
super.insertAll(index, iterable);
}
static final _isEmptyId =
Jni.accessors.getMethodIDOf(_class.reference, r"isEmpty", r"()Z");
@override
bool get isEmpty => Jni.accessors.callMethodWithArgs(
reference, _isEmptyId, JniCallType.booleanType, []).boolean;
@override
bool get isNotEmpty => !isEmpty;
static final _iteratorId = Jni.accessors
.getMethodIDOf(_class.reference, r"iterator", r"()Ljava/util/Iterator;");
@override
JIterator<$E> get iterator =>
JIteratorType(E).fromRef(Jni.accessors.callMethodWithArgs(
reference, _iteratorId, JniCallType.objectType, []).object);
static final _lastIndexOfId = Jni.accessors.getMethodIDOf(
_class.reference, r"lastIndexOf", r"(Ljava/lang/Object;)I");
@override
int lastIndexOf(Object? element, [int? start]) {
if (element is! JObject) return -1;
if (start == null || start >= this.length) start = this.length - 1;
if (start == this.length - 1) {
return Jni.accessors.callMethodWithArgs(reference, _lastIndexOfId,
JniCallType.intType, [element.reference]).integer;
}
final range = getRange(start, length);
final res = Jni.accessors.callMethodWithArgs(
range.reference,
_lastIndexOfId,
JniCallType.intType,
[element.reference],
).integer;
range.release();
return res;
}
static final _removeId = Jni.accessors
.getMethodIDOf(_class.reference, r"remove", r"(Ljava/lang/Object;)Z");
@override
bool remove(Object? element) {
if (element is! JObject) return false;
return Jni.accessors.callMethodWithArgs(reference, _removeId,
JniCallType.booleanType, [element.reference]).boolean;
}
static final _removeAtId = Jni.accessors
.getMethodIDOf(_class.reference, r"remove", r"(I)Ljava/lang/Object;");
@override
$E removeAt(int index) {
return E.fromRef(Jni.accessors.callMethodWithArgs(reference, _removeAtId,
JniCallType.objectType, [JValueInt(index)]).object);
}
@override
void removeRange(int start, int end) {
final range = getRange(start, end);
range.clear();
range.release();
}
@override
JSet<$E> toSet() {
return toJSet(E);
}
}
extension ToJavaList<E extends JObject> on Iterable<E> {
JList<E> toJList(JObjType<E> type) {
final list = JList.array(type);
list.addAll(this);
return list;
}
}