diff options
author | Marc Mutz <[email protected]> | 2023-12-22 11:41:03 +0100 |
---|---|---|
committer | Marc Mutz <[email protected]> | 2024-01-10 02:25:24 +0000 |
commit | 37e2aa7698a16fb5bc0d2f74388620d921d977c3 (patch) | |
tree | 0174de0db1348b8181740bf2e15c757f1abb3763 | |
parent | 7fe7ed0a3f6c40cb4d5d060ea3cb30d1566a6998 (diff) |
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.7 6.6 6.5
Change-Id: I2fa5d0e68f95864126bc95e3d8154134eee85553
Reviewed-by: Thiago Macieira <[email protected]>
Reviewed-by: Qt CI Bot <[email protected]>
-rw-r--r-- | src/corelib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/corelib/tools/qtyperevision.cpp | 216 | ||||
-rw-r--r-- | src/corelib/tools/qtyperevision.h | 181 | ||||
-rw-r--r-- | src/corelib/tools/qversionnumber.cpp | 195 | ||||
-rw-r--r-- | src/corelib/tools/qversionnumber.h | 156 | ||||
-rw-r--r-- | src/tools/moc/moc.h | 2 | ||||
-rw-r--r-- | tests/auto/corelib/tools/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qtyperevision/CMakeLists.txt | 13 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qtyperevision/tst_qtyperevision.cpp | 168 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp | 156 | ||||
-rw-r--r-- | tests/auto/tools/moc/tst_moc.cpp | 2 |
11 files changed, 590 insertions, 501 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index 4c88ba497fa..c3f80f03d93 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -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 diff --git a/src/corelib/tools/qtyperevision.cpp b/src/corelib/tools/qtyperevision.cpp new file mode 100644 index 00000000000..c505e47f2f4 --- /dev/null +++ b/src/corelib/tools/qtyperevision.cpp @@ -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 diff --git a/src/corelib/tools/qtyperevision.h b/src/corelib/tools/qtyperevision.h new file mode 100644 index 00000000000..308d89b6aba --- /dev/null +++ b/src/corelib/tools/qtyperevision.h @@ -0,0 +1,181 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// Copyright (C) 2022 Intel Corporation. +// Copyright (C) 2015 Keith Gardner <[email protected]> +// 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 diff --git a/src/corelib/tools/qversionnumber.cpp b/src/corelib/tools/qversionnumber.cpp index 924ab0d2085..62714afbf64 100644 --- a/src/corelib/tools/qversionnumber.cpp +++ b/src/corelib/tools/qversionnumber.cpp @@ -22,7 +22,6 @@ QT_BEGIN_NAMESPACE QT_IMPL_METATYPE_EXTERN(QVersionNumber) -QT_IMPL_METATYPE_EXTERN(QTypeRevision) /*! \class QVersionNumber @@ -533,198 +532,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 diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber.h index a7c2b44a7e5..2e9e15e1fac 100644 --- a/src/corelib/tools/qversionnumber.h +++ b/src/corelib/tools/qversionnumber.h @@ -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 diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 5abab49c8b0..d425351e136 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -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> diff --git a/tests/auto/corelib/tools/CMakeLists.txt b/tests/auto/corelib/tools/CMakeLists.txt index 22836aea0e2..5cca2e2df60 100644 --- a/tests/auto/corelib/tools/CMakeLists.txt +++ b/tests/auto/corelib/tools/CMakeLists.txt @@ -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) diff --git a/tests/auto/corelib/tools/qtyperevision/CMakeLists.txt b/tests/auto/corelib/tools/qtyperevision/CMakeLists.txt new file mode 100644 index 00000000000..d39d051a513 --- /dev/null +++ b/tests/auto/corelib/tools/qtyperevision/CMakeLists.txt @@ -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 +) diff --git a/tests/auto/corelib/tools/qtyperevision/tst_qtyperevision.cpp b/tests/auto/corelib/tools/qtyperevision/tst_qtyperevision.cpp new file mode 100644 index 00000000000..3d29c73972b --- /dev/null +++ b/tests/auto/corelib/tools/qtyperevision/tst_qtyperevision.cpp @@ -0,0 +1,168 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2014 Keith Gardner <[email protected]> +// 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" diff --git a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp index cc17188c546..6b86d50f751 100644 --- a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp +++ b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp @@ -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" diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index a7fe0e94557..e12a1d66e42 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -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> |