diff options
Diffstat (limited to 'src/corelib/kernel/qvariant.cpp')
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 364 |
1 files changed, 354 insertions, 10 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 6192b66487..4d1aa911f7 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2018 Intel Corporation. ** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com> ** Contact: https://www.qt.io/licensing/ ** @@ -60,6 +60,9 @@ #include "qabstractitemmodel.h" #endif #ifndef QT_BOOTSTRAPPED +#include "qcborarray.h" +#include "qcborcommon.h" +#include "qcbormap.h" #include "qjsonvalue.h" #include "qjsonobject.h" #include "qjsonarray.h" @@ -167,6 +170,8 @@ static qlonglong qMetaTypeNumber(const QVariant::Private *d) #ifndef QT_BOOTSTRAPPED case QMetaType::QJsonValue: return v_cast<QJsonValue>(d)->toDouble(); + case QMetaType::QCborValue: + return v_cast<QCborValue>(d)->toInteger(); #endif } Q_ASSERT(false); @@ -205,6 +210,10 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok) case QVariant::Bool: return qlonglong(d->data.b); #ifndef QT_BOOTSTRAPPED + case QMetaType::QCborValue: + if (!v_cast<QCborValue>(d)->isInteger() && !v_cast<QCborValue>(d)->isDouble()) + break; + return qMetaTypeNumber(d); case QMetaType::QJsonValue: if (!v_cast<QJsonValue>(d)->isDouble()) break; @@ -229,7 +238,7 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok) } QMetaType typeInfo(d->type); - if (typeInfo.flags() & QMetaType::IsEnumeration) { + if (typeInfo.flags() & QMetaType::IsEnumeration || d->type == QMetaType::QCborSimpleType) { switch (typeInfo.sizeOf()) { case 1: return d->is_shared ? *reinterpret_cast<signed char *>(d->data.shared->ptr) : d->data.sc; @@ -261,6 +270,8 @@ static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok) case QMetaType::ULong: return qreal(qMetaTypeUNumber(d)); #ifndef QT_BOOTSTRAPPED + case QMetaType::QCborValue: + return v_cast<QCborValue>(d)->toDouble(); case QMetaType::QJsonValue: return v_cast<QJsonValue>(d)->toDouble(); #endif @@ -284,6 +295,12 @@ static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok) case QVariant::Bool: return qulonglong(d->data.b); #ifndef QT_BOOTSTRAPPED + case QMetaType::QCborValue: + if (v_cast<QCborValue>(d)->isDouble()) + return qulonglong(qConvertToRealNumber(d, ok)); + if (!v_cast<QCborValue>(d)->isInteger()) + return false; + return qulonglong(qMetaTypeNumber(d)); case QMetaType::QJsonValue: if (!v_cast<QJsonValue>(d)->isDouble()) break; @@ -391,6 +408,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) case QVariant::String: *static_cast<QUrl *>(result) = QUrl(*v_cast<QString>(d)); break; + case QMetaType::QCborValue: + if (v_cast<QCborValue>(d)->isUrl()) { + *static_cast<QUrl *>(result) = v_cast<QCborValue>(d)->toUrl(); + break; + } + return false; default: return false; } @@ -476,6 +499,11 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) else if (!v_cast<QJsonValue>(d)->isNull()) return false; break; + case QMetaType::QCborValue: + if (v_cast<QCborValue>(d)->isContainer() || v_cast<QCborValue>(d)->isTag()) + return false; + *str = v_cast<QCborValue>(d)->toVariant().toString(); + break; #endif case QVariant::Uuid: *str = v_cast<QUuid>(d)->toString(); @@ -621,6 +649,14 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) case QVariant::String: *dt = QDateTime::fromString(*v_cast<QString>(d), Qt::ISODate); break; +# ifndef QT_BOOTSTRAPPED + case QMetaType::QCborValue: + if (v_cast<QCborValue>(d)->isDateTime()) + *dt = v_cast<QCborValue>(d)->toDateTime(); + else + return false; + break; +# endif #endif case QVariant::Date: *dt = QDateTime(*v_cast<QDate>(d)); @@ -668,6 +704,14 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) case QMetaType::Nullptr: *ba = QByteArray(); break; +#ifndef QT_BOOTSTRAPPED + case QMetaType::QCborValue: + if (v_cast<QCborValue>(d)->isByteArray()) + *ba = v_cast<QCborValue>(d)->toByteArray(); + else + return false; + break; +#endif default: #ifndef QT_NO_QOBJECT { @@ -746,6 +790,11 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) *b = qMetaTypeUNumber(d) != Q_UINT64_C(0); break; #ifndef QT_BOOTSTRAPPED + case QMetaType::QCborValue: + *b = v_cast<QCborValue>(d)->toBool(); + if (!v_cast<QCborValue>(d)->isBool()) + return false; + break; case QMetaType::QJsonValue: *b = v_cast<QJsonValue>(d)->toBool(false); if (!v_cast<QJsonValue>(d)->isBool()) @@ -789,6 +838,11 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) *f = double(qMetaTypeUNumber(d)); break; #ifndef QT_BOOTSTRAPPED + case QMetaType::QCborValue: + *f = v_cast<QCborValue>(d)->toDouble(); + if (!v_cast<QCborValue>(d)->isDouble()) + return false; + break; case QMetaType::QJsonValue: *f = v_cast<QJsonValue>(d)->toDouble(0.0); if (!v_cast<QJsonValue>(d)->isDouble()) @@ -832,6 +886,11 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) *f = float(qMetaTypeUNumber(d)); break; #ifndef QT_BOOTSTRAPPED + case QMetaType::QCborValue: + *f = v_cast<QCborValue>(d)->toDouble(); + if (!v_cast<QCborValue>(d)->isDouble()) + return false; + break; case QMetaType::QJsonValue: *f = v_cast<QJsonValue>(d)->toDouble(0.0); if (!v_cast<QJsonValue>(d)->isDouble()) @@ -856,6 +915,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) *static_cast<QVariantList *>(result) = *static_cast<QList<QVariant> *>(d->data.shared->ptr); #ifndef QT_BOOTSTRAPPED + } else if (d->type == QMetaType::QCborValue) { + if (!v_cast<QCborValue>(d)->isArray()) + return false; + *static_cast<QVariantList *>(result) = v_cast<QCborValue>(d)->toArray().toVariantList(); + } else if (d->type == QMetaType::QCborArray) { + *static_cast<QVariantList *>(result) = v_cast<QCborArray>(d)->toVariantList(); } else if (d->type == QMetaType::QJsonValue) { if (!v_cast<QJsonValue>(d)->isArray()) return false; @@ -878,6 +943,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) for (auto it = hash->begin(); it != end; ++it) map->insertMulti(it.key(), it.value()); #ifndef QT_BOOTSTRAPPED + } else if (d->type == QMetaType::QCborValue) { + if (!v_cast<QCborValue>(d)->isMap()) + return false; + *static_cast<QVariantMap *>(result) = v_cast<QCborValue>(d)->toMap().toVariantMap(); + } else if (d->type == QMetaType::QCborMap) { + *static_cast<QVariantMap *>(result) = v_cast<QCborMap>(d)->toVariantMap(); } else if (d->type == QMetaType::QJsonValue) { if (!v_cast<QJsonValue>(d)->isObject()) return false; @@ -900,6 +971,12 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) for (auto it = map->begin(); it != end; ++it) hash->insertMulti(it.key(), it.value()); #ifndef QT_BOOTSTRAPPED + } else if (d->type == QMetaType::QCborValue) { + if (!v_cast<QCborValue>(d)->isMap()) + return false; + *static_cast<QVariantHash *>(result) = v_cast<QCborValue>(d)->toMap().toVariantHash(); + } else if (d->type == QMetaType::QCborMap) { + *static_cast<QVariantHash *>(result) = v_cast<QCborMap>(d)->toVariantHash(); } else if (d->type == QMetaType::QJsonValue) { if (!v_cast<QJsonValue>(d)->isObject()) return false; @@ -950,11 +1027,36 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) case QVariant::ByteArray: *static_cast<QUuid *>(result) = QUuid(*v_cast<QByteArray>(d)); break; +#ifndef QT_BOOTSTRAPPED + case QMetaType::QCborValue: + if (!v_cast<QCborValue>(d)->isUuid()) + return false; + *static_cast<QUuid *>(result) = v_cast<QCborValue>(d)->toUuid(); + break; +#endif default: return false; } break; + case QMetaType::Nullptr: + *static_cast<std::nullptr_t *>(result) = nullptr; + if (QMetaType::typeFlags(t) & (QMetaType::PointerToGadget | QMetaType::PointerToQObject) + || d->type == QMetaType::VoidStar) { + if (v_cast<const void *>(d) == nullptr) + break; + } #ifndef QT_BOOTSTRAPPED + if (d->type == QMetaType::QCborValue && v_cast<QCborValue>(d)->isNull()) + break; +#endif + return false; + +#ifndef QT_BOOTSTRAPPED + case QMetaType::QRegularExpression: + if (d->type != QMetaType::QCborValue || !v_cast<QCborValue>(d)->isRegularExpression()) + return false; + *static_cast<QRegularExpression *>(result) = v_cast<QCborValue>(d)->toRegularExpression(); + break; case QMetaType::QJsonValue: switch (d->type) { case QMetaType::Nullptr: @@ -1005,6 +1107,15 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) *static_cast<QJsonValue *>(result) = doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object()); break; } + case QMetaType::QCborValue: + *static_cast<QJsonValue *>(result) = v_cast<QCborValue>(d)->toJsonValue(); + break; + case QMetaType::QCborMap: + *static_cast<QJsonValue *>(result) = v_cast<QCborMap>(d)->toJsonObject(); + break; + case QMetaType::QCborArray: + *static_cast<QJsonValue *>(result) = v_cast<QCborArray>(d)->toJsonArray(); + break; default: *static_cast<QJsonValue *>(result) = QJsonValue(QJsonValue::Undefined); return false; @@ -1028,6 +1139,14 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) return false; *static_cast<QJsonArray *>(result) = v_cast<QJsonDocument>(d)->array(); break; + case QMetaType::QCborValue: + if (!v_cast<QCborValue>(d)->isArray()) + return false; + *static_cast<QJsonArray *>(result) = v_cast<QCborValue>(d)->toArray().toJsonArray(); + break; + case QMetaType::QCborArray: + *static_cast<QJsonArray *>(result) = v_cast<QCborArray>(d)->toJsonArray(); + break; default: return false; } @@ -1050,11 +1169,177 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) return false; *static_cast<QJsonObject *>(result) = v_cast<QJsonDocument>(d)->object(); break; + case QMetaType::QCborValue: + if (!v_cast<QCborValue>(d)->isMap()) + return false; + *static_cast<QJsonObject *>(result) = v_cast<QCborValue>(d)->toMap().toJsonObject(); + break; + case QMetaType::QCborMap: + *static_cast<QJsonObject *>(result) = v_cast<QCborMap>(d)->toJsonObject(); + break; + default: + return false; + } + break; + case QMetaType::QCborSimpleType: + if (d->type == QMetaType::QCborValue && v_cast<QCborValue>(d)->isSimpleType()) { + *static_cast<QCborSimpleType *>(result) = v_cast<QCborValue>(d)->toSimpleType(); + break; + } + return false; + case QMetaType::QCborValue: + switch (d->type) { + case QMetaType::Nullptr: + *static_cast<QCborValue *>(result) = QCborValue(QCborValue::Null); + break; + case QVariant::Bool: + *static_cast<QCborValue *>(result) = QCborValue(d->data.b); + break; + case QMetaType::Int: + case QMetaType::UInt: + case QMetaType::ULong: + case QMetaType::Long: + case QMetaType::LongLong: + case QMetaType::ULongLong: + case QMetaType::UShort: + case QMetaType::UChar: + case QMetaType::Char: + case QMetaType::SChar: + case QMetaType::Short: + *static_cast<QCborValue *>(result) = QCborValue(qConvertToNumber(d, ok)); + Q_ASSERT(ok); + break; + case QMetaType::Double: + case QMetaType::Float: + *static_cast<QCborValue *>(result) = QCborValue(qConvertToRealNumber(d, ok)); + Q_ASSERT(ok); + break; + case QVariant::String: + *static_cast<QCborValue *>(result) = *v_cast<QString>(d); + break; + case QVariant::StringList: + *static_cast<QCborValue *>(result) = QCborArray::fromStringList(*v_cast<QStringList>(d)); + break; + case QVariant::ByteArray: + *static_cast<QCborValue *>(result) = *v_cast<QByteArray>(d); + break; + case QVariant::Date: + *static_cast<QCborValue *>(result) = QCborValue(QDateTime(*v_cast<QDate>(d))); + break; + case QVariant::DateTime: + *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QDateTime>(d)); + break; + case QVariant::Url: + *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QUrl>(d)); + break; + case QVariant::RegularExpression: + *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QRegularExpression>(d)); + break; + case QVariant::Uuid: + *static_cast<QCborValue *>(result) = QCborValue(*v_cast<QUuid>(d)); + break; + case QVariant::List: + *static_cast<QCborValue *>(result) = QCborArray::fromVariantList(*v_cast<QVariantList>(d)); + break; + case QVariant::Map: + *static_cast<QCborValue *>(result) = QCborMap::fromVariantMap(*v_cast<QVariantMap>(d)); + break; + case QVariant::Hash: + *static_cast<QCborValue *>(result) = QCborMap::fromVariantHash(*v_cast<QVariantHash>(d)); + break; + case QMetaType::QJsonValue: + *static_cast<QCborValue *>(result) = QCborValue::fromJsonValue(*v_cast<QJsonValue>(d)); + break; + case QMetaType::QJsonObject: + *static_cast<QCborValue *>(result) = QCborMap::fromJsonObject(*v_cast<QJsonObject>(d)); + break; + case QMetaType::QJsonArray: + *static_cast<QCborValue *>(result) = QCborArray::fromJsonArray(*v_cast<QJsonArray>(d)); + break; + case QMetaType::QJsonDocument: { + QJsonDocument doc = *v_cast<QJsonDocument>(d); + if (doc.isArray()) + *static_cast<QCborValue *>(result) = QCborArray::fromJsonArray(doc.array()); + else + *static_cast<QCborValue *>(result) = QCborMap::fromJsonObject(doc.object()); + break; + } + case QMetaType::QCborSimpleType: + *static_cast<QCborValue *>(result) = *v_cast<QCborSimpleType>(d); + break; + case QMetaType::QCborMap: + *static_cast<QCborValue *>(result) = *v_cast<QCborMap>(d); + break; + case QMetaType::QCborArray: + *static_cast<QCborValue *>(result) = *v_cast<QCborArray>(d); + break; + default: + *static_cast<QCborValue *>(result) = {}; + return false; + } + break; + case QMetaType::QCborArray: + switch (d->type) { + case QVariant::StringList: + *static_cast<QCborArray *>(result) = QCborArray::fromStringList(*v_cast<QStringList>(d)); + break; + case QVariant::List: + *static_cast<QCborArray *>(result) = QCborArray::fromVariantList(*v_cast<QVariantList>(d)); + break; + case QMetaType::QCborValue: + if (!v_cast<QCborValue>(d)->isArray()) + return false; + *static_cast<QCborArray *>(result) = v_cast<QCborValue>(d)->toArray(); + break; + case QMetaType::QJsonDocument: + if (!v_cast<QJsonDocument>(d)->isArray()) + return false; + *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(v_cast<QJsonDocument>(d)->array()); + break; + case QMetaType::QJsonValue: + if (!v_cast<QJsonValue>(d)->isArray()) + return false; + *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(v_cast<QJsonValue>(d)->toArray()); + break; + case QMetaType::QJsonArray: + *static_cast<QCborArray *>(result) = QCborArray::fromJsonArray(*v_cast<QJsonArray>(d)); + break; + default: + return false; + } + break; + case QMetaType::QCborMap: + switch (d->type) { + case QVariant::Map: + *static_cast<QCborMap *>(result) = QCborMap::fromVariantMap(*v_cast<QVariantMap>(d)); + break; + case QVariant::Hash: + *static_cast<QCborMap *>(result) = QCborMap::fromVariantHash(*v_cast<QVariantHash>(d)); + break; + case QMetaType::QCborValue: + if (!v_cast<QCborValue>(d)->isMap()) + return false; + *static_cast<QCborMap *>(result) = v_cast<QCborValue>(d)->toMap(); + break; + case QMetaType::QJsonDocument: + if (v_cast<QJsonDocument>(d)->isArray()) + return false; + *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(v_cast<QJsonDocument>(d)->object()); + break; + case QMetaType::QJsonValue: + if (!v_cast<QJsonValue>(d)->isObject()) + return false; + *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(v_cast<QJsonValue>(d)->toObject()); + break; + case QMetaType::QJsonObject: + *static_cast<QCborMap *>(result) = QCborMap::fromJsonObject(*v_cast<QJsonObject>(d)); + break; default: return false; } break; #endif + default: #ifndef QT_NO_QOBJECT if (d->type == QVariant::String || d->type == QVariant::ByteArray) { @@ -1081,7 +1366,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) } } #endif - if (QMetaType::typeFlags(t) & QMetaType::IsEnumeration) { + if (QMetaType::typeFlags(t) & QMetaType::IsEnumeration || d->type == QMetaType::QCborSimpleType) { qlonglong value = qConvertToNumber(d, ok); if (*ok) { switch (QMetaType::sizeOf(t)) { @@ -1175,9 +1460,16 @@ static void customConstruct(QVariant::Private *d, const void *copy) type.construct(&d->data.ptr, copy); d->is_shared = false; } else { - void *ptr = type.create(copy); + // Private::Data contains long long, and long double is the biggest standard type. + const size_t maxAlignment = + qMax(Q_ALIGNOF(QVariant::Private::Data), Q_ALIGNOF(long double)); + const size_t s = sizeof(QVariant::PrivateShared); + const size_t offset = s + ((s * maxAlignment - s) % maxAlignment); + void *data = operator new(offset + size); + void *ptr = static_cast<char *>(data) + offset; + type.construct(ptr, copy); d->is_shared = true; - d->data.shared = new QVariant::PrivateShared(ptr); + d->data.shared = new (data) QVariant::PrivateShared(ptr); } } @@ -1186,8 +1478,9 @@ static void customClear(QVariant::Private *d) if (!d->is_shared) { QMetaType::destruct(d->type, &d->data.ptr); } else { - QMetaType::destroy(d->type, d->data.shared->ptr); - delete d->data.shared; + QMetaType::destruct(d->type, d->data.shared->ptr); + d->data.shared->~PrivateShared(); + operator delete(d->data.shared); } } @@ -3272,15 +3565,66 @@ bool QVariant::canConvert(int targetTypeId) const case QMetaType::QVariantList: case QMetaType::QVariantMap: case QMetaType::QVariantHash: + case QMetaType::QCborValue: + case QMetaType::QCborArray: + case QMetaType::QCborMap: return true; default: return false; } } if (currentType == QMetaType::QJsonArray) - return targetTypeId == QMetaType::QVariantList; + return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue + || targetTypeId == QMetaType::QCborArray; if (currentType == QMetaType::QJsonObject) - return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash; + return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash + || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QCborMap; + + if (currentType == QMetaType::QCborValue || targetTypeId == QMetaType::QCborValue) { + switch (currentType == QMetaType::QCborValue ? targetTypeId : currentType) { + case QMetaType::UnknownType: + case QMetaType::Nullptr: + case QMetaType::Bool: + case QMetaType::Int: + case QMetaType::UInt: + case QMetaType::Double: + case QMetaType::Float: + case QMetaType::ULong: + case QMetaType::Long: + case QMetaType::LongLong: + case QMetaType::ULongLong: + case QMetaType::UShort: + case QMetaType::UChar: + case QMetaType::Char: + case QMetaType::SChar: + case QMetaType::Short: + case QMetaType::QString: + case QMetaType::QByteArray: + case QMetaType::QDateTime: + case QMetaType::QUrl: + case QMetaType::QRegularExpression: + case QMetaType::QUuid: + case QMetaType::QVariantList: + case QMetaType::QVariantMap: + case QMetaType::QVariantHash: + case QMetaType::QJsonValue: + case QMetaType::QJsonArray: + case QMetaType::QJsonObject: + case QMetaType::QJsonDocument: + case QMetaType::QCborArray: + case QMetaType::QCborMap: + case QMetaType::QCborSimpleType: + return true; + default: + return false; + } + } + if (currentType == QMetaType::QCborArray) + return targetTypeId == QMetaType::QVariantList || targetTypeId == QMetaType::QCborValue + || targetTypeId == QMetaType::QJsonArray; + if (currentType == QMetaType::QCborMap) + return targetTypeId == QMetaType::QVariantMap || targetTypeId == QMetaType::QVariantHash + || targetTypeId == QMetaType::QCborValue || targetTypeId == QMetaType::QJsonObject; // FIXME It should be LastCoreType intead of Uuid if (currentType > int(QMetaType::QUuid) || targetTypeId > int(QMetaType::QUuid)) { @@ -3380,7 +3724,7 @@ bool QVariant::convert(int targetTypeId) create(targetTypeId, 0); // Fail if the value is not initialized or was forced null by a previous failed convert. - if (oldValue.d.is_null) + if (oldValue.d.is_null && oldValue.d.type != QMetaType::Nullptr) return false; if ((QMetaType::typeFlags(oldValue.userType()) & QMetaType::PointerToQObject) && (QMetaType::typeFlags(targetTypeId) & QMetaType::PointerToQObject)) { |