diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index 3c5301fee2..176711ef90 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -949,6 +949,7 @@ qt_internal_extend_target(Core CONDITION ANDROID SOURCES io/qstandardpaths_android.cpp io/qstorageinfo_unix.cpp + kernel/qjnitypes.h kernel/qjnienvironment.cpp kernel/qjnienvironment.h kernel/qjniobject.cpp kernel/qjniobject.h kernel/qjnihelpers.cpp kernel/qjnihelpers_p.h diff --git a/src/corelib/kernel/qjniobject.h b/src/corelib/kernel/qjniobject.h index 80568b2970..829823efec 100644 --- a/src/corelib/kernel/qjniobject.h +++ b/src/corelib/kernel/qjniobject.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -45,6 +45,7 @@ #if defined(Q_QDOC) || defined(Q_OS_ANDROID) #include #include +#include QT_BEGIN_NAMESPACE @@ -64,7 +65,7 @@ public: jobject object() const; template T object() const { - assertJniObjectType(); + QtJniTypes::assertObjectType(); return static_cast(javaObject()); } @@ -74,7 +75,7 @@ public: template T callMethod(const char *methodName, const char *signature, ...) const { - assertJniPrimitiveType(); + QtJniTypes::assertPrimitiveType(); QJniEnvironment env; T res{}; jmethodID id = getCachedMethodID(env.jniEnv(), methodName, signature); @@ -106,23 +107,17 @@ public: template T callMethod(const char *methodName) const { - assertJniPrimitiveType(); - constexpr const char *signature = getTypeSignature(); - return callMethod(methodName, QByteArray(signature).prepend("()").constData()); - } - - template <> - void callMethod(const char *methodName) const - { - callMethod(methodName, "()V"); + QtJniTypes::assertPrimitiveType(); + constexpr auto signature = QtJniTypes::methodSignature(); + return callMethod(methodName, signature); } template QJniObject callObjectMethod(const char *methodName) const { - assertJniObjectType(); - constexpr const char *signature = getTypeSignature(); - return callObjectMethod(methodName, QByteArray(signature).prepend("()").constData()); + QtJniTypes::assertObjectType(); + constexpr auto signature = QtJniTypes::methodSignature(); + return callObjectMethod(methodName, signature); } QJniObject callObjectMethod(const char *methodName, const char *signature, ...) const; @@ -131,7 +126,7 @@ public: static T callStaticMethod(const char *className, const char *methodName, const char *signature, ...) { - assertJniPrimitiveType(); + QtJniTypes::assertPrimitiveType(); QJniEnvironment env; T res{}; jclass clazz = QJniObject::loadClass(className, env.jniEnv()); @@ -174,21 +169,15 @@ public: template static T callStaticMethod(const char *className, const char *methodName) { - assertJniPrimitiveType(); - constexpr const char *signature = getTypeSignature(); - return callStaticMethod(className, methodName, QByteArray(signature).prepend("()").constData()); - } - - template <> - void callStaticMethod(const char *className, const char *methodName) - { - callStaticMethod(className, methodName, "()V"); + QtJniTypes::assertPrimitiveType(); + constexpr auto signature = QtJniTypes::methodSignature(); + return callStaticMethod(className, methodName, signature); } template static T callStaticMethod(jclass clazz, const char *methodName, const char *signature, ...) { - assertJniPrimitiveType(); + QtJniTypes::assertPrimitiveType(); QJniEnvironment env; T res{}; if (clazz) { @@ -225,7 +214,7 @@ public: template static T callStaticMethod(jclass clazz, jmethodID methodId, ...) { - assertJniPrimitiveType(); + QtJniTypes::assertPrimitiveType(); QJniEnvironment env; T res{}; if (clazz && methodId) { @@ -254,23 +243,17 @@ public: template static T callStaticMethod(jclass clazz, const char *methodName) { - assertJniPrimitiveType(); - constexpr const char *signature = getTypeSignature(); - return callStaticMethod(clazz, methodName, QByteArray(signature).prepend("()").constData()); - } - - template <> - void callStaticMethod(jclass clazz, const char *methodName) - { - callStaticMethod(clazz, methodName, "()V"); + QtJniTypes::assertPrimitiveType(); + constexpr auto signature = QtJniTypes::methodSignature(); + return callStaticMethod(clazz, methodName, signature); } template static QJniObject callStaticObjectMethod(const char *className, const char *methodName) { - assertJniObjectType(); - constexpr const char *signature = getTypeSignature(); - return callStaticObjectMethod(className, methodName, QByteArray(signature).prepend("()").constData()); + QtJniTypes::assertObjectType(); + constexpr auto signature = QtJniTypes::methodSignature(); + return callStaticObjectMethod(className, methodName, signature); } static QJniObject callStaticObjectMethod(const char *className, const char *methodName, @@ -279,9 +262,9 @@ public: template static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName) { - assertJniObjectType(); - constexpr const char *signature = getTypeSignature(); - return callStaticObjectMethod(clazz, methodName, QByteArray(signature).prepend("()").constData()); + QtJniTypes::assertObjectType(); + constexpr auto signature = QtJniTypes::methodSignature(); + return callStaticObjectMethod(clazz, methodName, signature); } static QJniObject callStaticObjectMethod(jclass clazz, const char *methodName, @@ -291,10 +274,10 @@ public: template T getField(const char *fieldName) const { - assertJniPrimitiveType(); + QtJniTypes::assertPrimitiveType(); QJniEnvironment env; T res{}; - constexpr const char *signature = getTypeSignature(); + constexpr auto signature = QtJniTypes::fieldSignature(); jfieldID id = getCachedFieldID(env.jniEnv(), fieldName, signature); if (id) { getFieldForType(env.jniEnv(), res, object(), id); @@ -307,13 +290,13 @@ public: template static T getStaticField(const char *className, const char *fieldName) { - assertJniPrimitiveType(); + QtJniTypes::assertPrimitiveType(); QJniEnvironment env; jclass clazz = QJniObject::loadClass(className, env.jniEnv()); if (!clazz) return 0; - constexpr const char *signature = getTypeSignature(); + constexpr auto signature = QtJniTypes::fieldSignature(); jfieldID id = getCachedFieldID(env.jniEnv(), clazz, QJniObject::toBinaryEncClassName(className), fieldName, @@ -331,10 +314,10 @@ public: template static T getStaticField(jclass clazz, const char *fieldName) { - assertJniPrimitiveType(); + QtJniTypes::assertPrimitiveType(); QJniEnvironment env; T res{}; - constexpr const char *signature = getTypeSignature(); + constexpr auto signature = QtJniTypes::fieldSignature(); jfieldID id = getFieldID(env.jniEnv(), clazz, fieldName, signature, true); if (id) { getStaticFieldForType(env.jniEnv(), res, clazz, id); @@ -347,8 +330,8 @@ public: template QJniObject getObjectField(const char *fieldName) const { - assertJniObjectType(); - constexpr const char *signature = getTypeSignature(); + QtJniTypes::assertObjectType(); + constexpr auto signature = QtJniTypes::fieldSignature(); return getObjectField(fieldName, signature); } @@ -357,8 +340,8 @@ public: template static QJniObject getStaticObjectField(const char *className, const char *fieldName) { - assertJniObjectType(); - constexpr const char *signature = getTypeSignature(); + QtJniTypes::assertObjectType(); + constexpr auto signature = QtJniTypes::fieldSignature(); return getStaticObjectField(className, fieldName, signature); } @@ -369,8 +352,8 @@ public: template static QJniObject getStaticObjectField(jclass clazz, const char *fieldName) { - assertJniObjectType(); - constexpr const char *signature = getTypeSignature(); + QtJniTypes::assertObjectType(); + constexpr auto signature = QtJniTypes::fieldSignature(); return getStaticObjectField(clazz, fieldName, signature); } @@ -379,9 +362,9 @@ public: template void setField(const char *fieldName, T value) { - assertJniType(); + QtJniTypes::assertType(); QJniEnvironment env; - constexpr const char *signature = getTypeSignature(); + constexpr auto signature = QtJniTypes::fieldSignature(); jfieldID id = getCachedFieldID(env.jniEnv(), fieldName, signature); if (id) { setFieldForType(env.jniEnv(), object(), id, value); @@ -392,7 +375,7 @@ public: template void setField(const char *fieldName, const char *signature, T value) { - assertJniType(); + QtJniTypes::assertType(); QJniEnvironment env; jfieldID id = getCachedFieldID(env.jniEnv(), fieldName, signature); if (id) { @@ -404,13 +387,13 @@ public: template static void setStaticField(const char *className, const char *fieldName, T value) { - assertJniType(); + QtJniTypes::assertType(); QJniEnvironment env; jclass clazz = QJniObject::loadClass(className, env.jniEnv()); if (!clazz) return; - constexpr const char *signature = getTypeSignature(); + constexpr auto signature = QtJniTypes::fieldSignature(); jfieldID id = getCachedFieldID(env.jniEnv(), clazz, className, fieldName, signature, true); if (!id) @@ -424,7 +407,7 @@ public: static void setStaticField(const char *className, const char *fieldName, const char *signature, T value) { - assertJniType(); + QtJniTypes::assertType(); QJniEnvironment env; jclass clazz = QJniObject::loadClass(className, env.jniEnv()); @@ -443,7 +426,7 @@ public: static void setStaticField(jclass clazz, const char *fieldName, const char *signature, T value) { - assertJniType(); + QtJniTypes::assertType(); QJniEnvironment env; jfieldID id = getFieldID(env.jniEnv(), clazz, fieldName, signature, true); @@ -456,9 +439,9 @@ public: template static void setStaticField(jclass clazz, const char *fieldName, T value) { - assertJniType(); + QtJniTypes::assertType(); QJniEnvironment env; - constexpr const char *signature = getTypeSignature(); + constexpr auto signature = QtJniTypes::fieldSignature(); jfieldID id = getFieldID(env.jniEnv(), clazz, fieldName, signature, true); if (id) { setStaticFieldForType(env.jniEnv(), clazz, id, value); @@ -477,7 +460,7 @@ public: template QJniObject &operator=(T obj) { - assertJniType(); + QtJniTypes::assertType(); assign(static_cast(obj)); return *this; } @@ -525,100 +508,6 @@ private: friend bool operator==(const QJniObject &, const QJniObject &); friend bool operator!=(const QJniObject&, const QJniObject&); - template - static void staticAssertTypeMismatch() - { - static_assert(flag, "The used type is not supported by this template call. " - "Use a JNI based type instead."); - } - - template - static constexpr bool isJniPrimitiveType() - { - if constexpr(!std::is_same::value - && !std::is_same::value - && !std::is_same::value - && !std::is_same::value - && !std::is_same::value - && !std::is_same::value - && !std::is_same::value - && !std::is_same::value) { - return false; - } - - return true; - } - - template - static constexpr void assertJniPrimitiveType() - { - if constexpr(!isJniPrimitiveType()) - staticAssertTypeMismatch(); - } - - template - static constexpr void assertJniObjectType() - { - if constexpr(!std::is_convertible::value) - staticAssertTypeMismatch(); - } - - template - static constexpr void assertJniType() - { - if constexpr(!isJniPrimitiveType() && !std::is_convertible::value) - staticAssertTypeMismatch(); - } - - template - static constexpr const char* getTypeSignature() - { - if constexpr(std::is_same::value) - return "Ljava/lang/Object;"; - else if constexpr(std::is_same::value) - return "Ljava/lang/Class;"; - else if constexpr(std::is_same::value) - return "Ljava/lang/String;"; - else if constexpr(std::is_same::value) - return "[Ljava/lang/Object;"; - else if constexpr(std::is_same::value) - return "Ljava/lang/Throwable;"; - else if constexpr(std::is_same::value) - return "[Z"; - else if constexpr(std::is_same::value) - return "[B"; - else if constexpr(std::is_same::value) - return "[S"; - else if constexpr(std::is_same::value) - return "[I"; - else if constexpr(std::is_same::value) - return "[J"; - else if constexpr(std::is_same::value) - return "[F"; - else if constexpr(std::is_same::value) - return "[D"; - else if constexpr(std::is_same::value) - return "[C"; - else if constexpr(std::is_same::value) - return "Z"; - else if constexpr(std::is_same::value) - return "B"; - else if constexpr(std::is_same::value) - return "C"; - else if constexpr(std::is_same::value) - return "S"; - else if constexpr(std::is_same::value) - return "I"; - else if constexpr(std::is_same::value) - return "J"; - else if constexpr(std::is_same::value) - return "F"; - else if constexpr(std::is_same::value) - return "D"; - else - staticAssertTypeMismatch(); - } - template static constexpr void callMethodForType(JNIEnv *env, T &res, jobject obj, jmethodID id, va_list args) @@ -640,7 +529,7 @@ private: else if constexpr(std::is_same::value) res = env->CallDoubleMethodV(obj, id, args); else - staticAssertTypeMismatch(); + QtJniTypes::staticAssertTypeMismatch(); } template @@ -664,7 +553,7 @@ private: else if constexpr(std::is_same::value) res = env->CallStaticDoubleMethodV(clazz, id, args); else - staticAssertTypeMismatch(); + QtJniTypes::staticAssertTypeMismatch(); } template @@ -688,7 +577,7 @@ private: else if constexpr(std::is_same::value) res = env->GetDoubleField(obj, id); else - staticAssertTypeMismatch(); + QtJniTypes::staticAssertTypeMismatch(); } template @@ -712,7 +601,7 @@ private: else if constexpr(std::is_same::value) res = env->GetStaticDoubleField(clazz, id); else - staticAssertTypeMismatch(); + QtJniTypes::staticAssertTypeMismatch(); } template @@ -738,7 +627,7 @@ private: else if constexpr(std::is_convertible::value) env->SetObjectField(obj, id, value); else - staticAssertTypeMismatch(); + QtJniTypes::staticAssertTypeMismatch(); } template @@ -764,7 +653,7 @@ private: else if constexpr(std::is_convertible::value) env->SetStaticObjectField(clazz, id, value); else - staticAssertTypeMismatch(); + QtJniTypes::staticAssertTypeMismatch(); } friend QJniObjectPrivate; diff --git a/src/corelib/kernel/qjnitypes.h b/src/corelib/kernel/qjnitypes.h new file mode 100644 index 0000000000..0dde398ef2 --- /dev/null +++ b/src/corelib/kernel/qjnitypes.h @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QJNITYPES_H +#define QJNITYPES_H + +#include + +#if defined(Q_QDOC) || defined(Q_OS_ANDROID) +#include + +QT_BEGIN_NAMESPACE + +namespace QtJniTypes +{ + +// a constexpr type for string literals of any character width, aware of the length +// of the string. +template +struct String +{ + BaseType m_data[N_WITH_NULL] = {}; + + constexpr String() noexcept {} + // Can be instantiated (only) with a string literal + constexpr explicit String(const BaseType (&data)[N_WITH_NULL]) noexcept + { + for (size_t i = 0; i < N_WITH_NULL - 1; ++i) + m_data[i] = data[i]; + } + + constexpr BaseType at(size_t i) const { return m_data[i]; } + constexpr BaseType operator[](size_t i) const { return at(i); } + static constexpr size_t size() noexcept { return N_WITH_NULL; } + constexpr operator const BaseType *() const noexcept { return m_data; } + constexpr const BaseType *data() const noexcept { return m_data; } + template + constexpr bool startsWith(const BaseType (&lit)[N2_WITH_NULL]) const noexcept + { + if constexpr (N2_WITH_NULL > N_WITH_NULL) { + return false; + } else { + for (size_t i = 0; i < N2_WITH_NULL - 1; ++i) { + if (m_data[i] != lit[i]) + return false; + } + } + return true; + } + constexpr bool startsWith(BaseType c) const noexcept + { + return N_WITH_NULL > 1 && m_data[0] == c; + } + template + constexpr bool endsWith(const BaseType (&lit)[N2_WITH_NULL]) const noexcept + { + if constexpr (N2_WITH_NULL > N_WITH_NULL) { + return false; + } else { + for (size_t i = 0; i < N2_WITH_NULL; ++i) { + if (m_data[N_WITH_NULL - i - 1] != lit[N2_WITH_NULL - i - 1]) + return false; + } + } + return true; + } + constexpr bool endsWith(BaseType c) const noexcept + { + return N_WITH_NULL > 1 && m_data[N_WITH_NULL - 2] == c; + } + + template + friend inline constexpr bool operator==(const String &lhs, + const String &rhs) noexcept + { + if constexpr (N_WITH_NULL != N2_WITH_NULL) { + return false; + } else { + for (size_t i = 0; i < N_WITH_NULL - 1; ++i) { + if (lhs.at(i) != rhs.at(i)) + return false; + } + } + return true; + } + + template + friend inline constexpr bool operator!=(const String &lhs, + const String &rhs) noexcept + { + return !operator==(lhs, rhs); + } + + template + friend inline constexpr bool operator==(const String &lhs, + const BaseType (&rhs)[N2_WITH_NULL]) noexcept + { + return operator==(lhs, String(rhs)); + } + template + friend inline constexpr bool operator==(const BaseType (&lhs)[N2_WITH_NULL], + const String &rhs) noexcept + { + return operator==(String(lhs), rhs); + } + + template + friend inline constexpr bool operator!=(const String &lhs, + const BaseType (&rhs)[N2_WITH_NULL]) noexcept + { + return operator!=(lhs, String(rhs)); + } + template + friend inline constexpr bool operator!=(const BaseType (&lhs)[N2_WITH_NULL], + const String &rhs) noexcept + { + return operator!=(String(lhs), rhs); + } + + template + friend inline constexpr auto operator+(const String &lhs, + const String &rhs) noexcept + { + char data[N_WITH_NULL + N2_WITH_NULL - 1] = {}; + for (size_t i = 0; i < N_WITH_NULL - 1; ++i) + data[i] = lhs[i]; + for (size_t i = 0; i < N2_WITH_NULL - 1; ++i) + data[N_WITH_NULL - 1 + i] = rhs[i]; + return String(data); + } +}; + + +// Helper types that allow us to disable variadic overloads that would conflict +// with overloads that take a const char*. +template struct IsStringType : std::false_type {}; +template<> struct IsStringType : std::true_type {}; +template struct IsStringType> : std::true_type {}; +template struct IsStringType : std::true_type {}; + +template +static void staticAssertTypeMismatch() +{ + static_assert(flag, "The used type is not supported by this template call. " + "Use a JNI based type instead."); +} + +template +constexpr auto typeSignature() +{ + if constexpr(std::is_same::value) + return String("Ljava/lang/Object;"); + else if constexpr(std::is_same::value) + return String("Ljava/lang/Class;"); + else if constexpr(std::is_same::value) + return String("Ljava/lang/String;"); + else if constexpr(std::is_same::value) + return String("[Ljava/lang/Object;"); + else if constexpr(std::is_same::value) + return String("Ljava/lang/Throwable;"); + else if constexpr(std::is_same::value) + return String("[Z"); + else if constexpr(std::is_same::value) + return String("[B"); + else if constexpr(std::is_same::value) + return String("[S"); + else if constexpr(std::is_same::value) + return String("[I"); + else if constexpr(std::is_same::value) + return String("[J"); + else if constexpr(std::is_same::value) + return String("[F"); + else if constexpr(std::is_same::value) + return String("[D"); + else if constexpr(std::is_same::value) + return String("[C"); + else if constexpr(std::is_same::value) + return String("Z"); + else if constexpr(std::is_same::value) + return String("Z"); + else if constexpr(std::is_same::value) + return String("B"); + else if constexpr(std::is_same::value) + return String("C"); + else if constexpr(std::is_same::value) + return String("C"); + else if constexpr(std::is_same::value) + return String("S"); + else if constexpr(std::is_same::value) + return String("S"); + else if constexpr(std::is_same::value) + return String("I"); + else if constexpr(std::is_same::value) + return String("I"); + else if constexpr(std::is_same::value) + return String("I"); + else if constexpr(std::is_same::value) + return String("J"); + else if constexpr(std::is_same::value) + return String("J"); + else if constexpr(std::is_same::value) + return String("F"); + else if constexpr(std::is_same::value) + return String("F"); + else if constexpr(std::is_same::value) + return String("D"); + else if constexpr(std::is_same::value) + return String("D"); + else if constexpr(std::is_same::value) + return String("V"); + else if constexpr(IsStringType::value) + static_assert(!IsStringType::value, "Don't use a literal type, call data!"); + else + staticAssertTypeMismatch(); +} + +template +static constexpr bool isPrimitiveType() +{ + return typeSignature().size() == 2; +} + +template +static constexpr bool isObjectType() +{ + if constexpr(std::is_convertible::value) { + return true; + } else { + constexpr auto signature = typeSignature(); + return signature.startsWith('L') && signature.endsWith(';'); + } +} + +template +static constexpr void assertPrimitiveType() +{ + static_assert(isPrimitiveType(), "Type needs to be a primitive JNI type!"); +} + +template +static constexpr void assertObjectType() +{ + static_assert(isObjectType(), + "Type needs to be a JNI object type (convertible to jobject, or with " + "an object type signature registered)!"); +} + +template +static constexpr void assertType() +{ + static_assert(isPrimitiveType() || isObjectType(), + "Type needs to be a JNI type!"); +} + +template +static constexpr auto methodSignature() +{ + return (String("(") + + ... + typeSignature>()) + + String(")") + + typeSignature(); +} + +template +static constexpr auto fieldSignature() +{ + return QtJniTypes::typeSignature(); +} + +template +static constexpr auto constructorSignature() +{ + return methodSignature(); +} + +} // namespace QtJniTypes + +QT_END_NAMESPACE + +#endif + +#endif // QJNITYPES_H diff --git a/tests/auto/corelib/kernel/CMakeLists.txt b/tests/auto/corelib/kernel/CMakeLists.txt index 18f20bfadc..3083652945 100644 --- a/tests/auto/corelib/kernel/CMakeLists.txt +++ b/tests/auto/corelib/kernel/CMakeLists.txt @@ -49,4 +49,5 @@ endif() if(ANDROID) add_subdirectory(qjnienvironment) add_subdirectory(qjniobject) + add_subdirectory(qjnitypes) endif() diff --git a/tests/auto/corelib/kernel/qjnitypes/CMakeLists.txt b/tests/auto/corelib/kernel/qjnitypes/CMakeLists.txt new file mode 100644 index 0000000000..8184e91a11 --- /dev/null +++ b/tests/auto/corelib/kernel/qjnitypes/CMakeLists.txt @@ -0,0 +1,4 @@ +qt_internal_add_test(tst_qjnitypes + SOURCES + tst_qjnitypes.cpp +) diff --git a/tests/auto/corelib/kernel/qjnitypes/tst_qjnitypes.cpp b/tests/auto/corelib/kernel/qjnitypes/tst_qjnitypes.cpp new file mode 100644 index 0000000000..559fcd47c9 --- /dev/null +++ b/tests/auto/corelib/kernel/qjnitypes/tst_qjnitypes.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include + +class tst_QJniTypes : public QObject +{ + Q_OBJECT + +public: + tst_QJniTypes() = default; + +private slots: + void initTestCase(); +}; + +struct QtJavaWrapper {}; +template<> +constexpr auto QtJniTypes::typeSignature() +{ + return QtJniTypes::String("Lorg/qtproject/qt/android/QtJavaWrapper;"); +} + +template<> +constexpr auto QtJniTypes::typeSignature() +{ + return QtJniTypes::String("Ljava/lang/Object;"); +} + +struct QtCustomJniObject : QJniObject {}; +template<> +constexpr auto QtJniTypes::typeSignature() +{ + return QtJniTypes::String("Lorg/qtproject/qt/android/QtCustomJniObject;"); +} + +static_assert(QtJniTypes::typeSignature() == "Lorg/qtproject/qt/android/QtJavaWrapper;"); +static_assert(QtJniTypes::typeSignature() != "Ljava/lang/Object;"); +static_assert(!(QtJniTypes::typeSignature() == "X")); + +static_assert(QtJniTypes::fieldSignature() == "I"); +static_assert(QtJniTypes::fieldSignature() != "X"); +static_assert(QtJniTypes::fieldSignature() != "Ljava/lang/Object;"); +static_assert(QtJniTypes::fieldSignature() == "J"); +static_assert(QtJniTypes::fieldSignature() == "Ljava/lang/String;"); +static_assert(QtJniTypes::fieldSignature() == "Ljava/lang/Object;"); +static_assert(QtJniTypes::fieldSignature() == "[Ljava/lang/Object;"); +static_assert(QtJniTypes::fieldSignature() == "Ljava/lang/Object;"); +static_assert(QtJniTypes::fieldSignature() == "Lorg/qtproject/qt/android/QtJavaWrapper;"); +static_assert(QtJniTypes::fieldSignature() == "Lorg/qtproject/qt/android/QtCustomJniObject;"); + +static_assert(QtJniTypes::methodSignature() == "()V"); +static_assert(QtJniTypes::methodSignature() != "()X"); +static_assert(QtJniTypes::methodSignature() == "(I)V"); +static_assert(QtJniTypes::methodSignature() == "(ILjava/lang/String;)V"); +static_assert(QtJniTypes::methodSignature() == "(ILjava/lang/Class;)J"); +static_assert(QtJniTypes::methodSignature() == "(ILjava/lang/String;)Ljava/lang/Object;"); + +static_assert(QtJniTypes::isPrimitiveType()); +static_assert(QtJniTypes::isPrimitiveType()); +static_assert(!QtJniTypes::isPrimitiveType()); +static_assert(!QtJniTypes::isPrimitiveType()); + +static_assert(!QtJniTypes::isObjectType()); +static_assert(!QtJniTypes::isObjectType()); +static_assert(QtJniTypes::isObjectType()); +static_assert(QtJniTypes::isObjectType()); + +static_assert(QtJniTypes::String("ABCDE").startsWith("ABC")); +static_assert(QtJniTypes::String("ABCDE").startsWith("A")); +static_assert(QtJniTypes::String("ABCDE").startsWith("ABCDE")); +static_assert(!QtJniTypes::String("ABCDE").startsWith("ABCDEF")); +static_assert(!QtJniTypes::String("ABCDE").startsWith("9AB")); +static_assert(QtJniTypes::String("ABCDE").startsWith('A')); +static_assert(!QtJniTypes::String("ABCDE").startsWith('B')); + +static_assert(QtJniTypes::String("ABCDE").endsWith("CDE")); +static_assert(QtJniTypes::String("ABCDE").endsWith("E")); +static_assert(QtJniTypes::String("ABCDE").endsWith("ABCDE")); +static_assert(!QtJniTypes::String("ABCDE").endsWith("DEF")); +static_assert(!QtJniTypes::String("ABCDE").endsWith("ABCDEF")); +static_assert(QtJniTypes::String("ABCDE").endsWith('E')); +static_assert(!QtJniTypes::String("ABCDE").endsWith('F')); + +void tst_QJniTypes::initTestCase() +{ +} + +QTEST_MAIN(tst_QJniTypes) + +#include "tst_qjnitypes.moc"