File indexing completed on 2024-06-23 05:08:44

0001 /*
0002     SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #ifndef KANDROIDEXTRAS_JNISIGNATURE_H
0008 #define KANDROIDEXTRAS_JNISIGNATURE_H
0009 
0010 #include "jnitypes.h"
0011 
0012 #include "jni.h"
0013 #include <cstdint>
0014 #include <utility>
0015 
0016 namespace KAndroidExtras {
0017 
0018 namespace Jni {
0019 template <typename T> class Array;
0020 }
0021 
0022 /** @cond internal */
0023 namespace Internal {
0024 
0025 /** Compile-time concat-able string. */
0026 template <char... String>
0027 struct StaticString {
0028     inline operator const char*() const
0029     {
0030         static const char data[] = { String..., 0 };
0031         return data;
0032     }
0033 };
0034 
0035 /** Compile-time strlen. */
0036 constexpr inline int static_strlen(const char *str)
0037 {
0038     return str[0] == '\0' ? 0 : static_strlen(str + 1) + 1;
0039 }
0040 
0041 /** Compile-time concat for two StaticString. */
0042 template <char... String1, char... String2>
0043 constexpr inline auto static_concat(const StaticString<String1...>&, const StaticString<String2...>&)
0044 {
0045     return StaticString<String1..., String2...>();
0046 }
0047 
0048 /** Compile-time concept for N StaticString. */
0049 template <typename String1, typename String2, class... Strings>
0050 constexpr inline auto static_concat(const String1& str1, const String2& str2, const Strings&... strs)
0051 {
0052     return static_concat(static_concat(str1, str2), strs...);
0053 }
0054 
0055 /** Conversion from const char* literals to StaticString. */
0056 template <typename, typename> struct staticStringFromJniType;
0057 template <typename T, std::size_t... Indexes>
0058 struct staticStringFromJniType<T, std::index_sequence<Indexes...>>
0059 {
0060     typedef StaticString<Jni::typeName<T>()[Indexes]...> value;
0061 };
0062 
0063 /** Meta function for assembling JNI signatures. */
0064 template <typename T>
0065 struct JniSignature
0066 {
0067     constexpr inline auto operator()() const
0068     {
0069         using namespace Internal;
0070         return static_concat(StaticString<'L'>(), typename staticStringFromJniType<T, std::make_index_sequence<static_strlen(Jni::typeName<T>())>>::value(), StaticString<';'>());
0071     }
0072 };
0073 
0074 template <> struct JniSignature<jboolean> { constexpr inline auto operator()() const { return StaticString<'Z'>(); } };
0075 template <> struct JniSignature<jbyte> { constexpr inline auto operator()() const { return StaticString<'B'>(); } };
0076 template <> struct JniSignature<jchar> { constexpr inline auto operator()() const { return StaticString<'C'>(); } };
0077 template <> struct JniSignature<jshort> { constexpr inline auto operator()() const { return StaticString<'S'>(); } };
0078 template <> struct JniSignature<jint> { constexpr inline auto operator()() const { return StaticString<'I'>(); } };
0079 template <> struct JniSignature<jlong> { constexpr inline auto operator()() const { return StaticString<'J'>(); } };
0080 template <> struct JniSignature<jfloat> { constexpr inline auto operator()() const { return StaticString<'F'>(); } };
0081 template <> struct JniSignature<jdouble> { constexpr inline auto operator()() const { return StaticString<'D'>(); } };
0082 template <> struct JniSignature<void> { constexpr inline auto operator()() const { return StaticString<'V'>(); } };
0083 // special case due to jboolean != bool
0084 template <> struct JniSignature<bool> { constexpr inline auto operator()() const { return StaticString<'Z'>(); } };
0085 
0086 template <typename T>
0087 struct JniSignature<T*>
0088 {
0089     constexpr inline auto operator()() const
0090     {
0091         using namespace Internal;
0092         return static_concat(StaticString<'['>(), JniSignature<T>()());
0093     }
0094 };
0095 
0096 template <typename T>
0097 struct JniSignature<Jni::Array<T>>
0098 {
0099     constexpr inline auto operator()() const
0100     {
0101         using namespace Internal;
0102         return static_concat(StaticString<'['>(), JniSignature<T>()());
0103     }
0104 };
0105 
0106 template <typename RetT, typename... Args>
0107 struct JniSignature<RetT(Args...)>
0108 {
0109     constexpr inline auto operator()() const
0110     {
0111         using namespace Internal;
0112         return static_concat(StaticString<'('>(), JniSignature<Args>()()..., StaticString<')'>(), JniSignature<RetT>()());
0113     }
0114 };
0115 }
0116 /** @endcond */
0117 
0118 /** Helper methods to deal with JNI. */
0119 namespace Jni
0120 {
0121     /** Returns the JNI signature string for the template argument types. */
0122     template <typename... Args> constexpr __attribute__((__unused__)) Internal::JniSignature<Args...> signature = {};
0123 }
0124 
0125 }
0126 
0127 #endif // KANDROIDEXTRAS_JNISIGNATURE_H