1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qresultstore.h"
41
42QT_BEGIN_NAMESPACE
43
44namespace QtPrivate {
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::operator==(const ResultIteratorBase &other) const
92{
93 return (mapIterator == other.mapIterator && m_vectorIndex == other.m_vectorIndex);
94}
95
96bool ResultIteratorBase::operator!=(const ResultIteratorBase &other) const
97{
98 return !operator==(other);
99}
100
101bool ResultIteratorBase::isVector() const
102{
103 return mapIterator.value().isVector();
104}
105
106bool ResultIteratorBase::canIncrementVectorIndex() const
107{
108 return (m_vectorIndex + 1 < mapIterator.value().m_count);
109}
110
111ResultStoreBase::ResultStoreBase()
112 : insertIndex(0), resultCount(0), m_filterMode(false), filteredResults(0) { }
113
114ResultStoreBase::~ResultStoreBase()
115{
116 // QFutureInterface's dtor must delete the contents of m_results.
117 Q_ASSERT(m_results.isEmpty());
118}
119
120void ResultStoreBase::setFilterMode(bool enable)
121{
122 m_filterMode = enable;
123}
124
125bool ResultStoreBase::filterMode() const
126{
127 return m_filterMode;
128}
129
130void ResultStoreBase::syncResultCount()
131{
132 ResultIteratorBase it = resultAt(index: resultCount);
133 while (it != end()) {
134 resultCount += it.batchSize();
135 it = resultAt(index: resultCount);
136 }
137}
138
139void ResultStoreBase::insertResultItemIfValid(int index, ResultItem &resultItem)
140{
141 if (resultItem.isValid()) {
142 m_results[index] = resultItem;
143 syncResultCount();
144 } else {
145 filteredResults += resultItem.count();
146 }
147}
148
149int ResultStoreBase::insertResultItem(int index, ResultItem &resultItem)
150{
151 int storeIndex;
152 if (m_filterMode && index != -1 && index > insertIndex) {
153 pendingResults[index] = resultItem;
154 storeIndex = index;
155 } else {
156 storeIndex = updateInsertIndex(index, count: resultItem.count());
157 insertResultItemIfValid(index: storeIndex - filteredResults, resultItem);
158 }
159 syncPendingResults();
160 return storeIndex;
161}
162
163void ResultStoreBase::syncPendingResults()
164{
165 // check if we can insert any of the pending results:
166 QMap<int, ResultItem>::iterator it = pendingResults.begin();
167 while (it != pendingResults.end()) {
168 int index = it.key();
169 if (index != resultCount + filteredResults)
170 break;
171
172 ResultItem result = it.value();
173 insertResultItemIfValid(index: index - filteredResults, resultItem&: result);
174 pendingResults.erase(it);
175 it = pendingResults.begin();
176 }
177}
178
179int ResultStoreBase::addResult(int index, const void *result)
180{
181 ResultItem resultItem(result, 0); // 0 means "not a vector"
182 return insertResultItem(index, resultItem);
183}
184
185int ResultStoreBase::addResults(int index, const void *results, int vectorSize, int totalCount)
186{
187 if (m_filterMode == false || vectorSize == totalCount) {
188 Q_ASSERT(vectorSize != 0);
189 ResultItem resultItem(results, vectorSize);
190 return insertResultItem(index, resultItem);
191 } else {
192 if (vectorSize > 0) {
193 ResultItem filteredIn(results, vectorSize);
194 insertResultItem(index, resultItem&: filteredIn);
195 }
196 ResultItem filteredAway(nullptr, totalCount - vectorSize);
197 return insertResultItem(index: index + vectorSize, resultItem&: filteredAway);
198 }
199}
200
201ResultIteratorBase ResultStoreBase::begin() const
202{
203 return ResultIteratorBase(m_results.begin());
204}
205
206ResultIteratorBase ResultStoreBase::end() const
207{
208 return ResultIteratorBase(m_results.end());
209}
210
211bool ResultStoreBase::hasNextResult() const
212{
213 return begin() != end();
214}
215
216ResultIteratorBase ResultStoreBase::resultAt(int index) const
217{
218 if (m_results.isEmpty())
219 return ResultIteratorBase(m_results.end());
220 QMap<int, ResultItem>::const_iterator it = m_results.lowerBound(akey: index);
221
222 // lowerBound returns either an iterator to the result or an iterator
223 // to the nearest greater index. If the latter happens it might be
224 // that the result is stored in a vector at the previous index.
225 if (it == m_results.end()) {
226 --it;
227 if (it.value().isVector() == false) {
228 return ResultIteratorBase(m_results.end());
229 }
230 } else {
231 if (it.key() > index) {
232 if (it == m_results.begin())
233 return ResultIteratorBase(m_results.end());
234 --it;
235 }
236 }
237
238 const int vectorIndex = index - it.key();
239
240 if (vectorIndex >= it.value().count())
241 return ResultIteratorBase(m_results.end());
242 else if (it.value().isVector() == false && vectorIndex != 0)
243 return ResultIteratorBase(m_results.end());
244 return ResultIteratorBase(it, vectorIndex);
245}
246
247bool ResultStoreBase::contains(int index) const
248{
249 return (resultAt(index) != end());
250}
251
252int ResultStoreBase::count() const
253{
254 return resultCount;
255}
256
257// returns the insert index, calling this function with
258// index equal to -1 returns the next available index.
259int ResultStoreBase::updateInsertIndex(int index, int _count)
260{
261 if (index == -1) {
262 index = insertIndex;
263 insertIndex += _count;
264 } else {
265 insertIndex = qMax(a: index + _count, b: insertIndex);
266 }
267 return index;
268}
269
270} // namespace QtPrivate
271
272QT_END_NAMESPACE
273

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