Bug 1238761 - Add specializations of jni::Ref for primitive arrays; r=snorp

This patch adds specializations of jni::Ref for primitive arrays like
IntArray and FloatArray, so that the arrays can be accessed through the
GetElement, GetElements, and Length members.
This commit is contained in:
Jim Chen 2016-01-15 13:05:44 -05:00
parent ebe41f27c9
commit 296a0a08cc
4 changed files with 104 additions and 8 deletions

View File

@ -44,9 +44,8 @@ struct PrefsHelper
namesPtrArray.AppendElement(nullptr); namesPtrArray.AppendElement(nullptr);
continue; continue;
} }
namesPtrArray.AppendElement(namesStrArray.AppendElement( namesPtrArray.AppendElement(namesStrArray.AppendElement(nsString(
nsString(jni::String::LocalRef( jni::String::Ref::From(namesRefArray[i])))->Data());
mozilla::Move(namesRefArray[i]))))->Data());
} }
nsIAndroidBrowserApp* browserApp = nullptr; nsIAndroidBrowserApp* browserApp = nullptr;

View File

@ -548,6 +548,96 @@ public:
}; };
// Ref specialization for arrays.
template<class Type, typename JNIType, class ElementType>
class ArrayRefBase : public RefBase<Type, JNIType>
{
typedef RefBase<Type, JNIType> Base;
protected:
ArrayRefBase(jobject instance) : Base(instance) {}
ArrayRefBase(const ArrayRefBase& ref) : Base(ref.mInstance) {}
public:
size_t Length() const
{
MOZ_ASSERT(Base::mInstance);
JNIEnv* const env = GetEnvForThread();
const size_t ret = env->GetArrayLength(JNIType(Base::mInstance));
MOZ_CATCH_JNI_EXCEPTION(env);
return ret;
}
ElementType GetElement(size_t index) const
{
MOZ_ASSERT(Base::mInstance);
JNIEnv* const env = GetEnvForThread();
ElementType ret;
(env->*detail::TypeAdapter<ElementType>::GetArray)(
JNIType(Base::mInstance), jsize(index), 1, &ret);
MOZ_CATCH_JNI_EXCEPTION(env);
return ret;
}
nsTArray<ElementType> GetElements() const
{
MOZ_ASSERT(Base::mInstance);
static_assert(sizeof(ElementType) ==
sizeof(typename detail::TypeAdapter<ElementType>::JNIType),
"Size of native type must match size of JNI type");
JNIEnv* const env = GetEnvForThread();
const jsize len = size_t(env->GetArrayLength(
JNIType(Base::mInstance)));
nsTArray<ElementType> array((size_t(len)));
array.SetLength(size_t(len));
(env->*detail::TypeAdapter<ElementType>::GetArray)(
JNIType(Base::mInstance), 0, len, array.Elements());
return array;
}
ElementType operator[](size_t index) const
{
return GetElement(index);
}
operator nsTArray<ElementType>() const
{
return GetElements();
}
};
#define DEFINE_PRIMITIVE_ARRAY_REF(Type, JNIType, ElementType) \
template<> \
class Ref<Type> : public ArrayRefBase<Type, JNIType, ElementType> \
{ \
friend class RefBase<Type, JNIType>; \
friend class detail::TypeAdapter<Ref<Type>>; \
\
typedef ArrayRefBase<Type, JNIType, ElementType> Base; \
\
protected: \
Ref(jobject instance) : Base(instance) {} \
\
Ref(const Ref& ref) : Base(ref.mInstance) {} \
\
public: \
MOZ_IMPLICIT Ref(decltype(nullptr)) : Base(nullptr) {} \
}
DEFINE_PRIMITIVE_ARRAY_REF(BooleanArray, jbooleanArray, bool);
DEFINE_PRIMITIVE_ARRAY_REF(ByteArray, jbyteArray, int8_t);
DEFINE_PRIMITIVE_ARRAY_REF(CharArray, jcharArray, char16_t);
DEFINE_PRIMITIVE_ARRAY_REF(ShortArray, jshortArray, int16_t);
DEFINE_PRIMITIVE_ARRAY_REF(IntArray, jintArray, int32_t);
DEFINE_PRIMITIVE_ARRAY_REF(LongArray, jlongArray, int64_t);
DEFINE_PRIMITIVE_ARRAY_REF(FloatArray, jfloatArray, float);
DEFINE_PRIMITIVE_ARRAY_REF(DoubleArray, jdoubleArray, double);
#undef DEFINE_PRIMITIVE_ARRAY_REF
// Ref specialization for jobjectArray. // Ref specialization for jobjectArray.
template<> template<>
class Ref<ObjectArray> : public RefBase<ObjectArray, jobjectArray> class Ref<ObjectArray> : public RefBase<ObjectArray, jobjectArray>
@ -565,12 +655,11 @@ protected:
public: public:
MOZ_IMPLICIT Ref(decltype(nullptr)) : Base(nullptr) {} MOZ_IMPLICIT Ref(decltype(nullptr)) : Base(nullptr) {}
// Get the length of the object array.
size_t Length() const size_t Length() const
{ {
MOZ_ASSERT(ObjectArray::mInstance); MOZ_ASSERT(Base::mInstance);
JNIEnv* const env = GetEnvForThread(); JNIEnv* const env = GetEnvForThread();
const size_t ret = env->GetArrayLength(jarray(ObjectArray::mInstance)); const size_t ret = env->GetArrayLength(jobjectArray(Base::mInstance));
MOZ_CATCH_JNI_EXCEPTION(env); MOZ_CATCH_JNI_EXCEPTION(env);
return ret; return ret;
} }
@ -602,6 +691,11 @@ public:
return array; return array;
} }
Object::LocalRef operator[](size_t index) const
{
return GetElement(index);
}
operator nsTArray<Object::LocalRef>() const operator nsTArray<Object::LocalRef>() const
{ {
return GetElements(); return GetElements();

View File

@ -106,6 +106,7 @@ template<class Cls> struct TypeAdapter<const Cls&>
static constexpr auto StaticGet = &JNIEnv::GetStatic ## JNIName ## Field; \ static constexpr auto StaticGet = &JNIEnv::GetStatic ## JNIName ## Field; \
static constexpr auto Set = &JNIEnv::Set ## JNIName ## Field; \ static constexpr auto Set = &JNIEnv::Set ## JNIName ## Field; \
static constexpr auto StaticSet = &JNIEnv::SetStatic ## JNIName ## Field; \ static constexpr auto StaticSet = &JNIEnv::SetStatic ## JNIName ## Field; \
static constexpr auto GetArray = &JNIEnv::Get ## JNIName ## ArrayRegion; \
\ \
static JNIType FromNative(JNIEnv*, NativeType val) { \ static JNIType FromNative(JNIEnv*, NativeType val) { \
return static_cast<JNIType>(val); \ return static_cast<JNIType>(val); \

View File

@ -17,7 +17,7 @@ namespace jni {
namespace detail { namespace detail {
#define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName, ABIName) \ #define DEFINE_PRIMITIVE_TYPE_ADAPTER(NativeType, JNIType, JNIName, ABIName) \
\ \
constexpr JNIType (JNIEnv::*TypeAdapter<NativeType>::Call) \ constexpr JNIType (JNIEnv::*TypeAdapter<NativeType>::Call) \
(jobject, jmethodID, jvalue*) MOZ_JNICALL_ABI; \ (jobject, jmethodID, jvalue*) MOZ_JNICALL_ABI; \
@ -30,7 +30,9 @@ namespace detail {
constexpr void (JNIEnv::*TypeAdapter<NativeType>::Set) \ constexpr void (JNIEnv::*TypeAdapter<NativeType>::Set) \
(jobject, jfieldID, JNIType) ABIName; \ (jobject, jfieldID, JNIType) ABIName; \
constexpr void (JNIEnv::*TypeAdapter<NativeType>::StaticSet) \ constexpr void (JNIEnv::*TypeAdapter<NativeType>::StaticSet) \
(jclass, jfieldID, JNIType) ABIName (jclass, jfieldID, JNIType) ABIName; \
constexpr void (JNIEnv::*TypeAdapter<NativeType>::GetArray) \
(JNIType ## Array, jsize, jsize, JNIType*)
DEFINE_PRIMITIVE_TYPE_ADAPTER(bool, jboolean, Boolean, /*nothing*/); DEFINE_PRIMITIVE_TYPE_ADAPTER(bool, jboolean, Boolean, /*nothing*/);
DEFINE_PRIMITIVE_TYPE_ADAPTER(int8_t, jbyte, Byte, /*nothing*/); DEFINE_PRIMITIVE_TYPE_ADAPTER(int8_t, jbyte, Byte, /*nothing*/);