7#include <QtCore/qlist.h>
9#if defined(Q_QDOC) || defined(Q_OS_ANDROID)
10#include <QtCore/qbytearray.h>
11#include <QtCore/qjniobject.h>
15#include <QtCore/q20type_traits.h>
19template <
typename T>
class QJniArray;
23 QJniArrayIterator() =
default;
25 constexpr QJniArrayIterator(
const QJniArrayIterator &
other)
noexcept =
default;
26 constexpr QJniArrayIterator(QJniArrayIterator &&
other)
noexcept =
default;
27 constexpr QJniArrayIterator &operator=(
const QJniArrayIterator &
other)
noexcept =
default;
28 constexpr QJniArrayIterator &operator=(QJniArrayIterator &&
other)
noexcept =
default;
30 using difference_type = jsize;
35 using iterator_category = std::bidirectional_iterator_tag;
37 friend bool operator==(
const QJniArrayIterator &lhs,
const QJniArrayIterator &rhs)
noexcept
39 return lhs.m_array == rhs.m_array && lhs.m_index == rhs.m_index;
41 friend bool operator!=(
const QJniArrayIterator &lhs,
const QJniArrayIterator &rhs)
noexcept
47 return m_array->at(m_index);
49 friend QJniArrayIterator &operator++(QJniArrayIterator &that)
noexcept
54 friend QJniArrayIterator operator++(QJniArrayIterator &that,
int)
noexcept
60 friend QJniArrayIterator &operator--(QJniArrayIterator &that)
noexcept
65 friend QJniArrayIterator operator--(QJniArrayIterator &that,
int)
noexcept
71 void swap(QJniArrayIterator &
other)
noexcept
73 std::swap(m_index,
other.m_index);
78 using VT = std::remove_const_t<T>;
79 friend class QJniArray<VT>;
82 const QJniArray<VT> *m_array =
nullptr;
92 template <
typename Container,
typename =
void>
struct CanConvertHelper : std::false_type {};
93 template <
typename Container>
94 struct CanConvertHelper<Container,
std::void_t<decltype(std::data(std::declval<Container>())),
95 decltype(std::size(std::declval<Container>())),
96 typename Container::value_type
98 > : std::true_type {};
101 using size_type = jsize;
102 using difference_type = size_type;
104 operator QJniObject()
const {
return m_object; }
106 template <
typename T = j
object>
107 T
object()
const {
return m_object.object<T>(); }
108 bool isValid()
const {
return m_object.isValid(); }
110 size_type
size()
const
112 if (jarray
array = m_object.object<jarray>())
113 return jniEnv()->GetArrayLength(
array);
117 template <
typename Container>
118 static constexpr bool canConvert = CanConvertHelper<q20::remove_cvref_t<Container>>
::value;
119 template <
typename Container>
120 using IfCanConvert = std::enable_if_t<canConvert<Container>,
bool>;
121 template <
typename Container
122 , IfCanConvert<Container> =
true
124 static auto fromContainer(Container &&container)
126 Q_ASSERT_X(
size_t(std::size(container)) <=
size_t((std::numeric_limits<size_type>::max)()),
127 "QJniArray::fromContainer",
"Container is too large for a Java array");
129 using ElementType =
typename std::remove_reference_t<Container>::value_type;
130 if constexpr (std::disjunction_v<std::is_same<ElementType, jobject>,
131 std::is_same<ElementType, QJniObject>,
132 std::is_same<ElementType, QString>,
133 std::is_base_of<QtJniTypes::JObjectBase, ElementType>
135 return makeObjectArray(std::forward<Container>(container));
136 }
else if constexpr (std::is_same_v<ElementType, jfloat>) {
137 return makeArray<jfloat>(std::forward<Container>(container), &JNIEnv::NewFloatArray,
138 &JNIEnv::SetFloatArrayRegion);
139 }
else if constexpr (std::is_same_v<ElementType, jdouble>) {
140 return makeArray<jdouble>(std::forward<Container>(container), &JNIEnv::NewDoubleArray,
141 &JNIEnv::SetDoubleArrayRegion);
142 }
else if constexpr (std::disjunction_v<std::is_same<ElementType, jboolean>,
143 std::is_same<ElementType, bool>>) {
144 return makeArray<jboolean>(std::forward<Container>(container), &JNIEnv::NewBooleanArray,
145 &JNIEnv::SetBooleanArrayRegion);
146 }
else if constexpr (std::disjunction_v<std::is_same<ElementType, jbyte>,
147 std::is_same<ElementType, char>>) {
148 return makeArray<jbyte>(std::forward<Container>(container), &JNIEnv::NewByteArray,
149 &JNIEnv::SetByteArrayRegion);
150 }
else if constexpr (std::disjunction_v<std::is_same<ElementType, jchar>,
151 std::is_same<ElementType, QChar>>) {
152 return makeArray<jchar>(std::forward<Container>(container), &JNIEnv::NewCharArray,
153 &JNIEnv::SetCharArrayRegion);
154 }
else if constexpr (std::is_same_v<ElementType, jshort>
155 ||
sizeof(ElementType) ==
sizeof(jshort)) {
156 return makeArray<jshort>(std::forward<Container>(container), &JNIEnv::NewShortArray,
157 &JNIEnv::SetShortArrayRegion);
158 }
else if constexpr (std::is_same_v<ElementType, jint>
159 ||
sizeof(ElementType) ==
sizeof(jint)) {
160 return makeArray<jint>(std::forward<Container>(container), &JNIEnv::NewIntArray,
161 &JNIEnv::SetIntArrayRegion);
162 }
else if constexpr (std::is_same_v<ElementType, jlong>
163 ||
sizeof(ElementType) ==
sizeof(jlong)) {
164 return makeArray<jlong>(std::forward<Container>(container), &JNIEnv::NewLongArray,
165 &JNIEnv::SetLongArrayRegion);
170 QJniArrayBase() =
default;
171 ~QJniArrayBase() =
default;
173 explicit QJniArrayBase(jarray
array)
174 : m_object(static_cast<jobject>(
array))
177 explicit QJniArrayBase(
const QJniObject &
object)
180 explicit QJniArrayBase(
QJniObject &&
object) noexcept
181 : m_object(std::move(
object))
184 JNIEnv *jniEnv() const noexcept {
return QJniEnvironment::getJniEnv(); }
186 template <
typename ElementType,
typename List,
typename NewFn,
typename SetFn>
187 static auto makeArray(List &&
list, NewFn &&newArray, SetFn &&setRegion);
188 template <
typename List>
189 static auto makeObjectArray(List &&
list);
198 friend struct QJniArrayIterator<T>;
208 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
210 QJniArray() =
default;
211 explicit QJniArray(jarray
array) : QJniArrayBase(
array) {}
213 explicit QJniArray(
QJniObject &&
object) noexcept : QJniArrayBase(std::move(
object)) {}
216 QJniArray(
const QJniArray &
other) =
default;
217 QJniArray(QJniArray &&
other)
noexcept =
default;
218 QJniArray &operator=(
const QJniArray &
other) =
default;
219 QJniArray &operator=(QJniArray &&
other)
noexcept =
default;
221 template <
typename Container
222 , IfCanConvert<Container> =
true
224 explicit QJniArray(Container &&container)
225 : QJniArrayBase(QJniArrayBase::fromContainer(
std::forward<Container>(container)))
229 template <
typename E = T
230 , IfCanConvert<std::initializer_list<E>> =
true
233 : QJniArrayBase(QJniArrayBase::fromContainer(
list))
237 template <
typename Other, std::enable_if_t<std::is_convertible_v<Other, Type>,
bool> = true>
238 QJniArray(QJniArray<Other> &&
other)
242 ~QJniArray() =
default;
244 auto arrayObject()
const
246 if constexpr (std::is_convertible_v<jobject, T>)
247 return object<jobjectArray>();
248 else if constexpr (std::is_same_v<T, jbyte>)
249 return object<jbyteArray>();
250 else if constexpr (std::is_same_v<T, jchar>)
251 return object<jcharArray>();
252 else if constexpr (std::is_same_v<T, jboolean>)
253 return object<jbooleanArray>();
254 else if constexpr (std::is_same_v<T, jshort>)
255 return object<jshortArray>();
256 else if constexpr (std::is_same_v<T, jint>)
257 return object<jintArray>();
258 else if constexpr (std::is_same_v<T, jlong>)
259 return object<jlongArray>();
260 else if constexpr (std::is_same_v<T, jfloat>)
261 return object<jfloatArray>();
262 else if constexpr (std::is_same_v<T, jdouble>)
263 return object<jdoubleArray>();
265 return object<jarray>();
275 const_reverse_iterator rbegin() const noexcept {
return const_reverse_iterator(
end()); }
276 const_reverse_iterator rend() const noexcept {
return const_reverse_iterator(
begin()); }
277 const_reverse_iterator crbegin() const noexcept {
return const_reverse_iterator(
end()); }
278 const_reverse_iterator crend() const noexcept {
return const_reverse_iterator(
begin()); }
283 JNIEnv *env = jniEnv();
284 if constexpr (std::is_convertible_v<jobject, T>) {
285 jobject element = env->GetObjectArrayElement(object<jobjectArray>(),
i);
286 if constexpr (std::is_base_of_v<QJniObject, T>)
287 return QJniObject::fromLocalRef(element);
288 else if constexpr (std::is_base_of_v<QtJniTypes::JObjectBase, T>)
289 return T::fromLocalRef(element);
292 }
else if constexpr (std::is_base_of_v<std::remove_pointer_t<jobject>, std::remove_pointer_t<T>>) {
294 return static_cast<T
>(env->GetObjectArrayElement(object<jobjectArray>(),
i));
297 if constexpr (std::is_same_v<T, jbyte>)
298 env->GetByteArrayRegion(object<jbyteArray>(),
i, 1, &
res);
299 else if constexpr (std::is_same_v<T, jchar>)
300 env->GetCharArrayRegion(object<jcharArray>(),
i, 1, &
res);
301 else if constexpr (std::is_same_v<T, jboolean>)
302 env->GetBooleanArrayRegion(object<jbooleanArray>(),
i, 1, &
res);
303 else if constexpr (std::is_same_v<T, jshort>)
304 env->GetShortArrayRegion(object<jshortArray>(),
i, 1, &
res);
305 else if constexpr (std::is_same_v<T, jint>)
306 env->GetIntArrayRegion(object<jbyteArray>(),
i, 1, &
res);
307 else if constexpr (std::is_same_v<T, jlong>)
308 env->GetLongArrayRegion(object<jlongArray>(),
i, 1, &
res);
309 else if constexpr (std::is_same_v<T, jfloat>)
310 env->GetFloatArrayRegion(object<jfloatArray>(),
i, 1, &
res);
311 else if constexpr (std::is_same_v<T, jdouble>)
312 env->GetDoubleArrayRegion(object<jdoubleArray>(),
i, 1, &
res);
316 auto toContainer()
const
318 JNIEnv *env = jniEnv();
319 if constexpr (std::is_same_v<T, jobject>) {
322 for (
auto element : *
this)
325 }
else if constexpr (std::is_same_v<T, jstring>) {
328 for (
auto element : *
this)
331 }
else if constexpr (std::is_same_v<T, jbyte>) {
334 env->GetByteArrayRegion(object<jbyteArray>(),
335 0, bytecount,
reinterpret_cast<jbyte *
>(
res.data()));
340 if constexpr (std::is_same_v<T, jchar>) {
341 env->GetCharArrayRegion(object<jcharArray>(),
342 0,
res.size(),
res.data());
343 }
else if constexpr (std::is_same_v<T, jboolean>) {
344 env->GetBooleanArrayRegion(object<jbooleanArray>(),
345 0,
res.size(),
res.data());
346 }
else if constexpr (std::is_same_v<T, jshort>) {
347 env->GetShortArrayRegion(object<jshortArray>(),
348 0,
res.size(),
res.data());
349 }
else if constexpr (std::is_same_v<T, jint>) {
350 env->GetIntArrayRegion(object<jintArray>(),
351 0,
res.size(),
res.data());
352 }
else if constexpr (std::is_same_v<T, jlong>) {
353 env->GetLongArrayRegion(object<jlongArray>(),
354 0,
res.size(),
res.data());
355 }
else if constexpr (std::is_same_v<T, jfloat>) {
356 env->GetFloatArrayRegion(object<jfloatArray>(),
357 0,
res.size(),
res.data());
358 }
else if constexpr (std::is_same_v<T, jdouble>) {
359 env->GetDoubleArrayRegion(object<jdoubleArray>(),
360 0,
res.size(),
res.data());
369template <
typename ElementType,
typename List,
typename NewFn,
typename SetFn>
370auto QJniArrayBase::makeArray(List &&
list, NewFn &&newArray, SetFn &&setRegion)
372 const size_type
length = size_type(std::size(
list));
373 JNIEnv *env = QJniEnvironment::getJniEnv();
374 auto localArray = (env->*newArray)(
length);
375 if (QJniEnvironment::checkAndClearExceptions(env))
376 return QJniArray<ElementType>();
380 (env->*setRegion)(localArray, 0,
length,
381 reinterpret_cast<const ElementType *
>(std::data(std::as_const(
list))));
383 return QJniArray<ElementType>(localArray);
386template <
typename List>
387auto QJniArrayBase::makeObjectArray(List &&
list)
390 using ResultType = QJniArray<
decltype(std::declval<QJniObject::LocalFrame<>>().convertToJni(
391 std::declval<ElementType>()))
394 if (std::size(
list) == 0)
397 JNIEnv *env = QJniEnvironment::getJniEnv();
398 const size_type
length = size_type(std::size(
list));
401 jclass elementClass =
nullptr;
402 if constexpr (std::disjunction_v<std::is_same<ElementType, QJniObject>,
403 std::is_base_of<QtJniTypes::JObjectBase, ElementType>>) {
404 elementClass = std::begin(
list)->objectClass();
405 }
else if constexpr (std::is_same_v<ElementType, QString>) {
406 elementClass = env->FindClass(
"java/lang/String");
408 elementClass = env->GetObjectClass(*std::begin(
list));
410 auto localArray = env->NewObjectArray(
length, elementClass,
nullptr);
411 if (QJniEnvironment::checkAndClearExceptions(env))
415 QJniObject::LocalFrame
frame(env);
416 constexpr jint frameCapacity = 100;
418 for (
const auto &element :
std::as_const(
list)) {
419 if (
i % frameCapacity == 0) {
421 env->PopLocalFrame(
nullptr);
422 if (env->PushLocalFrame(frameCapacity) != 0)
425 jobject
object =
frame.convertToJni(element);
426 env->SetObjectArrayElement(localArray,
i,
object);
430 env->PopLocalFrame(
nullptr);
431 return ResultType(localArray);
436template <
typename T>
struct IsJniArray: std::false_type {};
437template <
typename T>
struct IsJniArray<QJniArray<T>> : std::true_type {};
438template <
typename T>
struct Traits<QJniArray<T>> {
439 template <IfVal
idFieldType<T> = true>
442 return CTString(
"[") + Traits<T>::signature();
445template <
typename T>
struct Traits<
QList<T>> {
446 template <IfVal
idFieldType<T> = true>
449 return CTString(
"[") + Traits<T>::signature();
455 return CTString(
"[B");
list append(new Employee("Blackpool", "Stephen"))
typename C::value_type value_type
typename C::const_iterator const_iterator
const PluginKeyMapConstIterator cend
Combined button and popup list for selecting options.
const T & const_reference()
bool canConvert(const QQmlPropertyCache *fromMo, const QQmlPropertyCache *toMo)
std::remove_cv_t< std::remove_reference_t< T > > remove_cvref_t
static jboolean copy(JNIEnv *, jobject)
constexpr bool operator!=(const timespec &t1, const timespec &t2)
constexpr timespec operator*(const timespec &t1, int mul)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLsizei const void * pointer
bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
#define Q_ASSERT_X(cond, x, msg)
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
constexpr void qt_ptr_swap(T *&lhs, T *&rhs) noexcept
#define QT_TECH_PREVIEW_API
char * toString(const MyType &t)
[31]