[wpiutil] jni_util: Add Mac-friendly MakeJLongArray/JArrayRef (#4383)

Mac has jlong == long long and int64_t = long, so the types are
incompatible despite being the same size.
This commit is contained in:
Peter Johnson
2022-08-30 20:39:42 -07:00
committed by GitHub
parent c3a93fb995
commit fdb5a2791f

View File

@@ -179,7 +179,12 @@ class JStringRef {
namespace detail {
template <typename C, typename T>
class JArrayRefInner {};
class JArrayRefInner {
public:
operator span<const T>() const { // NOLINT
return static_cast<const C*>(this)->array();
}
};
/**
* Specialization of JArrayRefBase to provide std::string_view conversion.
@@ -198,6 +203,25 @@ class JArrayRefInner<C, jbyte> {
}
};
/**
* Specialization of JArrayRefBase to handle both "long long" and "long" on
* 64-bit systems.
*/
template <typename C>
class JArrayRefInner<C, jlong> {
public:
template <typename U,
typename = std::enable_if_t<sizeof(U) == sizeof(jlong) &&
std::is_integral_v<U>>>
operator span<const U>() const { // NOLINT
auto arr = static_cast<const C*>(this)->array();
if (arr.empty()) {
return {};
}
return {reinterpret_cast<const U*>(arr.data()), arr.size()};
}
};
/**
* Base class for J*ArrayRef and CriticalJ*ArrayRef
*/
@@ -206,8 +230,6 @@ class JArrayRefBase : public JArrayRefInner<JArrayRefBase<T>, T> {
public:
explicit operator bool() const { return this->m_elements != nullptr; }
operator span<const T>() const { return array(); } // NOLINT
span<const T> array() const {
if (!this->m_elements) {
return {};
@@ -538,12 +560,24 @@ inline jbooleanArray MakeJBooleanArray(JNIEnv* env, span<const bool> arr) {
WPI_JNI_MAKEJARRAY(jboolean, Boolean)
WPI_JNI_MAKEJARRAY(jbyte, Byte)
WPI_JNI_MAKEJARRAY(jshort, Short)
WPI_JNI_MAKEJARRAY(jlong, Long)
WPI_JNI_MAKEJARRAY(jfloat, Float)
WPI_JNI_MAKEJARRAY(jdouble, Double)
#undef WPI_JNI_MAKEJARRAY
template <class T, typename = std::enable_if_t<
sizeof(typename T::value_type) == sizeof(jlong) &&
std::is_integral_v<typename T::value_type>>>
inline jlongArray MakeJLongArray(JNIEnv* env, const T& arr) {
jlongArray jarr = env->NewLongArray(arr.size());
if (!jarr) {
return nullptr;
}
env->SetLongArrayRegion(jarr, 0, arr.size(),
reinterpret_cast<const jlong*>(arr.data()));
return jarr;
}
/**
* Convert an array of std::string into a jarray of jstring.
*