aboutsummaryrefslogtreecommitdiffstats
path: root/include/qdotnetarray.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/qdotnetarray.h')
-rw-r--r--include/qdotnetarray.h147
1 files changed, 147 insertions, 0 deletions
diff --git a/include/qdotnetarray.h b/include/qdotnetarray.h
new file mode 100644
index 0000000..3a0289b
--- /dev/null
+++ b/include/qdotnetarray.h
@@ -0,0 +1,147 @@
+/***************************************************************************************************
+ Copyright (C) 2023 The Qt Company Ltd.
+ SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+***************************************************************************************************/
+
+#pragma once
+
+#include "qdotnetobject.h"
+
+#ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wconversion"
+#endif
+#include <QString>
+#include <QRegularExpression>
+#ifdef __GNUC__
+# pragma GCC diagnostic pop
+#endif
+
+template <typename T, std::enable_if_t<
+ std::is_fundamental_v<T>
+ || std::is_same_v<T, QString>
+ || std::is_base_of_v<QDotNetRef, T>, bool> = true>
+class QDotNetArray : public QDotNetObject
+{
+ class Element;
+ static QString arrayOf(const QString& typeName)
+ {
+ const auto idx = typeName.indexOf(QRegularExpression(",|$"));
+ return QString("%1[]%2").arg(typeName.left(idx)).arg(typeName.mid(idx));
+ }
+
+public:
+ Q_DOTNET_OBJECT_INLINE(QDotNetArray, arrayOf(QDotNetTypeOf<T>::TypeName));
+
+ QDotNetArray(qint32 length)
+ {
+ const QString elementTypeName = QDotNetTypeOf<T>::TypeName;
+ const QDotNetType elementType = QDotNetType::find(elementTypeName);
+
+ QDotNetType arrayType = QDotNetType::find(QDotNetArray::FullyQualifiedTypeName);
+ auto ctor = constructor<QDotNetArray, qint32>();
+ *this = ctor(length);
+ }
+
+ qint32 length() const
+ {
+ return method("get_Length", fnLength).invoke(*this);
+ }
+
+ T get(qint32 idx) const
+ {
+ if constexpr (std::is_fundamental_v<T>)
+ return method("Get", fnGetValue).invoke(*this, idx);
+ if constexpr (std::is_same_v<T, QString>)
+ return method("Get", fnGetObject).invoke(*this, idx).toString();
+ if constexpr (std::is_base_of_v<QDotNetRef, T>)
+ return method("Get", fnGetObject).invoke(*this, idx).template cast<T>();
+ throw std::invalid_argument("T");
+ }
+
+ void set(qint32 idx, const T &value)
+ {
+ if constexpr (std::is_same_v<T, QString>) {
+ if (!fnSetString.isValid()) {
+ QDotNetFunction<void, qint32, QDotNetObject> const func = adapter()
+ .resolveInstanceMethod(*this, "Set",
+ { UnmanagedType::Void, UnmanagedType::I4, QDotNetParameter::String });
+ fnSetString = func;
+ }
+ return method("Set", fnSet).invoke(*this, idx, value);
+ }
+ return method("Set", fnSet).invoke(*this, idx, value);
+ }
+
+ Element operator[](qint32 idx)
+ {
+ return Element(this, idx);
+ }
+
+ Element begin()
+ {
+ return Element(this, 0);
+ }
+
+ Element end()
+ {
+ return Element(this, length());
+ }
+
+private:
+ class Element
+ {
+ friend class QDotNetArray;
+
+ public:
+ operator T()
+ {
+ return value = a->get(idx);
+ }
+ T *operator->()
+ {
+ value = a->get(idx);
+ return &value;
+ }
+ T &operator*()
+ {
+ value = a->get(idx);
+ return value;
+ }
+ Element &operator=(const T &value)
+ {
+ a->set(idx, value);
+ return *this;
+ }
+ bool isEnd() const
+ {
+ return idx >= a->length();
+ }
+ Element &operator++()
+ {
+ ++idx;
+ return *this;
+ }
+ bool operator !=(const Element &that) const
+ {
+ if (isEnd() && that.isEnd())
+ return false;
+ return a != that.a || idx != that.idx;
+ }
+
+ private:
+ Element(QDotNetArray *a, qint32 idx)
+ : a(a)
+ , idx(idx)
+ {}
+ QDotNetArray* a = nullptr;
+ qint32 idx;
+ T value;
+ };
+
+ mutable QDotNetSafeMethod<qint32> fnLength;
+ mutable QDotNetSafeMethod<T, qint32> fnGetValue;
+ mutable QDotNetSafeMethod<QDotNetObject, qint32> fnGetObject;
+ QDotNetSafeMethod<void, qint32, T> fnSet;
+ QDotNetSafeMethod<void, qint32, QDotNetObject> fnSetString;
+};