summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qvariant.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2014-11-17 18:18:07 -0800
committerThiago Macieira <thiago.macieira@intel.com>2014-12-03 18:09:05 +0100
commit38174159bea2dbc401fe92c30545acdf3ac4cf2f (patch)
treefdce27334108f6c9fa0e2a7360399a10823ded46 /src/corelib/kernel/qvariant.cpp
parentcf475b91ae8dc3f6f72b70ca624533c42be34b9e (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.cpp63
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)) {