|
| 1 | +#ifndef FIREBASE_FIRESTORE_CLIENT_CPP_SRC_JNI_TRAITS_H_ |
| 2 | +#define FIREBASE_FIRESTORE_CLIENT_CPP_SRC_JNI_TRAITS_H_ |
| 3 | + |
| 4 | +#include <jni.h> |
| 5 | + |
| 6 | +#include "app/src/include/firebase/internal/type_traits.h" |
| 7 | + |
| 8 | +namespace firebase { |
| 9 | +namespace firestore { |
| 10 | +namespace jni { |
| 11 | + |
| 12 | +class Object; |
| 13 | + |
| 14 | +// clang-format off |
| 15 | + |
| 16 | +// MARK: Primitive and Reference Type traits |
| 17 | + |
| 18 | +template <typename T> struct IsPrimitive : public false_type {}; |
| 19 | +template <> struct IsPrimitive<jboolean> : public true_type {}; |
| 20 | +template <> struct IsPrimitive<jbyte> : public true_type {}; |
| 21 | +template <> struct IsPrimitive<jchar> : public true_type {}; |
| 22 | +template <> struct IsPrimitive<jshort> : public true_type {}; |
| 23 | +template <> struct IsPrimitive<jint> : public true_type {}; |
| 24 | +template <> struct IsPrimitive<jlong> : public true_type {}; |
| 25 | +template <> struct IsPrimitive<jfloat> : public true_type {}; |
| 26 | +template <> struct IsPrimitive<jdouble> : public true_type {}; |
| 27 | + |
| 28 | +template <typename T> struct IsReference : public false_type {}; |
| 29 | +template <> struct IsReference<jclass> : public true_type {}; |
| 30 | +template <> struct IsReference<jobject> : public true_type {}; |
| 31 | +template <> struct IsReference<jstring> : public true_type {}; |
| 32 | +template <> struct IsReference<jthrowable> : public true_type {}; |
| 33 | +template <> struct IsReference<jbyteArray> : public true_type {}; |
| 34 | +template <> struct IsReference<jobjectArray> : public true_type {}; |
| 35 | + |
| 36 | + |
| 37 | +// MARK: Type mapping |
| 38 | + |
| 39 | +// A compile-time map from C++ types to their JNI equivalents. |
| 40 | +template <typename T> struct JniTypeMap {}; |
| 41 | +template <> struct JniTypeMap<bool> { using type = jboolean; }; |
| 42 | +template <> struct JniTypeMap<uint8_t> { using type = jbyte; }; |
| 43 | +template <> struct JniTypeMap<uint16_t> { using type = jchar; }; |
| 44 | +template <> struct JniTypeMap<int16_t> { using type = jshort; }; |
| 45 | +template <> struct JniTypeMap<int32_t> { using type = jint; }; |
| 46 | +template <> struct JniTypeMap<int64_t> { using type = jlong; }; |
| 47 | +template <> struct JniTypeMap<float> { using type = jfloat; }; |
| 48 | +template <> struct JniTypeMap<double> { using type = jdouble; }; |
| 49 | +template <> struct JniTypeMap<size_t> { using type = jsize; }; |
| 50 | + |
| 51 | +template <> struct JniTypeMap<jobject> { using type = jobject; }; |
| 52 | + |
| 53 | +template <> struct JniTypeMap<Object> { using type = jobject; }; |
| 54 | + |
| 55 | +template <typename T> |
| 56 | +using JniType = typename JniTypeMap<decay_t<T>>::type; |
| 57 | + |
| 58 | +// clang-format on |
| 59 | + |
| 60 | +// MARK: Enable If Helpers |
| 61 | + |
| 62 | +template <typename T, typename R = T> |
| 63 | +using EnableForPrimitive = |
| 64 | + typename enable_if<IsPrimitive<JniType<T>>::value, R>::type; |
| 65 | + |
| 66 | +template <typename T, typename R = T> |
| 67 | +using EnableForReference = |
| 68 | + typename enable_if<IsReference<JniType<T>>::value, R>::type; |
| 69 | + |
| 70 | +// MARK: Type converters |
| 71 | + |
| 72 | +// Converts C++ primitives to their equivalent JNI primitive types by casting. |
| 73 | +template <typename T> |
| 74 | +EnableForPrimitive<T, JniType<T>> ToJni(const T& value) { |
| 75 | + return static_cast<JniType<T>>(value); |
| 76 | +} |
| 77 | + |
| 78 | +// Converts JNI wrapper reference types (like `const Object&`) and any ownership |
| 79 | +// wrappers of those types to their underlying `jobject`-derived reference. |
| 80 | +template <typename T> |
| 81 | +EnableForReference<T, JniType<T>> ToJni(const T& value) { |
| 82 | + return value.get(); |
| 83 | +} |
| 84 | +template <typename T, typename J = typename T::jni_type> |
| 85 | +J ToJni(const T& value) { |
| 86 | + return value.get(); |
| 87 | +} |
| 88 | + |
| 89 | +// Preexisting JNI types can be passed directly. This makes incremental |
| 90 | +// migration possible. Ideally this could eventually be removed. |
| 91 | +inline jobject ToJni(jobject value) { return value; } |
| 92 | + |
| 93 | +} // namespace jni |
| 94 | +} // namespace firestore |
| 95 | +} // namespace firebase |
| 96 | + |
| 97 | +#endif // FIREBASE_FIRESTORE_CLIENT_CPP_SRC_JNI_TRAITS_H_ |
0 commit comments