Optimize QVariant::cmp()
Don't always copy the variants that we want to compare. This can in some cases be a relatively expensive operation. Change-Id: I2b3fd246ac136b19d8a8d281fbdcfb0417c8fb6c Reviewed-by: Sean Harmer <sean.harmer@kdab.com> Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@qt.io>
This commit is contained in:
parent
84fcc38955
commit
b6e99ec056
@ -3517,29 +3517,36 @@ static int numericCompare(const QVariant::Private *d1, const QVariant::Private *
|
|||||||
*/
|
*/
|
||||||
bool QVariant::cmp(const QVariant &v) const
|
bool QVariant::cmp(const QVariant &v) const
|
||||||
{
|
{
|
||||||
|
auto cmp_helper = [] (const QVariant::Private &d1, const QVariant::Private &d2)
|
||||||
|
{
|
||||||
|
Q_ASSERT(d1.type == d2.type);
|
||||||
|
if (d1.type >= QMetaType::User) {
|
||||||
|
int result;
|
||||||
|
if (QMetaType::equals(QT_PREPEND_NAMESPACE(constData(d1)), QT_PREPEND_NAMESPACE(constData(d2)), d1.type, &result))
|
||||||
|
return result == 0;
|
||||||
|
}
|
||||||
|
return handlerManager[d1.type]->compare(&d1, &d2);
|
||||||
|
};
|
||||||
|
|
||||||
// try numerics first, with C++ type promotion rules (no conversion)
|
// try numerics first, with C++ type promotion rules (no conversion)
|
||||||
if (qIsNumericType(d.type) && qIsNumericType(v.d.type))
|
if (qIsNumericType(d.type) && qIsNumericType(v.d.type))
|
||||||
return numericCompare(&d, &v.d) == 0;
|
return numericCompare(&d, &v.d) == 0;
|
||||||
|
|
||||||
|
if (d.type == v.d.type)
|
||||||
|
return cmp_helper(d, v.d);
|
||||||
|
|
||||||
QVariant v1 = *this;
|
QVariant v1 = *this;
|
||||||
QVariant v2 = v;
|
QVariant v2 = v;
|
||||||
if (d.type != v2.d.type) {
|
if (v2.canConvert(v1.d.type)) {
|
||||||
if (v2.canConvert(v1.d.type)) {
|
if (!v2.convert(v1.d.type))
|
||||||
if (!v2.convert(v1.d.type))
|
return false;
|
||||||
return false;
|
} else {
|
||||||
} else {
|
// try the opposite conversion, it might work
|
||||||
// try the opposite conversion, it might work
|
qSwap(v1, v2);
|
||||||
qSwap(v1, v2);
|
if (!v2.convert(v1.d.type))
|
||||||
if (!v2.convert(v1.d.type))
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (v1.d.type >= QMetaType::User) {
|
return cmp_helper(v1.d, v2.d);
|
||||||
int result;
|
|
||||||
if (QMetaType::equals(QT_PREPEND_NAMESPACE(constData(v1.d)), QT_PREPEND_NAMESPACE(constData(v2.d)), v1.d.type, &result))
|
|
||||||
return result == 0;
|
|
||||||
}
|
|
||||||
return handlerManager[v1.d.type]->compare(&v1.d, &v2.d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -3555,51 +3562,53 @@ int QVariant::compare(const QVariant &v) const
|
|||||||
if (cmp(v))
|
if (cmp(v))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
QVariant v1 = *this;
|
const QVariant *v1 = this;
|
||||||
QVariant v2 = v;
|
const QVariant *v2 = &v;
|
||||||
|
QVariant converted1;
|
||||||
|
QVariant converted2;
|
||||||
|
|
||||||
if (v1.d.type != v2.d.type) {
|
if (d.type != v.d.type) {
|
||||||
// if both types differ, try to convert
|
// if both types differ, try to convert
|
||||||
if (v2.canConvert(v1.d.type)) {
|
if (v2->canConvert(v1->d.type)) {
|
||||||
QVariant temp = v2;
|
converted2 = *v2;
|
||||||
if (temp.convert(v1.d.type))
|
if (converted2.convert(v1->d.type))
|
||||||
v2 = temp;
|
v2 = &converted2;
|
||||||
}
|
}
|
||||||
if (v1.d.type != v2.d.type && v1.canConvert(v2.d.type)) {
|
if (v1->d.type != v2->d.type && v1->canConvert(v2->d.type)) {
|
||||||
QVariant temp = v1;
|
converted1 = *v1;
|
||||||
if (temp.convert(v2.d.type))
|
if (converted1.convert(v2->d.type))
|
||||||
v1 = temp;
|
v1 = &converted1;
|
||||||
}
|
}
|
||||||
if (v1.d.type != v2.d.type) {
|
if (v1->d.type != v2->d.type) {
|
||||||
// if conversion fails, default to toString
|
// if conversion fails, default to toString
|
||||||
int r = v1.toString().compare(v2.toString(), Qt::CaseInsensitive);
|
int r = v1->toString().compare(v2->toString(), Qt::CaseInsensitive);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
// cmp(v) returned false, so we should try to agree with it.
|
// cmp(v) returned false, so we should try to agree with it.
|
||||||
return (v1.d.type < v2.d.type) ? -1 : 1;
|
return (v1->d.type < v2->d.type) ? -1 : 1;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// did we end up with two numerics? If so, restart
|
// did we end up with two numerics? If so, restart
|
||||||
if (qIsNumericType(v1.d.type) && qIsNumericType(v2.d.type))
|
if (qIsNumericType(v1->d.type) && qIsNumericType(v2->d.type))
|
||||||
return v1.compare(v2);
|
return v1->compare(*v2);
|
||||||
}
|
}
|
||||||
if (v1.d.type >= QMetaType::User) {
|
if (v1->d.type >= QMetaType::User) {
|
||||||
int result;
|
int result;
|
||||||
if (QMetaType::compare(QT_PREPEND_NAMESPACE(constData(d)), QT_PREPEND_NAMESPACE(constData(v2.d)), d.type, &result))
|
if (QMetaType::compare(QT_PREPEND_NAMESPACE(constData(d)), QT_PREPEND_NAMESPACE(constData(v2->d)), d.type, &result))
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
switch (v1.d.type) {
|
switch (v1->d.type) {
|
||||||
case QVariant::Date:
|
case QVariant::Date:
|
||||||
return v1.toDate() < v2.toDate() ? -1 : 1;
|
return v1->toDate() < v2->toDate() ? -1 : 1;
|
||||||
case QVariant::Time:
|
case QVariant::Time:
|
||||||
return v1.toTime() < v2.toTime() ? -1 : 1;
|
return v1->toTime() < v2->toTime() ? -1 : 1;
|
||||||
case QVariant::DateTime:
|
case QVariant::DateTime:
|
||||||
return v1.toDateTime() < v2.toDateTime() ? -1 : 1;
|
return v1->toDateTime() < v2->toDateTime() ? -1 : 1;
|
||||||
case QVariant::StringList:
|
case QVariant::StringList:
|
||||||
return v1.toStringList() < v2.toStringList() ? -1 : 1;
|
return v1->toStringList() < v2->toStringList() ? -1 : 1;
|
||||||
}
|
}
|
||||||
int r = v1.toString().compare(v2.toString(), Qt::CaseInsensitive);
|
int r = v1->toString().compare(v2->toString(), Qt::CaseInsensitive);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
// cmp(v) returned false, so we should try to agree with it.
|
// cmp(v) returned false, so we should try to agree with it.
|
||||||
return (d.type < v.d.type) ? -1 : 1;
|
return (d.type < v.d.type) ? -1 : 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user