From: Aaron Kennedy Date: Thu, 21 Jul 2011 13:08:53 +0000 (+1000) Subject: Introduce QHashField for use in "contains" tests. X-Git-Tag: qt-v5.0.0-alpha1~1822 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=18307bfffff4cf8867706c9b1eafe163465379a7;p=profile%2Fivi%2Fqtdeclarative.git Introduce QHashField for use in "contains" tests. Change-Id: I35aadace15b71b44c1b9e30a76eadf79fe03afad Reviewed-on: http://codereview.qt.nokia.com/3767 Reviewed-by: Roberto Raggi --- diff --git a/src/declarative/qml/ftw/ftw.pri b/src/declarative/qml/ftw/ftw.pri index 7e88598..545c47e 100644 --- a/src/declarative/qml/ftw/ftw.pri +++ b/src/declarative/qml/ftw/ftw.pri @@ -11,6 +11,7 @@ HEADERS += \ $$PWD/qfieldlist_p.h \ $$PWD/qdeclarativeutils_p.h \ $$PWD/qfastmetabuilder_p.h \ + $$PWD/qhashfield_p.h \ SOURCES += \ $$PWD/qintrusivelist.cpp \ diff --git a/src/declarative/qml/ftw/qhashfield_p.h b/src/declarative/qml/ftw/qhashfield_p.h new file mode 100644 index 0000000..8746264 --- /dev/null +++ b/src/declarative/qml/ftw/qhashfield_p.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** 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 QHASHFIELD_P_H +#define QHASHFIELD_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 + +QT_BEGIN_NAMESPACE + +// QHashField can be used for doing coarse grained set testing, in +// cases where you do not expect the set to contain the item. For +// example where you would write: +// QSet strings; +// for (int ii = 0; ii < mystrings.count(); ++ii) { +// if (strings.contains(mystrings.at(ii))) +// qFatal("Duplication!"); +// strings.insert(mystrings); +// } +// You may write: +// QHashField strings; +// for (int ii = 0; ii < mystrings.count(); ++ii) { +// if (strings.testAndSet(qHash(mystrings.at(ii)))) { +// // The string *might* be duplicated +// for (int jj = 0; jj < ii; ++jj) { +// if (mystrings.at(ii) == mystrings.at(jj)) +// qFatal("Duplication!"); +// } +// } +// } +// For small lists of things, where the hash is cheap to calculate +// and you don't expect duplication this will be much faster. +class QHashField { +public: + inline QHashField(); + + inline void clear(); + + inline bool test(quint32 hash); + inline bool testAndSet(quint32 hash); +private: + quint32 m_field; +}; + +QHashField::QHashField() +: m_field(0) +{ +} + +void QHashField::clear() +{ + m_field = 0; +} + +bool QHashField::test(quint32 hash) +{ + return m_field & (1 << (hash % 31)); +} + +bool QHashField::testAndSet(quint32 hash) +{ + quint32 mask = 1 << (hash % 31); + bool rv = m_field & mask; + m_field |= mask; + return rv; +} + +QT_END_NAMESPACE + +#endif // QHASHFIELD_P_H diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 9c59787..bb2742c 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -848,6 +848,7 @@ bool QDeclarativeCompiler::buildObject(QDeclarativeParser::Object *obj, const Bi const QMetaObject *metaObject = obj->metaObject(); Q_ASSERT(metaObject); + // XXX aakenned QMetaProperty p = QDeclarativeMetaType::defaultProperty(metaObject); if (p.name()) { Property *explicitProperty = obj->getProperty(QString::fromUtf8(p.name()), false); @@ -2388,8 +2389,8 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj) // We use a coarse grain, 31 bit hash to check if there are duplicates. // Calculating the hash for the names is not a waste as we have to test // them against the illegalNames set anyway. - quint32 propNames = 0; - quint32 methodNames = 0; + QHashField propNames; + QHashField methodNames; // Check properties int dpCount = obj->dynamicProperties.count(); @@ -2402,16 +2403,13 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj) seenDefaultProperty = true; } - quint32 hash = prop.name.hash(); - quint32 bit = hash % 31; - if (propNames & (1 << bit)) { + if (propNames.testAndSet(prop.name.hash())) { for (Object::DynamicProperty *p2 = obj->dynamicProperties.first(); p2 != p; p2 = obj->dynamicProperties.next(p2)) { if (p2->name == prop.name) COMPILE_EXCEPTION(&prop, tr("Duplicate property name")); } } - propNames |= (1 << bit); if (QDeclarativeUtils::isUpper(prop.name.at(0))) COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter")); diff --git a/src/declarative/qml/qdeclarativeparser.cpp b/src/declarative/qml/qdeclarativeparser.cpp index 00bad1d..6a78598 100644 --- a/src/declarative/qml/qdeclarativeparser.cpp +++ b/src/declarative/qml/qdeclarativeparser.cpp @@ -132,14 +132,18 @@ void QDeclarativeParser::Object::addScriptStringProperty(Property *p) scriptStringProperties.append(p); } +// This lookup is optimized for missing, and having to create a new property. Property *QDeclarativeParser::Object::getProperty(const QHashedStringRef &name, bool create) { - for (Property *p = properties.first(); p; p = properties.next(p)) { - if (p->name() == name) - return p; - } - if (create) { + quint32 h = name.hash(); + if (propertiesHashField.testAndSet(h)) { + for (Property *p = properties.first(); p; p = properties.next(p)) { + if (p->name() == name) + return p; + } + } + Property *property = pool()->New(); property->parent = this; property->_name = name; @@ -147,7 +151,10 @@ Property *QDeclarativeParser::Object::getProperty(const QHashedStringRef &name, properties.prepend(property); return property; } else { - return 0; + for (Property *p = properties.first(); p; p = properties.next(p)) { + if (p->name() == name) + return p; + } } } @@ -167,6 +174,7 @@ Property *QDeclarativeParser::Object::getProperty(const QString &name, bool crea Property *property = pool()->New(); property->parent = this; property->_name = QStringRef(pool()->NewString(name)); + propertiesHashField.testAndSet(property->_name.hash()); property->isDefault = false; properties.prepend(property); return property; diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h index 86b06de..d7af045 100644 --- a/src/declarative/qml/qdeclarativeparser_p.h +++ b/src/declarative/qml/qdeclarativeparser_p.h @@ -69,6 +69,7 @@ #include #include #include +#include QT_BEGIN_HEADER @@ -327,6 +328,7 @@ namespace QDeclarativeParser typedef QFieldList MainPropertyList; MainPropertyList properties; + QHashField propertiesHashField; // Output of the compilation phase (these properties continue to exist // in either the defaultProperty or properties members too)