summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qversionnumber.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools/qversionnumber.cpp')
-rw-r--r--src/corelib/tools/qversionnumber.cpp449
1 files changed, 144 insertions, 305 deletions
diff --git a/src/corelib/tools/qversionnumber.cpp b/src/corelib/tools/qversionnumber.cpp
index da093a417d..4b8ace71cc 100644
--- a/src/corelib/tools/qversionnumber.cpp
+++ b/src/corelib/tools/qversionnumber.cpp
@@ -1,43 +1,7 @@
-/****************************************************************************
-**
-** Copyright (C) 2021 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2021 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/qversionnumber.h>
#include <QtCore/qhash.h>
@@ -57,6 +21,8 @@
QT_BEGIN_NAMESPACE
+QT_IMPL_METATYPE_EXTERN(QVersionNumber)
+
/*!
\class QVersionNumber
\inmodule QtCore
@@ -105,18 +71,23 @@ QT_BEGIN_NAMESPACE
\fn QVersionNumber::QVersionNumber(QList<int> &&seg)
Move-constructs a version number from the list of numbers contained in \a seg.
-
- This constructor is only enabled if the compiler supports C++11 move semantics.
*/
/*!
\fn QVersionNumber::QVersionNumber(std::initializer_list<int> args)
- Construct a version number from the std::initializer_list specified by
+ Constructs a version number from the std::initializer_list specified by
\a args.
+*/
+
+/*!
+ \fn QVersionNumber::QVersionNumber(QSpan<const int> args)
+ \since 6.8
+
+ Constructs a version number from the span specified by \a args.
- This constructor is only enabled if the compiler supports C++11 initializer
- lists.
+ \note In Qt versions prior to 6.8, QVersionNumber could only be constructed
+ from QList, QVarLenthArray or std::initializer_list.
*/
/*!
@@ -168,7 +139,7 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn const QList<int>& QVersionNumber::segments() const
+ \fn QList<int> QVersionNumber::segments() const
Returns all of the numerical segments.
@@ -181,13 +152,13 @@ QList<int> QVersionNumber::segments() const
QList<int> result;
result.resize(segmentCount());
- for (int i = 0; i < segmentCount(); ++i)
+ for (qsizetype i = 0; i < segmentCount(); ++i)
result[i] = segmentAt(i);
return result;
}
/*!
- \fn int QVersionNumber::segmentAt(int index) const
+ \fn int QVersionNumber::segmentAt(qsizetype index) const
Returns the segment value at \a index. If the index does not exist,
returns 0.
@@ -196,7 +167,7 @@ QList<int> QVersionNumber::segments() const
*/
/*!
- \fn int QVersionNumber::segmentCount() const
+ \fn qsizetype QVersionNumber::segmentCount() const
Returns the number of integers stored in segments().
@@ -204,6 +175,55 @@ QList<int> QVersionNumber::segments() const
*/
/*!
+ \typedef QVersionNumber::const_iterator
+ \typedef QVersionNumber::const_reverse_iterator
+ \since 6.8
+
+ Typedefs for an opaque class that implements a (reverse) random-access
+ iterator over QVersionNumber segments.
+
+ \note QVersionNumber does not support modifying segments in-place, so
+ there is no mutable iterator.
+*/
+
+/*!
+ \typedef QVersionNumber::value_type
+ \typedef QVersionNumber::difference_type
+ \typedef QVersionNumber::size_type
+ \typedef QVersionNumber::reference
+ \typedef QVersionNumber::const_reference
+ \typedef QVersionNumber::pointer
+ \typedef QVersionNumber::const_pointer
+ \since 6.8
+
+ Provided for STL-compatibility.
+
+ \note QVersionNumber does not support modifying segments in-place, so
+ reference and const_reference, as well as pointer and const_pointer are
+ pairwise the same types.
+*/
+
+/*!
+ \fn QVersionNumber::begin() const
+ \fn QVersionNumber::end() const;
+ \fn QVersionNumber::rbegin() const
+ \fn QVersionNumber::rend() const;
+ \fn QVersionNumber::cbegin() const
+ \fn QVersionNumber::cend() const;
+ \fn QVersionNumber::crbegin() const
+ \fn QVersionNumber::crend() const;
+ \fn QVersionNumber::constBegin() const;
+ \fn QVersionNumber::constEnd() const;
+ \since 6.8
+
+ Returns a const_iterator or const_reverse_iterator, respectively, pointing
+ to the first or one past the last segment of this version number.
+
+ \note QVersionNumber does not support modifying segments in-place, so
+ there is no mutable iterator.
+*/
+
+/*!
\fn QVersionNumber QVersionNumber::normalized() const
Returns an equivalent version number but with all trailing zeros removed.
@@ -215,7 +235,7 @@ QList<int> QVersionNumber::segments() const
*/
QVersionNumber QVersionNumber::normalized() const
{
- int i;
+ qsizetype i;
for (i = m_segments.size(); i; --i)
if (m_segments.at(i - 1) != 0)
break;
@@ -239,7 +259,7 @@ bool QVersionNumber::isPrefixOf(const QVersionNumber &other) const noexcept
{
if (segmentCount() > other.segmentCount())
return false;
- for (int i = 0; i < segmentCount(); ++i) {
+ for (qsizetype i = 0; i < segmentCount(); ++i) {
if (segmentAt(i) != other.segmentAt(i))
return false;
}
@@ -261,7 +281,7 @@ bool QVersionNumber::isPrefixOf(const QVersionNumber &other) const noexcept
*/
int QVersionNumber::compare(const QVersionNumber &v1, const QVersionNumber &v2) noexcept
{
- int commonlen;
+ qsizetype commonlen;
if (Q_LIKELY(!v1.m_segments.isUsingPointer() && !v2.m_segments.isUsingPointer())) {
// we can't use memcmp because it interprets the data as unsigned bytes
@@ -269,12 +289,12 @@ int QVersionNumber::compare(const QVersionNumber &v1, const QVersionNumber &v2)
const qint8 *ptr2 = v2.m_segments.inline_segments + InlineSegmentStartIdx;
commonlen = qMin(v1.m_segments.size(),
v2.m_segments.size());
- for (int i = 0; i < commonlen; ++i)
+ for (qsizetype i = 0; i < commonlen; ++i)
if (int x = ptr1[i] - ptr2[i])
return x;
} else {
commonlen = qMin(v1.segmentCount(), v2.segmentCount());
- for (int i = 0; i < commonlen; ++i) {
+ for (qsizetype i = 0; i < commonlen; ++i) {
if (v1.segmentAt(i) != v2.segmentAt(i))
return v1.segmentAt(i) - v2.segmentAt(i);
}
@@ -311,8 +331,8 @@ int QVersionNumber::compare(const QVersionNumber &v1, const QVersionNumber &v2)
QVersionNumber QVersionNumber::commonPrefix(const QVersionNumber &v1,
const QVersionNumber &v2)
{
- int commonlen = qMin(v1.segmentCount(), v2.segmentCount());
- int i;
+ qsizetype commonlen = qMin(v1.segmentCount(), v2.segmentCount());
+ qsizetype i;
for (i = 0; i < commonlen; ++i) {
if (v1.segmentAt(i) != v2.segmentAt(i))
break;
@@ -391,17 +411,19 @@ QString QVersionNumber::toString() const
QString version;
version.reserve(qMax(segmentCount() * 2 - 1, 0));
bool first = true;
- for (int i = 0; i < segmentCount(); ++i) {
+ for (qsizetype i = 0; i < segmentCount(); ++i) {
if (!first)
- version += QLatin1Char('.');
+ version += u'.';
version += QString::number(segmentAt(i));
first = false;
}
return version;
}
-#if QT_STRINGVIEW_LEVEL < 2
/*!
+ \fn QVersionNumber QVersionNumber::fromString(QAnyStringView string, qsizetype *suffixIndex)
+ \since 6.4
+
Constructs a QVersionNumber from a specially formatted \a string of
non-negative decimal numbers delimited by a period (\c{.}).
@@ -409,74 +431,86 @@ QString QVersionNumber::toString() const
is considered to be the suffix string. The start index of that string will be
stored in \a suffixIndex if it is not null.
- \snippet qversionnumber/main.cpp 3
+ \snippet qversionnumber/main.cpp 3-latin1-1
+
+ \note In versions prior to Qt 6.4, this function was overloaded for QString,
+ QLatin1StringView and QStringView instead, and \a suffixIndex was an \c{int*}.
\sa isNull()
*/
-QVersionNumber QVersionNumber::fromString(const QString &string, int *suffixIndex)
+
+static QVersionNumber from_string(QLatin1StringView string, qsizetype *suffixIndex)
{
- return fromString(QLatin1String(string.toLatin1()), suffixIndex);
-}
-#endif
+ // 32 should be more than enough, and, crucially, it means we're allocating
+ // not more (and often less) often when compared with direct QList usage
+ // for all possible segment counts (under the constraint that we don't want
+ // to keep more capacity around for the lifetime of the resulting
+ // QVersionNumber than required), esp. in the common case where the inline
+ // storage can be used.
+ QVarLengthArray<int, 32> seg;
-/*!
- \since 5.10
- \overload
+ const char *start = string.begin();
+ const char *lastGoodEnd = start;
+ const char *endOfString = string.end();
- Constructs a QVersionNumber from a specially formatted \a string of
- non-negative decimal numbers delimited by '.'.
+ do {
+ // parsing as unsigned so a minus sign is rejected
+ auto [value, used] = qstrntoull(start, endOfString - start, 10);
+ if (used <= 0 || value > qulonglong(std::numeric_limits<int>::max()))
+ break;
+ seg.append(int(value));
+ start += used + 1;
+ lastGoodEnd = start - 1;
+ } while (start < endOfString && *lastGoodEnd == '.');
- Once the numerical segments have been parsed, the remainder of the string
- is considered to be the suffix string. The start index of that string will be
- stored in \a suffixIndex if it is not null.
+ if (suffixIndex)
+ *suffixIndex = lastGoodEnd - string.begin();
- \snippet qversionnumber/main.cpp 3
+ return QVersionNumber(seg);
+}
- \sa isNull()
-*/
-QVersionNumber QVersionNumber::fromString(QStringView string, int *suffixIndex)
+static QVersionNumber from_string(q_no_char8_t::QUtf8StringView string, qsizetype *suffixIndex)
{
- return fromString(QLatin1String(string.toLatin1()), suffixIndex);
+ return from_string(QLatin1StringView(string.data(), string.size()), suffixIndex);
}
-/*!
- \since 5.10
- \overload
-
- Constructs a QVersionNumber from a specially formatted \a string of
- non-negative decimal numbers delimited by '.'.
-
- Once the numerical segments have been parsed, the remainder of the string
- is considered to be the suffix string. The start index of that string will be
- stored in \a suffixIndex if it is not null.
+// in qstring.cpp
+extern void qt_to_latin1(uchar *dst, const char16_t *uc, qsizetype len);
- \snippet qversionnumber/main.cpp 3-latin1-1
+static QVersionNumber from_string(QStringView string, qsizetype *suffixIndex)
+{
+ QVarLengthArray<char> copy;
+ copy.resize(string.size());
+ qt_to_latin1(reinterpret_cast<uchar*>(copy.data()), string.utf16(), string.size());
+ return from_string(QLatin1StringView(copy.data(), copy.size()), suffixIndex);
+}
- \sa isNull()
-*/
-QVersionNumber QVersionNumber::fromString(QLatin1String string, int *suffixIndex)
+QVersionNumber QVersionNumber::fromString(QAnyStringView string, qsizetype *suffixIndex)
{
- QList<int> seg;
+ return string.visit([=] (auto string) { return from_string(string, suffixIndex); });
+}
- const char *start = string.begin();
- const char *end = start;
- const char *lastGoodEnd = start;
- const char *endOfString = string.end();
+void QVersionNumber::SegmentStorage::setListData(const QList<int> &seg)
+{
+ pointer_segments = new QList<int>(seg);
+}
- do {
- bool ok = false;
- const qulonglong value = qstrntoull(start, endOfString - start, &end, 10, &ok);
- if (!ok || value > qulonglong(std::numeric_limits<int>::max()))
- break;
- seg.append(int(value));
- start = end + 1;
- lastGoodEnd = end;
- } while (start < endOfString && (end < endOfString && *end == '.'));
+void QVersionNumber::SegmentStorage::setListData(QList<int> &&seg)
+{
+ pointer_segments = new QList<int>(std::move(seg));
+}
- if (suffixIndex)
- *suffixIndex = int(lastGoodEnd - string.begin());
+void QVersionNumber::SegmentStorage::setListData(const int *first, const int *last)
+{
+ pointer_segments = new QList<int>(first, last);
+}
- return QVersionNumber(std::move(seg));
+void QVersionNumber::SegmentStorage::resize(qsizetype len)
+{
+ if (isUsingPointer())
+ pointer_segments->resize(len);
+ else
+ setInlineSize(len);
}
void QVersionNumber::SegmentStorage::setVector(int len, int maj, int min, int mic)
@@ -529,13 +563,13 @@ QDataStream& operator>>(QDataStream &in, QVersionNumber &version)
QDebug operator<<(QDebug debug, const QVersionNumber &version)
{
QDebugStateSaver saver(debug);
- debug.noquote() << version.toString();
+ debug.nospace().noquote();
+ debug << "QVersionNumber(" << version.toString() << ")";
return debug;
}
#endif
/*!
- \fn size_t qHash(const QVersionNumber &key, size_t seed)
\relates QHash
\since 5.6
@@ -550,199 +584,4 @@ size_t qHash(const QVersionNumber &key, size_t seed)
return seed;
}
-/*!
- \class QTypeRevision
- \inmodule QtCore
- \since 6.0
- \brief The QTypeRevision class contains a lightweight representation of
- a version number with two 8-bit segments, major and minor, either
- of which can be unknown.
-
- Use this class to describe revisions of a type. Compatible revisions can be
- expressed as increments of the minor version. Breaking changes can be
- expressed as increments of the major version. The return values of
- \l QMetaMethod::revision() and \l QMetaProperty::revision() can be passed to
- \l QTypeRevision::fromEncodedVersion(). The resulting major and minor versions
- specify in which Qt versions the properties and methods were added.
-
- \sa QMetaMethod::revision(), QMetaProperty::revision()
-*/
-
-/*!
- \fn template<typename Integer> static bool QTypeRevision::isValidSegment(Integer segment)
-
- Returns true if the given number can be used as either major or minor
- version in a QTypeRevision. The valid range for \a segment is \c {>= 0} and \c {< 255}.
-*/
-
-/*!
- \fn QTypeRevision::QTypeRevision()
-
- Produces an invalid revision.
-
- \sa isValid()
-*/
-
-/*!
- \fn template <typename Major, typename Minor> static QTypeRevision QTypeRevision::fromVersion(Major majorVersion, Minor minorVersion)
-
- Produces a QTypeRevision from the given \a majorVersion and \a minorVersion,
- both of which need to be a valid segments.
-
- \sa isValidSegment()
-*/
-
-/*!
- \fn template <typename Major> static QTypeRevision QTypeRevision::fromMajorVersion(Major majorVersion)
-
- Produces a QTypeRevision from the given \a majorVersion with an invalid minor
- version. \a majorVersion needs to be a valid segment.
-
- \sa isValidSegment()
-*/
-
-/*!
- \fn template <typename Minor> static QTypeRevision QTypeRevision::fromMinorVersion(Minor minorVersion)
-
- Produces a QTypeRevision from the given \a minorVersion with an invalid major
- version. \a minorVersion needs to be a valid segment.
-
- \sa isValidSegment()
-*/
-
-/*!
- \fn template <typename Integer> static QTypeRevision QTypeRevision::fromEncodedVersion(Integer value)
-
- Produces a QTypeRevision from the given \a value. \a value encodes both the
- minor and major versions in the least significant and second least
- significant byte, respectively.
-
- \a value must not have any bits outside the least significant two bytes set.
- \c Integer needs to be at least 16 bits wide, and must not have a sign bit
- in the least significant 16 bits.
-
- \sa toEncodedVersion()
-*/
-
-/*!
- \fn static QTypeRevision QTypeRevision::zero()
-
- Produces a QTypeRevision with major and minor version \c{0}.
-*/
-
-/*!
- \fn bool QTypeRevision::hasMajorVersion() const
-
- Returns true if the major version is known, otherwise false.
-
- \sa majorVersion(), hasMinorVersion()
-*/
-
-/*!
- \fn quint8 QTypeRevision::majorVersion() const
-
- Returns the major version encoded in the revision.
-
- \sa hasMajorVersion(), minorVersion()
-*/
-
-/*!
- \fn bool QTypeRevision::hasMinorVersion() const
-
- Returns true if the minor version is known, otherwise false.
-
- \sa minorVersion(), hasMajorVersion()
-*/
-
-/*!
- \fn quint8 QTypeRevision::minorVersion() const
-
- Returns the minor version encoded in the revision.
-
- \sa hasMinorVersion(), majorVersion()
-*/
-
-/*!
- \fn bool QTypeRevision::isValid() const
-
- Returns true if the major version or the minor version is known,
- otherwise false.
-
- \sa hasMajorVersion(), hasMinorVersion()
-*/
-
-/*!
- \fn template<typename Integer> Integer QTypeRevision::toEncodedVersion() const
-
- Transforms the revision into an integer value, encoding the minor
- version into the least significant byte, and the major version into
- the second least significant byte.
-
- \c Integer needs to be at least 16 bits wide, and must not have a sign bit
- in the least significant 16 bits.
-
- \sa fromEncodedVersion()
-*/
-
-#ifndef QT_NO_DATASTREAM
-/*!
- \fn QDataStream& operator<<(QDataStream &out, const QTypeRevision &revision)
- \relates QTypeRevision
- \since 6.0
-
- Writes the revision \a revision to stream \a out.
- */
-QDataStream &operator<<(QDataStream &out, const QTypeRevision &revision)
-{
- return out << revision.toEncodedVersion<quint16>();
-}
-
-/*!
- \fn QDataStream& operator>>(QDataStream &in, QTypeRevision &revision)
- \relates QTypeRevision
- \since 6.0
-
- Reads a revision from stream \a in and stores it in \a revision.
- */
-QDataStream &operator>>(QDataStream &in, QTypeRevision &revision)
-{
- quint16 value;
- in >> value;
- revision = QTypeRevision::fromEncodedVersion(value);
- return in;
-}
-#endif
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug debug, const QTypeRevision &revision)
-{
- QDebugStateSaver saver(debug);
- if (revision.hasMajorVersion()) {
- if (revision.hasMinorVersion())
- debug.nospace() << revision.majorVersion() << '.' << revision.minorVersion();
- else
- debug.nospace().noquote() << revision.majorVersion() << ".x";
- } else {
- if (revision.hasMinorVersion())
- debug << revision.minorVersion();
- else
- debug.noquote() << "invalid";
- }
- return debug;
-}
-#endif
-
-/*!
- \fn size_t qHash(const QTypeRevision &key, size_t seed)
- \relates QHash
- \since 6.0
-
- Returns the hash value for the \a key, using \a seed to seed the
- calculation.
-*/
-size_t qHash(const QTypeRevision &key, size_t seed)
-{
- return qHash(key.toEncodedVersion<quint16>(), seed);
-}
-
QT_END_NAMESPACE