File indexing completed on 2024-05-12 04:38:03

0001 /*
0002     SPDX-FileCopyrightText: 2006 Hamish Rodda <rodda@kde.org>
0003     SPDX-FileCopyrightText: 2007-2009 David Nolden <david.nolden.kdevelop@art-master.de>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-only
0006 */
0007 
0008 #ifndef KDEVPLATFORM_INDEXEDDUCONTEXT_H
0009 #define KDEVPLATFORM_INDEXEDDUCONTEXT_H
0010 
0011 #include <language/languageexport.h>
0012 #include <language/util/kdevhash.h>
0013 
0014 #include <QPair>
0015 
0016 namespace KDevelop {
0017 class DUContext;
0018 class IndexedTopDUContext;
0019 
0020 /**
0021  * Represents a context only by its global indices
0022  */
0023 class KDEVPLATFORMLANGUAGE_EXPORT IndexedDUContext
0024 {
0025 public:
0026     IndexedDUContext(DUContext* decl);
0027     IndexedDUContext(uint topContext = 0, uint contextIndex = 0);
0028 
0029     ///Duchain must be read locked
0030     DUContext* context() const;
0031 
0032     ///Duchain must be read locked
0033     DUContext* data() const
0034     {
0035         return context();
0036     }
0037 
0038     bool operator==(const IndexedDUContext& rhs) const
0039     {
0040         return m_topContext == rhs.m_topContext && m_contextIndex == rhs.m_contextIndex;
0041     }
0042     uint hash() const
0043     {
0044         return KDevHash() << m_topContext << m_contextIndex;
0045     }
0046 
0047     bool isValid() const
0048     {
0049         return !isDummy() && context() != nullptr;
0050     }
0051 
0052     bool operator<(const IndexedDUContext& rhs) const
0053     {
0054         Q_ASSERT(!isDummy());
0055         return m_topContext < rhs.m_topContext ||
0056                (m_topContext == rhs.m_topContext && m_contextIndex < rhs.m_contextIndex);
0057     }
0058 
0059     //Index within the top-context
0060     uint localIndex() const
0061     {
0062         if (isDummy())
0063             return 0;
0064 
0065         return m_contextIndex;
0066     }
0067 
0068     uint topContextIndex() const
0069     {
0070         return m_topContext;
0071     }
0072 
0073     IndexedTopDUContext indexedTopContext() const;
0074 
0075     /**
0076      * The following functions allow storing 2 integers in this object and marking it as a dummy,
0077      * which makes the isValid() function always return false for this object, and use the integers
0078      * for other purposes
0079      * Clears the contained data
0080      */
0081     void setIsDummy(bool dummy)
0082     {
0083         if (isDummy() == dummy)
0084             return;
0085         if (dummy)
0086             m_topContext = 1 << 31;
0087         else
0088             m_topContext = 0;
0089         m_contextIndex = 0;
0090     }
0091 
0092     bool isDummy() const
0093     {
0094         //We use the second highest bit to mark dummies, because the highest is used for the sign bit of stored
0095         //integers
0096         return ( bool )(m_topContext & (1 << 31));
0097     }
0098 
0099     QPair<uint, uint> dummyData() const
0100     {
0101         Q_ASSERT(isDummy());
0102         return qMakePair(m_topContext & (~(1 << 31)), m_contextIndex);
0103     }
0104 
0105     ///Do not call this when this object is valid. The first integer loses one bit of precision.
0106     void setDummyData(QPair<uint, uint> data)
0107     {
0108         Q_ASSERT(isDummy());
0109 
0110         m_topContext = data.first;
0111         m_contextIndex = data.second;
0112         Q_ASSERT(!isDummy());
0113         m_topContext |= (1 << 31); //Mark as dummy
0114         Q_ASSERT(isDummy());
0115         Q_ASSERT(dummyData() == data);
0116     }
0117 
0118 private:
0119     uint m_topContext;
0120     uint m_contextIndex;
0121 };
0122 
0123 inline uint qHash(const IndexedDUContext& ctx)
0124 {
0125     return ctx.hash();
0126 }
0127 }
0128 
0129 Q_DECLARE_TYPEINFO(KDevelop::IndexedDUContext, Q_MOVABLE_TYPE);
0130 
0131 #endif // KDEVPLATFORM_INDEXEDDUCONTEXT_H