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>
This commit is contained in:
parent
f21a7116e9
commit
fefb1c1362
@ -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;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -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)
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -4366,11 +4366,6 @@ template<typename Enum> void testVariant(Enum value, bool *ok)
|
||||
QCOMPARE(var.value<short>(), static_cast<short>(value));
|
||||
QCOMPARE(var.value<unsigned short>(), static_cast<unsigned short>(value));
|
||||
QCOMPARE(var.value<qint64>(), static_cast<qint64>(value));
|
||||
if (sizeof(value) < 8 && static_cast<qint64>(value) < 0) {
|
||||
QEXPECT_FAIL("", "The metatype system don't store the sign of enums", Continue);
|
||||
// The value is stored internaly with 32 bit. When asked to convert it to 64 bit unsigned,
|
||||
// we consider that the value was unsigned, so we don't extent the bit signs
|
||||
}
|
||||
QCOMPARE(var.value<quint64>(), static_cast<quint64>(value));
|
||||
|
||||
QVariant var2 = var;
|
||||
|
Loading…
Reference in New Issue
Block a user