Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qversionnumber.cpp
Go to the documentation of this file.
1
// Copyright (C) 2021 The Qt Company Ltd.
2
// Copyright (C) 2016 Intel Corporation.
3
// Copyright (C) 2014 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
// Qt-Security score:critical reason:data-parser
6
7
#
include
<
QtCore
/
qversionnumber
.
h
>
8
#
include
<
QtCore
/
qhash
.
h
>
9
#
include
<
QtCore
/
private
/
qlocale_tools_p
.
h
>
10
#
include
<
QtCore
/
qcollator
.
h
>
11
12
#
ifndef
QT_NO_DATASTREAM
13
#
include
<
QtCore
/
qdatastream
.
h
>
14
#
endif
15
16
#
ifndef
QT_NO_DEBUG_STREAM
17
#
include
<
QtCore
/
qdebug
.
h
>
18
#
endif
19
20
#
include
<
algorithm
>
21
#
include
<
limits
>
22
23
QT_BEGIN_NAMESPACE
24
25
QT_IMPL_METATYPE_EXTERN(QVersionNumber)
26
27
/*!
28
\class QVersionNumber
29
\inmodule QtCore
30
\since 5.6
31
\brief The QVersionNumber class contains a version number with an arbitrary
32
number of segments.
33
34
\compares strong
35
\snippet qversionnumber/main.cpp 0
36
*/
37
38
/*!
39
\fn QVersionNumber::QVersionNumber()
40
41
Produces a null version.
42
43
\sa isNull()
44
*/
45
46
/*!
47
\fn QVersionNumber::QVersionNumber(int maj)
48
49
Constructs a QVersionNumber consisting of just the major version number \a maj.
50
*/
51
52
/*!
53
\fn QVersionNumber::QVersionNumber(int maj, int min)
54
55
Constructs a QVersionNumber consisting of the major and minor
56
version numbers \a maj and \a min, respectively.
57
*/
58
59
/*!
60
\fn QVersionNumber::QVersionNumber(int maj, int min, int mic)
61
62
Constructs a QVersionNumber consisting of the major, minor, and
63
micro version numbers \a maj, \a min and \a mic, respectively.
64
*/
65
66
/*!
67
\fn QVersionNumber::QVersionNumber(const QList<int> &seg)
68
69
Constructs a version number from the list of numbers contained in \a seg.
70
*/
71
72
/*!
73
\fn QVersionNumber::QVersionNumber(QList<int> &&seg)
74
75
Move-constructs a version number from the list of numbers contained in \a seg.
76
*/
77
78
/*!
79
\fn QVersionNumber::QVersionNumber(std::initializer_list<int> args)
80
81
Constructs a version number from the std::initializer_list specified by
82
\a args.
83
*/
84
85
/*!
86
\fn QVersionNumber::QVersionNumber(QSpan<const int> args)
87
\since 6.8
88
89
Constructs a version number from the span specified by \a args.
90
91
\note In Qt versions prior to 6.8, QVersionNumber could only be constructed
92
from QList, QVarLenthArray or std::initializer_list.
93
*/
94
95
/*!
96
\fn bool QVersionNumber::isNull() const
97
98
Returns \c true if there are zero numerical segments, otherwise returns
99
\c false.
100
101
\sa segments()
102
*/
103
104
/*!
105
\fn bool QVersionNumber::isNormalized() const
106
107
Returns \c true if the version number does not contain any trailing zeros,
108
otherwise returns \c false.
109
110
\sa normalized()
111
*/
112
113
/*!
114
\fn int QVersionNumber::majorVersion() const
115
116
Returns the major version number, that is, the first segment.
117
This function is equivalent to segmentAt(0). If this QVersionNumber object
118
is null, this function returns 0.
119
120
\sa isNull(), segmentAt()
121
*/
122
123
/*!
124
\fn int QVersionNumber::minorVersion() const
125
126
Returns the minor version number, that is, the second segment.
127
This function is equivalent to segmentAt(1). If this QVersionNumber object
128
does not contain a minor number, this function returns 0.
129
130
\sa isNull(), segmentAt()
131
*/
132
133
/*!
134
\fn int QVersionNumber::microVersion() const
135
136
Returns the micro version number, that is, the third segment.
137
This function is equivalent to segmentAt(2). If this QVersionNumber object
138
does not contain a micro number, this function returns 0.
139
140
\sa isNull(), segmentAt()
141
*/
142
143
/*!
144
\fn QList<int> QVersionNumber::segments() const
145
146
Returns all of the numerical segments.
147
148
\sa majorVersion(), minorVersion(), microVersion()
149
*/
150
QList<
int
> QVersionNumber::segments()
const
151
{
152
if
(m_segments.isUsingPointer())
153
return
*m_segments.pointer_segments;
154
155
QList<
int
> result;
156
result.resize(segmentCount());
157
for
(qsizetype i = 0; i < segmentCount(); ++i)
158
result[i] = segmentAt(i);
159
return
result;
160
}
161
162
/*!
163
\fn int QVersionNumber::segmentAt(qsizetype index) const
164
165
Returns the segment value at \a index. If the index does not exist,
166
returns 0.
167
168
\sa segments(), segmentCount()
169
*/
170
171
/*!
172
\fn qsizetype QVersionNumber::segmentCount() const
173
174
Returns the number of integers stored in segments().
175
176
\sa segments()
177
*/
178
179
/*!
180
\typedef QVersionNumber::const_iterator
181
\typedef QVersionNumber::const_reverse_iterator
182
\since 6.8
183
184
Typedefs for an opaque class that implements a (reverse) random-access
185
iterator over QVersionNumber segments.
186
187
\note QVersionNumber does not support modifying segments in-place, so
188
there is no mutable iterator.
189
*/
190
191
/*!
192
\typedef QVersionNumber::value_type
193
\typedef QVersionNumber::difference_type
194
\typedef QVersionNumber::size_type
195
\typedef QVersionNumber::reference
196
\typedef QVersionNumber::const_reference
197
\typedef QVersionNumber::pointer
198
\typedef QVersionNumber::const_pointer
199
\since 6.8
200
201
Provided for STL-compatibility.
202
203
\note QVersionNumber does not support modifying segments in-place, so
204
reference and const_reference, as well as pointer and const_pointer are
205
pairwise the same types.
206
*/
207
208
/*!
209
\fn QVersionNumber::begin() const
210
\fn QVersionNumber::end() const;
211
\fn QVersionNumber::rbegin() const
212
\fn QVersionNumber::rend() const;
213
\fn QVersionNumber::cbegin() const
214
\fn QVersionNumber::cend() const;
215
\fn QVersionNumber::crbegin() const
216
\fn QVersionNumber::crend() const;
217
\fn QVersionNumber::constBegin() const;
218
\fn QVersionNumber::constEnd() const;
219
\since 6.8
220
221
Returns a const_iterator or const_reverse_iterator, respectively, pointing
222
to the first or one past the last segment of this version number.
223
224
\note QVersionNumber does not support modifying segments in-place, so
225
there is no mutable iterator.
226
*/
227
228
/*!
229
\fn QVersionNumber QVersionNumber::normalized() const
230
231
Returns an equivalent version number but with all trailing zeros removed.
232
233
To check if two numbers are equivalent, use normalized() on both version
234
numbers before performing the compare.
235
236
\snippet qversionnumber/main.cpp 4
237
*/
238
QVersionNumber QVersionNumber::normalized()
const
239
{
240
qsizetype i;
241
for
(i = m_segments.size(); i; --i)
242
if
(m_segments.at(i - 1) != 0)
243
break
;
244
245
QVersionNumber result(*
this
);
246
result.m_segments.resize(i);
247
return
result;
248
}
249
250
/*!
251
\fn bool QVersionNumber::isPrefixOf(const QVersionNumber &other) const
252
253
Returns \c true if the current version number is contained in the \a other
254
version number, otherwise returns \c false.
255
256
\snippet qversionnumber/main.cpp 2
257
258
\sa commonPrefix()
259
*/
260
bool
QVersionNumber::isPrefixOf(
const
QVersionNumber &other)
const
noexcept
261
{
262
if
(segmentCount() > other.segmentCount())
263
return
false
;
264
for
(qsizetype i = 0; i < segmentCount(); ++i) {
265
if
(segmentAt(i) != other.segmentAt(i))
266
return
false
;
267
}
268
return
true
;
269
}
270
271
/*!
272
\fn int QVersionNumber::compare(const QVersionNumber &v1,
273
const QVersionNumber &v2)
274
275
Compares \a v1 with \a v2 and returns an integer less than, equal to, or
276
greater than zero, depending on whether \a v1 is less than, equal to, or
277
greater than \a v2, respectively.
278
279
Comparisons are performed by comparing the segments of \a v1 and \a v2
280
starting at index 0 and working towards the end of the longer list.
281
282
\snippet qversionnumber/main.cpp 1
283
*/
284
int
QVersionNumber::compare(
const
QVersionNumber &v1,
const
QVersionNumber &v2)
noexcept
285
{
286
qsizetype commonlen;
287
288
if
(Q_LIKELY(!v1.m_segments.isUsingPointer() && !v2.m_segments.isUsingPointer())) {
289
// we can't use memcmp because it interprets the data as unsigned bytes
290
const
qint8 *ptr1 = v1.m_segments.inline_segments + InlineSegmentStartIdx;
291
const
qint8 *ptr2 = v2.m_segments.inline_segments + InlineSegmentStartIdx;
292
commonlen = qMin(v1.m_segments.size(),
293
v2.m_segments.size());
294
for
(qsizetype i = 0; i < commonlen; ++i)
295
if
(
int
x = ptr1[i] - ptr2[i])
296
return
x;
297
}
else
{
298
commonlen = qMin(v1.segmentCount(), v2.segmentCount());
299
for
(qsizetype i = 0; i < commonlen; ++i) {
300
if
(v1.segmentAt(i) != v2.segmentAt(i))
301
return
v1.segmentAt(i) - v2.segmentAt(i);
302
}
303
}
304
305
// ran out of segments in v1 and/or v2 and need to check the first trailing
306
// segment to finish the compare
307
if
(v1.segmentCount() > commonlen) {
308
// v1 is longer
309
if
(v1.segmentAt(commonlen) != 0)
310
return
v1.segmentAt(commonlen);
311
else
312
return
1;
313
}
else
if
(v2.segmentCount() > commonlen) {
314
// v2 is longer
315
if
(v2.segmentAt(commonlen) != 0)
316
return
-v2.segmentAt(commonlen);
317
else
318
return
-1;
319
}
320
321
// the two version numbers are the same
322
return
0;
323
}
324
325
/*!
326
QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
327
const QVersionNumber &v2)
328
329
Returns a version number that is a parent version of both \a v1 and \a v2.
330
331
\sa isPrefixOf()
332
*/
333
QVersionNumber QVersionNumber::commonPrefix(
const
QVersionNumber &v1,
334
const
QVersionNumber &v2)
335
{
336
qsizetype commonlen = qMin(v1.segmentCount(), v2.segmentCount());
337
qsizetype i;
338
for
(i = 0; i < commonlen; ++i) {
339
if
(v1.segmentAt(i) != v2.segmentAt(i))
340
break
;
341
}
342
343
if
(i == 0)
344
return
QVersionNumber();
345
346
// try to use the one with inline segments, if there's one
347
QVersionNumber result(!v1.m_segments.isUsingPointer() ? v1 : v2);
348
result.m_segments.resize(i);
349
return
result;
350
}
351
352
/*!
353
\fn bool QVersionNumber::operator<(const QVersionNumber &lhs, const QVersionNumber &rhs)
354
355
Returns \c true if \a lhs is less than \a rhs; otherwise returns \c false.
356
357
\sa QVersionNumber::compare()
358
*/
359
360
/*!
361
\fn bool QVersionNumber::operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs)
362
363
Returns \c true if \a lhs is less than or equal to \a rhs; otherwise
364
returns \c false.
365
366
\sa QVersionNumber::compare()
367
*/
368
369
/*!
370
\fn bool QVersionNumber::operator>(const QVersionNumber &lhs, const QVersionNumber &rhs)
371
372
Returns \c true if \a lhs is greater than \a rhs; otherwise returns \c
373
false.
374
375
\sa QVersionNumber::compare()
376
*/
377
378
/*!
379
\fn bool QVersionNumber::operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs)
380
381
Returns \c true if \a lhs is greater than or equal to \a rhs; otherwise
382
returns \c false.
383
384
\sa QVersionNumber::compare()
385
*/
386
387
/*!
388
\fn bool QVersionNumber::operator==(const QVersionNumber &lhs, const QVersionNumber &rhs)
389
390
Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
391
392
\sa QVersionNumber::compare()
393
*/
394
395
/*!
396
\fn bool QVersionNumber::operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs)
397
398
Returns \c true if \a lhs is not equal to \a rhs; otherwise returns
399
\c false.
400
401
\sa QVersionNumber::compare()
402
*/
403
404
/*!
405
\fn QString QVersionNumber::toString() const
406
407
Returns a string with all of the segments delimited by a period (\c{.}).
408
409
\sa majorVersion(), minorVersion(), microVersion(), segments()
410
*/
411
QString QVersionNumber::toString()
const
412
{
413
QString version;
414
version.reserve(qMax(segmentCount() * 2 - 1, 0));
415
bool
first =
true
;
416
for
(qsizetype i = 0; i < segmentCount(); ++i) {
417
if
(!first)
418
version += u'.';
419
version += QString::number(segmentAt(i));
420
first =
false
;
421
}
422
return
version;
423
}
424
425
/*!
426
\fn QVersionNumber QVersionNumber::fromString(QAnyStringView string, qsizetype *suffixIndex)
427
\since 6.4
428
429
Constructs a QVersionNumber from a specially formatted \a string of
430
non-negative decimal numbers delimited by a period (\c{.}).
431
432
Once the numerical segments have been parsed, the remainder of the string
433
is considered to be the suffix string. The start index of that string will be
434
stored in \a suffixIndex if it is not null.
435
436
\snippet qversionnumber/main.cpp 3-latin1-1
437
438
\note In versions prior to Qt 6.4, this function was overloaded for QString,
439
QLatin1StringView and QStringView instead, and \a suffixIndex was an \c{int*}.
440
441
\sa isNull()
442
*/
443
444
static
QVersionNumber from_string(QLatin1StringView string, qsizetype *suffixIndex)
445
{
446
// 32 should be more than enough, and, crucially, it means we're allocating
447
// not more (and often less) often when compared with direct QList usage
448
// for all possible segment counts (under the constraint that we don't want
449
// to keep more capacity around for the lifetime of the resulting
450
// QVersionNumber than required), esp. in the common case where the inline
451
// storage can be used.
452
QVarLengthArray<
int
, 32> seg;
453
454
const
char
*start = string.begin();
455
const
char
*lastGoodEnd = start;
456
const
char
*endOfString = string.end();
457
458
do
{
459
// parsing as unsigned so a minus sign is rejected
460
auto
[value, used] = qstrntoull(start, endOfString - start, 10);
461
if
(used <= 0 || value > qulonglong(std::numeric_limits<
int
>::max()))
462
break
;
463
seg.append(
int
(value));
464
start += used + 1;
465
lastGoodEnd = start - 1;
466
}
while
(start < endOfString && *lastGoodEnd ==
'.'
);
467
468
if
(suffixIndex)
469
*suffixIndex = lastGoodEnd - string.begin();
470
471
return
QVersionNumber(seg);
472
}
473
474
static
QVersionNumber from_string(q_no_char8_t::QUtf8StringView string, qsizetype *suffixIndex)
475
{
476
return
from_string(QLatin1StringView(string.data(), string.size()), suffixIndex);
477
}
478
479
// in qstring.cpp
480
extern
void
qt_to_latin1(uchar *dst,
const
char16_t
*uc, qsizetype len);
481
482
static
QVersionNumber
from_string
(QStringView string, qsizetype *suffixIndex)
483
{
484
QVarLengthArray<
char
> copy;
485
copy.resize(string.size());
486
qt_to_latin1(
reinterpret_cast
<uchar*>(copy.data()), string.utf16(), string.size());
487
return
from_string(QLatin1StringView(copy.data(), copy.size()), suffixIndex);
488
}
489
490
QVersionNumber QVersionNumber::fromString(QAnyStringView string, qsizetype *suffixIndex)
491
{
492
return
string.visit([=] (
auto
string) {
return
from_string(string, suffixIndex); });
493
}
494
495
void
QVersionNumber::SegmentStorage::setListData(
const
QList<
int
> &seg)
496
{
497
pointer_segments =
new
QList<
int
>(seg);
498
}
499
500
void
QVersionNumber::SegmentStorage::setListData(QList<
int
> &&seg)
501
{
502
pointer_segments =
new
QList<
int
>(std::move(seg));
503
}
504
505
void
QVersionNumber::SegmentStorage::setListData(
const
int
*first,
const
int
*last)
506
{
507
pointer_segments =
new
QList<
int
>(first, last);
508
}
509
510
void
QVersionNumber::SegmentStorage::resize(qsizetype len)
511
{
512
if
(isUsingPointer())
513
pointer_segments->resize(len);
514
else
515
setInlineSize(len);
516
}
517
518
void
QVersionNumber::SegmentStorage::setVector(
int
len,
int
maj,
int
min,
int
mic)
519
{
520
pointer_segments =
new
QList<
int
>;
521
pointer_segments->resize(len);
522
pointer_segments->data()[0] = maj;
523
if
(len > 1) {
524
pointer_segments->data()[1] = min;
525
if
(len > 2) {
526
pointer_segments->data()[2] = mic;
527
}
528
}
529
}
530
531
#
ifndef
QT_NO_DATASTREAM
532
/*!
533
\fn QDataStream& operator<<(QDataStream &out,
534
const QVersionNumber &version)
535
\relates QVersionNumber
536
537
Writes the version number \a version to stream \a out.
538
539
Note that this has nothing to do with QDataStream::version().
540
*/
541
QDataStream
&
operator
<<(QDataStream &out,
const
QVersionNumber &version)
542
{
543
out << version.segments();
544
return
out;
545
}
546
547
/*!
548
\fn QDataStream& operator>>(QDataStream &in, QVersionNumber &version)
549
\relates QVersionNumber
550
551
Reads a version number from stream \a in and stores it in \a version.
552
553
Note that this has nothing to do with QDataStream::version().
554
*/
555
QDataStream
&
operator
>>(QDataStream &in, QVersionNumber &version)
556
{
557
if
(!version.m_segments.isUsingPointer())
558
version.m_segments.pointer_segments =
new
QList<
int
>;
559
in >> *version.m_segments.pointer_segments;
560
return
in;
561
}
562
#
endif
563
564
#
ifndef
QT_NO_DEBUG_STREAM
565
QDebug
operator
<<(QDebug debug,
const
QVersionNumber &version)
566
{
567
QDebugStateSaver saver(debug);
568
debug.nospace().noquote();
569
debug <<
"QVersionNumber("
<< version.toString() <<
")"
;
570
return
debug;
571
}
572
#
endif
573
574
/*!
575
\qhashold{QHash}
576
\since 5.6
577
*/
578
size_t
qHash
(
const
QVersionNumber &key, size_t seed)
579
{
580
return
qHashRange(key.begin(), key.end(), seed);
581
}
582
583
QT_END_NAMESPACE
operator<<
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
Definition
qfileinfo.cpp:1830
qHash
constexpr size_t qHash(const QSize &s, size_t seed=0) noexcept
Definition
qsize.h:192
from_string
static QVersionNumber from_string(QStringView string, qsizetype *suffixIndex)
Definition
qversionnumber.cpp:482
operator<<
QDataStream & operator<<(QDataStream &stream, const QImage &image)
[0]
Definition
qimage.cpp:4045
operator>>
QDataStream & operator>>(QDataStream &stream, QImage &image)
Definition
qimage.cpp:4071
qtbase
src
corelib
tools
qversionnumber.cpp
Generated on
for Qt by
1.18.0