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

Deduplicate tags to unique jni::Tag<...> types #12

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
10 changes: 5 additions & 5 deletions include/jni/array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,11 @@ namespace jni
};

template < class TheTag >
class Array< Object<TheTag> >
class Array< TypedObject<TheTag> >
{
public:
using TagType = TheTag;
using ElementType = Object<TagType>;
using ElementType = TypedObject<TagType>;
using UntaggedType = jarray<jobject>;
using UntaggedElementType = typename ElementType::UntaggedObjectType;

Expand Down Expand Up @@ -124,12 +124,12 @@ namespace jni
SetObjectArrayElement(env, SafeDereference(env, array), index, Untag(value));
}

static Array<Object<TheTag>> New(JNIEnv& env, jsize length, const Class<TheTag>& clazz, const Object<TheTag>& initialElement = Object<TheTag>())
static Array<TypedObject<TheTag>> New(JNIEnv& env, jsize length, const TypedClass<TheTag>& clazz, const TypedObject<TheTag>& initialElement = TypedObject<TheTag>())
{
return Array<Object<TheTag>>(&NewObjectArray(env, length, clazz, initialElement.Get()));
return Array<TypedObject<TheTag>>(&NewObjectArray(env, length, clazz, initialElement.Get()));
}

UniqueArray<Object<TheTag>> NewGlobalRef(JNIEnv& env) const
UniqueArray<TypedObject<TheTag>> NewGlobalRef(JNIEnv& env) const
{
return Seize(env, Array(jni::NewGlobalRef(env, array).release()));
}
Expand Down
99 changes: 52 additions & 47 deletions include/jni/class.hpp
Original file line number Diff line number Diff line change
@@ -1,40 +1,44 @@
#pragma once

#include <jni/functions.hpp>
#include <jni/type.hpp>
#include <jni/tagging.hpp>
#include <jni/pointer_to_value.hpp>

