1// Copyright (C) 2020 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
4#include "qresultstore.h"
5
6QT_BEGIN_NAMESPACE
7
8namespace QtPrivate {
9
10/*!
11 \internal
12
13 Finds result in \a store by \a index
14 */
15static ResultIteratorBase findResult(const QMap<int, ResultItem> &store, int index)
16{
17 if (store.isEmpty())
18 return ResultIteratorBase(store.end());
19 QMap<int, ResultItem>::const_iterator it = store.lowerBound(key: index);
20
21 // lowerBound returns either an iterator to the result or an iterator
22 // to the nearest greater index. If the latter happens it might be
23 // that the result is stored in a vector at the previous index.
24 if (it == store.end()) {
25 --it;
26 if (it.value().isVector() == false) {
27 return ResultIteratorBase(store.end());
28 }
29 } else {
30 if (it.key() > index) {
31 if (it == store.begin())
32 return ResultIteratorBase(store.end());
33 --it;
34 }
35 }
36
37 const int vectorIndex = index - it.key();
38
39 if (vectorIndex >= it.value().count())
40 return ResultIteratorBase(store.end());
41 else if (it.value().isVector() == false && vectorIndex != 0)
42 return ResultIteratorBase(store.end());
43 return ResultIteratorBase(it, vectorIndex);
44}
45
46/*!
47 \class QtPrivate::ResultItem
48 \internal
49 */
50
51/*!
52 \class QtPrivate::ResultIteratorBase
53 \internal
54 */
55
56/*!
57 \class QtPrivate::ResultStoreBase
58 \internal
59 */
60
61ResultIteratorBase::ResultIteratorBase()
62 : mapIterator(QMap<int, ResultItem>::const_iterator()), m_vectorIndex(0) { }
63ResultIteratorBase::ResultIteratorBase(QMap<int, ResultItem>::const_iterator _mapIterator, int _vectorIndex)
64 : mapIterator(_mapIterator), m_vectorIndex(_vectorIndex) { }
65
66int ResultIteratorBase::vectorIndex() const { return m_vectorIndex; }
67int ResultIteratorBase::resultIndex() const { return mapIterator.key() + m_vectorIndex; }
68
69ResultIteratorBase ResultIteratorBase::operator++()
70{
71 if (canIncrementVectorIndex()) {
72 ++m_vectorIndex;
73 } else {
74 ++mapIterator;
75 m_vectorIndex = 0;
76 }
77 return *this;
78}
79
80int ResultIteratorBase::batchSize() const
81{
82 return mapIterator.value().count();
83}
84
85void ResultIteratorBase::batchedAdvance()
86{
87 ++mapIterator;
88 m_vectorIndex = 0;
89}
90
91bool ResultIteratorBase::isVector() const
92{
93 return mapIterator.value().isVector();
94}
95
96bool ResultIteratorBase::canIncrementVectorIndex() const
97{
98 return (m_vectorIndex + 1 < mapIterator.value().m_count);
99}
100
101bool ResultIteratorBase::isValid() const
102{
103 return mapIterator.value().isValid();
104}
105
106ResultStoreBase::ResultStoreBase()
107 : insertIndex(0), resultCount(0), m_filterMode(false), filteredResults(0) { }
108
109ResultStoreBase::~ResultStoreBase()
110{
111 // QFutureInterface's dtor must delete the contents of m_results.
112 Q_ASSERT(m_results.isEmpty());
113}
114
115void ResultStoreBase::setFilterMode(bool enable)
116{
117 m_filterMode = enable;
118}
119
120bool ResultStoreBase::filterMode() const
121{
122 return m_filterMode;
123}
124
125void ResultStoreBase::syncResultCount()
126{
127 ResultIteratorBase it = resultAt(index: resultCount);
128 while (it != end()) {
129 resultCount += it.batchSize();
130 it = resultAt(index: resultCount);
131 }
132}
133
134void ResultStoreBase::insertResultItemIfValid(int index, ResultItem &resultItem)
135{
136 if (resultItem.isValid()) {
137 m_results[index] = resultItem;
138 syncResultCount();
139 } else {
140 filteredResults += resultItem.count();
141 }
142}
143
144int ResultStoreBase::insertResultItem(int index, ResultItem &resultItem)
145{
146 int storeIndex;
147 if (m_filterMode && index != -1 && index > insertIndex) {
148 pendingResults[index] = resultItem;
149 storeIndex = index;
150 } else {
151 storeIndex = updateInsertIndex(index, count: resultItem.count());
152 insertResultItemIfValid(index: storeIndex - filteredResults, resultItem);
153 }
154 syncPendingResults();
155 return storeIndex;
156}
157
158bool ResultStoreBase::containsValidResultItem(int index) const
159{
160 // index might refer to either visible or pending result
161 const bool inPending = m_filterMode && index != -1 && index > insertIndex;
162 const auto &store = inPending ? pendingResults : m_results;
163 auto it = findResult(store, index);
164 return it != ResultIteratorBase(store.end()) && it.isValid();
165}
166
167void ResultStoreBase::syncPendingResults()
168{
169 // check if we can insert any of the pending results:
170 QMap<int, ResultItem>::iterator it = pendingResults.begin();
171 while (it != pendingResults.end()) {
172 int index = it.key();
173 if (index != resultCount + filteredResults)
174 break;
175
176 ResultItem result = it.value();
177 insertResultItemIfValid(index: index - filteredResults, resultItem&: result);
178 pendingResults.erase(it);
179 it = pendingResults.begin();
180 }
181}
182
183int ResultStoreBase::addResult(int index, const void *result)
184{
185 ResultItem resultItem(result, 0); // 0 means "not a vector"
186 return insertResultItem(index, resultItem);
187}
188
189int ResultStoreBase::addResults(int index, const void *results, int vectorSize, int totalCount)
190{
191 if (m_filterMode == false || vectorSize == totalCount) {
192 Q_ASSERT(vectorSize != 0);
193 ResultItem resultItem(results, vectorSize);
194 return insertResultItem(index, resultItem);
195 } else {
196 if (vectorSize > 0) {
197 ResultItem filteredIn(results, vectorSize);
198 insertResultItem(index, resultItem&: filteredIn);
199 }
200 ResultItem filteredAway(nullptr, totalCount - vectorSize);
201 return insertResultItem(index: index + vectorSize, resultItem&: filteredAway);
202 }
203}
204
205ResultIteratorBase ResultStoreBase::begin() const
206{
207 return ResultIteratorBase(m_results.begin());
208}
209
210ResultIteratorBase ResultStoreBase::end() const
211{
212 return ResultIteratorBase(m_results.end());
213}
214
215bool ResultStoreBase::hasNextResult() const
216{
217 return begin() != end();
218}
219
220ResultIteratorBase ResultStoreBase::resultAt(int index) const
221{
222 return findResult(store: m_results, index);
223}
224
225bool ResultStoreBase::contains(int index) const
226{
227 return (resultAt(index) != end());
228}
229
230int ResultStoreBase::count() const
231{
232 return resultCount;
233}
234
235// returns the insert index, calling this function with
236// index equal to -1 returns the next available index.
237int ResultStoreBase::updateInsertIndex(int index, int _count)
238{
239 if (index == -1) {
240 index = insertIndex;
241 insertIndex += _count;
242 } else {
243 insertIndex = qMax(a: index + _count, b: insertIndex);
244 }
245 return index;
246}
247
248} // namespace QtPrivate
249
250QT_END_NAMESPACE
251

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtbase/src/corelib/thread/qresultstore.cpp