summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-07-13 16:13:29 +0200
committerLars Knoll <lars.knoll@qt.io>2020-08-24 00:17:50 +0200
commitfefb1c136220750ff4bbe2638108c4f7273bab19 (patch)
tree912e7f452c470798d62e2120b78aecaacfa55409 /src/corelib/kernel
parentf21a7116e950286b7f13cdff23aab653fefc2ddb (diff)
Move enum conversions over into QMetaType
Take the opportunity to properly handle the underlying type (size and signed vs unsigned). Change-Id: I0cb8cf40acac6de03c24ed3fe570db68268952c8 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/qmetatype.cpp145
-rw-r--r--src/corelib/kernel/qmetatype.h7
-rw-r--r--src/corelib/kernel/qvariant.cpp89
3 files changed, 151 insertions, 90 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 776b593d23..4bbc228a9e 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -71,6 +71,7 @@
# include "qcborarray.h"
# include "qcbormap.h"
# include "qbytearraylist.h"
+# include "qmetaobject.h"
#endif
#if QT_CONFIG(itemmodel)
@@ -86,6 +87,7 @@
#include <bitset>
#include <new>
+#include <cstring>
QT_BEGIN_NAMESPACE
@@ -1541,6 +1543,138 @@ bool QMetaType::hasRegisteredDebugStreamOperator() const
}
#endif
+#ifndef QT_NO_QOBJECT
+/*!
+ \internal
+ returns a QMetaEnum for a given meta tape type id if possible
+*/
+static QMetaEnum metaEnumFromType(QMetaType t)
+{
+ if (t.flags() & QMetaType::IsEnumeration) {
+ if (const QMetaObject *metaObject = t.metaObject()) {
+ const QByteArray enumName = t.name();
+ const char *lastColon = std::strrchr(enumName, ':');
+ return metaObject->enumerator(metaObject->indexOfEnumerator(
+ lastColon ? lastColon + 1 : enumName.constData()));
+ }
+ }
+ return QMetaEnum();
+}
+#endif
+
+static bool convertFromEnum(const void *from, const QMetaType &fromType, void *to, int toTypeId)
+{
+ qlonglong ll;
+ if (fromType.flags() & QMetaType::IsUnsignedEnumeration) {
+ qulonglong ull;
+ switch (fromType.sizeOf()) {
+ case 1:
+ ull = *static_cast<const unsigned char *>(from);
+ break;
+ case 2:
+ ull = *static_cast<const unsigned short *>(from);
+ break;
+ case 4:
+ ull = *static_cast<const unsigned int *>(from);
+ break;
+ case 8:
+ ull = *static_cast<const quint64 *>(from);
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+ if (toTypeId == QMetaType::ULongLong) {
+ *static_cast<qulonglong *>(to) = ull;
+ return true;
+ }
+ if (toTypeId != QMetaType::QString && toTypeId != QMetaType::QByteArray)
+ return QMetaType::convert(&ull, QMetaType::ULongLong, to, toTypeId);
+ ll = qlonglong(ull);
+ } else {
+ switch (fromType.sizeOf()) {
+ case 1:
+ ll = *static_cast<const signed char *>(from);
+ break;
+ case 2:
+ ll = *static_cast<const short *>(from);
+ break;
+ case 4:
+ ll = *static_cast<const int *>(from);
+ break;
+ case 8:
+ ll = *static_cast<const qint64 *>(from);
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+ if (toTypeId == QMetaType::LongLong) {
+ *static_cast<qlonglong *>(to) = ll;
+ return true;
+ }
+ if (toTypeId != QMetaType::QString && toTypeId != QMetaType::QByteArray)
+ return QMetaType::convert(&ll, QMetaType::LongLong, to, toTypeId);
+ }
+ Q_ASSERT(toTypeId == QMetaType::QString || toTypeId == QMetaType::QByteArray);
+#ifndef QT_NO_QOBJECT
+ QMetaEnum en = metaEnumFromType(fromType);
+ if (en.isValid()) {
+ const char *key = en.valueToKey(ll);
+ if (toTypeId == QMetaType::QString)
+ *static_cast<QString *>(to) = QString::fromUtf8(key);
+ else
+ *static_cast<QByteArray *>(to) = key;
+ return true;
+ }
+#endif
+ return false;
+}
+
+static bool convertToEnum(const void *from, int fromTypeId, void *to, const QMetaType &toType)
+{
+ qlonglong value;
+ bool ok = false;
+#ifndef QT_NO_QOBJECT
+ if (fromTypeId == QMetaType::QString || fromTypeId == QMetaType::QByteArray) {
+ QMetaEnum en = metaEnumFromType(toType);
+ if (!en.isValid())
+ return false;
+ QByteArray keys = (fromTypeId == QMetaType::QString)
+ ? static_cast<const QString *>(from)->toUtf8()
+ : *static_cast<const QByteArray *>(from);
+ value = en.keysToValue(keys.constData(), &ok);
+ }
+#endif
+ if (!ok) {
+ if (fromTypeId == QMetaType::LongLong) {
+ value = *static_cast<const qlonglong *>(from);
+ ok = true;
+ } else {
+ ok = QMetaType::convert(from, fromTypeId, &value, QMetaType::LongLong);
+ }
+ }
+
+ if (!ok)
+ return false;
+
+ switch (toType.sizeOf()) {
+ case 1:
+ *static_cast<signed char *>(to) = value;
+ return true;
+ case 2:
+ *static_cast<qint16 *>(to) = value;
+ return true;
+ case 4:
+ *static_cast<qint32 *>(to) = value;
+ return true;
+ case 8:
+ *static_cast<qint64 *>(to) = value;
+ return true;
+ default:
+ Q_UNREACHABLE();
+ return false;
+ }
+}
+
/*!
Converts the object at \a from from \a fromTypeId to the preallocated space at \a to
typed \a toTypeId. Returns \c true, if the conversion succeeded, otherwise false.
@@ -1554,7 +1688,16 @@ bool QMetaType::convert(const void *from, int fromTypeId, void *to, int toTypeId
}
const QMetaType::ConverterFunction * const f =
customTypesConversionRegistry()->function(qMakePair(fromTypeId, toTypeId));
- return f && (*f)(from, to);
+ if (f)
+ return (*f)(from, to);
+
+ QMetaType fromType(fromTypeId);
+ if (fromType.flags() & QMetaType::IsEnumeration)
+ return convertFromEnum(from, fromType, to, toTypeId);
+ QMetaType toType(toTypeId);
+ if (toType.flags() & QMetaType::IsEnumeration)
+ return convertToEnum(from, fromTypeId, to, toType);
+ return false;
}
/*!
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index a6c415b268..b4217bc3a1 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -356,6 +356,7 @@ public:
IsGadget = 0x200,
PointerToGadget = 0x400,
IsPointer = 0x800,
+ IsUnsignedEnumeration = 0x1000
};
Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
@@ -1428,6 +1429,11 @@ namespace QtPrivate {
template <typename Result, typename... Args>
struct IsPointerToTypeDerivedFromQObject<Result(*)(Args...)> { enum { Value = false }; };
+ template<typename T, bool = std::is_enum<T>::value>
+ constexpr bool IsUnsignedEnum = false;
+ template<typename T>
+ constexpr bool IsUnsignedEnum<T, true> = !std::is_signed_v<std::underlying_type_t<T>>;
+
template<typename T>
struct QMetaTypeTypeFlags
{
@@ -1442,6 +1448,7 @@ namespace QtPrivate {
| (IsGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::IsGadget : 0)
| (IsPointerToGadgetHelper<T>::IsGadgetOrDerivedFrom ? QMetaType::PointerToGadget : 0)
| (QTypeInfo<T>::isPointer ? QMetaType::IsPointer : 0)
+ | (IsUnsignedEnum<T> ? QMetaType::IsUnsignedEnumeration : 0)
};
};
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index f904879190..1877832db3 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -312,25 +312,6 @@ inline bool qt_convertToBool(const QVariant::Private *const d)
return !(str.isEmpty() || str == LiteralWrapper("0") || str == LiteralWrapper("false"));
}
-#ifndef QT_NO_QOBJECT
-/*!
- \internal
- returns a QMetaEnum for a given meta tape type id if possible
-*/
-static QMetaEnum metaEnumFromType(QMetaType t)
-{
- if (t.flags() & QMetaType::IsEnumeration) {
- if (const QMetaObject *metaObject = t.metaObject()) {
- const QByteArray enumName = t.name();
- const char *lastColon = std::strrchr(enumName, ':');
- return metaObject->enumerator(metaObject->indexOfEnumerator(
- lastColon ? lastColon + 1 : enumName.constData()));
- }
- }
- return QMetaEnum();
-}
-#endif
-
/*!
\internal
@@ -349,28 +330,6 @@ static bool convert(const QVariant::Private *d, int t, void *result)
bool ok = true;
switch (uint(t)) {
- case QMetaType::QString: {
- QString *str = static_cast<QString *>(result);
-#ifndef QT_NO_QOBJECT
- QMetaEnum en = metaEnumFromType(d->type());
- if (en.isValid()) {
- *str = QString::fromUtf8(en.valueToKey(qConvertToNumber(d, &ok)));
- return ok;
- }
-#endif
- return false;
- }
- case QMetaType::QByteArray: {
-#ifndef QT_NO_QOBJECT
- QMetaEnum en = metaEnumFromType(d->type());
- if (en.isValid()) {
- QByteArray *ba = static_cast<QByteArray *>(result);
- *ba = en.valueToKey(qConvertToNumber(d, &ok));
- return ok;
- }
-#endif
- return false;
- }
case QMetaType::Short:
*static_cast<short *>(result) = short(qConvertToNumber(d, &ok));
return ok;
@@ -716,54 +675,6 @@ static bool convert(const QVariant::Private *d, int t, void *result)
#endif
default:
-#ifndef QT_NO_QOBJECT
- if (d->typeId() == QMetaType::QString || d->typeId() == QMetaType::QByteArray) {
- QMetaEnum en = metaEnumFromType(QMetaType(t));
- if (en.isValid()) {
- QByteArray keys = (d->typeId() == QMetaType::QString)
- ? d->get<QString>().toUtf8()
- : d->get<QByteArray>();
- int value = en.keysToValue(keys.constData(), &ok);
- if (ok) {
- switch (QMetaType::sizeOf(t)) {
- case 1:
- *static_cast<signed char *>(result) = value;
- return true;
- case 2:
- *static_cast<qint16 *>(result) = value;
- return true;
- case 4:
- *static_cast<qint32 *>(result) = value;
- return true;
- case 8:
- *static_cast<qint64 *>(result) = value;
- return true;
- }
- }
- }
- }
-#endif
- if (QMetaType::typeFlags(t) & QMetaType::IsEnumeration
- || d->typeId() == QMetaType::QCborSimpleType) {
- qlonglong value = qConvertToNumber(d, &ok);
- if (ok) {
- switch (QMetaType::sizeOf(t)) {
- case 1:
- *static_cast<signed char *>(result) = value;
- return true;
- case 2:
- *static_cast<qint16 *>(result) = value;
- return true;
- case 4:
- *static_cast<qint32 *>(result) = value;
- return true;
- case 8:
- *static_cast<qint64 *>(result) = value;
- return true;
- }
- }
- return ok;
- }
return false;
}
return true;