Qt 6.x
The Qt SDK
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
6#include <QtCore/qversionnumber.h>
7#include <QtCore/qhash.h>
8#include <QtCore/private/qlocale_tools_p.h>
9#include <QtCore/qcollator.h>
10
11#ifndef QT_NO_DATASTREAM
12# include <QtCore/qdatastream.h>
13#endif
14
15#ifndef QT_NO_DEBUG_STREAM
16# include <QtCore/qdebug.h>
17#endif
18
19#include <algorithm>
20#include <limits>
21
23
26
27
152{
153 if (m_segments.isUsingPointer())
154 return *m_segments.pointer_segments;
155
157 result.resize(segmentCount());
158 for (qsizetype i = 0; i < segmentCount(); ++i)
159 result[i] = segmentAt(i);
160 return result;
161}
162
191{
192 qsizetype i;
193 for (i = m_segments.size(); i; --i)
194 if (m_segments.at(i - 1) != 0)
195 break;
196
197 QVersionNumber result(*this);
198 result.m_segments.resize(i);
199 return result;
200}
201
213{
214 if (segmentCount() > other.segmentCount())
215 return false;
216 for (qsizetype i = 0; i < segmentCount(); ++i) {
217 if (segmentAt(i) != other.segmentAt(i))
218 return false;
219 }
220 return true;
221}
222
237{
238 qsizetype commonlen;
239
240 if (Q_LIKELY(!v1.m_segments.isUsingPointer() && !v2.m_segments.isUsingPointer())) {
241 // we can't use memcmp because it interprets the data as unsigned bytes
242 const qint8 *ptr1 = v1.m_segments.inline_segments + InlineSegmentStartIdx;
243 const qint8 *ptr2 = v2.m_segments.inline_segments + InlineSegmentStartIdx;
244 commonlen = qMin(v1.m_segments.size(),
245 v2.m_segments.size());
246 for (qsizetype i = 0; i < commonlen; ++i)
247 if (int x = ptr1[i] - ptr2[i])
248 return x;
249 } else {
250 commonlen = qMin(v1.segmentCount(), v2.segmentCount());
251 for (qsizetype i = 0; i < commonlen; ++i) {
252 if (v1.segmentAt(i) != v2.segmentAt(i))
253 return v1.segmentAt(i) - v2.segmentAt(i);
254 }
255 }
256
257 // ran out of segments in v1 and/or v2 and need to check the first trailing
258 // segment to finish the compare
259 if (v1.segmentCount() > commonlen) {
260 // v1 is longer
261 if (v1.segmentAt(commonlen) != 0)
262 return v1.segmentAt(commonlen);
263 else
264 return 1;
265 } else if (v2.segmentCount() > commonlen) {
266 // v2 is longer
267 if (v2.segmentAt(commonlen) != 0)
268 return -v2.segmentAt(commonlen);
269 else
270 return -1;
271 }
272
273 // the two version numbers are the same
274 return 0;
275}
276
286 const QVersionNumber &v2)
287{
288 qsizetype commonlen = qMin(v1.segmentCount(), v2.segmentCount());
289 qsizetype i;
290 for (i = 0; i < commonlen; ++i) {
291 if (v1.segmentAt(i) != v2.segmentAt(i))
292 break;
293 }
294
295 if (i == 0)
296 return QVersionNumber();
297
298 // try to use the one with inline segments, if there's one
299 QVersionNumber result(!v1.m_segments.isUsingPointer() ? v1 : v2);
300 result.m_segments.resize(i);
301 return result;
302}
303
364{
365 QString version;
366 version.reserve(qMax(segmentCount() * 2 - 1, 0));
367 bool first = true;
368 for (qsizetype i = 0; i < segmentCount(); ++i) {
369 if (!first)
370 version += u'.';
371 version += QString::number(segmentAt(i));
372 first = false;
373 }
374 return version;
375}
376
397{
398 // 32 should be more than enough, and, crucially, it means we're allocating
399 // not more (and often less) often when compared with direct QList usage
400 // for all possible segment counts (under the constraint that we don't want
401 // to keep more capacity around for the lifetime of the resulting
402 // QVersionNumber than required), esp. in the common case where the inline
403 // storage can be used.
405
406 const char *start = string.begin();
407 const char *lastGoodEnd = start;
408 const char *endOfString = string.end();
409
410 do {
411 // parsing as unsigned so a minus sign is rejected
412 auto [value, used] = qstrntoull(start, endOfString - start, 10);
413 if (used <= 0 || value > qulonglong(std::numeric_limits<int>::max()))
414 break;
415 seg.append(int(value));
416 start += used + 1;
417 lastGoodEnd = start - 1;
418 } while (start < endOfString && *lastGoodEnd == '.');
419
420 if (suffixIndex)
421 *suffixIndex = lastGoodEnd - string.begin();
422
423 return QVersionNumber(seg);
424}
425
426static QVersionNumber from_string(q_no_char8_t::QUtf8StringView string, qsizetype *suffixIndex)
427{
428 return from_string(QLatin1StringView(string.data(), string.size()), suffixIndex);
429}
430
431// in qstring.cpp
432extern void qt_to_latin1(uchar *dst, const char16_t *uc, qsizetype len);
433
435{
437 copy.resize(string.size());
438 qt_to_latin1(reinterpret_cast<uchar*>(copy.data()), string.utf16(), string.size());
439 return from_string(QLatin1StringView(copy.data(), copy.size()), suffixIndex);
440}
441
443{
444 return string.visit([=] (auto string) { return from_string(string, suffixIndex); });
445}
446
447void QVersionNumber::SegmentStorage::setListData(const QList<int> &seg)
448{
449 pointer_segments = new QList<int>(seg);
450}
451
452void QVersionNumber::SegmentStorage::setListData(QList<int> &&seg)
453{
454 pointer_segments = new QList<int>(std::move(seg));
455}
456
457void QVersionNumber::SegmentStorage::setListData(const int *first, const int *last)
458{
459 pointer_segments = new QList<int>(first, last);
460}
461
462void QVersionNumber::SegmentStorage::resize(qsizetype len)
463{
464 if (isUsingPointer())
465 pointer_segments->resize(len);
466 else
467 setInlineSize(len);
468}
469
470void QVersionNumber::SegmentStorage::setVector(int len, int maj, int min, int mic)
471{
472 pointer_segments = new QList<int>;
473 pointer_segments->resize(len);
474 pointer_segments->data()[0] = maj;
475 if (len > 1) {
476 pointer_segments->data()[1] = min;
477 if (len > 2) {
478 pointer_segments->data()[2] = mic;
479 }
480 }
481}
482
483#ifndef QT_NO_DATASTREAM
494{
495 out << version.segments();
496 return out;
497}
498
508{
509 if (!version.m_segments.isUsingPointer())
510 version.m_segments.pointer_segments = new QList<int>;
511 in >> *version.m_segments.pointer_segments;
512 return in;
513}
514#endif
515
516#ifndef QT_NO_DEBUG_STREAM
518{
519 QDebugStateSaver saver(debug);
520 debug.nospace().noquote();
521 debug << "QVersionNumber(" << version.toString() << ")";
522 return debug;
523}
524#endif
525
533size_t qHash(const QVersionNumber &key, size_t seed)
534{
536 for (int i = 0; i < key.segmentCount(); ++i)
537 seed = hash(seed, key.segmentAt(i));
538 return seed;
539}
540
675#ifndef QT_NO_DATASTREAM
684{
685 return out << revision.toEncodedVersion<quint16>();
686}
687
696{
698 in >> value;
700 return in;
701}
702#endif
703
704#ifndef QT_NO_DEBUG_STREAM
706{
707 QDebugStateSaver saver(debug);
708 if (revision.hasMajorVersion()) {
709 if (revision.hasMinorVersion())
710 debug.nospace() << revision.majorVersion() << '.' << revision.minorVersion();
711 else
712 debug.nospace().noquote() << revision.majorVersion() << ".x";
713 } else {
714 if (revision.hasMinorVersion())
715 debug << revision.minorVersion();
716 else
717 debug.noquote() << "invalid";
718 }
719 return debug;
720}
721#endif
722
730size_t qHash(const QTypeRevision &key, size_t seed)
731{
732 return qHash(key.toEncodedVersion<quint16>(), seed);
733}
734
\inmodule QtCore
\inmodule QtCore\reentrant
Definition qdatastream.h:30
\inmodule QtCore
\inmodule QtCore
size_t qHash(const QVersionNumber &key, size_t seed)
size_t qHash(const QTypeRevision &key, size_t seed)
Definition qlist.h:74
void resize(qsizetype size)
Definition qlist.h:392
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
void reserve(qsizetype size)
Ensures the string has space for at least size characters.
Definition qstring.h:1173
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
\inmodule QtCore
static constexpr QTypeRevision fromEncodedVersion(Integer value)
Produces a QTypeRevision from the given value.
constexpr bool hasMinorVersion() const
Returns true if the minor version is known, otherwise false.
constexpr bool hasMajorVersion() const
Returns true if the major version is known, otherwise false.
constexpr Integer toEncodedVersion() const
Transforms the revision into an integer value, encoding the minor version into the least significant ...
constexpr quint8 minorVersion() const
Returns the minor version encoded in the revision.
constexpr quint8 majorVersion() const
Returns the major version encoded in the revision.
void append(const T &t)
iterator begin() noexcept
\inmodule QtCore
Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const noexcept
Returns true if the current version number is contained in the other version number,...
static Q_CORE_EXPORT QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2)
QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1, ...
QVersionNumber() noexcept
Produces a null version.
static Q_CORE_EXPORT QVersionNumber fromString(QAnyStringView string, qsizetype *suffixIndex=nullptr)
Q_CORE_EXPORT QList< int > segments() const
Returns all of the numerical segments.
qsizetype segmentCount() const noexcept
Returns the number of integers stored in segments().
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.
int segmentAt(qsizetype index) const noexcept
Returns the segment value at index.
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,...
QHash< int, QWidget * > hash
[35multi]
Combined button and popup list for selecting options.
constexpr const T & min(const T &a, const T &b)
Definition qnumeric.h:366
static jboolean copy(JNIEnv *, jobject)
#define Q_LIKELY(x)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
size_t qHash(const QFileSystemWatcherPathKey &key, size_t seed=0)
QSimpleParsedNumber< qulonglong > qstrntoull(const char *begin, qsizetype size, int base)
#define QT_IMPL_METATYPE_EXTERN(TYPE)
Definition qmetatype.h:1369
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLint GLfloat GLfloat GLfloat v2
GLint GLint GLint GLint GLint x
[0]
GLuint64 key
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum dst
GLint GLfloat GLfloat v1
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLint first
GLenum GLsizei len
GLuint in
GLuint segments
GLuint64EXT * result
[6]
static int segmentCount(const QPainterPath &path, qreal pathLength)
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
unsigned char uchar
Definition qtypes.h:27
unsigned short quint16
Definition qtypes.h:43
quint64 qulonglong
Definition qtypes.h:59
ptrdiff_t qsizetype
Definition qtypes.h:70
QT_BEGIN_NAMESPACE typedef signed char qint8
Definition qtypes.h:40
QDataStream & operator<<(QDataStream &out, const QVersionNumber &version)
QDataStream & operator>>(QDataStream &in, QVersionNumber &version)
static QVersionNumber from_string(QLatin1StringView string, qsizetype *suffixIndex)
void qt_to_latin1(uchar *dst, const char16_t *uc, qsizetype len)
Definition qstring.cpp:1193
QTextStream out(stdout)
[7]
QSharedPointer< T > other(t)
[5]