/**************************************************************************** ** ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** 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 "coreconstants.h" #include #include #include #include #include namespace Core { /*! \class Core::Id \brief The class Id encapsulates an identifier. It is used as a type-safe helper class instead of a \c QString or \c QByteArray. The internal representation of the id is assumed to be plain 7-bit-clean ASCII. */ class StringHolder { public: explicit StringHolder(const char *s) : str(s) { n = strlen(s); int m = n; h = 0; while (m--) { 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 && strcmp(sh1.str, sh1.str) == 0; } static uint qHash(const StringHolder &sh) { return sh.h; } struct IdCache : public QHash { #ifndef QTC_ALLOW_STATIC_LEAKS ~IdCache() { for (IdCache::iterator it = begin(); it != end(); ++it) delete[](const_cast(it.key().str)); } #endif }; static int lastUid = 0; static QVector stringFromId; static IdCache idFromString; static int theId(const char *str) { QTC_ASSERT(str && *str, return 0); StringHolder sh(str); int res = idFromString.value(sh, 0); if (res == 0) { if (lastUid == 0) stringFromId.append(QByteArray()); res = ++lastUid; sh.str = qstrdup(sh.str); idFromString[sh] = res; stringFromId.append(QByteArray::fromRawData(sh.str, sh.n)); } return res; } Id::Id(const char *name) : m_id(theId(name)) {} Id::Id(const QString &name) : m_id(theId(name.toUtf8())) {} QByteArray Id::name() const { return stringFromId.at(m_id); } QString Id::toString() const { return QString::fromUtf8(stringFromId.at(m_id)); } bool Id::operator==(const char *name) const { return strcmp(stringFromId.at(m_id).constData(), name) == 0; } // For debugging purposes CORE_EXPORT const char *nameForId(int id) { return (stringFromId.constData() + id)->constData(); } } // namespace Core