Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qversionnumber.h
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2022 Intel Corporation.
3// Copyright (C) 2015 Keith Gardner <kreios4004@gmail.com>
4// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
5
6#ifndef QVERSIONNUMBER_H
7#define QVERSIONNUMBER_H
8
9#include <QtCore/qcompare.h>
10#include <QtCore/qcontainertools_impl.h>
11#include <QtCore/qlist.h>
12#include <QtCore/qmetatype.h>
13#include <QtCore/qnamespace.h>
14#include <QtCore/qspan.h>
15#include <QtCore/qstring.h>
16#include <QtCore/qtypeinfo.h>
17#if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 2
18#include <QtCore/qtyperevision.h>
19#endif // lean headers level 2
20
22
23class QVersionNumber;
24Q_CORE_EXPORT size_t qHash(const QVersionNumber &key, size_t seed = 0);
25
26#ifndef QT_NO_DATASTREAM
27Q_CORE_EXPORT QDataStream &operator<<(QDataStream &out, const QVersionNumber &version);
28Q_CORE_EXPORT QDataStream &operator>>(QDataStream &in, QVersionNumber &version);
29#endif
30
32{
33 /*
34 * QVersionNumber stores small values inline, without memory allocation.
35 * We do that by setting the LSB in the pointer that would otherwise hold
36 * the longer form of the segments.
37 * The constants below help us deal with the permutations for 32- and 64-bit,
38 * little- and big-endian architectures.
39 */
40 enum {
41 // in little-endian, inline_segments[0] is shared with the pointer's LSB, while
42 // in big-endian, it's inline_segments[7]
43 InlineSegmentMarker = Q_BYTE_ORDER == Q_LITTLE_ENDIAN ? 0 : sizeof(void *) - 1,
44 InlineSegmentStartIdx = !InlineSegmentMarker, // 0 for BE, 1 for LE
45 InlineSegmentCount = sizeof(void *) - 1
46 };
47 static_assert(InlineSegmentCount >= 3); // at least major, minor, micro
48
49 struct SegmentStorage
50 {
51 // Note: we alias the use of dummy and inline_segments in the use of the
52 // union below. This is undefined behavior in C++98, but most compilers implement
53 // the C++11 behavior. The one known exception is older versions of Sun Studio.
54 union {
55 quintptr dummy;
56 qint8 inline_segments[sizeof(void *)];
57 QList<int> *pointer_segments;
58 };
59
60 // set the InlineSegmentMarker and set length to zero
61 SegmentStorage() noexcept : dummy(1) {}
62
63 SegmentStorage(const QList<int> &seg)
64 {
65 if (dataFitsInline(seg.data(), seg.size()))
66 setInlineData(seg.data(), seg.size());
67 else
68 setListData(seg);
69 }
70
71 Q_CORE_EXPORT void setListData(const QList<int> &seg);
72
73 SegmentStorage(const SegmentStorage &other)
74 {
75 if (other.isUsingPointer())
76 setListData(*other.pointer_segments);
77 else
78 dummy = other.dummy;
79 }
80
81 SegmentStorage &operator=(const SegmentStorage &other)
82 {
83 if (isUsingPointer() && other.isUsingPointer()) {
84 *pointer_segments = *other.pointer_segments;
85 } else if (other.isUsingPointer()) {
86 setListData(*other.pointer_segments);
87 } else {
88 if (isUsingPointer())
89 delete pointer_segments;
90 dummy = other.dummy;
91 }
92 return *this;
93 }
94
95 SegmentStorage(SegmentStorage &&other) noexcept
96 : dummy(other.dummy)
97 {
98 other.dummy = 1;
99 }
100
101 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(SegmentStorage)
102
103 void swap(SegmentStorage &other) noexcept
104 {
105 std::swap(dummy, other.dummy);
106 }
107
108 explicit SegmentStorage(QList<int> &&seg)
109 {
110 if (dataFitsInline(std::as_const(seg).data(), seg.size()))
111 setInlineData(std::as_const(seg).data(), seg.size());
112 else
113 setListData(std::move(seg));
114 }
115
116 Q_CORE_EXPORT void setListData(QList<int> &&seg);
117
118 explicit SegmentStorage(QSpan<const int> args)
119 : SegmentStorage(args.begin(), args.end()) {}
120
121 explicit SegmentStorage(const int *first, const int *last)
122 {
123 if (dataFitsInline(first, last - first)) {
124 setInlineData(first, last - first);
125 } else {
126 setListData(first, last);
127 }
128 }
129
130 Q_CORE_EXPORT void setListData(const int *first, const int *last);
131
132 ~SegmentStorage() { if (isUsingPointer()) delete pointer_segments; }
133
134 bool isUsingPointer() const noexcept
135 { return (inline_segments[InlineSegmentMarker] & 1) == 0; }
136
137 qsizetype size() const noexcept
138 { return isUsingPointer() ? pointer_segments->size() : (inline_segments[InlineSegmentMarker] >> 1); }
139
140 void setInlineSize(qsizetype len)
141 {
142 Q_ASSERT(len <= InlineSegmentCount);
143 inline_segments[InlineSegmentMarker] = qint8(1 + 2 * len);
144 }
145
146 Q_CORE_EXPORT void resize(qsizetype len);
147
148 int at(qsizetype index) const
149 {
150 return isUsingPointer() ?
151 pointer_segments->at(index) :
152 inline_segments[InlineSegmentStartIdx + index];
153 }
154
155 void setSegments(int len, int maj, int min = 0, int mic = 0)
156 {
157 if (maj == qint8(maj) && min == qint8(min) && mic == qint8(mic)) {
158 int data[] = { maj, min, mic };
159 setInlineData(data, len);
160 } else {
161 setVector(len, maj, min, mic);
162 }
163 }
164
165 private:
166 static bool dataFitsInline(const int *data, qsizetype len)
167 {
168 if (len > InlineSegmentCount)
169 return false;
170 for (qsizetype i = 0; i < len; ++i)
171 if (data[i] != qint8(data[i]))
172 return false;
173 return true;
174 }
175 void setInlineData(const int *data, qsizetype len)
176 {
177 Q_ASSERT(len <= InlineSegmentCount);
178 dummy = 1 + len * 2;
179#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
180 for (qsizetype i = 0; i < len; ++i)
181 dummy |= quintptr(data[i] & 0xFF) << (8 * (i + 1));
182#elif Q_BYTE_ORDER == Q_BIG_ENDIAN
183 for (qsizetype i = 0; i < len; ++i)
184 dummy |= quintptr(data[i] & 0xFF) << (8 * (sizeof(void *) - i - 1));
185#else
186 // the code above is equivalent to:
187 setInlineSize(len);
188 for (qsizetype i = 0; i < len; ++i)
189 inline_segments[InlineSegmentStartIdx + i] = data[i] & 0xFF;
190#endif
191 }
192
193 Q_CORE_EXPORT void setVector(int len, int maj, int min, int mic);
194 } m_segments;
195
196 class It
197 {
198 const QVersionNumber *v;
199 qsizetype i;
200
201 friend class QVersionNumber;
202 explicit constexpr It(const QVersionNumber *vn, qsizetype idx) noexcept : v(vn), i(idx) {}
203
204 friend constexpr bool comparesEqual(const It &lhs, const It &rhs)
205 { Q_ASSERT(lhs.v == rhs.v); return lhs.i == rhs.i; }
206 friend constexpr Qt::strong_ordering compareThreeWay(const It &lhs, const It &rhs)
207 { Q_ASSERT(lhs.v == rhs.v); return Qt::compareThreeWay(lhs.i, rhs.i); }
209
210 public:
211 // Rule Of Zero applies
212 It() = default;
213
214 using iterator_category = std::random_access_iterator_tag;
215 using value_type = int;
216#ifdef QT_COMPILER_HAS_LWG3346
217 using element_type = const int;
218#endif
219 using difference_type = qptrdiff; // difference to container requirements
220 using size_type = qsizetype; // difference to container requirements
221 using reference = value_type; // difference to container requirements
223
224 reference operator*() const { return v->segmentAt(i); }
225 pointer operator->() const { return {**this}; }
226
227 It &operator++() { ++i; return *this; }
228 It operator++(int) { auto copy = *this; ++*this; return copy; }
229
230 It &operator--() { --i; return *this; }
231 It operator--(int) { auto copy = *this; --*this; return copy; }
232
233 It &operator+=(difference_type n) { i += n; return *this; }
234 friend It operator+(It it, difference_type n) { it += n; return it; }
235 friend It operator+(difference_type n, It it) { return it + n; }
236
237 It &operator-=(difference_type n) { i -= n; return *this; }
238 friend It operator-(It it, difference_type n) { it -= n; return it; }
239
240 friend difference_type operator-(It lhs, It rhs)
241 { Q_ASSERT(lhs.v == rhs.v); return lhs.i - rhs.i; }
242
243 reference operator[](difference_type n) const { return *(*this + n); }
244 };
245
246public:
247 using const_iterator = It;
248 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
249
250 using value_type = It::value_type;
251 using difference_type = It::difference_type;
252 using size_type = It::size_type;
253 using reference = It::reference;
257
258 inline QVersionNumber() noexcept
259 : m_segments()
260 {}
262 inline explicit QVersionNumber(const QList<int> &seg) : m_segments(seg) { }
263
264 // compiler-generated copy/move ctor/assignment operators and the destructor are ok
265
267 explicit QVersionNumber(QList<int> &&seg) : m_segments(std::move(seg)) { }
268
269 inline QVersionNumber(std::initializer_list<int> args)
270 : m_segments(QSpan{args})
271 {}
272
273 explicit QVersionNumber(QSpan<const int> args)
274 : m_segments(args)
275 {}
276
277 inline explicit QVersionNumber(int maj)
278 { m_segments.setSegments(1, maj); }
279
280 inline explicit QVersionNumber(int maj, int min)
281 { m_segments.setSegments(2, maj, min); }
282
283 inline explicit QVersionNumber(int maj, int min, int mic)
284 { m_segments.setSegments(3, maj, min, mic); }
285
286 [[nodiscard]] inline bool isNull() const noexcept
287 { return segmentCount() == 0; }
288
289 [[nodiscard]] inline bool isNormalized() const noexcept
290 { return isNull() || segmentAt(segmentCount() - 1) != 0; }
291
292 [[nodiscard]] inline int majorVersion() const noexcept
293 { return segmentAt(0); }
294
295 [[nodiscard]] inline int minorVersion() const noexcept
296 { return segmentAt(1); }
297
298 [[nodiscard]] inline int microVersion() const noexcept
299 { return segmentAt(2); }
300
301 [[nodiscard]] Q_CORE_EXPORT QVersionNumber normalized() const;
302
303 [[nodiscard]] Q_CORE_EXPORT QList<int> segments() const;
304
305 [[nodiscard]] inline int segmentAt(qsizetype index) const noexcept
306 { return (m_segments.size() > index) ? m_segments.at(index) : 0; }
307
308 [[nodiscard]] inline qsizetype segmentCount() const noexcept
309 { return m_segments.size(); }
310
311 [[nodiscard]] const_iterator begin() const noexcept { return const_iterator{this, 0}; }
312 [[nodiscard]] const_iterator end() const noexcept { return begin() + segmentCount(); }
313 [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); }
314 [[nodiscard]] const_iterator cend() const noexcept { return end(); }
315
316 [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{end()}; }
317 [[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator{begin()}; }
318 [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return rbegin(); }
319 [[nodiscard]] const_reverse_iterator crend() const noexcept { return rend(); }
320
321 [[nodiscard]] const_iterator constBegin() const noexcept { return begin(); }
322 [[nodiscard]] const_iterator constEnd() const noexcept { return end(); }
323
324 [[nodiscard]] Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const noexcept;
325
326 [[nodiscard]] Q_CORE_EXPORT static int compare(const QVersionNumber &v1, const QVersionNumber &v2) noexcept;
327
328 [[nodiscard]] Q_CORE_EXPORT static QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2);
329
330 [[nodiscard]] Q_CORE_EXPORT QString toString() const;
331 [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(QAnyStringView string, qsizetype *suffixIndex = nullptr);
332
333#if QT_DEPRECATED_SINCE(6, 4) && QT_POINTER_SIZE != 4
335 QT_DEPRECATED_VERSION_X_6_4("Use the 'qsizetype *suffixIndex' overload.")
336 [[nodiscard]] static QVersionNumber fromString(QAnyStringView string, int *suffixIndex)
337 {
339 // fromString() writes to *n unconditionally, but GCC can't know that
340 QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized")
341 qsizetype n;
342 auto r = fromString(string, &n);
343 if (suffixIndex) {
344 Q_ASSERT(int(n) == n);
345 *suffixIndex = int(n);
346 }
347 return r;
349 }
350#endif
351
352
353#if QT_CORE_REMOVED_SINCE(6, 4)
354 [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(const QString &string, int *suffixIndex);
355 [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(QLatin1StringView string, int *suffixIndex);
356 [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(QStringView string, int *suffixIndex);
357#endif
358
359private:
360 [[nodiscard]] friend bool comparesEqual(const QVersionNumber &lhs,
361 const QVersionNumber &rhs) noexcept
362 {
363 return compare(lhs, rhs) == 0;
364 }
365 [[nodiscard]] friend Qt::strong_ordering compareThreeWay(const QVersionNumber &lhs,
366 const QVersionNumber &rhs) noexcept
367 {
368 int c = compare(lhs, rhs);
369 return Qt::compareThreeWay(c, 0);
370 }
372
373#ifndef QT_NO_DATASTREAM
374 friend Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version);
375#endif
376 friend Q_CORE_EXPORT size_t qHash(const QVersionNumber &key, size_t seed);
377};
378
380
381#ifndef QT_NO_DEBUG_STREAM
382Q_CORE_EXPORT QDebug operator<<(QDebug, const QVersionNumber &version);
383#endif
384
386
388
389#endif // QVERSIONNUMBER_H
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qdatastream.h:46
\inmodule QtCore
qsizetype size() const noexcept
Definition qlist.h:397
iterator end()
Definition qlist.h:626
const_reference at(qsizetype i) const noexcept
Definition qlist.h:446
iterator begin()
Definition qlist.h:625
Definition qspan.h:315
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\inmodule QtCore
QVersionNumber(std::initializer_list< int > args)
Constructs a version number from the std::initializer_list specified by args.
Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const noexcept
Returns true if the current version number is contained in the other version number,...
friend Q_CORE_EXPORT QDataStream & operator>>(QDataStream &in, QVersionNumber &version)
Reads a version number from stream in and stores it in version.
const_reverse_iterator rend() const noexcept
bool isNull() const noexcept
Returns true if there are zero numerical segments, otherwise returns false.
int minorVersion() const noexcept
Returns the minor version number, that is, the second segment.
friend Qt::strong_ordering compareThreeWay(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
QVersionNumber(QSpan< const int > args)
static Q_CORE_EXPORT QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2)
QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1, ...
const_reverse_iterator crbegin() const noexcept
int majorVersion() const noexcept
Returns the major version number, that is, the first segment.
Q_WEAK_OVERLOAD QVersionNumber(const QList< int > &seg)
Constructs a version number from the list of numbers contained in seg.
It::value_type value_type
QVersionNumber() noexcept
Produces a null version.
It::pointer pointer
const_iterator cbegin() const noexcept
static Q_CORE_EXPORT QVersionNumber fromString(QAnyStringView string, qsizetype *suffixIndex=nullptr)
const_iterator constBegin() const noexcept
const_iterator begin() const noexcept
friend bool comparesEqual(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
const_iterator end() const noexcept
It::reference reference
qsizetype segmentCount() const noexcept
Returns the number of integers stored in segments().
bool isNormalized() const noexcept
Returns true if the version number does not contain any trailing zeros, otherwise returns false.
const_iterator cend() const noexcept
It::difference_type difference_type
const_reverse_iterator rbegin() const noexcept
Q_CORE_EXPORT QString toString() const
Returns a string with all of the segments delimited by a period ({.}).
Q_CORE_EXPORT QVersionNumber normalized() const
Returns an equivalent version number but with all trailing zeros removed.
QVersionNumber(int maj, int min, int mic)
Constructs a QVersionNumber consisting of the major, minor, and micro version numbers maj,...
QVersionNumber(int maj, int min)
Constructs a QVersionNumber consisting of the major and minor version numbers maj and min,...
const_reverse_iterator crend() const noexcept
QVersionNumber(int maj)
Constructs a QVersionNumber consisting of just the major version number maj.
std::reverse_iterator< const_iterator > const_reverse_iterator
int segmentAt(qsizetype index) const noexcept
Returns the segment value at index.
friend Q_CORE_EXPORT size_t qHash(const QVersionNumber &key, size_t seed)
int microVersion() const noexcept
Returns the micro version number, that is, the third segment.
const_iterator constEnd() const noexcept
reference const_reference
static Q_CORE_EXPORT int compare(const QVersionNumber &v1, const QVersionNumber &v2) noexcept
Compares v1 with v2 and returns an integer less than, equal to, or greater than zero,...
Q_WEAK_OVERLOAD QVersionNumber(QList< int > &&seg)
Move-constructs a version number from the list of numbers contained in seg.
It::size_type size_type
\inmodule QtCore \title Classes and helpers for defining comparison operators \keyword qtcompare
Definition qcompare.h:400
QSet< QString >::iterator it
Combined button and popup list for selecting options.
constexpr Qt::strong_ordering compareThreeWay(LeftInt lhs, RightInt rhs) noexcept
static jboolean copy(JNIEnv *, jobject)
#define Q_DECLARE_STRONGLY_ORDERED(...)
#define Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(...)
#define Q_WEAK_OVERLOAD
#define QT_WARNING_POP
#define QT_WARNING_DISABLE_GCC(text)
#define QT_WARNING_PUSH
constexpr timespec operator+(const timespec &t1, const timespec &t2)
constexpr timespec operator*(const timespec &t1, int mul)
constexpr timespec & operator+=(timespec &t1, const timespec &t2)
constexpr timespec operator-(const timespec &t1, const timespec &t2)
bool comparesEqual(const QDir &lhs, const QDir &rhs)
Definition qdir.cpp:1819
#define QT_DECL_METATYPE_EXTERN(TYPE, EXPORT)
Definition qmetatype.h:1388
GLint GLfloat GLfloat GLfloat v2
GLsizei const GLfloat * v
[13]
GLuint64 key
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLfloat GLfloat v1
GLint first
GLfloat n
const GLubyte * c
GLuint in
GLuint segments
GLenum GLsizei len
#define Q_LITTLE_ENDIAN
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QT_DEPRECATED_VERSION_X_6_4(text)
@ Q_RELOCATABLE_TYPE
Definition qtypeinfo.h:158
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS)
Definition qtypeinfo.h:180
size_t quintptr
Definition qtypes.h:167
ptrdiff_t qptrdiff
Definition qtypes.h:164
ptrdiff_t qsizetype
Definition qtypes.h:165
QT_BEGIN_NAMESPACE typedef signed char qint8
Definition qtypes.h:45
Qt::weak_ordering compareThreeWay(const QUrl &lhs, const QUrl &rhs)
Definition qurl.cpp:3079
Q_CORE_EXPORT size_t qHash(const QVersionNumber &key, size_t seed=0)
Q_CORE_EXPORT QDataStream & operator<<(QDataStream &out, const QVersionNumber &version)
Q_CORE_EXPORT QDataStream & operator>>(QDataStream &in, QVersionNumber &version)
if(qFloatDistance(a, b)<(1<< 7))
[0]
QTextStream out(stdout)
[7]
QSharedPointer< T > other(t)
[5]
QAction * at
QJSValueList args