Dissociate QTypeRevision from QVersionNumber

They have nothing to do with each other, so give QTypeRevision its own
header and implementation file instead of piggy-backing on
QVersionNumber's.

Picking back to current LTS to incur the merge conflict only once, not
per (expected) follow-up change.

Amends ed080c64ae21d22115d16780a5903d7cc4fd1546.

Pick-to: 6.6 6.5
Change-Id: I2fa5d0e68f95864126bc95e3d8154134eee85553
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
(cherry picked from commit 37e2aa7698a16fb5bc0d2f74388620d921d977c3)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Marc Mutz 2023-12-22 11:41:03 +01:00 committed by Qt Cherry-pick Bot
parent 2f59eee2bc
commit 1482081ced
11 changed files with 590 additions and 501 deletions

View File

@ -311,6 +311,7 @@ qt_internal_add_module(Core
tools/qstack.h
tools/qtaggedpointer.h
tools/qtools_p.h
tools/qtyperevision.cpp tools/qtyperevision.h
tools/quniquehandle_p.h
tools/qvarlengtharray.h
tools/qvector.h

View File

@ -0,0 +1,216 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <QtCore/qtyperevision.h>
#include <QtCore/qhashfunctions.h>
#ifndef QT_NO_DATASTREAM
# include <QtCore/qdatastream.h>
#endif
#ifndef QT_NO_DEBUG_STREAM
# include <QtCore/qdebug.h>
#endif
#include <algorithm>
#include <limits>
QT_BEGIN_NAMESPACE
QT_IMPL_METATYPE_EXTERN(QTypeRevision)
/*!
\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, QTypeRevision::if_valid_segment_type<Integer> = true> 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, QTypeRevision::if_valid_segment_type<Major> = true, QTypeRevision::if_valid_segment_type<Minor> = true> 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, QTypeRevision::if_valid_segment_type<Major> = true> 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, QTypeRevision::if_valid_segment_type<Minor> = true> 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, QTypeRevision::if_valid_value_type<Integer> = true> 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, QTypeRevision::if_valid_value_type<Integer> = true> 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
/*!
\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

View File

@ -0,0 +1,181 @@
// Copyright (C) 2020 The Qt Company Ltd.
// Copyright (C) 2022 Intel Corporation.
// Copyright (C) 2015 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
#ifndef QTYPEREVISION_H
#define QTYPEREVISION_H
#include <QtCore/qassert.h>
#include <QtCore/qcontainertools_impl.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qtypeinfo.h>
#include <limits>
QT_BEGIN_NAMESPACE
class QDataStream;
class QDebug;
class QTypeRevision;
Q_CORE_EXPORT size_t qHash(const QTypeRevision &key, size_t seed = 0);
#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream& operator<<(QDataStream &out, const QTypeRevision &revision);
Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QTypeRevision &revision);
#endif
class QTypeRevision
{
public:
template<typename Integer>
using if_valid_segment_type = typename std::enable_if<
std::is_integral<Integer>::value, bool>::type;
template<typename Integer>
using if_valid_value_type = typename std::enable_if<
std::is_integral<Integer>::value
&& (sizeof(Integer) > sizeof(quint16)
|| (sizeof(Integer) == sizeof(quint16)
&& !std::is_signed<Integer>::value)), bool>::type;
template<typename Integer, if_valid_segment_type<Integer> = true>
static constexpr bool isValidSegment(Integer segment)
{
// using extra parentheses around max to avoid expanding it if it is a macro
return segment >= Integer(0)
&& ((std::numeric_limits<Integer>::max)() < Integer(SegmentUnknown)
|| segment < Integer(SegmentUnknown));
}
template<typename Major, typename Minor,
if_valid_segment_type<Major> = true,
if_valid_segment_type<Minor> = true>
static constexpr QTypeRevision fromVersion(Major majorVersion, Minor minorVersion)
{
return Q_ASSERT(isValidSegment(majorVersion)),
Q_ASSERT(isValidSegment(minorVersion)),
QTypeRevision(quint8(majorVersion), quint8(minorVersion));
}
template<typename Major, if_valid_segment_type<Major> = true>
static constexpr QTypeRevision fromMajorVersion(Major majorVersion)
{
return Q_ASSERT(isValidSegment(majorVersion)),
QTypeRevision(quint8(majorVersion), SegmentUnknown);
}
template<typename Minor, if_valid_segment_type<Minor> = true>
static constexpr QTypeRevision fromMinorVersion(Minor minorVersion)
{
return Q_ASSERT(isValidSegment(minorVersion)),
QTypeRevision(SegmentUnknown, quint8(minorVersion));
}
template<typename Integer, if_valid_value_type<Integer> = true>
static constexpr QTypeRevision fromEncodedVersion(Integer value)
{
return Q_ASSERT((value & ~Integer(0xffff)) == Integer(0)),
QTypeRevision((value & Integer(0xff00)) >> 8, value & Integer(0xff));
}
static constexpr QTypeRevision zero() { return QTypeRevision(0, 0); }
constexpr QTypeRevision() = default;
constexpr bool hasMajorVersion() const { return m_majorVersion != SegmentUnknown; }
constexpr quint8 majorVersion() const { return m_majorVersion; }
constexpr bool hasMinorVersion() const { return m_minorVersion != SegmentUnknown; }
constexpr quint8 minorVersion() const { return m_minorVersion; }
constexpr bool isValid() const { return hasMajorVersion() || hasMinorVersion(); }
template<typename Integer, if_valid_value_type<Integer> = true>
constexpr Integer toEncodedVersion() const
{
return Integer(m_majorVersion << 8) | Integer(m_minorVersion);
}
[[nodiscard]] friend constexpr bool operator==(QTypeRevision lhs, QTypeRevision rhs)
{
return lhs.toEncodedVersion<quint16>() == rhs.toEncodedVersion<quint16>();
}
[[nodiscard]] friend constexpr bool operator!=(QTypeRevision lhs, QTypeRevision rhs)
{
return lhs.toEncodedVersion<quint16>() != rhs.toEncodedVersion<quint16>();
}
[[nodiscard]] friend constexpr bool operator<(QTypeRevision lhs, QTypeRevision rhs)
{
return (!lhs.hasMajorVersion() && rhs.hasMajorVersion())
// non-0 major > unspecified major > major 0
? rhs.majorVersion() != 0
: ((lhs.hasMajorVersion() && !rhs.hasMajorVersion())
// major 0 < unspecified major < non-0 major
? lhs.majorVersion() == 0
: (lhs.majorVersion() != rhs.majorVersion()
// both majors specified and non-0
? lhs.majorVersion() < rhs.majorVersion()
: ((!lhs.hasMinorVersion() && rhs.hasMinorVersion())
// non-0 minor > unspecified minor > minor 0
? rhs.minorVersion() != 0
: ((lhs.hasMinorVersion() && !rhs.hasMinorVersion())
// minor 0 < unspecified minor < non-0 minor
? lhs.minorVersion() == 0
// both minors specified and non-0
: lhs.minorVersion() < rhs.minorVersion()))));
}
[[nodiscard]] friend constexpr bool operator>(QTypeRevision lhs, QTypeRevision rhs)
{
return lhs != rhs && !(lhs < rhs);
}
[[nodiscard]] friend constexpr bool operator<=(QTypeRevision lhs, QTypeRevision rhs)
{
return lhs == rhs || lhs < rhs;
}
[[nodiscard]] friend constexpr bool operator>=(QTypeRevision lhs, QTypeRevision rhs)
{
return lhs == rhs || !(lhs < rhs);
}
private:
enum { SegmentUnknown = 0xff };
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
constexpr QTypeRevision(quint8 major, quint8 minor)
: m_minorVersion(minor), m_majorVersion(major) {}
quint8 m_minorVersion = SegmentUnknown;
quint8 m_majorVersion = SegmentUnknown;
#else
constexpr QTypeRevision(quint8 major, quint8 minor)
: m_majorVersion(major), m_minorVersion(minor) {}
quint8 m_majorVersion = SegmentUnknown;
quint8 m_minorVersion = SegmentUnknown;
#endif
};
static_assert(sizeof(QTypeRevision) == 2);
Q_DECLARE_TYPEINFO(QTypeRevision, Q_RELOCATABLE_TYPE);
#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug, const QTypeRevision &revision);
#endif
QT_END_NAMESPACE
QT_DECL_METATYPE_EXTERN(QTypeRevision, Q_CORE_EXPORT)
#endif // QTYPEREVISION_H
#if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 2
// make QVersionNumber available from <QTypeRevision>
#include <QtCore/qversionnumber.h>
#endif

View File

@ -22,7 +22,6 @@
QT_BEGIN_NAMESPACE
QT_IMPL_METATYPE_EXTERN(QVersionNumber)
QT_IMPL_METATYPE_EXTERN(QTypeRevision)
/*!
\class QVersionNumber
@ -538,198 +537,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, QTypeRevision::if_valid_segment_type<Integer> = true> 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, QTypeRevision::if_valid_segment_type<Major> = true, QTypeRevision::if_valid_segment_type<Minor> = true> 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, QTypeRevision::if_valid_segment_type<Major> = true> 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, QTypeRevision::if_valid_segment_type<Minor> = true> 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, QTypeRevision::if_valid_value_type<Integer> = true> 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, QTypeRevision::if_valid_value_type<Integer> = true> 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
/*!
\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

View File

@ -11,7 +11,9 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qstring.h>
#include <QtCore/qtypeinfo.h>
#include <limits>
#if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 2
#include <QtCore/qtyperevision.h>
#endif // lean headers level 2
QT_BEGIN_NAMESPACE
@ -307,160 +309,8 @@ Q_DECLARE_TYPEINFO(QVersionNumber, Q_RELOCATABLE_TYPE);
Q_CORE_EXPORT QDebug operator<<(QDebug, const QVersionNumber &version);
#endif
class QTypeRevision;
Q_CORE_EXPORT size_t qHash(const QTypeRevision &key, size_t seed = 0);
#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream& operator<<(QDataStream &out, const QTypeRevision &revision);
Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QTypeRevision &revision);
#endif
class QTypeRevision
{
public:
template<typename Integer>
using if_valid_segment_type = typename std::enable_if<
std::is_integral<Integer>::value, bool>::type;
template<typename Integer>
using if_valid_value_type = typename std::enable_if<
std::is_integral<Integer>::value
&& (sizeof(Integer) > sizeof(quint16)
|| (sizeof(Integer) == sizeof(quint16)
&& !std::is_signed<Integer>::value)), bool>::type;
template<typename Integer, if_valid_segment_type<Integer> = true>
static constexpr bool isValidSegment(Integer segment)
{
// using extra parentheses around max to avoid expanding it if it is a macro
return segment >= Integer(0)
&& ((std::numeric_limits<Integer>::max)() < Integer(SegmentUnknown)
|| segment < Integer(SegmentUnknown));
}
template<typename Major, typename Minor,
if_valid_segment_type<Major> = true,
if_valid_segment_type<Minor> = true>
static constexpr QTypeRevision fromVersion(Major majorVersion, Minor minorVersion)
{
return Q_ASSERT(isValidSegment(majorVersion)),
Q_ASSERT(isValidSegment(minorVersion)),
QTypeRevision(quint8(majorVersion), quint8(minorVersion));
}
template<typename Major, if_valid_segment_type<Major> = true>
static constexpr QTypeRevision fromMajorVersion(Major majorVersion)
{
return Q_ASSERT(isValidSegment(majorVersion)),
QTypeRevision(quint8(majorVersion), SegmentUnknown);
}
template<typename Minor, if_valid_segment_type<Minor> = true>
static constexpr QTypeRevision fromMinorVersion(Minor minorVersion)
{
return Q_ASSERT(isValidSegment(minorVersion)),
QTypeRevision(SegmentUnknown, quint8(minorVersion));
}
template<typename Integer, if_valid_value_type<Integer> = true>
static constexpr QTypeRevision fromEncodedVersion(Integer value)
{
return Q_ASSERT((value & ~Integer(0xffff)) == Integer(0)),
QTypeRevision((value & Integer(0xff00)) >> 8, value & Integer(0xff));
}
static constexpr QTypeRevision zero() { return QTypeRevision(0, 0); }
constexpr QTypeRevision() = default;
constexpr bool hasMajorVersion() const { return m_majorVersion != SegmentUnknown; }
constexpr quint8 majorVersion() const { return m_majorVersion; }
constexpr bool hasMinorVersion() const { return m_minorVersion != SegmentUnknown; }
constexpr quint8 minorVersion() const { return m_minorVersion; }
constexpr bool isValid() const { return hasMajorVersion() || hasMinorVersion(); }
template<typename Integer, if_valid_value_type<Integer> = true>
constexpr Integer toEncodedVersion() const
{
return Integer(m_majorVersion << 8) | Integer(m_minorVersion);
}
[[nodiscard]] friend constexpr bool operator==(QTypeRevision lhs, QTypeRevision rhs)
{
return lhs.toEncodedVersion<quint16>() == rhs.toEncodedVersion<quint16>();
}
[[nodiscard]] friend constexpr bool operator!=(QTypeRevision lhs, QTypeRevision rhs)
{
return lhs.toEncodedVersion<quint16>() != rhs.toEncodedVersion<quint16>();
}
[[nodiscard]] friend constexpr bool operator<(QTypeRevision lhs, QTypeRevision rhs)
{
return (!lhs.hasMajorVersion() && rhs.hasMajorVersion())
// non-0 major > unspecified major > major 0
? rhs.majorVersion() != 0
: ((lhs.hasMajorVersion() && !rhs.hasMajorVersion())
// major 0 < unspecified major < non-0 major
? lhs.majorVersion() == 0
: (lhs.majorVersion() != rhs.majorVersion()
// both majors specified and non-0
? lhs.majorVersion() < rhs.majorVersion()
: ((!lhs.hasMinorVersion() && rhs.hasMinorVersion())
// non-0 minor > unspecified minor > minor 0
? rhs.minorVersion() != 0
: ((lhs.hasMinorVersion() && !rhs.hasMinorVersion())
// minor 0 < unspecified minor < non-0 minor
? lhs.minorVersion() == 0
// both minors specified and non-0
: lhs.minorVersion() < rhs.minorVersion()))));
}
[[nodiscard]] friend constexpr bool operator>(QTypeRevision lhs, QTypeRevision rhs)
{
return lhs != rhs && !(lhs < rhs);
}
[[nodiscard]] friend constexpr bool operator<=(QTypeRevision lhs, QTypeRevision rhs)
{
return lhs == rhs || lhs < rhs;
}
[[nodiscard]] friend constexpr bool operator>=(QTypeRevision lhs, QTypeRevision rhs)
{
return lhs == rhs || !(lhs < rhs);
}
private:
enum { SegmentUnknown = 0xff };
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
constexpr QTypeRevision(quint8 major, quint8 minor)
: m_minorVersion(minor), m_majorVersion(major) {}
quint8 m_minorVersion = SegmentUnknown;
quint8 m_majorVersion = SegmentUnknown;
#else
constexpr QTypeRevision(quint8 major, quint8 minor)
: m_majorVersion(major), m_minorVersion(minor) {}
quint8 m_majorVersion = SegmentUnknown;
quint8 m_minorVersion = SegmentUnknown;
#endif
};
static_assert(sizeof(QTypeRevision) == 2);
Q_DECLARE_TYPEINFO(QTypeRevision, Q_RELOCATABLE_TYPE);
#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug, const QTypeRevision &revision);
#endif
QT_END_NAMESPACE
QT_DECL_METATYPE_EXTERN(QVersionNumber, Q_CORE_EXPORT)
QT_DECL_METATYPE_EXTERN(QTypeRevision, Q_CORE_EXPORT)
#endif // QVERSIONNUMBER_H

View File

@ -10,7 +10,7 @@
#include <qjsondocument.h>
#include <qjsonarray.h>
#include <qjsonobject.h>
#include <qversionnumber.h>
#include <qtyperevision.h>
#include <stdio.h>
#include <private/qtools_p.h>

View File

@ -42,6 +42,7 @@ add_subdirectory(qscopedpointer)
add_subdirectory(qscopedvaluerollback)
add_subdirectory(qscopeguard)
add_subdirectory(qtaggedpointer)
add_subdirectory(qtyperevision)
add_subdirectory(qset)
add_subdirectory(qsharedpointer)
add_subdirectory(qsize)

View File

@ -0,0 +1,13 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_qtyperevision LANGUAGES CXX)
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
qt_internal_add_test(tst_qtyperevision
SOURCES
tst_qtyperevision.cpp
)

View File

@ -0,0 +1,168 @@
// Copyright (C) 2016 The Qt Company Ltd.
// Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com>
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QTest>
#include <QtCore/qtyperevision.h>
class tst_QTypeRevision : public QObject
{
Q_OBJECT
private slots:
void qTypeRevision_data();
void qTypeRevision();
void qTypeRevisionTypes();
void qTypeRevisionComparison();
};
template<typename Integer>
void compileTestRevisionMajorMinor()
{
const Integer major = 8;
const Integer minor = 4;
const QTypeRevision r2 = QTypeRevision::fromVersion(major, minor);
QCOMPARE(r2.majorVersion(), 8);
QCOMPARE(r2.minorVersion(), 4);
const QTypeRevision r3 = QTypeRevision::fromMajorVersion(major);
QCOMPARE(r3.majorVersion(), 8);
QVERIFY(!r3.hasMinorVersion());
const QTypeRevision r4 = QTypeRevision::fromMinorVersion(minor);
QVERIFY(!r4.hasMajorVersion());
QCOMPARE(r4.minorVersion(), 4);
}
template<typename Integer>
void compileTestRevision()
{
if (std::is_signed<Integer>::value)
compileTestRevision<typename QIntegerForSize<sizeof(Integer) / 2>::Signed>();
else
compileTestRevision<typename QIntegerForSize<sizeof(Integer) / 2>::Unsigned>();
const Integer value = 0x0510;
const QTypeRevision r = QTypeRevision::fromEncodedVersion(value);
QCOMPARE(r.majorVersion(), 5);
QCOMPARE(r.minorVersion(), 16);
QCOMPARE(r.toEncodedVersion<Integer>(), value);
compileTestRevisionMajorMinor<Integer>();
}
template<>
void compileTestRevision<qint16>()
{
compileTestRevisionMajorMinor<quint8>();
}
template<>
void compileTestRevision<quint8>()
{
compileTestRevisionMajorMinor<quint8>();
}
template<>
void compileTestRevision<qint8>()
{
compileTestRevisionMajorMinor<qint8>();
}
void tst_QTypeRevision::qTypeRevision_data()
{
QTest::addColumn<QTypeRevision>("revision");
QTest::addColumn<bool>("valid");
QTest::addColumn<int>("major");
QTest::addColumn<int>("minor");
QTest::addRow("Qt revision") << QTypeRevision::fromVersion(QT_VERSION_MAJOR, QT_VERSION_MINOR)
<< true << QT_VERSION_MAJOR << QT_VERSION_MINOR;
QTest::addRow("invalid") << QTypeRevision() << false << 0xff << 0xff;
QTest::addRow("major") << QTypeRevision::fromMajorVersion(6) << true << 6 << 0xff;
QTest::addRow("minor") << QTypeRevision::fromMinorVersion(15) << true << 0xff << 15;
QTest::addRow("zero") << QTypeRevision::fromVersion(0, 0) << true << 0 << 0;
// We're intentionally not testing negative numbers.
// There are asserts against negative numbers in QTypeRevision.
// You must not pass them as major or minor versions, or values.
}
void tst_QTypeRevision::qTypeRevision()
{
const QTypeRevision other = QTypeRevision::fromVersion(127, 128);
QFETCH(QTypeRevision, revision);
QFETCH(bool, valid);
QFETCH(int, major);
QFETCH(int, minor);
QCOMPARE(revision.isValid(), valid);
QCOMPARE(revision.majorVersion(), major);
QCOMPARE(revision.minorVersion(), minor);
QCOMPARE(revision.hasMajorVersion(), QTypeRevision::isValidSegment(major));
QCOMPARE(revision.hasMinorVersion(), QTypeRevision::isValidSegment(minor));
const QTypeRevision copy = QTypeRevision::fromEncodedVersion(revision.toEncodedVersion<int>());
QCOMPARE(copy, revision);
QVERIFY(revision != other);
QVERIFY(copy != other);
}
void tst_QTypeRevision::qTypeRevisionTypes()
{
compileTestRevision<quint64>();
compileTestRevision<qint64>();
QVERIFY(!QTypeRevision::isValidSegment(0xff));
QVERIFY(!QTypeRevision::isValidSegment(-1));
const QTypeRevision maxRevision = QTypeRevision::fromVersion(254, 254);
QVERIFY(maxRevision.hasMajorVersion());
QVERIFY(maxRevision.hasMinorVersion());
}
void tst_QTypeRevision::qTypeRevisionComparison()
{
const QTypeRevision revisions[] = {
QTypeRevision::zero(),
QTypeRevision::fromMajorVersion(0),
QTypeRevision::fromVersion(0, 1),
QTypeRevision::fromVersion(0, 20),
QTypeRevision::fromMinorVersion(0),
QTypeRevision(),
QTypeRevision::fromMinorVersion(1),
QTypeRevision::fromMinorVersion(20),
QTypeRevision::fromVersion(1, 0),
QTypeRevision::fromMajorVersion(1),
QTypeRevision::fromVersion(1, 1),
QTypeRevision::fromVersion(1, 20),
QTypeRevision::fromVersion(20, 0),
QTypeRevision::fromMajorVersion(20),
QTypeRevision::fromVersion(20, 1),
QTypeRevision::fromVersion(20, 20),
};
const int length = sizeof(revisions) / sizeof(QTypeRevision);
for (int i = 0; i < length; ++i) {
for (int j = 0; j < length; ++j) {
QCOMPARE(revisions[i] == revisions[j], i == j);
QCOMPARE(revisions[i] != revisions[j], i != j);
QCOMPARE(revisions[i] < revisions[j], i < j);
QCOMPARE(revisions[i] > revisions[j], i > j);
QCOMPARE(revisions[i] <= revisions[j], i <= j);
QCOMPARE(revisions[i] >= revisions[j], i >= j);
}
}
}
QTEST_APPLESS_MAIN(tst_QTypeRevision)
#include "tst_qtyperevision.moc"

View File

@ -57,10 +57,6 @@ private slots:
void serialize();
void moveSemantics();
void qtVersion();
void qTypeRevision_data();
void qTypeRevision();
void qTypeRevisionTypes();
void qTypeRevisionComparison();
};
void tst_QVersionNumber::singleInstanceData()
@ -244,6 +240,11 @@ void tst_QVersionNumber::constructorExplicit()
QVersionNumber v8 = {4, 5, 6};
QCOMPARE(v7.segments(), v8.segments());
QVersionNumber v9(4, 5, 6);
QVersionNumber vA({4, 5, 6});
QCOMPARE(v9.segments(), vA.segments());
}
void tst_QVersionNumber::constructorCopy_data()
@ -665,153 +666,6 @@ void tst_QVersionNumber::qtVersion()
QCOMPARE(v.toString(), QString(qVersion()));
}
template<typename Integer>
void compileTestRevisionMajorMinor()
{
const Integer major = 8;
const Integer minor = 4;
const QTypeRevision r2 = QTypeRevision::fromVersion(major, minor);
QCOMPARE(r2.majorVersion(), 8);
QCOMPARE(r2.minorVersion(), 4);
const QTypeRevision r3 = QTypeRevision::fromMajorVersion(major);
QCOMPARE(r3.majorVersion(), 8);
QVERIFY(!r3.hasMinorVersion());
const QTypeRevision r4 = QTypeRevision::fromMinorVersion(minor);
QVERIFY(!r4.hasMajorVersion());
QCOMPARE(r4.minorVersion(), 4);
}
template<typename Integer>
void compileTestRevision()
{
if (std::is_signed<Integer>::value)
compileTestRevision<typename QIntegerForSize<sizeof(Integer) / 2>::Signed>();
else
compileTestRevision<typename QIntegerForSize<sizeof(Integer) / 2>::Unsigned>();
const Integer value = 0x0510;
const QTypeRevision r = QTypeRevision::fromEncodedVersion(value);
QCOMPARE(r.majorVersion(), 5);
QCOMPARE(r.minorVersion(), 16);
QCOMPARE(r.toEncodedVersion<Integer>(), value);
compileTestRevisionMajorMinor<Integer>();
}
template<>
void compileTestRevision<qint16>()
{
compileTestRevisionMajorMinor<quint8>();
}
template<>
void compileTestRevision<quint8>()
{
compileTestRevisionMajorMinor<quint8>();
}
template<>
void compileTestRevision<qint8>()
{
compileTestRevisionMajorMinor<qint8>();
}
void tst_QVersionNumber::qTypeRevision_data()
{
QTest::addColumn<QTypeRevision>("revision");
QTest::addColumn<bool>("valid");
QTest::addColumn<int>("major");
QTest::addColumn<int>("minor");
QTest::addRow("Qt revision") << QTypeRevision::fromVersion(QT_VERSION_MAJOR, QT_VERSION_MINOR)
<< true << QT_VERSION_MAJOR << QT_VERSION_MINOR;
QTest::addRow("invalid") << QTypeRevision() << false << 0xff << 0xff;
QTest::addRow("major") << QTypeRevision::fromMajorVersion(6) << true << 6 << 0xff;
QTest::addRow("minor") << QTypeRevision::fromMinorVersion(15) << true << 0xff << 15;
QTest::addRow("zero") << QTypeRevision::fromVersion(0, 0) << true << 0 << 0;
// We're intentionally not testing negative numbers.
// There are asserts against negative numbers in QTypeRevision.
// You must not pass them as major or minor versions, or values.
}
void tst_QVersionNumber::qTypeRevision()
{
const QTypeRevision other = QTypeRevision::fromVersion(127, 128);
QFETCH(QTypeRevision, revision);
QFETCH(bool, valid);
QFETCH(int, major);
QFETCH(int, minor);
QCOMPARE(revision.isValid(), valid);
QCOMPARE(revision.majorVersion(), major);
QCOMPARE(revision.minorVersion(), minor);
QCOMPARE(revision.hasMajorVersion(), QTypeRevision::isValidSegment(major));
QCOMPARE(revision.hasMinorVersion(), QTypeRevision::isValidSegment(minor));
const QTypeRevision copy = QTypeRevision::fromEncodedVersion(revision.toEncodedVersion<int>());
QCOMPARE(copy, revision);
QVERIFY(revision != other);
QVERIFY(copy != other);
}
void tst_QVersionNumber::qTypeRevisionTypes()
{
compileTestRevision<quint64>();
compileTestRevision<qint64>();
QVERIFY(!QTypeRevision::isValidSegment(0xff));
QVERIFY(!QTypeRevision::isValidSegment(-1));
const QTypeRevision maxRevision = QTypeRevision::fromVersion(254, 254);
QVERIFY(maxRevision.hasMajorVersion());
QVERIFY(maxRevision.hasMinorVersion());
}
void tst_QVersionNumber::qTypeRevisionComparison()
{
const QTypeRevision revisions[] = {
QTypeRevision::zero(),
QTypeRevision::fromMajorVersion(0),
QTypeRevision::fromVersion(0, 1),
QTypeRevision::fromVersion(0, 20),
QTypeRevision::fromMinorVersion(0),
QTypeRevision(),
QTypeRevision::fromMinorVersion(1),
QTypeRevision::fromMinorVersion(20),
QTypeRevision::fromVersion(1, 0),
QTypeRevision::fromMajorVersion(1),
QTypeRevision::fromVersion(1, 1),
QTypeRevision::fromVersion(1, 20),
QTypeRevision::fromVersion(20, 0),
QTypeRevision::fromMajorVersion(20),
QTypeRevision::fromVersion(20, 1),
QTypeRevision::fromVersion(20, 20),
};
const int length = sizeof(revisions) / sizeof(QTypeRevision);
for (int i = 0; i < length; ++i) {
for (int j = 0; j < length; ++j) {
QCOMPARE(revisions[i] == revisions[j], i == j);
QCOMPARE(revisions[i] != revisions[j], i != j);
QCOMPARE(revisions[i] < revisions[j], i < j);
QCOMPARE(revisions[i] > revisions[j], i > j);
QCOMPARE(revisions[i] <= revisions[j], i <= j);
QCOMPARE(revisions[i] >= revisions[j], i >= j);
}
}
}
QTEST_APPLESS_MAIN(tst_QVersionNumber)
#include "tst_qversionnumber.moc"

View File

@ -8,8 +8,8 @@
#include <qobject.h>
#include <qmetaobject.h>
#include <qjsondocument.h>
#include <qversionnumber.h>
#include <qregularexpression.h>
#include <qtyperevision.h>
#include <private/qobject_p.h>