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
qjslist.h
Go to the documentation of this file.
1// Copyright (C) 2023 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 QJSLIST_H
6#define QJSLIST_H
7
8#include <QtQml/qtqmlglobal.h>
9#include <QtQml/qqmllist.h>
10#include <QtQml/qjsengine.h>
11#include <QtCore/qobject.h>
12#include <QtCore/qstring.h>
13
14#include <algorithm>
15
16//
17// W A R N I N G
18// -------------
19//
20// This file is not part of the Qt API. It exists purely as an
21// implementation detail. This header file may change from version to
22// version. It will be kept compatible with the intended usage by
23// code generated using qmlcachegen.
24//
25// We mean it.
26//
27
28QT_BEGIN_NAMESPACE
29
30struct QJSListIndexClamp
31{
32 static qsizetype clamp(qsizetype start, qsizetype max, qsizetype min = 0)
33 {
34 Q_ASSERT(min >= 0);
35 Q_ASSERT(min <= max);
36 return std::clamp(start < 0 ? max + qsizetype(start) : qsizetype(start), min, max);
37 }
38};
39
40template<typename List, typename Value = typename List::value_type>
41struct QJSList : private QJSListIndexClamp
42{
44
46
48 {
49 Q_ASSERT(index >= 0 && index < size());
50 return *(m_list->cbegin() + index);
51 }
52
53 qsizetype size() const { return m_list->size(); }
54
56 {
58 }
59
60 bool includes(const Value &value) const
61 {
62 return std::find(m_list->cbegin(), m_list->cend(), value) != m_list->cend();
63 }
64
65 bool includes(const Value &value, qsizetype start) const
66 {
67 return std::find(m_list->cbegin() + clamp(start, m_list->size()), m_list->cend(), value)
68 != m_list->cend();
69 }
70
72 {
74 bool atBegin = true;
75 std::for_each(m_list->cbegin(), m_list->cend(), [&](const Value &value) {
76 if (atBegin)
77 atBegin = false;
78 else
81 });
82 return result;
83 }
84
85 List slice() const
86 {
87 return *m_list;
88 }
90 {
94 return result;
95 }
107
109 {
110 const auto begin = m_list->cbegin();
111 const auto end = m_list->cend();
112 const auto it = std::find(begin, end, value);
113 if (it == end)
114 return -1;
115 const qsizetype result = it - begin;
116 Q_ASSERT(result >= 0);
117 return result;
118 }
120 {
121 const auto begin = m_list->cbegin();
122 const auto end = m_list->cend();
123 const auto it = std::find(begin + clamp(start, m_list->size()), end, value);
124 if (it == end)
125 return -1;
126 const qsizetype result = it - begin;
127 Q_ASSERT(result >= 0);
128 return result;
129 }
130
132 {
133 const auto begin = std::make_reverse_iterator(m_list->cend());
134 const auto end = std::make_reverse_iterator(m_list->cbegin());
135 const auto it = std::find(begin, end, value);
136 return (end - it) - 1;
137 }
139 {
140 const qsizetype size = m_list->size();
141 if (size == 0)
142 return -1;
143
144 // Construct a one-past-end iterator as input.
145 const qsizetype clampedStart = std::min(clamp(start, size), size - 1);
147
148 const auto end = std::make_reverse_iterator(m_list->cbegin());
149 const auto it = std::find(begin, end, value);
150 return (end - it) - 1;
151 }
152
153 QString toString() const { return join(); }
154
155private:
156 List *m_list = nullptr;
157 QJSEngine *m_engine = nullptr;
158};
159
160template<>
161struct QJSList<QQmlListProperty<QObject>, QObject *> : private QJSListIndexClamp
162{
163 Q_DISABLE_COPY_MOVE(QJSList)
164
165 QJSList(QQmlListProperty<QObject> *list, QJSEngine *engine) : m_list(list), m_engine(engine) {}
166
167 QObject *at(qsizetype index) const
168 {
169 Q_ASSERT(index >= 0 && index < size());
170 return m_list->at(m_list, index);
171 }
172
173 qsizetype size() const
174 {
175 return m_list->count(m_list);
176 }
177
178 void resize(qsizetype size)
179 {
180 qsizetype current = m_list->count(m_list);
181 if (current < size && m_list->append) {
182 do {
183 m_list->append(m_list, nullptr);
184 } while (++current < size);
185 } else if (current > size && m_list->removeLast) {
186 do {
187 m_list->removeLast(m_list);
188 } while (--current > size);
189 }
190 }
191
192 bool includes(const QObject *value) const
193 {
194 if (!m_list->count || !m_list->at)
195 return false;
196
197 const qsizetype size = m_list->count(m_list);
198 for (qsizetype i = 0; i < size; ++i) {
199 if (m_list->at(m_list, i) == value)
200 return true;
201 }
202
203 return false;
204 }
205 bool includes(const QObject *value, qsizetype start) const
206 {
207 if (!m_list->count || !m_list->at)
208 return false;
209
210 const qsizetype size = m_list->count(m_list);
211 for (qsizetype i = clamp(start, size); i < size; ++i) {
212 if (m_list->at(m_list, i) == value)
213 return true;
214 }
215
216 return false;
217 }
218
219 QString join(const QString &separator = QStringLiteral(",")) const
220 {
221 QString result;
222 if (!m_list->count || !m_list->at)
223 return result;
224
225 for (qsizetype i = 0, end = m_list->count(m_list); i < end; ++i) {
226 if (i != 0)
227 result += separator;
228 result += m_engine->coerceValue<QObject *, QString>(m_list->at(m_list, i));
229 }
230
231 return result;
232 }
233
234 QObjectList slice() const
235 {
236 return m_list->toList<QObjectList>();
237 }
238 QObjectList slice(qsizetype start) const
239 {
240 QObjectList result;
241 if (!m_list->count || !m_list->at)
242 return result;
243
244 const qsizetype size = m_list->count(m_list);
245 const qsizetype clampedStart = clamp(start, size);
246 result.reserve(size - clampedStart);
247 for (qsizetype i = clampedStart; i < size; ++i)
248 result.append(m_list->at(m_list, i));
249 return result;
250 }
251 QObjectList slice(qsizetype start, qsizetype end) const
252 {
253 QObjectList result;
254 if (!m_list->count || !m_list->at)
255 return result;
256
257 const qsizetype size = m_list->count(m_list);
258 const qsizetype clampedStart = clamp(start, size);
259 const qsizetype clampedEnd = clamp(end, size, clampedStart);
260 result.reserve(clampedEnd - clampedStart);
261 for (qsizetype i = clampedStart; i < clampedEnd; ++i)
262 result.append(m_list->at(m_list, i));
263 return result;
264 }
265
266 qsizetype indexOf(const QObject *value) const
267 {
268 if (!m_list->count || !m_list->at)
269 return -1;
270
271 const qsizetype end = m_list->count(m_list);
272 for (qsizetype i = 0; i < end; ++i) {
273 if (m_list->at(m_list, i) == value)
274 return i;
275 }
276 return -1;
277 }
278 qsizetype indexOf(const QObject *value, qsizetype start) const
279 {
280 if (!m_list->count || !m_list->at)
281 return -1;
282
283 const qsizetype size = m_list->count(m_list);
284 for (qsizetype i = clamp(start, size); i < size; ++i) {
285 if (m_list->at(m_list, i) == value)
286 return i;
287 }
288 return -1;
289 }
290
291 qsizetype lastIndexOf(const QObject *value) const
292 {
293 if (!m_list->count || !m_list->at)
294 return -1;
295
296 for (qsizetype i = m_list->count(m_list) - 1; i >= 0; --i) {
297 if (m_list->at(m_list, i) == value)
298 return i;
299 }
300 return -1;
301 }
302 qsizetype lastIndexOf(const QObject *value, qsizetype start) const
303 {
304 if (!m_list->count || !m_list->at)
305 return -1;
306
307 const qsizetype size = m_list->count(m_list);
308 if (size == 0)
309 return -1;
310
311 qsizetype clampedStart = std::min(clamp(start, size), size - 1);
312 for (qsizetype i = clampedStart; i >= 0; --i) {
313 if (m_list->at(m_list, i) == value)
314 return i;
315 }
316 return -1;
317 }
318
319 QString toString() const { return join(); }
320
321private:
322 QQmlListProperty<QObject> *m_list = nullptr;
323 QJSEngine *m_engine = nullptr;
324};
325
327{
328public:
330 template<typename List, typename Value>
331 void init(const QJSList<List, Value> &list)
332 {
333 m_index = 0;
334 m_size = list.size();
335 }
336
337 bool hasNext() const { return m_index < m_size; }
338 qsizetype next() { return m_index++; }
339
340private:
341 qsizetype m_index;
342 qsizetype m_size;
343};
344
345// QJSListForInIterator must not require initialization so that we can jump over it with goto.
346static_assert(std::is_trivial_v<QJSListForInIterator>);
347
349{
350public:
352 void init() { m_index = 0; }
353
354 template<typename List, typename Value>
355 bool hasNext(const QJSList<List, Value> &list) const { return m_index < list.size(); }
356
357 template<typename List, typename Value>
358 Value next(const QJSList<List, Value> &list) { return list.at(m_index++); }
359
360private:
361 qsizetype m_index;
362};
363
364// QJSListForOfIterator must not require initialization so that we can jump over it with goto.
365static_assert(std::is_trivial_v<QJSListForOfIterator>);
366
367QT_END_NAMESPACE
368
369#endif // QJSLIST_H
bool hasNext() const
Definition qjslist.h:337
void init(const QJSList< List, Value > &list)
Definition qjslist.h:331
QJSListForInIterator * Ptr
Definition qjslist.h:329
qsizetype next()
Definition qjslist.h:338
QJSListForOfIterator * Ptr
Definition qjslist.h:351
Value next(const QJSList< List, Value > &list)
Definition qjslist.h:358
bool hasNext(const QJSList< List, Value > &list) const
Definition qjslist.h:355