QJniArray: add missing typedefs

Add missing nested typedefs for both the QJniArray container and
the QJniArrayIterator. Expand test case to make sure that some standard
algorithms (such as std::distance and ranged for) work with those
types.

Found during header review.

Task-number: QTBUG-119952
Change-Id: I96f348215c6f1e0e1ce777d9bdd2f172d7e52974
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
(cherry picked from commit 8f04615bcddbe4d8d00f2f7e977e13f93f90fddb)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Volker Hilsheimer 2024-01-22 13:45:14 +01:00 committed by Qt Cherry-pick Bot
parent 036e9811d2
commit 2cb6d38089
2 changed files with 30 additions and 7 deletions

View File

@ -26,6 +26,13 @@ struct QJniArrayIterator
constexpr QJniArrayIterator &operator=(const QJniArrayIterator &other) noexcept = default; constexpr QJniArrayIterator &operator=(const QJniArrayIterator &other) noexcept = default;
constexpr QJniArrayIterator &operator=(QJniArrayIterator &&other) noexcept = default; constexpr QJniArrayIterator &operator=(QJniArrayIterator &&other) noexcept = default;
using difference_type = jsize;
using value_type = T;
using pointer = T *;
using reference = T; // difference to container requirements
using const_reference = reference;
using iterator_category = std::forward_iterator_tag;
friend bool operator==(const QJniArrayIterator &lhs, const QJniArrayIterator &rhs) noexcept friend bool operator==(const QJniArrayIterator &lhs, const QJniArrayIterator &rhs) noexcept
{ {
return lhs.m_array == rhs.m_array && lhs.m_index == rhs.m_index; return lhs.m_array == rhs.m_array && lhs.m_index == rhs.m_index;
@ -34,7 +41,7 @@ struct QJniArrayIterator
{ {
return !(lhs == rhs); return !(lhs == rhs);
} }
T operator*() const const_reference operator*() const
{ {
return m_array->at(m_index); return m_array->at(m_index);
} }
@ -73,8 +80,10 @@ class QJniArrayBase : public QJniObject
> : std::true_type {}; > : std::true_type {};
public: public:
using size_type = jsize;
using difference_type = size_type;
qsizetype size() const size_type size() const
{ {
if (jarray array = object<jarray>()) if (jarray array = object<jarray>())
return jniEnv()->GetArrayLength(array); return jniEnv()->GetArrayLength(array);
@ -156,6 +165,12 @@ class QJniArray : public QJniArrayBase
friend struct QJniArrayIterator<T>; friend struct QJniArrayIterator<T>;
public: public:
using Type = T; using Type = T;
using value_type = T;
using reference = T;
using const_reference = const reference;
// read-only container, so no iterator typedef
using const_iterator = QJniArrayIterator<const T>; using const_iterator = QJniArrayIterator<const T>;
QJniArray() = default; QJniArray() = default;
@ -212,8 +227,8 @@ public:
const_iterator constEnd() const { return {end()}; } const_iterator constEnd() const { return {end()}; }
const_iterator cend() const { return {end()}; } const_iterator cend() const { return {end()}; }
T operator[](qsizetype i) const { return at(i); } const_reference operator[](size_type i) const { return at(i); }
T at(qsizetype i) const const_reference at(size_type i) const
{ {
JNIEnv *env = jniEnv(); JNIEnv *env = jniEnv();
if constexpr (std::is_convertible_v<jobject, T>) { if constexpr (std::is_convertible_v<jobject, T>) {
@ -295,7 +310,7 @@ public:
template <typename ElementType, typename List, typename NewFn, typename SetFn> template <typename ElementType, typename List, typename NewFn, typename SetFn>
auto QJniArrayBase::makeArray(List &&list, NewFn &&newArray, SetFn &&setRegion) auto QJniArrayBase::makeArray(List &&list, NewFn &&newArray, SetFn &&setRegion)
{ {
const int length = int(list.size()); const size_type length = size_type(list.size());
JNIEnv *env = QJniEnvironment::getJniEnv(); JNIEnv *env = QJniEnvironment::getJniEnv();
auto localArray = (env->*newArray)(length); auto localArray = (env->*newArray)(length);
if (QJniEnvironment::checkAndClearExceptions(env)) if (QJniEnvironment::checkAndClearExceptions(env))
@ -317,7 +332,7 @@ auto QJniArrayBase::makeObjectArray(List &&list)
return QJniArray<jobject>(); return QJniArray<jobject>();
JNIEnv *env = QJniEnvironment::getJniEnv(); JNIEnv *env = QJniEnvironment::getJniEnv();
const int length = int(list.size()); const size_type length = size_type(list.size());
// this assumes that all objects in the list have the same class // this assumes that all objects in the list have the same class
jclass elementClass = nullptr; jclass elementClass = nullptr;
@ -328,7 +343,7 @@ auto QJniArrayBase::makeObjectArray(List &&list)
auto localArray = env->NewObjectArray(length, elementClass, nullptr); auto localArray = env->NewObjectArray(length, elementClass, nullptr);
if (QJniEnvironment::checkAndClearExceptions(env)) if (QJniEnvironment::checkAndClearExceptions(env))
return QJniArray<jobject>(); return QJniArray<jobject>();
for (int i = 0; i < length; ++i) { for (size_type i = 0; i < length; ++i) {
jobject object; jobject object;
if constexpr (std::is_same_v<ElementType, QJniObject>) if constexpr (std::is_same_v<ElementType, QJniObject>)
object = list.at(i).object(); object = list.at(i).object();

View File

@ -100,6 +100,14 @@ void tst_QJniArray::operators()
it = array.begin(); it = array.begin();
QCOMPARE(it, array.begin()); QCOMPARE(it, array.begin());
} }
QCOMPARE(std::distance(array.begin(), array.end()), array.size());
qsizetype index = 0;
for (const auto &value : array) {
QCOMPARE(value, bytes.at(index));
++index;
}
} }
QTEST_MAIN(tst_QJniArray) QTEST_MAIN(tst_QJniArray)