diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 99 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.h | 17 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant_p.h | 43 |
3 files changed, 83 insertions, 76 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index b4427c0..ea66658 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -71,27 +71,6 @@ QT_BEGIN_NAMESPACE # define FLT_DIG 6 #endif - -static const void *constDataHelper(const QVariant::Private &d) -{ - switch (d.type) { - case QVariant::Int: - return &d.data.i; - case QVariant::UInt: - return &d.data.u; - case QVariant::Bool: - return &d.data.b; - case QVariant::LongLong: - return &d.data.ll; - case QVariant::ULongLong: - return &d.data.ull; - case QVariant::Double: - return &d.data.d; - default: - return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.ptr); - } -} - static void construct(QVariant::Private *x, const void *copy) { x->is_shared = false; @@ -179,6 +158,9 @@ static void construct(QVariant::Private *x, const void *copy) case QVariant::Double: x->data.d = copy ? *static_cast<const double*>(copy) : 0.0; break; + case QMetaType::Float: + x->data.f = copy ? *static_cast<const float*>(copy) : 0.0f; + break; case QVariant::LongLong: x->data.ll = copy ? *static_cast<const qlonglong *>(copy) : Q_INT64_C(0); break; @@ -274,6 +256,7 @@ static void clear(QVariant::Private *d) case QVariant::LongLong: case QVariant::ULongLong: case QVariant::Double: + case QMetaType::Float: break; case QVariant::Invalid: case QVariant::UserType: @@ -491,7 +474,7 @@ static qlonglong qMetaTypeNumber(const QVariant::Private *d) case QMetaType::Long: return qlonglong(*static_cast<long *>(d->data.shared->ptr)); case QMetaType::Float: - return qRound64(*static_cast<float *>(d->data.shared->ptr)); + return qRound64(d->data.f); case QVariant::Double: return qRound64(d->data.d); } @@ -628,7 +611,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, *str = QString::number(qMetaTypeUNumber(d)); break; case QMetaType::Float: - *str = QString::number(*static_cast<float *>(d->data.shared->ptr), 'g', FLT_DIG); + *str = QString::number(d->data.f, 'g', FLT_DIG); break; case QVariant::Double: *str = QString::number(d->data.d, 'g', DBL_DIG); @@ -799,7 +782,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, *ba = QByteArray::number(d->data.d, 'g', DBL_DIG); break; case QMetaType::Float: - *ba = QByteArray::number(*static_cast<float *>(d->data.shared->ptr), 'g', FLT_DIG); + *ba = QByteArray::number(d->data.f, 'g', FLT_DIG); break; case QMetaType::Char: case QMetaType::UChar: @@ -901,7 +884,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, *f = double(d->data.b); break; case QMetaType::Float: - *f = *static_cast<float *>(d->data.shared->ptr); + *f = double(d->data.f); break; case QVariant::LongLong: case QVariant::Int: @@ -1355,7 +1338,7 @@ void QVariant::create(int type, const void *copy) QVariant::~QVariant() { - if (d.type > Char && (!d.is_shared || !d.data.shared->ref.deref())) + if (d.type > Char && d.type != QMetaType::Float && (!d.is_shared || !d.data.shared->ref.deref())) handler->clear(&d); } @@ -1371,7 +1354,7 @@ QVariant::QVariant(const QVariant &p) { if (d.is_shared) { d.data.shared->ref.ref(); - } else if (p.d.type > Char) { + } else if (p.d.type > Char && p.d.type != QMetaType::Float) { handler->construct(&d, p.constData()); d.is_null = p.d.is_null; } @@ -1565,6 +1548,12 @@ QVariant::QVariant(const char *val) */ /*! + \fn QVariant::QVariant(float val) + + Constructs a new variant with a floating point value, \a val. +*/ + +/*! \fn QVariant::QVariant(const QList<QVariant> &val) Constructs a new variant with a list value, \a val. @@ -1619,44 +1608,44 @@ QVariant::QVariant(double val) { d.is_null = false; d.type = Double; d.data.d = val; } QVariant::QVariant(const QByteArray &val) -{ create(ByteArray, &val); } +{ d.is_null = false; d.type = ByteArray; v_construct<QByteArray>(&d, val); } QVariant::QVariant(const QBitArray &val) -{ create(BitArray, &val); } +{ d.is_null = false; d.type = BitArray; v_construct<QBitArray>(&d, val); } QVariant::QVariant(const QString &val) -{ create(String, &val); } +{ d.is_null = false; d.type = String; v_construct<QString>(&d, val); } QVariant::QVariant(const QChar &val) -{ create (Char, &val); } +{ d.is_null = false; d.type = Char; v_construct<QChar>(&d, val); } QVariant::QVariant(const QLatin1String &val) -{ QString str(val); create(String, &str); } +{ QString str(val); d.is_null = false; d.type = String; v_construct<QString>(&d, str); } QVariant::QVariant(const QStringList &val) -{ create(StringList, &val); } +{ d.is_null = false; d.type = StringList; v_construct<QStringList>(&d, val); } QVariant::QVariant(const QDate &val) -{ create(Date, &val); } +{ d.is_null = false; d.type = Date; v_construct<QDate>(&d, val); } QVariant::QVariant(const QTime &val) -{ create(Time, &val); } +{ d.is_null = false; d.type = Time; v_construct<QTime>(&d, val); } QVariant::QVariant(const QDateTime &val) -{ create(DateTime, &val); } +{ d.is_null = false; d.type = DateTime; v_construct<QDateTime>(&d, val); } QVariant::QVariant(const QList<QVariant> &list) -{ create(List, &list); } +{ d.is_null = false; d.type = List; v_construct<QVariantList>(&d, list); } QVariant::QVariant(const QMap<QString, QVariant> &map) -{ create(Map, &map); } +{ d.is_null = false; d.type = Map; v_construct<QVariantMap>(&d, map); } QVariant::QVariant(const QHash<QString, QVariant> &hash) -{ create(Hash, &hash); } +{ d.is_null = false; d.type = Hash; v_construct<QVariantHash>(&d, hash); } #ifndef QT_NO_GEOM_VARIANT -QVariant::QVariant(const QPoint &pt) { create(Point, &pt); } -QVariant::QVariant(const QPointF &pt) { create (PointF, &pt); } -QVariant::QVariant(const QRectF &r) { create (RectF, &r); } -QVariant::QVariant(const QLineF &l) { create (LineF, &l); } -QVariant::QVariant(const QLine &l) { create (Line, &l); } -QVariant::QVariant(const QRect &r) { create(Rect, &r); } -QVariant::QVariant(const QSize &s) { create(Size, &s); } -QVariant::QVariant(const QSizeF &s) { create(SizeF, &s); } +QVariant::QVariant(const QPoint &pt) { d.is_null = false; d.type = Point; v_construct<QPoint>(&d, pt); } +QVariant::QVariant(const QPointF &pt) { d.is_null = false; d.type = PointF; v_construct<QPointF>(&d, pt); } +QVariant::QVariant(const QRectF &r) { d.is_null = false; d.type = RectF; v_construct<QRectF>(&d, r); } +QVariant::QVariant(const QLineF &l) { d.is_null = false; d.type = LineF; v_construct<QLineF>(&d, l); } +QVariant::QVariant(const QLine &l) { d.is_null = false; d.type = Line; v_construct<QLine>(&d, l); } +QVariant::QVariant(const QRect &r) { d.is_null = false; d.type = Rect; v_construct<QRect>(&d, r); } +QVariant::QVariant(const QSize &s) { d.is_null = false; d.type = Size; v_construct<QSize>(&d, s); } +QVariant::QVariant(const QSizeF &s) { d.is_null = false; d.type = SizeF; v_construct<QSizeF>(&d, s); } #endif -QVariant::QVariant(const QUrl &u) { create(Url, &u); } -QVariant::QVariant(const QLocale &l) { create(Locale, &l); } +QVariant::QVariant(const QUrl &u) { d.is_null = false; d.type = Url; v_construct<QUrl>(&d, u); } +QVariant::QVariant(const QLocale &l) { d.is_null = false; d.type = Locale; v_construct<QLocale>(&d, l); } #ifndef QT_NO_REGEXP -QVariant::QVariant(const QRegExp ®Exp) { create(RegExp, ®Exp); } +QVariant::QVariant(const QRegExp ®Exp) { d.is_null = false; d.type = RegExp; v_construct<QRegExp>(&d, regExp); } #endif QVariant::QVariant(Qt::GlobalColor color) { create(62, &color); } @@ -1721,7 +1710,7 @@ QVariant& QVariant::operator=(const QVariant &variant) if (variant.d.is_shared) { variant.d.data.shared->ref.ref(); d = variant.d; - } else if (variant.d.type > Char) { + } else if (variant.d.type > Char && variant.d.type != QMetaType::Float) { d.type = variant.d.type; handler->construct(&d, variant.constData()); d.is_null = variant.d.is_null; @@ -1907,7 +1896,7 @@ void QVariant::load(QDataStream &s) } // const cast is safe since we operate on a newly constructed variant - if (!QMetaType::load(s, d.type, const_cast<void *>(constDataHelper(d)))) { + if (!QMetaType::load(s, d.type, const_cast<void *>(constData()))) { s.setStatus(QDataStream::ReadCorruptData); qWarning("QVariant::load: unable to load type %d.", d.type); } @@ -1947,7 +1936,7 @@ void QVariant::save(QDataStream &s) const return; } - if (!QMetaType::save(s, d.type, constDataHelper(d))) { + if (!QMetaType::save(s, d.type, constData())) { Q_ASSERT_X(false, "QVariant::save", "Invalid type to save"); qWarning("QVariant::save: unable to save type %d.", d.type); } @@ -2726,7 +2715,7 @@ bool QVariant::cmp(const QVariant &v) const const void *QVariant::constData() const { - return constDataHelper(d); + return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.ptr); } /*! @@ -2739,7 +2728,7 @@ const void *QVariant::constData() const void* QVariant::data() { detach(); - return const_cast<void *>(constDataHelper(d)); + return const_cast<void *>(constData()); } diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 580b101..d73fcbc 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -128,7 +128,7 @@ class Q_CORE_EXPORT QVariant LineF = 24, Point = 25, PointF = 26, - RegExp = 27, + RegExp = 27, Hash = 28, LastCoreType = Hash, @@ -181,6 +181,7 @@ class Q_CORE_EXPORT QVariant QVariant(qulonglong ull); QVariant(bool b); QVariant(double d); + QVariant(float f) { d.is_null = false; d.type = QMetaType::Float; d.data.f = f; } #ifndef QT_NO_CAST_FROM_ASCII QT_ASCII_CAST_WARN_CONSTRUCTOR QVariant(const char *str); #endif @@ -349,6 +350,7 @@ class Q_CORE_EXPORT QVariant uint u; bool b; double d; + float f; qlonglong ll; qulonglong ull; void *ptr; @@ -443,7 +445,18 @@ inline QVariant qVariantFromValue(const QVariant &t) { return t; } template <typename T> inline void qVariantSetValue(QVariant &v, const T &t) { - v = QVariant(qMetaTypeId<T>(reinterpret_cast<T *>(0)), &t); + //if possible we reuse the current QVariant private + const int type = qMetaTypeId<T>(reinterpret_cast<T *>(0)); + QVariant::Private &d = v.data_ptr(); + if (type <= int(QVariant::Char) || (type == d.type && v.isDetached())) { + d.type = type; + T *old = reinterpret_cast<T*>(d.is_shared ? d.data.shared->ptr : &d.data.ptr); + if (QTypeInfo<T>::isComplex) + old->~T(); + new (old) T(t); //call the copy constructor + } else { + v = QVariant(type, &t); + } } inline QVariant::QVariant() {} diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index 0764fe3..074575b 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -60,8 +60,6 @@ QT_BEGIN_NAMESPACE -extern Q_CORE_EXPORT const QVariant::Handler *qExtendedVariantHandler; - #ifdef Q_CC_SUN // Sun CC picks the wrong overload, so introduce awful hack template <typename T> @@ -70,7 +68,7 @@ inline T *v_cast(const QVariant::Private *nd, T * = 0) QVariant::Private *d = const_cast<QVariant::Private *>(nd); return ((sizeof(T) > sizeof(QVariant::Private::Data)) ? static_cast<T *>(d->data.shared->ptr) - : reinterpret_cast<T*>(&d->data.c)); + : static_cast<T *>(static_cast<void *>(&d->data.c))); } #else // every other compiler in this world @@ -80,7 +78,7 @@ inline const T *v_cast(const QVariant::Private *d, T * = 0) { return ((sizeof(T) > sizeof(QVariant::Private::Data)) ? static_cast<const T *>(d->data.shared->ptr) - : reinterpret_cast<const T *>(&d->data.c)); + : static_cast<const T *>(static_cast<const void *>(&d->data.c))); } template <typename T> @@ -88,15 +86,17 @@ inline T *v_cast(QVariant::Private *d, T * = 0) { return ((sizeof(T) > sizeof(QVariant::Private::Data)) ? static_cast<T *>(d->data.shared->ptr) - : reinterpret_cast<T *>(&d->data.c)); + : static_cast<T *>(static_cast<void *>(&d->data.c))); } #endif -//a simple template that avoids to allocate 2 buffers when creating a QVariant + +//a simple template that avoids to allocate 2 memory chunks when creating a QVariant template <class T> class QVariantPrivateSharedEx : public QVariant::PrivateShared { public: + QVariantPrivateSharedEx() : QVariant::PrivateShared(&m_t) { } QVariantPrivateSharedEx(const T&t) : QVariant::PrivateShared(&m_t), m_t(t) { } private: @@ -105,14 +105,12 @@ private: // constructs a new variant if copy is 0, otherwise copy-constructs template <class T> -inline void v_construct(QVariant::Private *x, const T& t) +inline void v_construct(QVariant::Private *x, const T &t) { - x->type = qMetaTypeId<T>(reinterpret_cast<T *>(0)); if (sizeof(T) > sizeof(QVariant::Private::Data)) { x->data.shared = new QVariantPrivateSharedEx<T>(t); x->is_shared = true; } else { - x->is_shared = false; new (&x->data.ptr) T(t); } } @@ -120,24 +118,31 @@ inline void v_construct(QVariant::Private *x, const T& t) template <class T> inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) { - if (copy) { - v_construct<T>(x, *reinterpret_cast<const T*>(copy)); + if (sizeof(T) > sizeof(QVariant::Private::Data)) { + x->data.shared = copy ? new QVariantPrivateSharedEx<T>(*static_cast<const T *>(copy)) + : new QVariantPrivateSharedEx<T>; + x->is_shared = true; } else { - T t; - v_construct<T>(x, t); + if (copy) + new (&x->data.ptr) T(*static_cast<const T *>(copy)); + else + new (&x->data.ptr) T; } } - // deletes the internal structures template <class T> inline void v_clear(QVariant::Private *d, T* = 0) { - //now we need to call the destructor in any case - //because QVariant::PrivateShared doesn't have a virtual destructor - v_cast<T>(d)->~T(); - if (sizeof(T) > sizeof(QVariant::Private::Data)) - delete d->data.shared; + + if (sizeof(T) > sizeof(QVariant::Private::Data)) { + //now we need to cast + //because QVariant::PrivateShared doesn't have a virtual destructor + delete static_cast<QVariantPrivateSharedEx<T>*>(d->data.shared); + } else { + v_cast<T>(d)->~T(); + } + } QT_END_NAMESPACE |