diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2014-11-17 18:18:07 -0800 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2014-12-03 18:09:05 +0100 |
commit | 38174159bea2dbc401fe92c30545acdf3ac4cf2f (patch) | |
tree | fdce27334108f6c9fa0e2a7360399a10823ded46 /src/corelib/kernel/qvariant.cpp | |
parent | cf475b91ae8dc3f6f72b70ca624533c42be34b9e (diff) |
Hoist the numeric comparisons in QVariant::{cmp,compare} further
I had already hoisted them a little in the previous commit, so that the
comparisons run without conversion. This now moves the numeric compare()
before the cmp() equality check, so it saves us a few more cycles.
Another benefit is reduced code duplication.
Change-Id: Ia96da94e169fe0b8d4e761177fc2b74e47d4daff
Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@theqtcompany.com>
Diffstat (limited to 'src/corelib/kernel/qvariant.cpp')
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 63 |
1 files changed, 47 insertions, 16 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 0ce1173a0f..1012d90bd8 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -238,6 +238,26 @@ static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok) return Q_INT64_C(0); } +static qreal qConvertToRealNumber(const QVariant::Private *d, bool *ok) +{ + *ok = true; + switch (uint(d->type)) { + case QVariant::Double: + return qreal(d->data.d); + case QMetaType::Float: + return qreal(d->data.f); + case QVariant::ULongLong: + case QVariant::UInt: + case QMetaType::UChar: + case QMetaType::UShort: + case QMetaType::ULong: + return qreal(qMetaTypeUNumber(d)); + default: + // includes enum conversion as well as invalid types + return qreal(qConvertToNumber(d, ok)); + } +} + static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok) { *ok = true; @@ -3236,21 +3256,35 @@ static int integralCompare(uint promotedType, const QVariant::Private *d1, const return 0; } +static int numericCompare(const QVariant::Private *d1, const QVariant::Private *d2) +{ + uint promotedType = numericTypePromotion(d1->type, d2->type); + if (promotedType != QMetaType::QReal) + return integralCompare(promotedType, d1, d2); + + // qreal comparisons + bool ok; + qreal r1 = qConvertToRealNumber(d1, &ok); + Q_ASSERT(ok); + qreal r2 = qConvertToRealNumber(d2, &ok); + Q_ASSERT(ok); + if (qFuzzyCompare(r1, r2)) + return 0; + return r1 < r2 ? -1 : 1; +} + /*! \internal */ bool QVariant::cmp(const QVariant &v) const { + // try numerics first, with C++ type promotion rules (no conversion) + if (qIsNumericType(d.type) && qIsNumericType(v.d.type)) + return numericCompare(&d, &v.d) == 0; + QVariant v1 = *this; QVariant v2 = v; if (d.type != v2.d.type) { - if (qIsNumericType(d.type) && qIsNumericType(v.d.type)) { - uint promotedType = numericTypePromotion(v1.d.type, v2.d.type); - if (promotedType == QMetaType::QReal) - return qFuzzyCompare(toReal(), v.toReal()); - else - return integralCompare(promotedType, &v1.d, &v2.d) == 0; - } if (v2.canConvert(v1.d.type)) { if (!v2.convert(v1.d.type)) return false; @@ -3274,20 +3308,17 @@ bool QVariant::cmp(const QVariant &v) const */ int QVariant::compare(const QVariant &v) const { + // try numerics first, with C++ type promotion rules (no conversion) + if (qIsNumericType(d.type) && qIsNumericType(v.d.type)) + return numericCompare(&d, &v.d); + + // check for equality next, as more types implement operator== than operator< if (cmp(v)) return 0; + QVariant v1 = *this; QVariant v2 = v; - // try numerics first, with C++ type promotion rules (no conversion) - if (qIsNumericType(v1.d.type) && qIsNumericType(v2.d.type)) { - uint promotedType = numericTypePromotion(v1.d.type, v2.d.type); - if (promotedType == QMetaType::QReal) - return v1.toReal() < v2.toReal() ? -1 : 1; - else - return integralCompare(promotedType, &v1.d, &v2.d); - } - if (v1.d.type != v2.d.type) { // if both types differ, try to convert if (v2.canConvert(v1.d.type)) { |