Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qlinkedstringhash_p.h
Go to the documentation of this file.
1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
4
5#ifndef QLINKEDSTRINGHASH_P_H
6#define QLINKEDSTRINGHASH_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <private/qstringhash_p.h>
20
21QT_BEGIN_NAMESPACE
22
23template<class T>
24class QLinkedStringHash : private QStringHash<T>
25{
26public:
27 using typename QStringHash<T>::Node;
28 using typename QStringHash<T>::NewedNode;
29 using typename QStringHash<T>::ReservedNodePool;
30 using typename QStringHash<T>::mapped_type;
31
32 using ConstIteratorData = QStringHashData::IteratorData<const QLinkedStringHash>;
33 using ConstIterator = typename QStringHash<T>::template Iterator<ConstIteratorData, const T>;
34
35 void linkAndReserve(const QLinkedStringHash<T> &other, int additionalReserve)
36 {
37 clear();
38
39 if (other.count()) {
40 data.size = other.data.size;
41 data.rehashToSize(other.count() + additionalReserve);
42
43 if (data.numBuckets == other.data.numBuckets) {
44 nodePool = new ReservedNodePool;
45 nodePool->count = additionalReserve;
46 nodePool->used = 0;
47 nodePool->nodes = new Node[additionalReserve];
48
49 for (int ii = 0; ii < data.numBuckets; ++ii)
50 data.buckets[ii] = (Node *)other.data.buckets[ii];
51
52 link = &other;
53 return;
54 }
55
56 data.size = 0;
57 }
58
59 data.numBits = other.data.numBits;
60 reserve(other.count() + additionalReserve);
61 copy(other);
62 }
63
64 inline bool isLinked() const
65 {
66 return link != 0;
67 }
68
69 void clear()
70 {
71 QStringHash<T>::clear();
72 link = nullptr;
73 }
74
75 template<typename K>
76 void insert(const K &key, const T &value)
77 {
78 // If this is a linked hash, we can't rely on owning the node, so we always
79 // create a new one.
80 Node *n = link ? nullptr : QStringHash<T>::findNode(key);
81 if (n)
82 n->value = value;
83 else
84 QStringHash<T>::createNode(key, value);
85 }
86
87 template<typename K>
88 inline ConstIterator find(const K &key) const
89 {
90 return iterator(QStringHash<T>::findNode(key));
91 }
92
93 ConstIterator begin() const
94 {
95 return ConstIterator(
96 QStringHash<T>::template iterateFirst<const QLinkedStringHash<T>,
97 ConstIteratorData>(this));
98 }
99
100 ConstIterator end() const { return ConstIterator(); }
101
102 inline T *value(const ConstIterator &iter) { return value(iter.node()->key()); }
103
104 using QStringHash<T>::value;
105 using QStringHash<T>::reserve;
106 using QStringHash<T>::copy;
107
108protected:
109 friend QStringHash<T>;
110 using QStringHash<T>::data;
111 using QStringHash<T>::nodePool;
112
113 using QStringHash<T>::createNode;
114
115 inline ConstIteratorData iterateFirst() const
116 {
117 const ConstIteratorData rv
118 = QStringHash<T>::template iterateFirst<const QLinkedStringHash<T>,
119 ConstIteratorData>(this);
120 return (rv.n == nullptr && link) ? link->iterateFirst() : rv;
121 }
122
123 static inline ConstIteratorData iterateNext(const ConstIteratorData &d)
124 {
125 const QLinkedStringHash<T> *self = d.p;
126 const ConstIteratorData rv = QStringHash<T>::iterateNext(d);
127 return (rv.n == nullptr && self->link) ? self->link->iterateFirst() : rv;
128 }
129
130 inline ConstIterator iterator(Node *n) const
131 {
132 if (!n)
133 return ConstIterator();
134
135 const QLinkedStringHash<T> *container = this;
136
137 if (link) {
138 // This node could be in the linked hash
139 if ((n >= nodePool->nodes) && (n < (nodePool->nodes + nodePool->used))) {
140 // The node is in this hash
141 } else if ((n >= link->nodePool->nodes)
142 && (n < (link->nodePool->nodes + link->nodePool->used))) {
143 // The node is in the linked hash
144 container = link;
145 } else {
146 const NewedNode *ln = link->newedNodes;
147 while (ln) {
148 if (ln == n) {
149 // This node is in the linked hash's newed list
150 container = link;
151 break;
152 }
153 ln = ln->nextNewed;
154 }
155 }
156 }
157
158
159 ConstIteratorData rv;
160 rv.n = n;
161 rv.p = container;
162 return ConstIterator(rv);
163 }
164
165 const QLinkedStringHash<T> *link = nullptr;
166};
167
168template<class T>
170{
171public:
173
174 template<typename K>
175 inline void insert(const K &key, const T &value)
176 {
177 // Always create a new node
178 QLinkedStringHash<T>::createNode(key, value);
179 }
180
181 inline void insert(const ConstIterator &iter)
182 {
183 // Always create a new node
184 QLinkedStringHash<T>::createNode(iter.key(), iter.value());
185 }
186
187 inline ConstIterator findNext(const ConstIterator &iter) const
188 {
189 if (auto *node = iter.node()) {
190 QHashedString key(node->key());
191 while ((node = static_cast<typename QLinkedStringHash<T>::Node *>(node->next.data()))) {
192 if (node->equals(key))
193 return QLinkedStringHash<T>::iterator(node);
194 }
195 }
196
197 return ConstIterator();
198 }
199};
200
201QT_END_NAMESPACE
202
203#endif // QLINKEDSTRINGHASH_P_H
ConstIterator findNext(const ConstIterator &iter) const
void insert(const K &key, const T &value)
void insert(const ConstIterator &iter)