diff options
-rw-r--r-- | src/declarative/qml/ftw/ftw.pri | 2 | ||||
-rw-r--r-- | src/declarative/qml/ftw/qfieldlist_p.h | 190 | ||||
-rw-r--r-- | src/declarative/qml/ftw/qflagpointer_p.h | 170 | ||||
-rw-r--r-- | src/declarative/qml/ftw/qlazilyallocated_p.h | 146 | ||||
-rw-r--r-- | src/declarative/qml/ftw/qpointervaluepair_p.h | 196 |
5 files changed, 695 insertions, 9 deletions
diff --git a/src/declarative/qml/ftw/ftw.pri b/src/declarative/qml/ftw/ftw.pri index e331c9e12a..26343422c5 100644 --- a/src/declarative/qml/ftw/ftw.pri +++ b/src/declarative/qml/ftw/ftw.pri @@ -15,6 +15,8 @@ HEADERS += \ $$PWD/qrecyclepool_p.h \ $$PWD/qflagpointer_p.h \ $$PWD/qdeclarativetrace_p.h \ + $$PWD/qpointervaluepair_p.h \ + $$PWD/qlazilyallocated_p.h \ SOURCES += \ $$PWD/qintrusivelist.cpp \ diff --git a/src/declarative/qml/ftw/qfieldlist_p.h b/src/declarative/qml/ftw/qfieldlist_p.h index ad70d44dce..4253779e78 100644 --- a/src/declarative/qml/ftw/qfieldlist_p.h +++ b/src/declarative/qml/ftw/qfieldlist_p.h @@ -55,6 +55,40 @@ #include <QtCore/qglobal.h> +#include <private/qflagpointer_p.h> + +// QForwardFieldList is a super simple linked list that can only prepend +template<class N, N *N::*nextMember> +class QForwardFieldList +{ +public: + inline QForwardFieldList(); + inline N *first() const; + inline N *takeFirst(); + + inline void prepend(N *); + + inline bool isEmpty() const; + inline bool isOne() const; + inline bool isMany() const; + + static inline N *next(N *v); + + inline bool flag() const; + inline void setFlag(); + inline void clearFlag(); + inline void setFlagValue(bool); + + inline bool flag2() const; + inline void setFlag2(); + inline void clearFlag2(); + inline void setFlag2Value(bool); +private: + QFlagPointer<N> _first; +}; + +// QFieldList is a simple linked list, that can append and prepend and also +// maintains a count template<class N, N *N::*nextMember> class QFieldList { @@ -76,18 +110,128 @@ public: inline void insertAfter(N *, QFieldList<N, nextMember> &); inline void copyAndClear(QFieldList<N, nextMember> &); + inline void copyAndClearAppend(QForwardFieldList<N, nextMember> &); + inline void copyAndClearPrepend(QForwardFieldList<N, nextMember> &); static inline N *next(N *v); + inline bool flag() const; + inline void setFlag(); + inline void clearFlag(); + inline void setFlagValue(bool); private: N *_first; N *_last; - int _count; + quint32 _flag:1; + quint32 _count:31; }; template<class N, N *N::*nextMember> +QForwardFieldList<N, nextMember>::QForwardFieldList() +{ +} + +template<class N, N *N::*nextMember> +N *QForwardFieldList<N, nextMember>::first() const +{ + return *_first; +} + +template<class N, N *N::*nextMember> +N *QForwardFieldList<N, nextMember>::takeFirst() +{ + N *value = *_first; + if (value) { + _first = next(value); + value->*nextMember = 0; + } + return value; +} + +template<class N, N *N::*nextMember> +void QForwardFieldList<N, nextMember>::prepend(N *v) +{ + Q_ASSERT(v->*nextMember == 0); + v->*nextMember = *_first; + _first = v; +} + +template<class N, N *N::*nextMember> +bool QForwardFieldList<N, nextMember>::isEmpty() const +{ + return _first.isNull(); +} + +template<class N, N *N::*nextMember> +bool QForwardFieldList<N, nextMember>::isOne() const +{ + return *_first && _first->*nextMember == 0; +} + +template<class N, N *N::*nextMember> +bool QForwardFieldList<N, nextMember>::isMany() const +{ + return *_first && _first->*nextMember != 0; +} + +template<class N, N *N::*nextMember> +N *QForwardFieldList<N, nextMember>::next(N *v) +{ + Q_ASSERT(v); + return v->*nextMember; +} + +template<class N, N *N::*nextMember> +bool QForwardFieldList<N, nextMember>::flag() const +{ + return _first.flag(); +} + +template<class N, N *N::*nextMember> +void QForwardFieldList<N, nextMember>::setFlag() +{ + _first.setFlag(); +} + +template<class N, N *N::*nextMember> +void QForwardFieldList<N, nextMember>::clearFlag() +{ + _first.clearFlag(); +} + +template<class N, N *N::*nextMember> +void QForwardFieldList<N, nextMember>::setFlagValue(bool v) +{ + _first.setFlagValue(v); +} + +template<class N, N *N::*nextMember> +bool QForwardFieldList<N, nextMember>::flag2() const +{ + return _first.flag2(); +} + +template<class N, N *N::*nextMember> +void QForwardFieldList<N, nextMember>::setFlag2() +{ + _first.setFlag2(); +} + +template<class N, N *N::*nextMember> +void QForwardFieldList<N, nextMember>::clearFlag2() +{ + _first.clearFlag2(); +} + +template<class N, N *N::*nextMember> +void QForwardFieldList<N, nextMember>::setFlag2Value(bool v) +{ + _first.setFlag2Value(v); +} + +template<class N, N *N::*nextMember> QFieldList<N, nextMember>::QFieldList() -: _first(0), _last(0), _count(0) +: _first(0), _last(0), _flag(0), _count(0) { } @@ -237,4 +381,46 @@ void QFieldList<N, nextMember>::copyAndClear(QFieldList<N, nextMember> &o) o._count = 0; } +template<class N, N *N::*nextMember> +void QFieldList<N, nextMember>::copyAndClearAppend(QForwardFieldList<N, nextMember> &o) +{ + _first = 0; + _last = 0; + _count = 0; + while (N *n = o.takeFirst()) append(n); +} + +template<class N, N *N::*nextMember> +void QFieldList<N, nextMember>::copyAndClearPrepend(QForwardFieldList<N, nextMember> &o) +{ + _first = 0; + _last = 0; + _count = 0; + while (N *n = o.takeFirst()) prepend(n); +} + +template<class N, N *N::*nextMember> +bool QFieldList<N, nextMember>::flag() const +{ + return _flag; +} + +template<class N, N *N::*nextMember> +void QFieldList<N, nextMember>::setFlag() +{ + _flag = true; +} + +template<class N, N *N::*nextMember> +void QFieldList<N, nextMember>::clearFlag() +{ + _flag = false; +} + +template<class N, N *N::*nextMember> +void QFieldList<N, nextMember>::setFlagValue(bool v) +{ + _flag = v; +} + #endif // QFIELDLIST_P_H diff --git a/src/declarative/qml/ftw/qflagpointer_p.h b/src/declarative/qml/ftw/qflagpointer_p.h index 2d503891ee..ac462cbe30 100644 --- a/src/declarative/qml/ftw/qflagpointer_p.h +++ b/src/declarative/qml/ftw/qflagpointer_p.h @@ -69,10 +69,12 @@ public: inline bool flag() const; inline void setFlag(); inline void clearFlag(); + inline void setFlagValue(bool); inline bool flag2() const; inline void setFlag2(); inline void clearFlag2(); + inline void setFlag2Value(bool); inline QFlagPointer<T> &operator=(const QFlagPointer &o); inline QFlagPointer<T> &operator=(T *); @@ -81,11 +83,43 @@ public: inline T *operator*() const; private: - intptr_t ptr_value; + quintptr ptr_value; - static const intptr_t FlagBit = 0x1; - static const intptr_t Flag2Bit = 0x2; - static const intptr_t FlagsMask = FlagBit | Flag2Bit; + static const quintptr FlagBit = 0x1; + static const quintptr Flag2Bit = 0x2; + static const quintptr FlagsMask = FlagBit | Flag2Bit; +}; + +template<typename T, typename T2> +class QBiPointer { +public: + inline QBiPointer(); + inline QBiPointer(T *); + inline QBiPointer(T2 *); + inline QBiPointer(const QBiPointer<T, T2> &o); + + inline bool isNull() const; + inline bool isT1() const; + inline bool isT2() const; + + inline bool flag() const; + inline void setFlag(); + inline void clearFlag(); + inline void setFlagValue(bool); + + inline QBiPointer<T, T2> &operator=(const QBiPointer<T, T2> &o); + inline QBiPointer<T, T2> &operator=(T *); + inline QBiPointer<T, T2> &operator=(T2 *); + + inline T *asT1() const; + inline T2 *asT2() const; + +private: + quintptr ptr_value; + + static const quintptr FlagBit = 0x1; + static const quintptr Flag2Bit = 0x2; + static const quintptr FlagsMask = FlagBit | Flag2Bit; }; template<typename T> @@ -96,7 +130,7 @@ QFlagPointer<T>::QFlagPointer() template<typename T> QFlagPointer<T>::QFlagPointer(T *v) -: ptr_value(intptr_t(v)) +: ptr_value(quintptr(v)) { Q_ASSERT((ptr_value & FlagsMask) == 0); } @@ -132,6 +166,13 @@ void QFlagPointer<T>::clearFlag() } template<typename T> +void QFlagPointer<T>::setFlagValue(bool v) +{ + if (v) setFlag(); + else clearFlag(); +} + +template<typename T> bool QFlagPointer<T>::flag2() const { return ptr_value & Flag2Bit; @@ -150,6 +191,13 @@ void QFlagPointer<T>::clearFlag2() } template<typename T> +void QFlagPointer<T>::setFlag2Value(bool v) +{ + if (v) setFlag2(); + else clearFlag2(); +} + +template<typename T> QFlagPointer<T> &QFlagPointer<T>::operator=(const QFlagPointer &o) { ptr_value = o.ptr_value; @@ -159,9 +207,9 @@ QFlagPointer<T> &QFlagPointer<T>::operator=(const QFlagPointer &o) template<typename T> QFlagPointer<T> &QFlagPointer<T>::operator=(T *o) { - Q_ASSERT((intptr_t(o) & FlagsMask) == 0); + Q_ASSERT((quintptr(o) & FlagsMask) == 0); - ptr_value = intptr_t(o) | (ptr_value & FlagsMask); + ptr_value = quintptr(o) | (ptr_value & FlagsMask); return *this; } @@ -177,6 +225,114 @@ T *QFlagPointer<T>::operator*() const return (T *)(ptr_value & ~FlagsMask); } +template<typename T, typename T2> +QBiPointer<T, T2>::QBiPointer() +: ptr_value(0) +{ +} + +template<typename T, typename T2> +QBiPointer<T, T2>::QBiPointer(T *v) +: ptr_value(quintptr(v)) +{ + Q_ASSERT((quintptr(v) & FlagsMask) == 0); +} + +template<typename T, typename T2> +QBiPointer<T, T2>::QBiPointer(T2 *v) +: ptr_value(quintptr(v) | Flag2Bit) +{ + Q_ASSERT((quintptr(v) & FlagsMask) == 0); +} + +template<typename T, typename T2> +QBiPointer<T, T2>::QBiPointer(const QBiPointer<T, T2> &o) +: ptr_value(o.ptr_value) +{ +} + +template<typename T, typename T2> +bool QBiPointer<T, T2>::isNull() const +{ + return 0 == (ptr_value & (~FlagsMask)); +} + +template<typename T, typename T2> +bool QBiPointer<T, T2>::isT1() const +{ + return !(ptr_value & Flag2Bit); +} + +template<typename T, typename T2> +bool QBiPointer<T, T2>::isT2() const +{ + return ptr_value & Flag2Bit; +} + +template<typename T, typename T2> +bool QBiPointer<T, T2>::flag() const +{ + return ptr_value & FlagBit; +} + +template<typename T, typename T2> +void QBiPointer<T, T2>::setFlag() +{ + ptr_value |= FlagBit; +} + +template<typename T, typename T2> +void QBiPointer<T, T2>::clearFlag() +{ + ptr_value &= ~FlagBit; +} + +template<typename T, typename T2> +void QBiPointer<T, T2>::setFlagValue(bool v) +{ + if (v) setFlag(); + else clearFlag(); +} + +template<typename T, typename T2> +QBiPointer<T, T2> &QBiPointer<T, T2>::operator=(const QBiPointer<T, T2> &o) +{ + ptr_value = o.ptr_value; + return *this; +} + +template<typename T, typename T2> +QBiPointer<T, T2> &QBiPointer<T, T2>::operator=(T *o) +{ + Q_ASSERT((quintptr(o) & FlagsMask) == 0); + + ptr_value = quintptr(o) | (ptr_value & FlagBit); + return *this; +} + +template<typename T, typename T2> +QBiPointer<T, T2> &QBiPointer<T, T2>::operator=(T2 *o) +{ + Q_ASSERT((quintptr(o) & FlagsMask) == 0); + + ptr_value = quintptr(o) | (ptr_value & FlagBit) | Flag2Bit; + return *this; +} + +template<typename T, typename T2> +T *QBiPointer<T, T2>::asT1() const +{ + Q_ASSERT(isT1()); + return (T *)(ptr_value & ~FlagsMask); +} + +template<typename T, typename T2> +T2 *QBiPointer<T, T2>::asT2() const +{ + Q_ASSERT(isT2()); + return (T2 *)(ptr_value & ~FlagsMask); +} + QT_END_NAMESPACE #endif // QFLAGPOINTER_P_H diff --git a/src/declarative/qml/ftw/qlazilyallocated_p.h b/src/declarative/qml/ftw/qlazilyallocated_p.h new file mode 100644 index 0000000000..d5a9dcc3ec --- /dev/null +++ b/src/declarative/qml/ftw/qlazilyallocated_p.h @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLAZILYALLOCATED_P_H +#define QLAZILYALLOCATED_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> + +#include <private/qflagpointer_p.h> + +QT_BEGIN_NAMESPACE + +template<typename T> +class QLazilyAllocated { +public: + inline QLazilyAllocated(); + inline ~QLazilyAllocated(); + + inline bool isAllocated() const; + + inline T *operator->() const; + + inline T &value(); + inline const T &value() const; + + inline bool flag() const; + inline void setFlag(); + inline void clearFlag(); + inline void setFlagValue(bool); +private: + mutable QFlagPointer<T> d; +}; + +template<typename T> +QLazilyAllocated<T>::QLazilyAllocated() +{ +} + +template<typename T> +QLazilyAllocated<T>::~QLazilyAllocated() +{ + delete *d; +} + +template<typename T> +bool QLazilyAllocated<T>::isAllocated() const +{ + return !d.isNull(); +} + +template<typename T> +T &QLazilyAllocated<T>::value() +{ + if (d.isNull()) d = new T; + return *(*d); +} + +template<typename T> +const T &QLazilyAllocated<T>::value() const +{ + if (d.isNull()) d = new T; + return *(*d); +} + +template<typename T> +T *QLazilyAllocated<T>::operator->() const +{ + return *d; +} + +template<typename T> +bool QLazilyAllocated<T>::flag() const +{ + return d.flag(); +} + +template<typename T> +void QLazilyAllocated<T>::setFlag() +{ + d.setFlag(); +} + +template<typename T> +void QLazilyAllocated<T>::clearFlag() +{ + d.clearFlag(); +} + +template<typename T> +void QLazilyAllocated<T>::setFlagValue(bool v) +{ + d.setFlagValue(v); +} + +QT_END_NAMESPACE + +#endif // QLAZILYALLOCATED_P_H diff --git a/src/declarative/qml/ftw/qpointervaluepair_p.h b/src/declarative/qml/ftw/qpointervaluepair_p.h new file mode 100644 index 0000000000..fd1a77004e --- /dev/null +++ b/src/declarative/qml/ftw/qpointervaluepair_p.h @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPOINTERVALUEPAIR_P_H +#define QPOINTERVALUEPAIR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> +#include <private/qflagpointer_p.h> + +QT_BEGIN_NAMESPACE + +// QPointerValuePair is intended to help reduce the memory consumption of a class. +// In the common case, QPointerValuePair behaves like a pointer. In this mode, it +// consumes the same memory as a regular pointer. +// Additionally, QPointerValuePair can store an arbitrary value type in *addition* +// to the pointer. In this case, it uses slightly more memory than the pointer and +// value type combined. +// Consequently, this class is most useful in cases where a pointer is always stored +// and a value type is rarely stored. +template<typename P, typename V> +class QPointerValuePair { +public: + inline QPointerValuePair(); + inline QPointerValuePair(P *); + inline ~QPointerValuePair(); + + inline bool isNull() const; + + inline bool flag() const; + inline void setFlag(); + inline void clearFlag(); + inline void setFlagValue(bool); + + inline QPointerValuePair<P, V> &operator=(P *); + + inline P *operator->() const; + inline P *operator*() const; + + inline bool hasValue() const; + inline V &value(); + inline const V *constValue() const; + +private: + struct Value { P *pointer; V value; }; + QBiPointer<P, Value> d; +}; + +template<typename P, typename V> +QPointerValuePair<P, V>::QPointerValuePair() +{ +} + +template<typename P, typename V> +QPointerValuePair<P, V>::QPointerValuePair(P *p) +: d(p) +{ +} + +template<typename P, typename V> +QPointerValuePair<P, V>::~QPointerValuePair() +{ + if (d.isT2()) delete d.asT2(); +} + +template<typename P, typename V> +bool QPointerValuePair<P, V>::isNull() const +{ + if (d.isT1()) return 0 == d.asT1(); + else return d.asT2()->pointer == 0; +} + +template<typename P, typename V> +bool QPointerValuePair<P, V>::flag() const +{ + return d.flag(); +} + +template<typename P, typename V> +void QPointerValuePair<P, V>::setFlag() +{ + d.setFlag(); +} + +template<typename P, typename V> +void QPointerValuePair<P, V>::clearFlag() +{ + d.clearFlag(); +} + +template<typename P, typename V> +void QPointerValuePair<P, V>::setFlagValue(bool v) +{ + d.setFlagValue(v); +} + +template<typename P, typename V> +QPointerValuePair<P, V> &QPointerValuePair<P, V>::operator=(P *o) +{ + if (d.isT1()) d = o; + else d.asT2()->pointer = o; + return *this; +} + +template<typename P, typename V> +P *QPointerValuePair<P, V>::operator->() const +{ + if (d.isT1()) return d.asT1(); + else return d.asT2()->pointer; +} + +template<typename P, typename V> +P *QPointerValuePair<P, V>::operator*() const +{ + if (d.isT1()) return d.asT1(); + else return d.asT2()->pointer; +} + +template<typename P, typename V> +bool QPointerValuePair<P, V>::hasValue() const +{ + return d.isT2(); +} + +template<typename P, typename V> +V &QPointerValuePair<P, V>::value() +{ + if (d.isT1()) { + P *p = d.asT1(); + Value *value = new Value; + value->pointer = p; + d = value; + } + + return d.asT2()->value; +} + +// Will return null if hasValue() == false +template<typename P, typename V> +const V *QPointerValuePair<P, V>::constValue() const +{ + if (d.isT2()) return &d.asT2()->value; + else return 0; +} + +QT_END_NAMESPACE + +#endif // QPOINTERVALUEPAIR_P_H |