namespace jni
{
template < class TheTag > class Object;
template < class TheTag, class... > class Constructor;
template < class TheTag, class > class Field;
template < class TheTag, class > class StaticField;
template < class TheTag, class > class Method;
template < class TheTag, class > class StaticMethod;
template < class TagType > class TypedObject;
template < class TagType, class... > class TypedConstructor;
template < class TagType, class > class TypedField;
template < class TagType, class > class TypedStaticField;
template < class TagType, class > class TypedMethod;
template < class TagType, class > class TypedStaticMethod;

template < class TheTag >
class Class;
template < class TagType >
class TypedClass;

template < class TagType >
class ClassDeleter;
class TypedClassDeleter;

template < class TagType >
using UniqueClass = std::unique_ptr< const Class<TagType>, ClassDeleter<TagType> >;
using TypedUniqueClass = std::unique_ptr< const TypedClass<TagType>, TypedClassDeleter<TagType> >;

template < class Tag >
using Class = TypedClass< TypeFromTag<Tag> >;

template < class TheTag >
class Class
template <char... Chars>
class TypedClass< Type<Chars...> >
{
private:
jclass* clazz = nullptr;

public:
using TagType = TheTag;
using TagType = Type<Chars...>;

explicit Class(std::nullptr_t = nullptr)
explicit TypedClass(std::nullptr_t = nullptr)
{}

explicit Class(jclass& c)
explicit TypedClass(jclass& c)
: clazz(&c)
{}

Expand All @@ -44,115 +48,116 @@ namespace jni
jclass& operator*() const { return *clazz; }
jclass* Get() const { return clazz; }

friend bool operator==( const Class& a, const Class& b ) { return a.Get() == b.Get(); }
friend bool operator!=( const Class& a, const Class& b ) { return !( a == b ); }
friend bool operator==( const TypedClass& a, const TypedClass& b ) { return a.Get() == b.Get(); }
friend bool operator!=( const TypedClass& a, const TypedClass& b ) { return !( a == b ); }

template < class... Args >
Object<TagType> New(JNIEnv& env, const Constructor<TagType, Args...>& method, const Args&... args) const
TypedObject<TagType> New(JNIEnv& env, const TypedConstructor<TagType, Args...>& method, const Args&... args) const
{
return Object<TagType>(&NewObject(env, *clazz, method, Untag(args)...));
return TypedObject<TagType>(&NewObject(env, *clazz, method, Untag(args)...));
}

template < class T >
auto Get(JNIEnv& env, const StaticField<TagType, T>& field) const
auto Get(JNIEnv& env, const TypedStaticField<TagType, T>& field) const
-> std::enable_if_t< IsPrimitive<T>::value, T >
{
return jni::GetStaticField<T>(env, *clazz, field);
}

template < class T >
auto Get(JNIEnv& env, const StaticField<TagType, T>& field) const
auto Get(JNIEnv& env, const TypedStaticField<TagType, T>& field) const
-> std::enable_if_t< !IsPrimitive<T>::value, T >
{
return T(reinterpret_cast<UntaggedType<T>>(jni::GetStaticField<jobject*>(env, *clazz, field)));
}

template < class T >
auto Set(JNIEnv& env, const StaticField<TagType, T>& field, T value) const
auto Set(JNIEnv& env, const TypedStaticField<TagType, T>& field, T value) const
-> std::enable_if_t< IsPrimitive<T>::value >
{
SetStaticField<T>(env, *clazz, field, value);
}

template < class T >
auto Set(JNIEnv& env, const StaticField<TagType, T>& field, const T& value) const
auto Set(JNIEnv& env, const TypedStaticField<TagType, T>& field, const T& value) const
-> std::enable_if_t< !IsPrimitive<T>::value >
{
SetStaticField<jobject*>(env, *clazz, field, value.Get());
}

template < class R, class... Args >
auto Call(JNIEnv& env, const StaticMethod<TagType, R (Args...)>& method, const Args&... args) const
auto Call(JNIEnv& env, const TypedStaticMethod<TagType, R (Args...)>& method, const Args&... args) const
-> std::enable_if_t< IsPrimitive<R>::value, R >
{
return CallStaticMethod<R>(env, *clazz, method, Untag(args)...);
}

template < class R, class... Args >
auto Call(JNIEnv& env, const StaticMethod<TagType, R (Args...)>& method, const Args&... args) const
auto Call(JNIEnv& env, const TypedStaticMethod<TagType, R (Args...)>& method, const Args&... args) const
-> std::enable_if_t< !IsPrimitive<R>::value, R >
{
return R(reinterpret_cast<UntaggedType<R>>(CallStaticMethod<jobject*>(env, *clazz, method, Untag(args)...)));
}

template < class... Args >
void Call(JNIEnv& env, const StaticMethod<TagType, void (Args...)>& method, const Args&... args) const
void Call(JNIEnv& env, const TypedStaticMethod<TagType, void (Args...)>& method, const Args&... args) const
{
CallStaticMethod<void>(env, *clazz, method, Untag(args)...);
}

static Class Find(JNIEnv& env)
static TypedClass Find(JNIEnv& env)
{
return Class(FindClass(env, TagType::Name()));
static constexpr const char name[] { Chars..., '\0' };
return TypedClass(FindClass(env, name));
}

template < class... Args >
Constructor<TagType, Args...> GetConstructor(JNIEnv& env)
TypedConstructor<TagType, Args...> GetConstructor(JNIEnv& env)
{
return Constructor<TagType, Args...>(env, *this);
return TypedConstructor<TagType, Args...>(env, *this);
}

template < class T >
Field<TagType, T> GetField(JNIEnv& env, const char* name)
TypedField<TagType, T> GetField(JNIEnv& env, const char* name)
{
return Field<TagType, T>(env, *this, name);
return TypedField<TagType, T>(env, *this, name);
}

template < class T >
StaticField<TagType, T> GetStaticField(JNIEnv& env, const char* name)
TypedStaticField<TagType, T> GetStaticField(JNIEnv& env, const char* name)
{
return StaticField<TagType, T>(env, *this, name);
return TypedStaticField<TagType, T>(env, *this, name);
}

template < class T >
Method<TagType, T> GetMethod(JNIEnv& env, const char* name)
TypedMethod<TagType, T> GetMethod(JNIEnv& env, const char* name)
{
return Method<TagType, T>(env, *this, name);
return TypedMethod<TagType, T>(env, *this, name);
}

template < class T >
StaticMethod<TagType, T> GetStaticMethod(JNIEnv& env, const char* name)
TypedStaticMethod<TagType, T> GetStaticMethod(JNIEnv& env, const char* name)
{
return StaticMethod<TagType, T>(env, *this, name);
return TypedStaticMethod<TagType, T>(env, *this, name);
}

UniqueClass<TagType> NewGlobalRef(JNIEnv& env) const
TypedUniqueClass<TagType> NewGlobalRef(JNIEnv& env) const
{
return Seize(env, Class(*jni::NewGlobalRef(env, clazz).release()));
return Seize(env, TypedClass(*jni::NewGlobalRef(env, clazz).release()));
}
};

template < class TagType >
class ClassDeleter
template <char... Chars>
class TypedClassDeleter< Type<Chars...> >
{
private:
JNIEnv* env = nullptr;

public:
using pointer = PointerToValue< Class<TagType> >;
using pointer = PointerToValue< TypedClass< Type<Chars...> > >;

ClassDeleter() = default;
ClassDeleter(JNIEnv& e) : env(&e) {}
TypedClassDeleter() = default;
TypedClassDeleter(JNIEnv& e) : env(&e) {}

void operator()(pointer p) const
{
Expand All @@ -165,8 +170,8 @@ namespace jni
};

template < class TagType >
UniqueClass<TagType> Seize(JNIEnv& env, Class<TagType>&& clazz)
TypedUniqueClass<TagType> Seize(JNIEnv& env, TypedClass<TagType>&& clazz)
{
return UniqueClass<TagType>(PointerToValue<Class<TagType>>(std::move(clazz)), ClassDeleter<TagType>(env));
return TypedUniqueClass<TagType>(PointerToValue<TypedClass<TagType>>(std::move(clazz)), TypedClassDeleter<TagType>(env));
};
}
10 changes: 7 additions & 3 deletions include/jni/constructor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@

namespace jni
{

template < class Tag, class... Args >
using Constructor = TypedConstructor< TypeFromTag<Tag>, Args... >;

template < class TagType, class... Args >
class Constructor : public Method<TagType, void (Args...)>
class TypedConstructor : public TypedMethod<TagType, void (Args...)>
{
public:
Constructor(JNIEnv& env, const Class<TagType>& clazz)
: Method<TagType, void (Args...)>(env, clazz, "<init>")
TypedConstructor(JNIEnv& env, const TypedClass<TagType>& clazz)
: TypedMethod<TagType, void (Args...)>(env, clazz, "<init>")
{}
};
}
14 changes: 10 additions & 4 deletions include/jni/field.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@

namespace jni
{
template < class TheTag, class T >
class Field
template < class TagType, class T >
class TypedField;

template < class Tag, class T >
using Field = TypedField< TypeFromTag<Tag>, T >;

template <char... Chars, class T>
class TypedField< Type<Chars...>, T >
{
private:
jfieldID& field;

public:
using TagType = TheTag;
using TagType = Type<Chars...>;

Field(JNIEnv& env, const Class<TagType>& clazz, const char* name)
TypedField(JNIEnv& env, const TypedClass<TagType>& clazz, const char* name)
: field(GetFieldID(env, clazz, name, TypeSignature<T>()()))
{}

Expand Down
15 changes: 9 additions & 6 deletions include/jni/method.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,22 @@

namespace jni
{
template < class TheTag, class >
class Method;
template < class TagType, class >
class TypedMethod;

template < class TheTag, class R, class... Args >
class Method< TheTag, R (Args...) >
template < class Tag, class R, class... Args >
using Method = TypedMethod< TypeFromTag<Tag>, R (Args...) >;

template < char... Chars, class R, class... Args >
class TypedMethod< Type<Chars...>, R (Args...) >
{
private:
jmethodID& method;

public:
using TagType = TheTag;
using TagType = Type<Chars...>;

Method(JNIEnv& env, const Class<TagType>& clazz, const char* name)
TypedMethod(JNIEnv& env, const TypedClass<TagType>& clazz, const char* name)
: method(GetMethodID(env, clazz, name, TypeSignature<R (Args...)>()()))
{}

Expand Down
Loading