Revision control

++ // Copyright (C) 2024 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
++
++ /*!
++ \class QJniArrayBase
++ \brief The QJniArrayBase class provides common, type-independent APIs for QJniArray.
++ \inmodule QtCore
++ \ingroup frameworks-technologies
++ \since 6.8
++ */
++
++ /*!
++ \typedef QJniArrayBase::size_type
++
++ A 32 bit integer.
++ */
++
++ /*!
++ \fn template <typename Container, QJniArrayBase::if_compatible_source_container<Container>> auto QJniArrayBase::fromContainer(Container &&container)
++
++ Creates a Java array holding the data in \a container, and returns a
++ QJniArray instance that wraps it.
++
++ //! [forward-iterable-containers]
++ \constraints \c{Container}
++ is a container that stores elements of a \l{JNI types}{JNI type} or equivalent
++ C++ type, and provides a forward iterator.
++
++ The specialization of the constructed QJniArray depends on the value type
++ of the \a container. For a \c{Container<T>} (such as e.g. \c{QList<T>}) it
++ will typically be \c{QJniArray<T>}, with the following exceptions:
++
++ \table
++ \header
++ \li Container
++ \li Specialization
++ \row
++ \li QByteArray
++ \li QJniArray<jbyte>
++ \row
++ \li QStringList
++ \li QJniArray<jstring>
++ \header
++ \li Container::value_type
++ \li Specialization
++ \row
++ \li QJniObject
++ \li QJniArray<jobject>
++ \endtable
++ //! [forward-iterable-containers]
++
++ \sa QJniArray::toContainer()
++ */
++
++ /*!
++ \fn QJniArrayBase::operator QJniObject() const
++
++ \return a QJniObject wrapping the same \c{jobject} as this QJniArray instance.
++ */
++
++ /*!
++ \fn void QJniArrayBase::swap(QJniArrayBase &other)
++ \memberswap{array object}
++ */
++
++ /*!
++ \fn template <typename T> T QJniArrayBase::object() const
++
++ \return the object held by the QJniArray as type T, which can be one of the
++ \l {QJniObject#Object Types}{JNI Object Types}.
++ */
++
++ /*!
++ \fn bool QJniArrayBase::isValid() const
++
++ \return whether the QJniArray object wraps a valid `jobject`. For invalid
++ QJniArray instances, object() returns \nullptr. Iterating over an invalid
++ object is safe (begin() will return the same as end()), and calling
++ \l{QJniArray::}{toContainer()} on an invalid array will return an empty
++ container.
++
++ \sa QJniObject::isValid(), object(), QJniArray::toContainer()
++ */
++
++ /*!
++ \fn bool QJniArrayBase::isEmpty() const
++
++ \return \c true if the array has size 0; otherwise returns \c false.
++
++ An \l{isValid}{invalid} array is always empty.
++
++ \c isValid(), size()
++ */
++
++ /*!
++ \fn QJniArrayBase::size_type QJniArrayBase::size() const
++
++ \return the size of the array.
++ */
++
++ /*!
++ \class QJniArray
++ \brief The QJniArray class is a template class that represents an array in Java.
++ \inmodule QtCore
++ \ingroup frameworks-technologies
++ \since 6.8
++
++ QJniArray is a template class where \a T specifies the element type of the
++ Java array. The type can be a JNI primitive type such as \c jint or \c jbyte,
++ or an object type such as \c jobject, \c jstring, or a type declared with
++ Q_DECLARE_JNI_CLASS.
++
++ The QJniArray template makes it easy to work with Java methods that return
++ or take a Java array.
++
++ \note \l{Java arrays} can hold primitive types and objects. The array
++ itself can be treated like a Java Object, and the JNI framework provides
++ explicit APIs to work with such arrays. In addition, the Java class library
++ provides container types such as \c{List} or \c{ArrayList}. Objects of
++ those types can not be represented by a QJniArray. Instead, use QJniObject
++ to call the class-specific member functions.
++
++ To create a QJniArray instance, either construct it from a corresponding C++
++ container:
++
++ \code
++ QList<int> intList;
++ const QJniArray intArray = QJniArray(intList);
++ \endcode
++
++ or from an initializer list:
++
++ \code
++ const QJniArray intArray{1, 2, 3};
++ \endcode
++
++ QJniArray will create a new Java array and copy the C++-side data into it.
++
++ When calling functions that return an array via QJniObject::callMethod,
++ such as \c{char[] toCharArray()} in the Java \c{String} class, specify the
++ return type as a C array (\c{jchar[]} in the following):
++
++ \code
++ const auto charArray = stringObject.callMethod<jchar[]>("toCharArray");
++ \endcode
++
++ The \c{charArray} variable will be of type \c{QJniArray<jchar>}, and hold
++ a new global reference to the \c{jcharArray} JNI object.
++
++ Note that the arrays in the code snippets above are all const. Accessing
++ elements in a const array is considerably more efficient than operating on
++ a mutable array.
++
++ A QJniArray can also be constructed from an existing \c{jarray} or
++ QJniObject. However, note that no type checking is performed to verify that
++ the \c{jarray} or QJniObject indeed represents an array holding elements of
++ the specified type, and accessing a mismatching QJniArray results in
++ undefined behavior.
++
++ The data in a QJniArray can either be accessed element by element using
++ at() or \l{QJniArray::}{operator[]()}, or iterated over.
++
++ \code
++ for (const auto &value : array)
++ process(value);
++ \endcode
++
++ To copy the entire array into a C++ side Qt container, use the toContainer()
++ function.
++
++ \code
++ const auto bytes = object.callMethod<jbyte[]>("getBytes");
++ QByteArray data = bytes.toContainer();
++ \endcode
++
++ which happens implicitly in
++
++ \code
++ const auto data = object.callMethod<QByteArray>("getBytes");
++ \endcode
++
++ The return type of toContainer() depends on the type that QJniArray has
++ been instantiated with.
++ //! [type-mapping]
++ For \c{QJniArray<T>} this will typically be \c{QList<T>}, with the
++ following exceptions:
++
++ \table
++ \header
++ \li Specialization
++ \li C++ type
++ \row
++ \li QJniArray<jbyte>
++ \li QByteArray
++ \row
++ \li QJniArray<char>
++ \li QByteArray
++ \row
++ \li QJniArray<jstring>
++ \li QStringList
++ \row
++ \li QJniArray<QString>
++ \li QStringList
++ \endtable
++ //! [type-mapping]
++
++ An array of a fixed size can also be created without any data, and can then
++ be populated element by element using
++ \l{QJniArray::operator[]()}{operator[]}:
++
++ \code
++ QJniArray<jint> intArray(size);
++ for (int i = 0; i < size; ++i)
++ intArray[i] = i;
++ \endcode
++
++ or a mutable iterator:
++
++ \code
++ QJniArray<QString> strings(size);
++ int i = 0;
++ for (auto string : strings) // note: not 'auto &string'
++ string = u"Row %1"_s.arg(i++);
++ \endcode
++
++ As in Java, the size of an array can not be changed, but the array variable
++ can be assigned to a different array.
++
++ \note Java arrays are limited to 32 bits, and the \c{size_type} member type of
++ QJniArray is \c{jsize}, which is a 32bit integer type. Trying to construct
++ a QJniArray from a C++ container that holds more than 2^32 elements will
++ cause a runtime assertion.
++ */
++
++ /*!
++ \fn template <typename T> QJniArray<T>::QJniArray()
++
++ Default constructor of QJniArray. This does not create a Java-side array,
++ and the instance will be invalid.
++
++ \sa isValid
++ */
++
++ /*!
++ \fn template <typename T> QJniArray<T>::QJniArray(jarray array)
++
++ Constructs a QJniArray that wraps the Java-side array \a array,
++ creating a new global reference to \a array.
++
++ //! [no-array-validation]
++ \note This constructor does not perform any validation of whether the
++ Java-side object is an array of the correct type. Accessing a
++ mismatching QJniArray results in undefined behavior.
++ //! [no-array-validation]
++ */
++
++ /*!
++ \fn template <typename T> QJniArray<T>::QJniArray(const QJniObject &object)
++
++ Constructs a QJniArray that wraps the same Java array as \a object,
++ creating a new global reference. To construct a QJniArray from an existing
++ local reference, use a QJniObject constructed via
++ \l{QJniObject::}{fromLocalRef()}.
++
++ \include qjniarray.qdoc no-array-validation
++ */
++
++ /*!
++ \fn template <typename T> QJniArray<T>::QJniArray(QJniObject &&object)
++
++ Constructs a QJniArray by moving from \a object. The QJniObject becomes
++ \l{QJniObject::isValid}{invalid}.
++
++ \include qjniarray.qdoc no-array-validation
++ */
++
++ /*!
++ \fn template <typename T> template <typename Other, QJniArrayBase::if_convertible<Other, T>> QJniArray<T>::QJniArray(const QJniArray<Other> &other)
++
++ Constructs a QJniArray by copying \a other. Both QJniArray objects will
++ reference the same Java array object.
++
++ \constraints the element
++ type \c{Other} of \a other is convertible to the element type \c{T} of the
++ QJniArray being constructed. However, no actual conversion takes place.
++ */
++
++ /*!
++ \fn template <typename T> template <typename Other, QJniArrayBase::if_convertible<Other, T>> QJniArray<T>::QJniArray(QJniArray<Other> &&other)
++
++ Constructs a QJniArray by moving from \a other. The \a other array becomes
++ \l{QJniArrayBase::isValid}{invalid}.
++
++ \constraints the element
++ type \c{Other} of \a other is convertible to the element type \c{T} of the
++ QJniArray being constructed. However, no actual conversion takes place.
++ */
++
++ /*!
++ \fn template <typename T> template <typename Other, QJniArrayBase::if_convertible<Other, T>> QJniArray &QJniArray<T>::operator=(const QJniArray<Other> &other)
++
++ Assigns \a other to this QJniArray, and returns a reference to this. Both
++ QJniArray objects will reference the same Java array object.
++
++ \constraints the element
++ type \c{Other} of \a other is convertible to the element type \c{T} of this
++ QJniArray. However, no actual conversion takes place.
++ */
++
++ /*!
++ \fn template <typename T> template <typename Other, QJniArrayBase::if_convertible<Other, T>> QJniArray &QJniArray<T>::operator=(QJniArray<Other> &&other)
++
++ Moves \a other into this QJniArray, and returns a reference to this. The
++ \a other array becomes \l{QJniArrayBase::isValid}{invalid}.
++
++ \constraints the element
++ type \c{Other} of \a other is convertible to the element type \c{T} of this
++ QJniArray. However, no actual conversion takes place.
++ */
++
++ /*!
++ \fn template <typename T> template <typename Container, QJniArrayBase::if_compatible_source_container<Container>> QJniArray<T>::QJniArray(Container &&container)
++
++ Constructs a QJniArray that wraps a newly-created Java array for elements of
++ type \c{Container::value_type}, and populates the Java array with the data from
++ \a container.
++
++ \include qjniarray.qdoc forward-iterable-containers
++
++ \sa QJniArrayBase::fromContainer(), toContainer()
++ */
++
++ /*!
++ \fn template <typename T> QJniArray<T>::QJniArray(std::initializer_list<T> &list)
++
++ Constructs a QJniArray that wraps a newly-created Java array for elements of
++ type \c{T}, and populates the Java array with the data from \a list.
++
++ \sa QJniArrayBase::fromContainer(), toContainer()
++ */
++
++ /*!
++ \fn template <typename T> QJniArray<T>::QJniArray(size_type size)
++ \since 6.9
++
++ Constructs an empty QJniArray of size \a size. The elements in the array do
++ not get initialized.
++ */
++
++ /*!
++ \fn template <typename T> QJniArray<T>::~QJniArray()
++
++ Destroys the QJniArray object and releases any references held to the
++ wrapped Java array.
++ */
++
++ /*!
++ \fn template <typename T> auto QJniArray<T>::arrayObject() const
++
++ \return the wrapped Java object as the suitable \c{jarray} type that
++ matches the element type \c{T} of this QJniArray object.
++
++ \table
++ \header
++ \li T
++ \li jarray type
++ \row
++ \li jbyte
++ \li jbyteArray
++ \row
++ \li jchar
++ \li jcharArray
++ \row
++ \li ...
++ \li ...
++ \row
++ \li jobject
++ \li jobjectArray
++ \row
++ \li QJniObject
++ \li jobjectArray
++ \row
++ \li Q_DECLARE_JNI_CLASS
++ \li jobjectArray
++ \endtable
++ */
++
++ /*!
++ \typedef QJniArray::iterator
++
++ A random-access iterator for QJniArray.
++ /*
++
++ /*!
++ \typedef QJniArray::const_iterator
++
++ A random-access, const iterator for QJniArray.
++ */
++
++ /*!
++ \typedef QJniArray::reverse_iterator
++
++ A reverse iterator for QJniArray, synonym for
++ \c{std::reverse_iterator<iterator>}.
++
++ //! [reverse_iterator-operator->]
++ \note Accessing the element of the reverse iterator using \c{operator->()}
++ requires C++20, as the C++17 reverse_iterator does not support iterators that
++ return a proxy object.
++ //! [reverse_iterator-operator->]
++ /*
++
++ /*!
++ \typedef QJniArray::const_reverse_iterator
++
++ A reverse iterator for the QJniArray, synonym for
++ \c{std::reverse_iterator<const_iterator>}.
++
++ \include qjniarray.qdoc reverse_iterator-operator->
++ */
++
++ /*!
++ \fn template <typename T> const_iterator QJniArray<T>::begin() const
++ \fn template <typename T> iterator QJniArray<T>::begin()
++ \fn template <typename T> const_iterator QJniArray<T>::constBegin() const
++ \fn template <typename T> const_iterator QJniArray<T>::cbegin() const
++
++ Returns an \l{STL-style iterators}{STL-style const iterator} pointing to the
++ first item in the array.
++
++ If the array is \l{QJniArrayBase::isValid()}{invalid}, then this will return
++ the same iterator as the corresponding end() function.
++
++ \sa end(), rbegin()
++ */
++
++ /*!
++ \fn template <typename T> const_iterator QJniArray<T>::end() const
++ \fn template <typename T> iterator QJniArray<T>::end()
++ \fn template <typename T> const_iterator QJniArray<T>::constEnd() const
++ \fn template <typename T> const_iterator QJniArray<T>::cend() const
++
++ Returns an \l{STL-style iterators}{STL-style iterator} pointing just
++ after the last item in the list.
++
++ \sa begin(), rend()
++ */
++
++ /*!
++ \fn template <typename T> const_reverse_iterator QJniArray<T>::rbegin() const
++ \fn template <typename T> reverse_iterator QJniArray<T>::rbegin()
++ \fn template <typename T> const_reverse_iterator QJniArray<T>::crbegin() const
++
++ Returns an \l{STL-style iterators}{STL-style reverse iterator} pointing to
++ the first item in the array, in reverse order.
++
++ If the array is \l{QJniArrayBase::isValid()}{invalid}, then this will return
++ the same iterator as the corresponding rend() function.
++
++ \include qjniarray.qdoc reverse_iterator-operator->
++
++ \sa rend(), begin()
++ */
++
++ /*!
++ \fn template <typename T> const_reverse_iterator QJniArray<T>::rend() const
++ \fn template <typename T> reverse_iterator QJniArray<T>::rend()
++ \fn template <typename T> const_reverse_iterator QJniArray<T>::crend() const
++
++ Returns an \l{STL-style iterators}{STL-style reverse iterator} pointing just
++ after the last item in the list, in reverse order.
++
++ \include qjniarray.qdoc reverse_iterator-operator->
++
++ \sa rbegin(), end()
++ */
++
++ /*!
++ \fn template <typename T> T QJniArray<T>::operator[](size_type i) const
++ \fn template <typename T> T QJniArray<T>::at(size_type i) const
++
++ Returns the value at position \a i in the wrapped Java array.
++
++ \a i must be a valid index position in the list (i.e.,
++ 0 <= \a i < size()).
++
++ \sa size()
++ */
++
++ /*!
++ \fn template <typename T> QJniArray<T>::reference QJniArray<T>::operator[](size_type i)
++ \since 6.9
++
++ Returns a reference object for value at position \a i in the wrapped Java
++ array.
++
++ \a i must be a valid index position in the list (i.e., 0 <= \a i < size()).
++
++ The returned reference object holds the value at position \a i, and in most
++ cases will convert implicitly to the value. Assigning to the returned
++ reference will overwrite the entry in the Java array. However, calling
++ mutating member functions on the object will not modify the entry in the
++ array. To call member function on the result of this operator, dereference
++ the reference object:
++
++ \code
++ QJniArray<QString> strings = object.callMethod<QString[]>("getStrings");
++ if (!strings.isEmpty()) {
++ if (!(*array[0]).isEmpty()) {
++ // ...
++ }
++ }
++ \endcode
++
++ However, if modifying the value in the array itself is not intended, make
++ the array const, or use \l{at()} instead.
++
++ \sa at(), size()
++ */
++
++ /*!
++ \fn template <typename T> template <typename Container, QJniArrayBase::if_compatible_target_container<T, Container>> Container QJniArray<T>::toContainer(Container &&container) const
++
++ \return a container populated with the data in the wrapped Java array.
++
++ If no \a container is provided, then the type of the container returned
++ depends on the element type of this QJniArray.
++ \include qjniarray.qdoc type-mapping
++
++ If you pass in a named container (an lvalue) for \a container, then that
++ container is filled, and a reference to it is returned. If you pass in a
++ temporary container (an rvalue, incl. the default argument), then that
++ container is filled, and returned by value.
++
++ This function returns immediately if the array is
++ \l{QJniArrayBase::isValid()}{invalid}.
++
++ \sa QJniArrayBase::fromContainer()
++ */