Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[jnigen] Add getRange method to JArray<JPrimitive> and change the dart equivalent type for JArray<jchar> to int #1095

Merged
merged 15 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion pkgs/jni/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
## 0.9.0-wip

- No changes yet.
- **Breaking Change**
([#1004](https://github.com/dart-lang/native/issues/1004)): Changed the return
type `operator []` of `JArray<jchar>` to `int` instead of `String`. Similarly,
change the argument type of `operator []=` to accept `int`.
- Added `getRange` method to `JArray` of primitive types that returns a
`TypedData` list depending on the kind of the array.

## 0.8.0

Expand Down
196 changes: 132 additions & 64 deletions pkgs/jni/lib/src/jarray.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// ignore_for_file: unnecessary_cast, overridden_fields

import 'dart:ffi';
import 'dart:typed_data';

import 'package:collection/collection.dart';
import 'package:ffi/ffi.dart';
Expand Down Expand Up @@ -131,16 +132,26 @@ class JArray<E> extends JObject {

extension NativeArray<E extends JPrimitive> on JArray<E> {
void _allocate<T extends NativeType>(
int size,
int rangeLength,
void Function(Pointer<T> ptr) use,
) {
using((arena) {
final ptr = arena.allocate<T>(size);
final ptr = arena.allocate<T>(rangeLength);
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) {
return _elementAt(index, JniCallType.booleanType).boolean;
Expand All @@ -154,16 +165,26 @@ extension BoolArray on JArray<jboolean> {
});
}

Uint8List getRange(int start, int end, {Allocator allocator = malloc}) {
RangeError.checkValidRange(start, end, length);
final rangeLength = end - start;
final buffer = allocator
.allocate<JBooleanMarker>(sizeOf<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 size = end - start;
final it = iterable.skip(skipCount).take(size);
_allocate<JBooleanMarker>(sizeOf<JBooleanMarker>() * size, (ptr) {
final rangeLength = end - start;
final it = iterable.skip(skipCount).take(rangeLength);
_allocate<JBooleanMarker>(sizeOf<JBooleanMarker>() * rangeLength, (ptr) {
it.forEachIndexed((index, element) {
ptr[index] = element ? 1 : 0;
});
Jni.env.SetBooleanArrayRegion(reference.pointer, start, size, ptr);
Jni.env.SetBooleanArrayRegion(reference.pointer, start, rangeLength, ptr);
});
}
}
Expand All @@ -181,45 +202,57 @@ extension ByteArray on JArray<jbyte> {
});
}

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 size = end - start;
final it = iterable.skip(skipCount).take(size);
_allocate<JByteMarker>(sizeOf<JByteMarker>() * size, (ptr) {
it.forEachIndexed((index, element) {
ptr[index] = element;
});
Jni.env.SetByteArrayRegion(reference.pointer, start, size, ptr);
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);
});
}
}

extension CharArray on JArray<jchar> {
String operator [](int index) {
return String.fromCharCode(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was broken, it didn't take into account characters consisting of more than one code unit.

_elementAt(index, JniCallType.charType).char,
);
int operator [](int index) {
HosseinYousefi marked this conversation as resolved.
Show resolved Hide resolved
return _elementAt(index, JniCallType.charType).char;
}

void operator []=(int index, String value) {
void operator []=(int index, int value) {
RangeError.checkValidIndex(index, this);
_allocate<JCharMarker>(sizeOf<JCharMarker>(), (ptr) {
HosseinYousefi marked this conversation as resolved.
Show resolved Hide resolved
ptr.value = value.codeUnits.first;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was broken. It didn't take into account characters with more than one code unit.

ptr.value = value;
Jni.env.SetCharArrayRegion(reference.pointer, index, 1, ptr);
});
}

void setRange(int start, int end, Iterable<String> iterable,
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 size = end - start;
final it = iterable.skip(skipCount).take(size);
_allocate<JCharMarker>(sizeOf<JCharMarker>() * size, (ptr) {
it.forEachIndexed((index, element) {
ptr[index] = element.codeUnits.first;
});
Jni.env.SetCharArrayRegion(reference.pointer, start, size, ptr);
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);
});
}
}
Expand All @@ -237,16 +270,23 @@ extension ShortArray on JArray<jshort> {
});
}

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 size = end - start;
final it = iterable.skip(skipCount).take(size);
_allocate<JShortMarker>(sizeOf<JShortMarker>() * size, (ptr) {
it.forEachIndexed((index, element) {
ptr[index] = element;
});
Jni.env.SetShortArrayRegion(reference.pointer, start, size, ptr);
final rangeLength = end - start;
_allocate<JShortMarker>(sizeOf<JShortMarker>() * rangeLength, (ptr) {
ptr
.asTypedList(rangeLength)
.setRange(0, rangeLength, iterable, skipCount);
HosseinYousefi marked this conversation as resolved.
Show resolved Hide resolved
Jni.env.SetShortArrayRegion(reference.pointer, start, rangeLength, ptr);
});
}
}
Expand All @@ -264,16 +304,23 @@ extension IntArray on JArray<jint> {
});
}

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 size = end - start;
final it = iterable.skip(skipCount).take(size);
_allocate<JIntMarker>(sizeOf<JIntMarker>() * size, (ptr) {
it.forEachIndexed((index, element) {
ptr[index] = element;
});
Jni.env.SetIntArrayRegion(reference.pointer, start, size, ptr);
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);
});
}
}
Expand All @@ -291,16 +338,23 @@ extension LongArray on JArray<jlong> {
});
}

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 size = end - start;
final it = iterable.skip(skipCount).take(size);
_allocate<JLongMarker>(sizeOf<JLongMarker>() * size, (ptr) {
it.forEachIndexed((index, element) {
ptr[index] = element;
});
Jni.env.SetLongArrayRegion(reference.pointer, start, size, ptr);
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);
});
}
}
Expand All @@ -318,16 +372,23 @@ extension FloatArray on JArray<jfloat> {
});
}

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 size = end - start;
final it = iterable.skip(skipCount).take(size);
_allocate<JFloatMarker>(sizeOf<JFloatMarker>() * size, (ptr) {
it.forEachIndexed((index, element) {
ptr[index] = element;
});
Jni.env.SetFloatArrayRegion(reference.pointer, start, size, ptr);
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);
});
}
}
Expand All @@ -345,16 +406,23 @@ extension DoubleArray on JArray<jdouble> {
});
}

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 size = end - start;
final it = iterable.skip(skipCount).take(size);
_allocate<JDoubleMarker>(sizeOf<JDoubleMarker>() * size, (ptr) {
it.forEachIndexed((index, element) {
ptr[index] = element;
});
Jni.env.SetDoubleArrayRegion(reference.pointer, start, size, ptr);
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);
});
}
}
Expand All @@ -373,8 +441,8 @@ extension ObjectArray<T extends JObject> on JArray<T> {

void setRange(int start, int end, Iterable<T> iterable, [int skipCount = 0]) {
RangeError.checkValidRange(start, end, length);
final size = end - start;
final it = iterable.skip(skipCount).take(size);
final rangeLength = end - start;
final it = iterable.skip(skipCount).take(rangeLength);
it.forEachIndexed((index, element) {
this[index] = element;
});
Expand Down
23 changes: 0 additions & 23 deletions pkgs/jni/src/dartjni.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,29 +343,6 @@ static inline jobject to_global_ref(jobject ref) {
return g;
}

// These functions are useful for C+Dart bindings, and not required for pure dart bindings.

FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr();

/// For use by jni_gen's generated code
/// don't use these.

// these 2 fn ptr vars will be defined by generated code library
extern JniContext* (*context_getter)(void);
extern JNIEnv* (*env_getter)(void);

// this function will be exported by generated code library
// it will set above 2 variables.
FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void),
JNIEnv* (*eg)(void));

static inline void load_env() {
if (jniEnv == NULL) {
jni = context_getter();
jniEnv = env_getter();
}
}

static inline jthrowable check_exception() {
jthrowable exception = (*jniEnv)->ExceptionOccurred(jniEnv);
if (exception != NULL) (*jniEnv)->ExceptionClear(jniEnv);
Expand Down
Loading
Loading