aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/corelib/tools/id.cpp
diff options
context:
space:
mode:
authorChristian Kandeler <christian.kandeler@digia.com>2014-01-09 17:50:40 +0100
committerJoerg Bornemann <joerg.bornemann@digia.com>2014-01-10 18:11:22 +0100
commit81af9acaa295a574c1cb5e6714725197dac7f530 (patch)
treecc8c94467f49a7d267e5249f624874feecc7eed4 /src/lib/corelib/tools/id.cpp
parent2fe25eb3f20ffb4e58cb559f2bcb9950c963290a (diff)
Move Qt profile setup into a dedicated library.
Otherwise all changes to the implementation will have to be duplicated in IDEs. Change-Id: I61e6d4fa1ee9b724eb5d9de9f233dc915a6c8bc3 Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Diffstat (limited to 'src/lib/corelib/tools/id.cpp')
-rw-r--r--src/lib/corelib/tools/id.cpp324
1 files changed, 324 insertions, 0 deletions
diff --git a/src/lib/corelib/tools/id.cpp b/src/lib/corelib/tools/id.cpp
new file mode 100644
index 000000000..a9dc07cbc
--- /dev/null
+++ b/src/lib/corelib/tools/id.cpp
@@ -0,0 +1,324 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the Qt Build Suite.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "id.h"
+#include "qbsassert.h"
+
+#include <QByteArray>
+#include <QHash>
+#include <QVector>
+
+namespace qbs {
+namespace Internal {
+
+/*!
+ \class qbs::Internal::Id
+
+ \brief The class Id encapsulates an identifier that is unique
+ within a specific running process, using the qbs library.
+
+ \c{Id} is used as facility to identify objects of interest
+ in a more typesafe and faster manner than a plain \c QString or
+ \c QByteArray would provide.
+
+ An id is internally represented as a 32 bit integer (its \c UID)
+ and associated with a plain 7-bit-clean ASCII name used
+ for display and persistency.
+
+ This class is copied from Qt Creator.
+*/
+
+class StringHolder
+{
+public:
+ StringHolder()
+ : n(0), str(0)
+ {}
+
+ StringHolder(const char *s, int length)
+ : n(length), str(s)
+ {
+ if (!n)
+ length = n = qstrlen(s);
+ h = 0;
+ while (length--) {
+ h = (h << 4) + *s++;
+ h ^= (h & 0xf0000000) >> 23;
+ h &= 0x0fffffff;
+ }
+ }
+ int n;
+ const char *str;
+ uint h;
+};
+
+static bool operator==(const StringHolder &sh1, const StringHolder &sh2)
+{
+ // sh.n is unlikely to discriminate better than the hash.
+ return sh1.h == sh2.h && sh1.str && sh2.str && strcmp(sh1.str, sh2.str) == 0;
+}
+
+
+static uint qHash(const StringHolder &sh)
+{
+ return sh.h;
+}
+
+struct IdCache : public QHash<StringHolder, int>
+{
+#ifndef QBS_ALLOW_STATIC_LEAKS
+ ~IdCache()
+ {
+ for (IdCache::iterator it = begin(); it != end(); ++it)
+ delete[](const_cast<char *>(it.key().str));
+ }
+#endif
+};
+
+
+static int firstUnusedId = Id::IdsPerPlugin * Id::ReservedPlugins;
+
+static QHash<int, StringHolder> stringFromId;
+static IdCache idFromString;
+
+static int theId(const char *str, int n = 0)
+{
+ QBS_ASSERT(str && *str, return 0);
+ StringHolder sh(str, n);
+ int res = idFromString.value(sh, 0);
+ if (res == 0) {
+ res = firstUnusedId++;
+ sh.str = qstrdup(sh.str);
+ idFromString[sh] = res;
+ stringFromId[res] = sh;
+ }
+ return res;
+}
+
+static int theId(const QByteArray &ba)
+{
+ return theId(ba.constData(), ba.size());
+}
+
+/*!
+ \fn qbs::Internal::Id(int uid)
+
+ \brief Constructs an id given a UID.
+
+ The UID is an integer value that is unique within the running
+ process.
+
+ It is the callers responsibility to ensure the uniqueness of
+ the passed integer. The recommended approach is to use
+ \c{registerId()} with an value taken from the plugin's
+ private range.
+
+ \sa registerId()
+
+*/
+
+/*!
+ Constructs an id given its associated name. The internal
+ representation will be unspecified, but consistent within a
+ process.
+
+*/
+Id::Id(const char *name)
+ : m_id(theId(name, 0))
+{}
+
+/*!
+ \overload
+
+*/
+Id::Id(const QByteArray &name)
+ : m_id(theId(name))
+{}
+
+///*!
+// \overload
+// \deprecated
+//*/
+//Id::Id(const QString &name)
+// : m_id(theId(name.toUtf8()))
+//{}
+
+/*!
+ Returns an internal representation of the id.
+*/
+
+QByteArray Id::name() const
+{
+ return stringFromId.value(m_id).str;
+}
+
+/*!
+ Returns a string representation of the id suitable
+ for UI display.
+
+ This should not be used to create a persistent version
+ of the Id, use \c{toSetting()} instead.
+
+ \sa fromString(), toSetting()
+*/
+
+QString Id::toString() const
+{
+ return QString::fromUtf8(stringFromId.value(m_id).str);
+}
+
+/*!
+ Creates an id from a string representation.
+
+ This should not be used to handle a persistent version
+ of the Id, use \c{fromSetting()} instead.
+
+ \deprecated
+
+ \sa toString(), fromSetting()
+*/
+
+Id Id::fromString(const QString &name)
+{
+ return Id(theId(name.toUtf8()));
+}
+
+/*!
+ Creates an id from a string representation.
+
+ This should not be used to handle a persistent version
+ of the Id, use \c{fromSetting()} instead.
+
+ \deprecated
+
+ \sa toString(), fromSetting()
+*/
+
+Id Id::fromName(const QByteArray &name)
+{
+ return Id(theId(name));
+}
+
+/*!
+ Returns a persistent value representing the id which is
+ suitable to be stored in QSettings.
+
+ \sa fromSetting()
+*/
+
+QVariant Id::toSetting() const
+{
+ return QVariant(QString::fromUtf8(stringFromId.value(m_id).str));
+}
+
+/*!
+ Reconstructs an id from a persistent value.
+
+ \sa toSetting()
+*/
+
+Id Id::fromSetting(const QVariant &variant)
+{
+ const QByteArray ba = variant.toString().toUtf8();
+ if (ba.isEmpty())
+ return Id();
+ return Id(theId(ba));
+}
+
+/*!
+ Constructs a derived id.
+
+ This can be used to construct groups of ids logically
+ belonging together. The associated internal name
+ will be generated by appending \c{suffix}.
+*/
+
+Id Id::withSuffix(int suffix) const
+{
+ const QByteArray ba = name() + QByteArray::number(suffix);
+ return Id(ba.constData());
+}
+
+/*!
+ \overload
+*/
+
+Id Id::withSuffix(const char *suffix) const
+{
+ const QByteArray ba = name() + suffix;
+ return Id(ba.constData());
+}
+
+/*!
+ Constructs a derived id.
+
+ This can be used to construct groups of ids logically
+ belonging together. The associated internal name
+ will be generated by prepending \c{prefix}.
+*/
+
+Id Id::withPrefix(const char *prefix) const
+{
+ const QByteArray ba = prefix + name();
+ return Id(ba.constData());
+}
+
+
+/*!
+ Associates a id with its uid and its string
+ representation.
+
+ The uid should be taken from the plugin's private range.
+
+ \sa fromSetting()
+*/
+
+void Id::registerId(int uid, const char *name)
+{
+ StringHolder sh(name, 0);
+ idFromString[sh] = uid;
+ stringFromId[uid] = sh;
+}
+
+bool Id::operator==(const char *name) const
+{
+ const char *string = stringFromId.value(m_id).str;
+ if (string && name)
+ return strcmp(string, name) == 0;
+ else
+ return false;
+}
+
+bool Id::alphabeticallyBefore(Id other) const
+{
+ return toString().compare(other.toString(), Qt::CaseInsensitive) < 0;
+}
+
+} // namespace Internal
+} // namespace qbs