From d88578e58b8e85038568355fcbe2d5127ed208f4 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 14 Feb 2012 11:20:32 +0000 Subject: [PATCH] Update ftw classes This is for the benefit of subsequent changes. Change-Id: Ib494efb1474d069c067194008c9832653d5d8eb4 Reviewed-by: Roberto Raggi --- src/declarative/qml/ftw/ftw.pri | 2 + src/declarative/qml/ftw/qfieldlist_p.h | 190 ++++++++++++++++++++++++- src/declarative/qml/ftw/qflagpointer_p.h | 170 +++++++++++++++++++++- src/declarative/qml/ftw/qlazilyallocated_p.h | 146 +++++++++++++++++++ src/declarative/qml/ftw/qpointervaluepair_p.h | 196 ++++++++++++++++++++++++++ 5 files changed, 695 insertions(+), 9 deletions(-) create mode 100644 src/declarative/qml/ftw/qlazilyallocated_p.h create mode 100644 src/declarative/qml/ftw/qpointervaluepair_p.h diff --git a/src/declarative/qml/ftw/ftw.pri b/src/declarative/qml/ftw/ftw.pri index e331c9e..2634342 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 ad70d44..4253779 100644 --- a/src/declarative/qml/ftw/qfieldlist_p.h +++ b/src/declarative/qml/ftw/qfieldlist_p.h @@ -55,6 +55,40 @@ #include +#include + +// QForwardFieldList is a super simple linked list that can only prepend +template +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 _first; +}; + +// QFieldList is a simple linked list, that can append and prepend and also +// maintains a count template class QFieldList { @@ -76,18 +110,128 @@ public: inline void insertAfter(N *, QFieldList &); inline void copyAndClear(QFieldList &); + inline void copyAndClearAppend(QForwardFieldList &); + inline void copyAndClearPrepend(QForwardFieldList &); 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 +QForwardFieldList::QForwardFieldList() +{ +} + +template +N *QForwardFieldList::first() const +{ + return *_first; +} + +template +N *QForwardFieldList::takeFirst() +{ + N *value = *_first; + if (value) { + _first = next(value); + value->*nextMember = 0; + } + return value; +} + +template +void QForwardFieldList::prepend(N *v) +{ + Q_ASSERT(v->*nextMember == 0); + v->*nextMember = *_first; + _first = v; +} + +template +bool QForwardFieldList::isEmpty() const +{ + return _first.isNull(); +} + +template +bool QForwardFieldList::isOne() const +{ + return *_first && _first->*nextMember == 0; +} + +template +bool QForwardFieldList::isMany() const +{ + return *_first && _first->*nextMember != 0; +} + +template +N *QForwardFieldList::next(N *v) +{ + Q_ASSERT(v); + return v->*nextMember; +} + +template +bool QForwardFieldList::flag() const +{ + return _first.flag(); +} + +template +void QForwardFieldList::setFlag() +{ + _first.setFlag(); +} + +template +void QForwardFieldList::clearFlag() +{ + _first.clearFlag(); +} + +template +void QForwardFieldList::setFlagValue(bool v) +{ + _first.setFlagValue(v); +} + +template +bool QForwardFieldList::flag2() const +{ + return _first.flag2(); +} + +template +void QForwardFieldList::setFlag2() +{ + _first.setFlag2(); +} + +template +void QForwardFieldList::clearFlag2() +{ + _first.clearFlag2(); +} + +template +void QForwardFieldList::setFlag2Value(bool v) +{ + _first.setFlag2Value(v); +} + +template QFieldList::QFieldList() -: _first(0), _last(0), _count(0) +: _first(0), _last(0), _flag(0), _count(0) { } @@ -237,4 +381,46 @@ void QFieldList::copyAndClear(QFieldList &o) o._count = 0; } +template +void QFieldList::copyAndClearAppend(QForwardFieldList &o) +{ + _first = 0; + _last = 0; + _count = 0; + while (N *n = o.takeFirst()) append(n); +} + +template +void QFieldList::copyAndClearPrepend(QForwardFieldList &o) +{ + _first = 0; + _last = 0; + _count = 0; + while (N *n = o.takeFirst()) prepend(n); +} + +template +bool QFieldList::flag() const +{ + return _flag; +} + +template +void QFieldList::setFlag() +{ + _flag = true; +} + +template +void QFieldList::clearFlag() +{ + _flag = false; +} + +template +void QFieldList::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 2d50389..ac462cb 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 &operator=(const QFlagPointer &o); inline QFlagPointer &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 +class QBiPointer { +public: + inline QBiPointer(); + inline QBiPointer(T *); + inline QBiPointer(T2 *); + inline QBiPointer(const QBiPointer &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 &operator=(const QBiPointer &o); + inline QBiPointer &operator=(T *); + inline QBiPointer &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 @@ -96,7 +130,7 @@ QFlagPointer::QFlagPointer() template QFlagPointer::QFlagPointer(T *v) -: ptr_value(intptr_t(v)) +: ptr_value(quintptr(v)) { Q_ASSERT((ptr_value & FlagsMask) == 0); } @@ -132,6 +166,13 @@ void QFlagPointer::clearFlag() } template +void QFlagPointer::setFlagValue(bool v) +{ + if (v) setFlag(); + else clearFlag(); +} + +template bool QFlagPointer::flag2() const { return ptr_value & Flag2Bit; @@ -150,6 +191,13 @@ void QFlagPointer::clearFlag2() } template +void QFlagPointer::setFlag2Value(bool v) +{ + if (v) setFlag2(); + else clearFlag2(); +} + +template QFlagPointer &QFlagPointer::operator=(const QFlagPointer &o) { ptr_value = o.ptr_value; @@ -159,9 +207,9 @@ QFlagPointer &QFlagPointer::operator=(const QFlagPointer &o) template QFlagPointer &QFlagPointer::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::operator*() const return (T *)(ptr_value & ~FlagsMask); } +template +QBiPointer::QBiPointer() +: ptr_value(0) +{ +} + +template +QBiPointer::QBiPointer(T *v) +: ptr_value(quintptr(v)) +{ + Q_ASSERT((quintptr(v) & FlagsMask) == 0); +} + +template +QBiPointer::QBiPointer(T2 *v) +: ptr_value(quintptr(v) | Flag2Bit) +{ + Q_ASSERT((quintptr(v) & FlagsMask) == 0); +} + +template +QBiPointer::QBiPointer(const QBiPointer &o) +: ptr_value(o.ptr_value) +{ +} + +template +bool QBiPointer::isNull() const +{ + return 0 == (ptr_value & (~FlagsMask)); +} + +template +bool QBiPointer::isT1() const +{ + return !(ptr_value & Flag2Bit); +} + +template +bool QBiPointer::isT2() const +{ + return ptr_value & Flag2Bit; +} + +template +bool QBiPointer::flag() const +{ + return ptr_value & FlagBit; +} + +template +void QBiPointer::setFlag() +{ + ptr_value |= FlagBit; +} + +template +void QBiPointer::clearFlag() +{ + ptr_value &= ~FlagBit; +} + +template +void QBiPointer::setFlagValue(bool v) +{ + if (v) setFlag(); + else clearFlag(); +} + +template +QBiPointer &QBiPointer::operator=(const QBiPointer &o) +{ + ptr_value = o.ptr_value; + return *this; +} + +template +QBiPointer &QBiPointer::operator=(T *o) +{ + Q_ASSERT((quintptr(o) & FlagsMask) == 0); + + ptr_value = quintptr(o) | (ptr_value & FlagBit); + return *this; +} + +template +QBiPointer &QBiPointer::operator=(T2 *o) +{ + Q_ASSERT((quintptr(o) & FlagsMask) == 0); + + ptr_value = quintptr(o) | (ptr_value & FlagBit) | Flag2Bit; + return *this; +} + +template +T *QBiPointer::asT1() const +{ + Q_ASSERT(isT1()); + return (T *)(ptr_value & ~FlagsMask); +} + +template +T2 *QBiPointer::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 0000000..d5a9dcc --- /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 + +#include + +QT_BEGIN_NAMESPACE + +template +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 d; +}; + +template +QLazilyAllocated::QLazilyAllocated() +{ +} + +template +QLazilyAllocated::~QLazilyAllocated() +{ + delete *d; +} + +template +bool QLazilyAllocated::isAllocated() const +{ + return !d.isNull(); +} + +template +T &QLazilyAllocated::value() +{ + if (d.isNull()) d = new T; + return *(*d); +} + +template +const T &QLazilyAllocated::value() const +{ + if (d.isNull()) d = new T; + return *(*d); +} + +template +T *QLazilyAllocated::operator->() const +{ + return *d; +} + +template +bool QLazilyAllocated::flag() const +{ + return d.flag(); +} + +template +void QLazilyAllocated::setFlag() +{ + d.setFlag(); +} + +template +void QLazilyAllocated::clearFlag() +{ + d.clearFlag(); +} + +template +void QLazilyAllocated::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 0000000..fd1a770 --- /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 +#include + +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 +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 &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 d; +}; + +template +QPointerValuePair::QPointerValuePair() +{ +} + +template +QPointerValuePair::QPointerValuePair(P *p) +: d(p) +{ +} + +template +QPointerValuePair::~QPointerValuePair() +{ + if (d.isT2()) delete d.asT2(); +} + +template +bool QPointerValuePair::isNull() const +{ + if (d.isT1()) return 0 == d.asT1(); + else return d.asT2()->pointer == 0; +} + +template +bool QPointerValuePair::flag() const +{ + return d.flag(); +} + +template +void QPointerValuePair::setFlag() +{ + d.setFlag(); +} + +template +void QPointerValuePair::clearFlag() +{ + d.clearFlag(); +} + +template +void QPointerValuePair::setFlagValue(bool v) +{ + d.setFlagValue(v); +} + +template +QPointerValuePair &QPointerValuePair::operator=(P *o) +{ + if (d.isT1()) d = o; + else d.asT2()->pointer = o; + return *this; +} + +template +P *QPointerValuePair::operator->() const +{ + if (d.isT1()) return d.asT1(); + else return d.asT2()->pointer; +} + +template +P *QPointerValuePair::operator*() const +{ + if (d.isT1()) return d.asT1(); + else return d.asT2()->pointer; +} + +template +bool QPointerValuePair::hasValue() const +{ + return d.isT2(); +} + +template +V &QPointerValuePair::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 +const V *QPointerValuePair::constValue() const +{ + if (d.isT2()) return &d.asT2()->value; + else return 0; +} + +QT_END_NAMESPACE + +#endif // QPOINTERVALUEPAIR_P_H -- 2.7.4