mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[wpiutil] jni_util: Add JSpan and CriticalJSpan (#5554)
These replace JArrayRef et al and support statically sized arrays similar to std::span.
This commit is contained in:
@@ -504,15 +504,14 @@ Java_edu_wpi_first_apriltag_jni_AprilTagJNI_estimatePoseHomography
|
||||
nullPointerEx.Throw(env, "homography cannot be null");
|
||||
return nullptr;
|
||||
}
|
||||
JDoubleArrayRef harr{env, homography};
|
||||
JSpan<const jdouble, 9> harr{env, homography};
|
||||
if (harr.size() != 9) {
|
||||
illegalArgEx.Throw(env, "homography array must be size 9");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AprilTagPoseEstimator estimator({units::meter_t{tagSize}, fx, fy, cx, cy});
|
||||
return MakeJObject(env, estimator.EstimateHomography(
|
||||
std::span<const double, 9>{harr.array()}));
|
||||
return MakeJObject(env, estimator.EstimateHomography(harr));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -530,7 +529,7 @@ Java_edu_wpi_first_apriltag_jni_AprilTagJNI_estimatePoseOrthogonalIteration
|
||||
nullPointerEx.Throw(env, "homography cannot be null");
|
||||
return nullptr;
|
||||
}
|
||||
JDoubleArrayRef harr{env, homography};
|
||||
JSpan<const jdouble, 9> harr{env, homography};
|
||||
if (harr.size() != 9) {
|
||||
illegalArgEx.Throw(env, "homography array must be size 9");
|
||||
return nullptr;
|
||||
@@ -541,7 +540,7 @@ Java_edu_wpi_first_apriltag_jni_AprilTagJNI_estimatePoseOrthogonalIteration
|
||||
nullPointerEx.Throw(env, "corners cannot be null");
|
||||
return nullptr;
|
||||
}
|
||||
JDoubleArrayRef carr{env, corners};
|
||||
JSpan<const jdouble, 8> carr{env, corners};
|
||||
if (carr.size() != 8) {
|
||||
illegalArgEx.Throw(env, "corners array must be size 8");
|
||||
return nullptr;
|
||||
@@ -549,9 +548,7 @@ Java_edu_wpi_first_apriltag_jni_AprilTagJNI_estimatePoseOrthogonalIteration
|
||||
|
||||
AprilTagPoseEstimator estimator({units::meter_t{tagSize}, fx, fy, cx, cy});
|
||||
return MakeJObject(env,
|
||||
estimator.EstimateOrthogonalIteration(
|
||||
std::span<const double, 9>{harr.array()},
|
||||
std::span<const double, 8>{carr.array()}, nIters));
|
||||
estimator.EstimateOrthogonalIteration(harr, carr, nIters));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -569,7 +566,7 @@ Java_edu_wpi_first_apriltag_jni_AprilTagJNI_estimatePose
|
||||
nullPointerEx.Throw(env, "homography cannot be null");
|
||||
return nullptr;
|
||||
}
|
||||
JDoubleArrayRef harr{env, homography};
|
||||
JSpan<const jdouble, 9> harr{env, homography};
|
||||
if (harr.size() != 9) {
|
||||
illegalArgEx.Throw(env, "homography array must be size 9");
|
||||
return nullptr;
|
||||
@@ -580,16 +577,14 @@ Java_edu_wpi_first_apriltag_jni_AprilTagJNI_estimatePose
|
||||
nullPointerEx.Throw(env, "corners cannot be null");
|
||||
return nullptr;
|
||||
}
|
||||
JDoubleArrayRef carr{env, corners};
|
||||
JSpan<const jdouble, 8> carr{env, corners};
|
||||
if (carr.size() != 8) {
|
||||
illegalArgEx.Throw(env, "corners array must be size 8");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AprilTagPoseEstimator estimator({units::meter_t{tagSize}, fx, fy, cx, cy});
|
||||
return MakeJObject(
|
||||
env, estimator.Estimate(std::span<const double, 9>{harr.array()},
|
||||
std::span<const double, 8>{carr.array()}));
|
||||
return MakeJObject(env, estimator.Estimate(harr, carr));
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
@@ -69,12 +69,11 @@ Java_edu_wpi_first_hal_AddressableLEDJNI_setData
|
||||
(JNIEnv* env, jclass, jint handle, jbyteArray arr)
|
||||
{
|
||||
int32_t status = 0;
|
||||
JByteArrayRef jArrRef{env, arr};
|
||||
auto arrRef = jArrRef.array();
|
||||
JSpan<const jbyte> jArrRef{env, arr};
|
||||
HAL_WriteAddressableLEDData(
|
||||
static_cast<HAL_AddressableLEDHandle>(handle),
|
||||
reinterpret_cast<const HAL_AddressableLEDData*>(arrRef.data()),
|
||||
arrRef.size() / 4, &status);
|
||||
reinterpret_cast<const HAL_AddressableLEDData*>(jArrRef.data()),
|
||||
jArrRef.size() / 4, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,11 +71,10 @@ Java_edu_wpi_first_hal_CANAPIJNI_writeCANPacket
|
||||
(JNIEnv* env, jclass, jint handle, jbyteArray data, jint apiId)
|
||||
{
|
||||
auto halHandle = static_cast<HAL_CANHandle>(handle);
|
||||
JByteArrayRef arr{env, data};
|
||||
auto arrRef = arr.array();
|
||||
JSpan<const jbyte> arr{env, data};
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacket(halHandle, reinterpret_cast<const uint8_t*>(arrRef.data()),
|
||||
arrRef.size(), apiId, &status);
|
||||
HAL_WriteCANPacket(halHandle, reinterpret_cast<const uint8_t*>(arr.data()),
|
||||
arr.size(), apiId, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
@@ -90,12 +89,11 @@ Java_edu_wpi_first_hal_CANAPIJNI_writeCANPacketRepeating
|
||||
jint timeoutMs)
|
||||
{
|
||||
auto halHandle = static_cast<HAL_CANHandle>(handle);
|
||||
JByteArrayRef arr{env, data};
|
||||
auto arrRef = arr.array();
|
||||
JSpan<const jbyte> arr{env, data};
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacketRepeating(halHandle,
|
||||
reinterpret_cast<const uint8_t*>(arrRef.data()),
|
||||
arrRef.size(), apiId, timeoutMs, &status);
|
||||
reinterpret_cast<const uint8_t*>(arr.data()),
|
||||
arr.size(), apiId, timeoutMs, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
@@ -124,11 +122,10 @@ Java_edu_wpi_first_hal_CANAPIJNI_writeCANPacketNoThrow
|
||||
(JNIEnv* env, jclass, jint handle, jbyteArray data, jint apiId)
|
||||
{
|
||||
auto halHandle = static_cast<HAL_CANHandle>(handle);
|
||||
JByteArrayRef arr{env, data};
|
||||
auto arrRef = arr.array();
|
||||
JSpan<const jbyte> arr{env, data};
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacket(halHandle, reinterpret_cast<const uint8_t*>(arrRef.data()),
|
||||
arrRef.size(), apiId, &status);
|
||||
HAL_WriteCANPacket(halHandle, reinterpret_cast<const uint8_t*>(arr.data()),
|
||||
arr.size(), apiId, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -143,12 +140,11 @@ Java_edu_wpi_first_hal_CANAPIJNI_writeCANPacketRepeatingNoThrow
|
||||
jint timeoutMs)
|
||||
{
|
||||
auto halHandle = static_cast<HAL_CANHandle>(handle);
|
||||
JByteArrayRef arr{env, data};
|
||||
auto arrRef = arr.array();
|
||||
JSpan<const jbyte> arr{env, data};
|
||||
int32_t status = 0;
|
||||
HAL_WriteCANPacketRepeating(halHandle,
|
||||
reinterpret_cast<const uint8_t*>(arrRef.data()),
|
||||
arrRef.size(), apiId, timeoutMs, &status);
|
||||
reinterpret_cast<const uint8_t*>(arr.data()),
|
||||
arr.size(), apiId, timeoutMs, &status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,11 +26,11 @@ JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_can_CANJNI_FRCNetCommCANSessionMuxSendMessage
|
||||
(JNIEnv* env, jclass, jint messageID, jbyteArray data, jint periodMs)
|
||||
{
|
||||
JByteArrayRef dataArray{env, data};
|
||||
JSpan<const jbyte> dataArray{env, data};
|
||||
|
||||
const uint8_t* dataBuffer =
|
||||
reinterpret_cast<const uint8_t*>(dataArray.array().data());
|
||||
uint8_t dataSize = dataArray.array().size();
|
||||
reinterpret_cast<const uint8_t*>(dataArray.data());
|
||||
uint8_t dataSize = dataArray.size();
|
||||
|
||||
int32_t status = 0;
|
||||
HAL_CAN_SendMessage(messageID, dataBuffer, dataSize, periodMs, &status);
|
||||
|
||||
@@ -5,12 +5,15 @@
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#include <wpi/jni_util.h>
|
||||
|
||||
#include "HALUtil.h"
|
||||
#include "edu_wpi_first_hal_DMAJNI.h"
|
||||
#include "hal/DMA.h"
|
||||
#include "hal/handles/HandlesInternal.h"
|
||||
|
||||
using namespace hal;
|
||||
using namespace wpi::java;
|
||||
|
||||
namespace hal {
|
||||
bool GetEncoderBaseHandle(HAL_EncoderHandle handle,
|
||||
@@ -312,20 +315,17 @@ Java_edu_wpi_first_hal_DMAJNI_readDMA
|
||||
env->SetIntArrayRegion(buf, 0, dmaSample.captureSize,
|
||||
reinterpret_cast<jint*>(dmaSample.readBuffer));
|
||||
|
||||
int32_t* nativeArr =
|
||||
static_cast<int32_t*>(env->GetPrimitiveArrayCritical(store, nullptr));
|
||||
CriticalJSpan<jint> nativeArr{env, store};
|
||||
|
||||
std::copy_n(
|
||||
dmaSample.channelOffsets,
|
||||
sizeof(dmaSample.channelOffsets) / sizeof(dmaSample.channelOffsets[0]),
|
||||
nativeArr);
|
||||
nativeArr.data());
|
||||
nativeArr[22] = static_cast<int32_t>(dmaSample.captureSize);
|
||||
nativeArr[23] = static_cast<int32_t>(dmaSample.triggerChannels);
|
||||
nativeArr[24] = remaining;
|
||||
nativeArr[25] = readStatus;
|
||||
|
||||
env->ReleasePrimitiveArrayCritical(store, nativeArr, JNI_ABORT);
|
||||
|
||||
return dmaSample.timeStamp;
|
||||
}
|
||||
|
||||
|
||||
@@ -251,10 +251,10 @@ Java_edu_wpi_first_hal_DriverStationJNI_getAllJoystickData
|
||||
|
||||
HAL_GetAllJoystickData(axes, povs, buttons);
|
||||
|
||||
CriticalJFloatArrayRef jAxes(env, axesArray);
|
||||
CriticalJByteArrayRef jRawAxes(env, rawAxesArray);
|
||||
CriticalJShortArrayRef jPovs(env, povsArray);
|
||||
CriticalJLongArrayRef jButtons(env, buttonsAndMetadataArray);
|
||||
CriticalJSpan<jfloat> jAxes(env, axesArray);
|
||||
CriticalJSpan<jbyte> jRawAxes(env, rawAxesArray);
|
||||
CriticalJSpan<jshort> jPovs(env, povsArray);
|
||||
CriticalJSpan<jlong> jButtons(env, buttonsAndMetadataArray);
|
||||
|
||||
static_assert(sizeof(jAxes[0]) == sizeof(axes[0].axes[0]));
|
||||
static_assert(sizeof(jRawAxes[0]) == sizeof(axes[0].raw[0]));
|
||||
|
||||
@@ -79,7 +79,7 @@ Java_edu_wpi_first_hal_I2CJNI_i2CTransactionB
|
||||
jint returnValue =
|
||||
HAL_TransactionI2C(static_cast<HAL_I2CPort>(port), address,
|
||||
reinterpret_cast<const uint8_t*>(
|
||||
JByteArrayRef(env, dataToSend).array().data()),
|
||||
JSpan<const jbyte>(env, dataToSend).data()),
|
||||
sendSize, recvBuf.data(), receiveSize);
|
||||
env->SetByteArrayRegion(dataReceived, 0, receiveSize,
|
||||
reinterpret_cast<const jbyte*>(recvBuf.data()));
|
||||
@@ -120,7 +120,7 @@ Java_edu_wpi_first_hal_I2CJNI_i2CWriteB
|
||||
jint returnValue =
|
||||
HAL_WriteI2C(static_cast<HAL_I2CPort>(port), address,
|
||||
reinterpret_cast<const uint8_t*>(
|
||||
JByteArrayRef(env, dataToSend).array().data()),
|
||||
JSpan<const jbyte>(env, dataToSend).data()),
|
||||
sendSize);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ Java_edu_wpi_first_hal_SPIJNI_spiTransactionB
|
||||
jint retVal =
|
||||
HAL_TransactionSPI(static_cast<HAL_SPIPort>(port),
|
||||
reinterpret_cast<const uint8_t*>(
|
||||
JByteArrayRef(env, dataToSend).array().data()),
|
||||
JSpan<const jbyte>(env, dataToSend).data()),
|
||||
recvBuf.data(), size);
|
||||
env->SetByteArrayRegion(dataReceived, 0, size,
|
||||
reinterpret_cast<const jbyte*>(recvBuf.data()));
|
||||
@@ -131,7 +131,7 @@ Java_edu_wpi_first_hal_SPIJNI_spiWriteB
|
||||
{
|
||||
jint retVal = HAL_WriteSPI(static_cast<HAL_SPIPort>(port),
|
||||
reinterpret_cast<const uint8_t*>(
|
||||
JByteArrayRef(env, dataToSend).array().data()),
|
||||
JSpan<const jbyte>(env, dataToSend).data()),
|
||||
size);
|
||||
return retVal;
|
||||
}
|
||||
@@ -356,12 +356,11 @@ JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_SPIJNI_spiSetAutoTransmitData
|
||||
(JNIEnv* env, jclass, jint port, jbyteArray dataToSend, jint zeroSize)
|
||||
{
|
||||
JByteArrayRef jarr(env, dataToSend);
|
||||
JSpan<const jbyte> jarr(env, dataToSend);
|
||||
int32_t status = 0;
|
||||
HAL_SetSPIAutoTransmitData(
|
||||
static_cast<HAL_SPIPort>(port),
|
||||
reinterpret_cast<const uint8_t*>(jarr.array().data()),
|
||||
jarr.array().size(), zeroSize, &status);
|
||||
HAL_SetSPIAutoTransmitData(static_cast<HAL_SPIPort>(port),
|
||||
reinterpret_cast<const uint8_t*>(jarr.data()),
|
||||
jarr.size(), zeroSize, &status);
|
||||
CheckStatus(env, status);
|
||||
}
|
||||
|
||||
|
||||
@@ -261,11 +261,10 @@ Java_edu_wpi_first_hal_SerialPortJNI_serialWrite
|
||||
(JNIEnv* env, jclass, jint handle, jbyteArray dataToSend, jint size)
|
||||
{
|
||||
int32_t status = 0;
|
||||
jint retVal =
|
||||
HAL_WriteSerial(static_cast<HAL_SerialPortHandle>(handle),
|
||||
reinterpret_cast<const char*>(
|
||||
JByteArrayRef(env, dataToSend).array().data()),
|
||||
size, &status);
|
||||
jint retVal = HAL_WriteSerial(
|
||||
static_cast<HAL_SerialPortHandle>(handle),
|
||||
reinterpret_cast<const char*>(JSpan<const jbyte>(env, dataToSend).data()),
|
||||
size, &status);
|
||||
CheckStatus(env, status);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ Java_edu_wpi_first_hal_SimDeviceJNI_createSimValueEnumDouble
|
||||
}
|
||||
return HAL_CreateSimValueEnumDouble(
|
||||
device, JStringRef{env, name}.c_str(), direction, len, carr.data(),
|
||||
JDoubleArrayRef{env, optionValues}.array().data(), initialValue);
|
||||
JSpan<const jdouble>{env, optionValues}.data(), initialValue);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -269,7 +269,7 @@ JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_hal_simulation_AddressableLEDDataJNI_setData
|
||||
(JNIEnv* env, jclass, jint index, jbyteArray arr)
|
||||
{
|
||||
JByteArrayRef jArrRef{env, arr};
|
||||
JSpan<const jbyte> jArrRef{env, arr};
|
||||
auto arrRef = jArrRef.array();
|
||||
HALSIM_SetAddressableLEDData(
|
||||
index, reinterpret_cast<const HAL_AddressableLEDData*>(arrRef.data()),
|
||||
|
||||
@@ -436,7 +436,7 @@ Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickAxes
|
||||
{
|
||||
HAL_JoystickAxes axes;
|
||||
{
|
||||
wpi::java::JFloatArrayRef jArrayRef(env, axesArray);
|
||||
JSpan<const jfloat> jArrayRef(env, axesArray);
|
||||
auto arrayRef = jArrayRef.array();
|
||||
auto arraySize = arrayRef.size();
|
||||
int maxCount =
|
||||
@@ -461,7 +461,7 @@ Java_edu_wpi_first_hal_simulation_DriverStationDataJNI_setJoystickPOVs
|
||||
{
|
||||
HAL_JoystickPOVs povs;
|
||||
{
|
||||
wpi::java::JShortArrayRef jArrayRef(env, povsArray);
|
||||
JSpan<const jshort> jArrayRef(env, povsArray);
|
||||
auto arrayRef = jArrayRef.array();
|
||||
auto arraySize = arrayRef.size();
|
||||
int maxCount =
|
||||
|
||||
@@ -77,7 +77,7 @@ void JNI_UnloadTypes(JNIEnv* env) {
|
||||
} // namespace nt
|
||||
|
||||
static std::vector<int> FromJavaBooleanArray(JNIEnv* env, jbooleanArray jarr) {
|
||||
CriticalJBooleanArrayRef ref{env, jarr};
|
||||
CriticalJSpan<const jboolean> ref{env, jarr};
|
||||
if (!ref) {
|
||||
return {};
|
||||
}
|
||||
@@ -214,7 +214,7 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_setRaw
|
||||
indexOobEx.Throw(env, "len must be >= 0");
|
||||
return false;
|
||||
}
|
||||
CriticalJByteArrayRef cvalue{env, value};
|
||||
CriticalJSpan<const jbyte> cvalue{env, value};
|
||||
if (static_cast<unsigned int>(start + len) > cvalue.size()) {
|
||||
indexOobEx.Throw(env, "start + len must be smaller than array length");
|
||||
return false;
|
||||
@@ -243,7 +243,7 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_setRawBuffer
|
||||
indexOobEx.Throw(env, "len must be >= 0");
|
||||
return false;
|
||||
}
|
||||
JByteArrayRef cvalue{env, value, start + len};
|
||||
JSpan<const jbyte> cvalue{env, value, static_cast<size_t>(start + len)};
|
||||
if (!cvalue) {
|
||||
illegalArgEx.Throw(env, "value must be a native ByteBuffer");
|
||||
return false;
|
||||
@@ -310,7 +310,7 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_setDefaultRaw
|
||||
indexOobEx.Throw(env, "len must be >= 0");
|
||||
return false;
|
||||
}
|
||||
CriticalJByteArrayRef cvalue{env, defaultValue};
|
||||
CriticalJSpan<const jbyte> cvalue{env, defaultValue};
|
||||
if (static_cast<unsigned int>(start + len) > cvalue.size()) {
|
||||
indexOobEx.Throw(env, "start + len must be smaller than array length");
|
||||
return false;
|
||||
@@ -339,7 +339,7 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_setDefaultRawBuffer
|
||||
indexOobEx.Throw(env, "len must be >= 0");
|
||||
return false;
|
||||
}
|
||||
JByteArrayRef cvalue{env, defaultValue, start + len};
|
||||
JSpan<const jbyte> cvalue{env, defaultValue, static_cast<size_t>(start + len)};
|
||||
if (!cvalue) {
|
||||
illegalArgEx.Throw(env, "value must be a native ByteBuffer");
|
||||
return false;
|
||||
|
||||
@@ -190,7 +190,7 @@
|
||||
"jtype": "jbyteArray",
|
||||
"jtypestr": "[B",
|
||||
"JavaObject": true,
|
||||
"FromJavaBegin": "CriticalJByteArrayRef{env, ",
|
||||
"FromJavaBegin": "CriticalJSpan<const jbyte>{env, ",
|
||||
"FromJavaEnd": "}.uarray()",
|
||||
"ToJavaBegin": "MakeJByteArray(env, ",
|
||||
"ToJavaEnd": ")",
|
||||
@@ -262,7 +262,7 @@
|
||||
"jtype": "jlongArray",
|
||||
"jtypestr": "[J",
|
||||
"JavaObject": true,
|
||||
"FromJavaBegin": "CriticalJLongArrayRef{env, ",
|
||||
"FromJavaBegin": "CriticalJSpan<const jlong>{env, ",
|
||||
"FromJavaEnd": "}",
|
||||
"ToJavaBegin": "MakeJLongArray(env, ",
|
||||
"ToJavaEnd": ")",
|
||||
@@ -298,7 +298,7 @@
|
||||
"jtype": "jfloatArray",
|
||||
"jtypestr": "[F",
|
||||
"JavaObject": true,
|
||||
"FromJavaBegin": "CriticalJFloatArrayRef{env, ",
|
||||
"FromJavaBegin": "CriticalJSpan<const jfloat>{env, ",
|
||||
"FromJavaEnd": "}",
|
||||
"ToJavaBegin": "MakeJFloatArray(env, ",
|
||||
"ToJavaEnd": ")",
|
||||
@@ -334,7 +334,7 @@
|
||||
"jtype": "jdoubleArray",
|
||||
"jtypestr": "[D",
|
||||
"JavaObject": true,
|
||||
"FromJavaBegin": "CriticalJDoubleArrayRef{env, ",
|
||||
"FromJavaBegin": "CriticalJSpan<const jdouble>{env, ",
|
||||
"FromJavaEnd": "}",
|
||||
"ToJavaBegin": "MakeJDoubleArray(env, ",
|
||||
"ToJavaEnd": ")",
|
||||
|
||||
@@ -1262,7 +1262,7 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_setServer__I_3Ljava_lang_Strin
|
||||
"serverNames and ports arrays must be the same size");
|
||||
return;
|
||||
}
|
||||
jint* portInts = env->GetIntArrayElements(ports, nullptr);
|
||||
JSpan<const jint> portInts{env, ports};
|
||||
if (!portInts) {
|
||||
return;
|
||||
}
|
||||
@@ -1282,7 +1282,6 @@ Java_edu_wpi_first_networktables_NetworkTablesJNI_setServer__I_3Ljava_lang_Strin
|
||||
servers.emplace_back(
|
||||
std::make_pair(std::string_view{names.back()}, portInts[i]));
|
||||
}
|
||||
env->ReleaseIntArrayElements(ports, portInts, JNI_ABORT);
|
||||
nt::SetServer(inst, servers);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,23 +72,23 @@ Java_edu_wpi_first_math_WPIMathJNI_dareDetailABQR
|
||||
(JNIEnv* env, jclass, jdoubleArray A, jdoubleArray B, jdoubleArray Q,
|
||||
jdoubleArray R, jint states, jint inputs, jdoubleArray S)
|
||||
{
|
||||
JDoubleArrayRef nativeA{env, A};
|
||||
JDoubleArrayRef nativeB{env, B};
|
||||
JDoubleArrayRef nativeQ{env, Q};
|
||||
JDoubleArrayRef nativeR{env, R};
|
||||
JSpan<const jdouble> nativeA{env, A};
|
||||
JSpan<const jdouble> nativeB{env, B};
|
||||
JSpan<const jdouble> nativeQ{env, Q};
|
||||
JSpan<const jdouble> nativeR{env, R};
|
||||
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Amat{nativeA.array().data(), states, states};
|
||||
Amat{nativeA.data(), states, states};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Bmat{nativeB.array().data(), states, inputs};
|
||||
Bmat{nativeB.data(), states, inputs};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Qmat{nativeQ.array().data(), states, states};
|
||||
Qmat{nativeQ.data(), states, states};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Rmat{nativeR.array().data(), inputs, inputs};
|
||||
Rmat{nativeR.data(), inputs, inputs};
|
||||
|
||||
Eigen::MatrixXd RmatCopy{Rmat};
|
||||
auto R_llt = RmatCopy.llt();
|
||||
@@ -109,27 +109,27 @@ Java_edu_wpi_first_math_WPIMathJNI_dareDetailABQRN
|
||||
(JNIEnv* env, jclass, jdoubleArray A, jdoubleArray B, jdoubleArray Q,
|
||||
jdoubleArray R, jdoubleArray N, jint states, jint inputs, jdoubleArray S)
|
||||
{
|
||||
JDoubleArrayRef nativeA{env, A};
|
||||
JDoubleArrayRef nativeB{env, B};
|
||||
JDoubleArrayRef nativeQ{env, Q};
|
||||
JDoubleArrayRef nativeR{env, R};
|
||||
JDoubleArrayRef nativeN{env, N};
|
||||
JSpan<const jdouble> nativeA{env, A};
|
||||
JSpan<const jdouble> nativeB{env, B};
|
||||
JSpan<const jdouble> nativeQ{env, Q};
|
||||
JSpan<const jdouble> nativeR{env, R};
|
||||
JSpan<const jdouble> nativeN{env, N};
|
||||
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Amat{nativeA.array().data(), states, states};
|
||||
Amat{nativeA.data(), states, states};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Bmat{nativeB.array().data(), states, inputs};
|
||||
Bmat{nativeB.data(), states, inputs};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Qmat{nativeQ.array().data(), states, states};
|
||||
Qmat{nativeQ.data(), states, states};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Rmat{nativeR.array().data(), inputs, inputs};
|
||||
Rmat{nativeR.data(), inputs, inputs};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Nmat{nativeN.array().data(), states, inputs};
|
||||
Nmat{nativeN.data(), states, inputs};
|
||||
|
||||
Eigen::MatrixXd Rcopy{Rmat};
|
||||
auto R_llt = Rcopy.llt();
|
||||
@@ -150,23 +150,23 @@ Java_edu_wpi_first_math_WPIMathJNI_dareABQR
|
||||
(JNIEnv* env, jclass, jdoubleArray A, jdoubleArray B, jdoubleArray Q,
|
||||
jdoubleArray R, jint states, jint inputs, jdoubleArray S)
|
||||
{
|
||||
JDoubleArrayRef nativeA{env, A};
|
||||
JDoubleArrayRef nativeB{env, B};
|
||||
JDoubleArrayRef nativeQ{env, Q};
|
||||
JDoubleArrayRef nativeR{env, R};
|
||||
JSpan<const jdouble> nativeA{env, A};
|
||||
JSpan<const jdouble> nativeB{env, B};
|
||||
JSpan<const jdouble> nativeQ{env, Q};
|
||||
JSpan<const jdouble> nativeR{env, R};
|
||||
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Amat{nativeA.array().data(), states, states};
|
||||
Amat{nativeA.data(), states, states};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Bmat{nativeB.array().data(), states, inputs};
|
||||
Bmat{nativeB.data(), states, inputs};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Qmat{nativeQ.array().data(), states, states};
|
||||
Qmat{nativeQ.data(), states, states};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Rmat{nativeR.array().data(), inputs, inputs};
|
||||
Rmat{nativeR.data(), inputs, inputs};
|
||||
|
||||
try {
|
||||
Eigen::MatrixXd result =
|
||||
@@ -191,27 +191,27 @@ Java_edu_wpi_first_math_WPIMathJNI_dareABQRN
|
||||
(JNIEnv* env, jclass, jdoubleArray A, jdoubleArray B, jdoubleArray Q,
|
||||
jdoubleArray R, jdoubleArray N, jint states, jint inputs, jdoubleArray S)
|
||||
{
|
||||
JDoubleArrayRef nativeA{env, A};
|
||||
JDoubleArrayRef nativeB{env, B};
|
||||
JDoubleArrayRef nativeQ{env, Q};
|
||||
JDoubleArrayRef nativeR{env, R};
|
||||
JDoubleArrayRef nativeN{env, N};
|
||||
JSpan<const jdouble> nativeA{env, A};
|
||||
JSpan<const jdouble> nativeB{env, B};
|
||||
JSpan<const jdouble> nativeQ{env, Q};
|
||||
JSpan<const jdouble> nativeR{env, R};
|
||||
JSpan<const jdouble> nativeN{env, N};
|
||||
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Amat{nativeA.array().data(), states, states};
|
||||
Amat{nativeA.data(), states, states};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Bmat{nativeB.array().data(), states, inputs};
|
||||
Bmat{nativeB.data(), states, inputs};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Qmat{nativeQ.array().data(), states, states};
|
||||
Qmat{nativeQ.data(), states, states};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Rmat{nativeR.array().data(), inputs, inputs};
|
||||
Rmat{nativeR.data(), inputs, inputs};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Nmat{nativeN.array().data(), states, inputs};
|
||||
Nmat{nativeN.data(), states, inputs};
|
||||
|
||||
try {
|
||||
Eigen::MatrixXd result =
|
||||
@@ -235,11 +235,11 @@ JNIEXPORT void JNICALL
|
||||
Java_edu_wpi_first_math_WPIMathJNI_exp
|
||||
(JNIEnv* env, jclass, jdoubleArray src, jint rows, jdoubleArray dst)
|
||||
{
|
||||
JDoubleArrayRef arrayBody{env, src};
|
||||
JSpan<const jdouble> arrayBody{env, src};
|
||||
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Amat{arrayBody.array().data(), rows, rows};
|
||||
Amat{arrayBody.data(), rows, rows};
|
||||
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> Aexp =
|
||||
Amat.exp();
|
||||
|
||||
@@ -256,11 +256,11 @@ Java_edu_wpi_first_math_WPIMathJNI_pow
|
||||
(JNIEnv* env, jclass, jdoubleArray src, jint rows, jdouble exponent,
|
||||
jdoubleArray dst)
|
||||
{
|
||||
JDoubleArrayRef arrayBody{env, src};
|
||||
JSpan<const jdouble> arrayBody{env, src};
|
||||
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Amat{arrayBody.array().data(), rows, rows}; // NOLINT
|
||||
Amat{arrayBody.data(), rows, rows}; // NOLINT
|
||||
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> Apow =
|
||||
Amat.pow(exponent);
|
||||
|
||||
@@ -331,16 +331,16 @@ Java_edu_wpi_first_math_WPIMathJNI_isStabilizable
|
||||
(JNIEnv* env, jclass, jint states, jint inputs, jdoubleArray aSrc,
|
||||
jdoubleArray bSrc)
|
||||
{
|
||||
JDoubleArrayRef nativeA{env, aSrc};
|
||||
JDoubleArrayRef nativeB{env, bSrc};
|
||||
JSpan<const jdouble> nativeA{env, aSrc};
|
||||
JSpan<const jdouble> nativeB{env, bSrc};
|
||||
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
A{nativeA.array().data(), states, states};
|
||||
A{nativeA.data(), states, states};
|
||||
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
B{nativeB.array().data(), states, inputs};
|
||||
B{nativeB.data(), states, inputs};
|
||||
|
||||
bool isStabilizable =
|
||||
frc::IsStabilizable<Eigen::Dynamic, Eigen::Dynamic>(A, B);
|
||||
@@ -382,7 +382,7 @@ Java_edu_wpi_first_math_WPIMathJNI_toPathweaverJson
|
||||
{
|
||||
try {
|
||||
auto trajectory =
|
||||
CreateTrajectoryFromElements(JDoubleArrayRef{env, elements});
|
||||
CreateTrajectoryFromElements(JSpan<const jdouble>{env, elements});
|
||||
frc::TrajectoryUtil::ToPathweaverJson(trajectory,
|
||||
JStringRef{env, path}.c_str());
|
||||
} catch (std::exception& e) {
|
||||
@@ -429,7 +429,7 @@ Java_edu_wpi_first_math_WPIMathJNI_serializeTrajectory
|
||||
{
|
||||
try {
|
||||
auto trajectory =
|
||||
CreateTrajectoryFromElements(JDoubleArrayRef{env, elements});
|
||||
CreateTrajectoryFromElements(JSpan<const jdouble>{env, elements});
|
||||
return MakeJString(env,
|
||||
frc::TrajectoryUtil::SerializeTrajectory(trajectory));
|
||||
} catch (std::exception& e) {
|
||||
@@ -453,24 +453,20 @@ Java_edu_wpi_first_math_WPIMathJNI_rankUpdate
|
||||
(JNIEnv* env, jclass, jdoubleArray mat, jint rows, jdoubleArray vec,
|
||||
jdouble sigma, jboolean lowerTriangular)
|
||||
{
|
||||
// TODO: Replace with JSpan<jdouble> matBody{env, mat} when that exists
|
||||
jdouble* matBody = env->GetDoubleArrayElements(mat, nullptr);
|
||||
JDoubleArrayRef vecBody{env, vec};
|
||||
JSpan<jdouble> matBody{env, mat};
|
||||
JSpan<const jdouble> vecBody{env, vec};
|
||||
|
||||
Eigen::Map<
|
||||
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>
|
||||
L{matBody, rows, rows};
|
||||
Eigen::Map<const Eigen::Vector<double, Eigen::Dynamic>> v{
|
||||
vecBody.array().data(), rows};
|
||||
L{matBody.data(), rows, rows};
|
||||
Eigen::Map<const Eigen::Vector<double, Eigen::Dynamic>> v{vecBody.data(),
|
||||
rows};
|
||||
|
||||
if (lowerTriangular == JNI_TRUE) {
|
||||
Eigen::internal::llt_inplace<double, Eigen::Lower>::rankUpdate(L, v, sigma);
|
||||
} else {
|
||||
Eigen::internal::llt_inplace<double, Eigen::Upper>::rankUpdate(L, v, sigma);
|
||||
}
|
||||
|
||||
// TODO: Remove this after JSpan transition
|
||||
env->ReleaseDoubleArrayElements(mat, matBody, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -483,15 +479,15 @@ Java_edu_wpi_first_math_WPIMathJNI_solveFullPivHouseholderQr
|
||||
(JNIEnv* env, jclass, jdoubleArray A, jint Arows, jint Acols, jdoubleArray B,
|
||||
jint Brows, jint Bcols, jdoubleArray dst)
|
||||
{
|
||||
JDoubleArrayRef nativeA{env, A};
|
||||
JDoubleArrayRef nativeB{env, B};
|
||||
JSpan<const jdouble> nativeA{env, A};
|
||||
JSpan<const jdouble> nativeB{env, B};
|
||||
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Amat{nativeA.array().data(), Arows, Acols};
|
||||
Amat{nativeA.data(), Arows, Acols};
|
||||
Eigen::Map<const Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic,
|
||||
Eigen::RowMajor>>
|
||||
Bmat{nativeB.array().data(), Brows, Bcols};
|
||||
Bmat{nativeB.data(), Brows, Bcols};
|
||||
|
||||
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> Xmat =
|
||||
Amat.fullPivHouseholderQr().solve(Bmat);
|
||||
|
||||
@@ -201,7 +201,7 @@ Java_edu_wpi_first_util_datalog_DataLogJNI_appendRaw
|
||||
wpi::ThrowIndexOobException(env, "length must be >= 0");
|
||||
return;
|
||||
}
|
||||
CriticalJByteArrayRef cvalue{env, value};
|
||||
CriticalJSpan<const jbyte> cvalue{env, value};
|
||||
if (static_cast<unsigned int>(start + length) > cvalue.size()) {
|
||||
wpi::ThrowIndexOobException(
|
||||
env, "start + len must be smaller than array length");
|
||||
@@ -237,7 +237,7 @@ Java_edu_wpi_first_util_datalog_DataLogJNI_appendRawBuffer
|
||||
wpi::ThrowIndexOobException(env, "length must be >= 0");
|
||||
return;
|
||||
}
|
||||
JByteArrayRef cvalue{env, value, start + length};
|
||||
JSpan<const jbyte> cvalue{env, value, static_cast<size_t>(start + length)};
|
||||
if (!cvalue) {
|
||||
wpi::ThrowIllegalArgumentException(env,
|
||||
"value must be a native ByteBuffer");
|
||||
@@ -347,7 +347,7 @@ Java_edu_wpi_first_util_datalog_DataLogJNI_appendBooleanArray
|
||||
return;
|
||||
}
|
||||
reinterpret_cast<DataLog*>(impl)->AppendBooleanArray(
|
||||
entry, JBooleanArrayRef{env, value}, timestamp);
|
||||
entry, JSpan<const jboolean>{env, value}, timestamp);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -368,17 +368,15 @@ Java_edu_wpi_first_util_datalog_DataLogJNI_appendIntegerArray
|
||||
wpi::ThrowNullPointerException(env, "value is null");
|
||||
return;
|
||||
}
|
||||
JLongArrayRef jarr{env, value};
|
||||
JSpan<const jlong> jarr{env, value};
|
||||
if constexpr (sizeof(jlong) == sizeof(int64_t)) {
|
||||
reinterpret_cast<DataLog*>(impl)->AppendIntegerArray(
|
||||
entry,
|
||||
{reinterpret_cast<const int64_t*>(jarr.array().data()),
|
||||
jarr.array().size()},
|
||||
entry, {reinterpret_cast<const int64_t*>(jarr.data()), jarr.size()},
|
||||
timestamp);
|
||||
} else {
|
||||
wpi::SmallVector<int64_t, 16> arr;
|
||||
arr.reserve(jarr.size());
|
||||
for (auto v : jarr.array()) {
|
||||
for (auto v : jarr) {
|
||||
arr.push_back(v);
|
||||
}
|
||||
reinterpret_cast<DataLog*>(impl)->AppendIntegerArray(entry, arr, timestamp);
|
||||
@@ -404,7 +402,7 @@ Java_edu_wpi_first_util_datalog_DataLogJNI_appendFloatArray
|
||||
return;
|
||||
}
|
||||
reinterpret_cast<DataLog*>(impl)->AppendFloatArray(
|
||||
entry, JFloatArrayRef{env, value}, timestamp);
|
||||
entry, JSpan<const jfloat>{env, value}, timestamp);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -426,7 +424,7 @@ Java_edu_wpi_first_util_datalog_DataLogJNI_appendDoubleArray
|
||||
return;
|
||||
}
|
||||
reinterpret_cast<DataLog*>(impl)->AppendDoubleArray(
|
||||
entry, JDoubleArrayRef{env, value}, timestamp);
|
||||
entry, JSpan<const jdouble>{env, value}, timestamp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -275,11 +275,11 @@ JNIEXPORT jintArray JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_waitForObjects
|
||||
(JNIEnv* env, jclass, jintArray handles)
|
||||
{
|
||||
JIntArrayRef handlesArr{env, handles};
|
||||
JSpan<const jint> handlesArr{env, handles};
|
||||
wpi::SmallVector<WPI_Handle, 8> signaledBuf;
|
||||
signaledBuf.resize(handlesArr.size());
|
||||
std::span<const WPI_Handle> handlesArr2{
|
||||
reinterpret_cast<const WPI_Handle*>(handlesArr.array().data()),
|
||||
reinterpret_cast<const WPI_Handle*>(handlesArr.data()),
|
||||
handlesArr.size()};
|
||||
|
||||
auto signaled = wpi::WaitForObjects(handlesArr2, signaledBuf);
|
||||
@@ -299,11 +299,11 @@ JNIEXPORT jintArray JNICALL
|
||||
Java_edu_wpi_first_util_WPIUtilJNI_waitForObjectsTimeout
|
||||
(JNIEnv* env, jclass, jintArray handles, jdouble timeout)
|
||||
{
|
||||
JIntArrayRef handlesArr{env, handles};
|
||||
JSpan<const jint> handlesArr{env, handles};
|
||||
wpi::SmallVector<WPI_Handle, 8> signaledBuf;
|
||||
signaledBuf.resize(handlesArr.size());
|
||||
std::span<const WPI_Handle> handlesArr2{
|
||||
reinterpret_cast<const WPI_Handle*>(handlesArr.array().data()),
|
||||
reinterpret_cast<const WPI_Handle*>(handlesArr.data()),
|
||||
handlesArr.size()};
|
||||
|
||||
bool timedOut;
|
||||
|
||||
@@ -175,207 +175,242 @@ class JStringRef {
|
||||
SmallString<128> m_str;
|
||||
};
|
||||
|
||||
// Details for J*ArrayRef and CriticalJ*ArrayRef
|
||||
namespace detail {
|
||||
|
||||
template <typename C, typename T>
|
||||
class JArrayRefInner {
|
||||
template <typename T>
|
||||
struct ArrayHelper {};
|
||||
|
||||
#define WPI_JNI_ARRAYHELPER(T, F) \
|
||||
template <> \
|
||||
struct ArrayHelper<T> { \
|
||||
using jarray_type = T##Array; \
|
||||
static T* GetArrayElements(JNIEnv* env, jarray_type jarr) { \
|
||||
return env->Get##F##ArrayElements(jarr, nullptr); \
|
||||
} \
|
||||
static void ReleaseArrayElements(JNIEnv* env, jarray_type jarr, T* elems, \
|
||||
jint mode) { \
|
||||
env->Release##F##ArrayElements(jarr, elems, mode); \
|
||||
} \
|
||||
};
|
||||
|
||||
WPI_JNI_ARRAYHELPER(jboolean, Boolean)
|
||||
WPI_JNI_ARRAYHELPER(jbyte, Byte)
|
||||
WPI_JNI_ARRAYHELPER(jshort, Short)
|
||||
WPI_JNI_ARRAYHELPER(jint, Int)
|
||||
WPI_JNI_ARRAYHELPER(jlong, Long)
|
||||
WPI_JNI_ARRAYHELPER(jfloat, Float)
|
||||
WPI_JNI_ARRAYHELPER(jdouble, Double)
|
||||
|
||||
#undef WPI_JNI_ARRAYHELPER
|
||||
|
||||
template <typename T>
|
||||
concept JArrayType =
|
||||
requires { typename ArrayHelper<std::remove_cv_t<T>>::jarray_type; };
|
||||
|
||||
template <typename CvSrc, typename Dest>
|
||||
struct copy_cv {
|
||||
private:
|
||||
using U0 = std::remove_cv_t<Dest>;
|
||||
using U1 = std::conditional_t<std::is_const_v<CvSrc>, const U0, U0>;
|
||||
using U2 = std::conditional_t<std::is_volatile_v<CvSrc>, volatile U1, U1>;
|
||||
|
||||
public:
|
||||
operator std::span<const T>() const { // NOLINT
|
||||
return static_cast<const C*>(this)->array();
|
||||
}
|
||||
using type = U2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Specialization of JArrayRefBase to provide std::string_view conversion
|
||||
* and span<const uint8_t> conversion.
|
||||
*/
|
||||
template <typename C>
|
||||
class JArrayRefInner<C, jbyte> {
|
||||
public:
|
||||
operator std::string_view() const { return str(); }
|
||||
template <typename CvSrc, typename Dest>
|
||||
using copy_cv_t = typename copy_cv<CvSrc, Dest>::type;
|
||||
|
||||
std::string_view str() const {
|
||||
auto arr = static_cast<const C*>(this)->array();
|
||||
template <typename From, typename To>
|
||||
constexpr bool is_qualification_convertible_v =
|
||||
!(std::is_const_v<From> && !std::is_const_v<To>)&&!(
|
||||
std::is_volatile_v<From> && !std::is_volatile_v<To>);
|
||||
|
||||
/**
|
||||
* Helper class for working with JNI arrays.
|
||||
*
|
||||
* This class exposes an is_valid() member and an explicit conversion to bool
|
||||
* which indicate if the span is valid. Operations on invalid spans are
|
||||
* undefined.
|
||||
*
|
||||
* Note that Set<PrimitiveType>ArrayRegion may be faster for pure writes since
|
||||
* it avoids copying the elements from Java to C++.
|
||||
*
|
||||
* @tparam T The element type of the array (e.g., jdouble).
|
||||
* @tparam IsCritical If true, Get/ReleasePrimitiveArrayCritical will be used
|
||||
* instead of Get/Release\<PrimitiveType\>ArrayElements.
|
||||
* @tparam Size The number of elements in the span.
|
||||
*/
|
||||
template <JArrayType T, bool IsCritical, size_t Size = std::dynamic_extent>
|
||||
class JSpanBase {
|
||||
using ArrHelper = ArrayHelper<std::remove_cv_t<T>>;
|
||||
using jarray_type = typename ArrHelper::jarray_type;
|
||||
|
||||
public:
|
||||
JSpanBase(const JSpanBase&) = delete;
|
||||
JSpanBase& operator=(const JSpanBase&) = delete;
|
||||
|
||||
JSpanBase(JSpanBase&& other)
|
||||
: m_valid{other.m_valid},
|
||||
m_env{other.m_env},
|
||||
m_jarr{other.m_jarr},
|
||||
m_size{other.m_size},
|
||||
m_elements{other.m_elements} {
|
||||
other.m_jarr = nullptr;
|
||||
other.m_elements = nullptr;
|
||||
}
|
||||
|
||||
JSpanBase& operator=(JSpanBase&& other) {
|
||||
m_valid = other.m_valid;
|
||||
m_env = other.m_env;
|
||||
m_jarr = other.m_jarr;
|
||||
m_size = other.m_size;
|
||||
m_elements = other.m_elements;
|
||||
other.m_valid = false;
|
||||
other.m_jarr = nullptr;
|
||||
other.m_elements = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
JSpanBase(JNIEnv* env, jobject bb, size_t size)
|
||||
requires(!IsCritical)
|
||||
: m_valid{Size == std::dynamic_extent || size == Size},
|
||||
m_env{env},
|
||||
m_jarr{nullptr},
|
||||
m_size{size},
|
||||
m_elements{static_cast<std::remove_cv_t<T>*>(
|
||||
bb ? env->GetDirectBufferAddress(bb) : nullptr)} {
|
||||
if (!bb) {
|
||||
errs() << "JSpan was passed a null pointer at \n"
|
||||
<< GetJavaStackTrace(env);
|
||||
}
|
||||
}
|
||||
|
||||
JSpanBase(JNIEnv* env, jarray_type jarr, size_t size)
|
||||
: m_valid{Size == std::dynamic_extent || size == Size},
|
||||
m_env{env},
|
||||
m_jarr{jarr},
|
||||
m_size{size},
|
||||
m_elements{nullptr} {
|
||||
if (jarr) {
|
||||
if constexpr (IsCritical) {
|
||||
m_elements = static_cast<std::remove_cv_t<T>*>(
|
||||
env->GetPrimitiveArrayCritical(jarr, nullptr));
|
||||
} else {
|
||||
m_elements = ArrHelper::GetArrayElements(env, jarr);
|
||||
}
|
||||
} else {
|
||||
errs() << "JSpan was passed a null pointer at \n"
|
||||
<< GetJavaStackTrace(env);
|
||||
}
|
||||
}
|
||||
|
||||
JSpanBase(JNIEnv* env, jarray_type jarr)
|
||||
: JSpanBase(env, jarr, jarr ? env->GetArrayLength(jarr) : 0) {}
|
||||
|
||||
~JSpanBase() {
|
||||
if (m_jarr && m_elements) {
|
||||
constexpr jint mode = std::is_const_v<T> ? JNI_ABORT : 0;
|
||||
if constexpr (IsCritical) {
|
||||
m_env->ReleasePrimitiveArrayCritical(m_jarr, m_elements, mode);
|
||||
} else {
|
||||
ArrHelper::ReleaseArrayElements(m_env, m_jarr, m_elements, mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
operator std::span<T, Size>() const { return array(); }
|
||||
|
||||
std::span<T, Size> array() const {
|
||||
// If Size is dynamic_extent, can return empty span
|
||||
// Unfortunately, sized spans will return a span over nullptr if m_elements
|
||||
// is nullptr
|
||||
if constexpr (Size == std::dynamic_extent) {
|
||||
if (!m_elements) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return std::span<T, Size>{m_elements, m_size};
|
||||
}
|
||||
|
||||
T* begin() const { return m_elements; }
|
||||
|
||||
T* end() const { return m_elements + m_size; }
|
||||
|
||||
bool is_valid() const { return m_valid && m_elements != nullptr; }
|
||||
|
||||
explicit operator bool() const { return is_valid(); }
|
||||
|
||||
T* data() const { return m_elements; }
|
||||
|
||||
size_t size() const { return m_size; }
|
||||
|
||||
const T& operator[](size_t i) const { return m_elements[i]; }
|
||||
|
||||
T& operator[](size_t i)
|
||||
requires(!std::is_const_v<T>)
|
||||
{
|
||||
return m_elements[i];
|
||||
}
|
||||
|
||||
// Provide std::string_view and span<const uint8_t> conversions for jbyte
|
||||
|
||||
operator std::string_view() const
|
||||
requires std::is_same_v<std::remove_cv_t<T>, jbyte>
|
||||
{
|
||||
return str();
|
||||
}
|
||||
|
||||
std::string_view str() const
|
||||
requires std::is_same_v<std::remove_cv_t<T>, jbyte>
|
||||
{
|
||||
auto arr = array();
|
||||
if (arr.empty()) {
|
||||
return {};
|
||||
}
|
||||
return {reinterpret_cast<const char*>(arr.data()), arr.size()};
|
||||
}
|
||||
|
||||
std::span<const uint8_t> uarray() const {
|
||||
auto arr = static_cast<const C*>(this)->array();
|
||||
std::span<copy_cv_t<T, uint8_t>, Size> uarray() const
|
||||
requires std::is_same_v<std::remove_cv_t<T>, jbyte>
|
||||
{
|
||||
auto arr = array();
|
||||
if (arr.empty()) {
|
||||
return {};
|
||||
}
|
||||
return {reinterpret_cast<const uint8_t*>(arr.data()), arr.size()};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Specialization of JArrayRefBase to handle both "long long" and "long" on
|
||||
* 64-bit systems.
|
||||
*/
|
||||
template <typename C>
|
||||
class JArrayRefInner<C, jlong> {
|
||||
public:
|
||||
// Support both "long long" and "long" on 64-bit systems
|
||||
|
||||
template <typename U>
|
||||
requires(sizeof(U) == sizeof(jlong) && std::integral<U>)
|
||||
operator std::span<const U>() const { // NOLINT
|
||||
auto arr = static_cast<const C*>(this)->array();
|
||||
requires(sizeof(U) == sizeof(jlong) && std::integral<U> &&
|
||||
is_qualification_convertible_v<T, U>)
|
||||
operator std::span<U, Size>() const
|
||||
requires std::is_same_v<std::remove_cv_t<T>, jlong>
|
||||
{
|
||||
auto arr = array();
|
||||
if (arr.empty()) {
|
||||
return {};
|
||||
}
|
||||
return {reinterpret_cast<const U*>(arr.data()), arr.size()};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for J*ArrayRef and CriticalJ*ArrayRef
|
||||
*/
|
||||
template <typename T>
|
||||
class JArrayRefBase : public JArrayRefInner<JArrayRefBase<T>, T> {
|
||||
public:
|
||||
explicit operator bool() const { return this->m_elements != nullptr; }
|
||||
|
||||
std::span<const T> array() const {
|
||||
if (!this->m_elements) {
|
||||
return {};
|
||||
}
|
||||
return {this->m_elements, this->m_size};
|
||||
return {reinterpret_cast<U*>(arr.data()), arr.size()};
|
||||
}
|
||||
|
||||
size_t size() const { return this->m_size; }
|
||||
T& operator[](size_t i) { return this->m_elements[i]; }
|
||||
const T& operator[](size_t i) const { return this->m_elements[i]; }
|
||||
|
||||
JArrayRefBase(const JArrayRefBase&) = delete;
|
||||
JArrayRefBase& operator=(const JArrayRefBase&) = delete;
|
||||
|
||||
JArrayRefBase(JArrayRefBase&& oth)
|
||||
: m_env(oth.m_env),
|
||||
m_jarr(oth.m_jarr),
|
||||
m_size(oth.m_size),
|
||||
m_elements(oth.m_elements) {
|
||||
oth.m_jarr = nullptr;
|
||||
oth.m_elements = nullptr;
|
||||
}
|
||||
|
||||
JArrayRefBase& operator=(JArrayRefBase&& oth) {
|
||||
this->m_env = oth.m_env;
|
||||
this->m_jarr = oth.m_jarr;
|
||||
this->m_size = oth.m_size;
|
||||
this->m_elements = oth.m_elements;
|
||||
oth.m_jarr = nullptr;
|
||||
oth.m_elements = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
JArrayRefBase(JNIEnv* env, T* elements, size_t size) {
|
||||
this->m_env = env;
|
||||
this->m_jarr = nullptr;
|
||||
this->m_size = size;
|
||||
this->m_elements = elements;
|
||||
}
|
||||
|
||||
JArrayRefBase(JNIEnv* env, jarray jarr, size_t size) {
|
||||
this->m_env = env;
|
||||
this->m_jarr = jarr;
|
||||
this->m_size = size;
|
||||
this->m_elements = nullptr;
|
||||
}
|
||||
|
||||
JArrayRefBase(JNIEnv* env, jarray jarr)
|
||||
: JArrayRefBase(env, jarr, jarr ? env->GetArrayLength(jarr) : 0) {}
|
||||
|
||||
private:
|
||||
bool m_valid;
|
||||
JNIEnv* m_env;
|
||||
jarray m_jarr = nullptr;
|
||||
jarray_type m_jarr = nullptr;
|
||||
size_t m_size;
|
||||
T* m_elements;
|
||||
std::remove_cv_t<T>* m_elements;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// Java array / DirectBuffer reference.
|
||||
template <typename T, size_t Extent = std::dynamic_extent>
|
||||
using JSpan = detail::JSpanBase<T, false, Extent>;
|
||||
|
||||
#define WPI_JNI_JARRAYREF(T, F) \
|
||||
class J##F##ArrayRef : public detail::JArrayRefBase<T> { \
|
||||
public: \
|
||||
J##F##ArrayRef(JNIEnv* env, jobject bb, int len) \
|
||||
: detail::JArrayRefBase<T>( \
|
||||
env, \
|
||||
static_cast<T*>(bb ? env->GetDirectBufferAddress(bb) : nullptr), \
|
||||
len) { \
|
||||
if (!bb) { \
|
||||
errs() << "JArrayRef was passed a null pointer at \n" \
|
||||
<< GetJavaStackTrace(env); \
|
||||
} \
|
||||
} \
|
||||
J##F##ArrayRef(JNIEnv* env, T##Array jarr, int len) \
|
||||
: detail::JArrayRefBase<T>(env, jarr, len) { \
|
||||
if (jarr) { \
|
||||
m_elements = env->Get##F##ArrayElements(jarr, nullptr); \
|
||||
} else { \
|
||||
errs() << "JArrayRef was passed a null pointer at \n" \
|
||||
<< GetJavaStackTrace(env); \
|
||||
} \
|
||||
} \
|
||||
J##F##ArrayRef(JNIEnv* env, T##Array jarr) \
|
||||
: detail::JArrayRefBase<T>(env, jarr) { \
|
||||
if (jarr) { \
|
||||
m_elements = env->Get##F##ArrayElements(jarr, nullptr); \
|
||||
} else { \
|
||||
errs() << "JArrayRef was passed a null pointer at \n" \
|
||||
<< GetJavaStackTrace(env); \
|
||||
} \
|
||||
} \
|
||||
~J##F##ArrayRef() { \
|
||||
if (m_jarr && m_elements) { \
|
||||
m_env->Release##F##ArrayElements(static_cast<T##Array>(m_jarr), \
|
||||
m_elements, JNI_ABORT); \
|
||||
} \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
class CriticalJ##F##ArrayRef : public detail::JArrayRefBase<T> { \
|
||||
public: \
|
||||
CriticalJ##F##ArrayRef(JNIEnv* env, T##Array jarr, int len) \
|
||||
: detail::JArrayRefBase<T>(env, jarr, len) { \
|
||||
if (jarr) { \
|
||||
m_elements = \
|
||||
static_cast<T*>(env->GetPrimitiveArrayCritical(jarr, nullptr)); \
|
||||
} else { \
|
||||
errs() << "JArrayRef was passed a null pointer at \n" \
|
||||
<< GetJavaStackTrace(env); \
|
||||
} \
|
||||
} \
|
||||
CriticalJ##F##ArrayRef(JNIEnv* env, T##Array jarr) \
|
||||
: detail::JArrayRefBase<T>(env, jarr) { \
|
||||
if (jarr) { \
|
||||
m_elements = \
|
||||
static_cast<T*>(env->GetPrimitiveArrayCritical(jarr, nullptr)); \
|
||||
} else { \
|
||||
errs() << "JArrayRef was passed a null pointer at \n" \
|
||||
<< GetJavaStackTrace(env); \
|
||||
} \
|
||||
} \
|
||||
~CriticalJ##F##ArrayRef() { \
|
||||
if (m_jarr && m_elements) { \
|
||||
m_env->ReleasePrimitiveArrayCritical(m_jarr, m_elements, JNI_ABORT); \
|
||||
} \
|
||||
} \
|
||||
};
|
||||
|
||||
WPI_JNI_JARRAYREF(jboolean, Boolean)
|
||||
WPI_JNI_JARRAYREF(jbyte, Byte)
|
||||
WPI_JNI_JARRAYREF(jshort, Short)
|
||||
WPI_JNI_JARRAYREF(jint, Int)
|
||||
WPI_JNI_JARRAYREF(jlong, Long)
|
||||
WPI_JNI_JARRAYREF(jfloat, Float)
|
||||
WPI_JNI_JARRAYREF(jdouble, Double)
|
||||
|
||||
#undef WPI_JNI_JARRAYREF
|
||||
template <typename T, size_t Extent = std::dynamic_extent>
|
||||
using CriticalJSpan = detail::JSpanBase<T, true, Extent>;
|
||||
|
||||
//
|
||||
// Conversions from C++ to Java objects
|
||||
|
||||
Reference in New Issue
Block a user