File indexing completed on 2025-09-17 09:09:37
0001
0002
0003
0004
0005
0006 #ifndef QTYPEREVISION_H
0007 #define QTYPEREVISION_H
0008
0009 #include <QtCore/qassert.h>
0010 #include <QtCore/qcompare.h>
0011 #include <QtCore/qcontainertools_impl.h>
0012 #include <QtCore/qmetatype.h>
0013 #include <QtCore/qtypeinfo.h>
0014
0015 #include <limits>
0016
0017 QT_BEGIN_NAMESPACE
0018
0019 class QDataStream;
0020 class QDebug;
0021
0022 class QTypeRevision;
0023 Q_CORE_EXPORT size_t qHash(const QTypeRevision &key, size_t seed = 0);
0024
0025 #ifndef QT_NO_DATASTREAM
0026 Q_CORE_EXPORT QDataStream& operator<<(QDataStream &out, const QTypeRevision &revision);
0027 Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QTypeRevision &revision);
0028 #endif
0029
0030 class QTypeRevision
0031 {
0032 public:
0033 template<typename Integer>
0034 using if_valid_segment_type = typename std::enable_if<
0035 std::is_integral<Integer>::value, bool>::type;
0036
0037 template<typename Integer>
0038 using if_valid_value_type = typename std::enable_if<
0039 std::is_integral<Integer>::value
0040 && (sizeof(Integer) > sizeof(quint16)
0041 || (sizeof(Integer) == sizeof(quint16)
0042 && !std::is_signed<Integer>::value)), bool>::type;
0043
0044 template<typename Integer, if_valid_segment_type<Integer> = true>
0045 static constexpr bool isValidSegment(Integer segment)
0046 {
0047
0048
0049 constexpr auto Max = (std::numeric_limits<Integer>::max)() + 0;
0050 constexpr bool HasSufficientRange = Max >= SegmentUnknown;
0051 return segment >= Integer(0)
0052 && (!HasSufficientRange || segment < Integer(SegmentUnknown));
0053 }
0054
0055 template<typename Major, typename Minor,
0056 if_valid_segment_type<Major> = true,
0057 if_valid_segment_type<Minor> = true>
0058 static constexpr QTypeRevision fromVersion(Major majorVersion, Minor minorVersion)
0059 {
0060 return Q_ASSERT(isValidSegment(majorVersion)),
0061 Q_ASSERT(isValidSegment(minorVersion)),
0062 QTypeRevision(quint8(majorVersion), quint8(minorVersion));
0063 }
0064
0065 template<typename Major, if_valid_segment_type<Major> = true>
0066 static constexpr QTypeRevision fromMajorVersion(Major majorVersion)
0067 {
0068 return Q_ASSERT(isValidSegment(majorVersion)),
0069 QTypeRevision(quint8(majorVersion), SegmentUnknown);
0070 }
0071
0072 template<typename Minor, if_valid_segment_type<Minor> = true>
0073 static constexpr QTypeRevision fromMinorVersion(Minor minorVersion)
0074 {
0075 return Q_ASSERT(isValidSegment(minorVersion)),
0076 QTypeRevision(SegmentUnknown, quint8(minorVersion));
0077 }
0078
0079 template<typename Integer, if_valid_value_type<Integer> = true>
0080 static constexpr QTypeRevision fromEncodedVersion(Integer value)
0081 {
0082 return Q_ASSERT((value & ~Integer(0xffff)) == Integer(0)),
0083 QTypeRevision((value & Integer(0xff00)) >> 8, value & Integer(0xff));
0084 }
0085
0086 static constexpr QTypeRevision zero() { return QTypeRevision(0, 0); }
0087
0088 constexpr QTypeRevision() = default;
0089
0090 constexpr bool hasMajorVersion() const { return m_majorVersion != SegmentUnknown; }
0091 constexpr quint8 majorVersion() const { return m_majorVersion; }
0092
0093 constexpr bool hasMinorVersion() const { return m_minorVersion != SegmentUnknown; }
0094 constexpr quint8 minorVersion() const { return m_minorVersion; }
0095
0096 constexpr bool isValid() const { return hasMajorVersion() || hasMinorVersion(); }
0097
0098 template<typename Integer, if_valid_value_type<Integer> = true>
0099 constexpr Integer toEncodedVersion() const
0100 {
0101 return Integer(m_majorVersion << 8) | Integer(m_minorVersion);
0102 }
0103
0104 private:
0105 friend constexpr bool
0106 comparesEqual(const QTypeRevision &lhs, const QTypeRevision &rhs) noexcept
0107 { return lhs.toEncodedVersion<quint16>() == rhs.toEncodedVersion<quint16>(); }
0108 friend constexpr Qt::strong_ordering
0109 compareThreeWay(const QTypeRevision &lhs, const QTypeRevision &rhs) noexcept
0110 {
0111
0112
0113 auto cmpUnspecified = [](quint8 leftVer, quint8 rightVer) {
0114 Q_ASSERT(leftVer != rightVer
0115 && (leftVer == QTypeRevision::SegmentUnknown
0116 || rightVer == QTypeRevision::SegmentUnknown));
0117 if (leftVer != QTypeRevision::SegmentUnknown)
0118 return leftVer > 0 ? Qt::strong_ordering::greater : Qt::strong_ordering::less;
0119 return rightVer > 0 ? Qt::strong_ordering::less : Qt::strong_ordering::greater;
0120 };
0121
0122 if (lhs.hasMajorVersion() != rhs.hasMajorVersion()) {
0123 return cmpUnspecified(lhs.majorVersion(), rhs.majorVersion());
0124 } else {
0125 const auto majorRes = Qt::compareThreeWay(lhs.majorVersion(), rhs.majorVersion());
0126 if (is_eq(majorRes)) {
0127 if (lhs.hasMinorVersion() != rhs.hasMinorVersion())
0128 return cmpUnspecified(lhs.minorVersion(), rhs.minorVersion());
0129 return Qt::compareThreeWay(lhs.minorVersion(), rhs.minorVersion());
0130 }
0131 return majorRes;
0132 }
0133 }
0134 Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QTypeRevision)
0135
0136 enum { SegmentUnknown = 0xff };
0137
0138 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
0139 constexpr QTypeRevision(quint8 major, quint8 minor)
0140 : m_minorVersion(minor), m_majorVersion(major) {}
0141
0142 quint8 m_minorVersion = SegmentUnknown;
0143 quint8 m_majorVersion = SegmentUnknown;
0144 #else
0145 constexpr QTypeRevision(quint8 major, quint8 minor)
0146 : m_majorVersion(major), m_minorVersion(minor) {}
0147
0148 quint8 m_majorVersion = SegmentUnknown;
0149 quint8 m_minorVersion = SegmentUnknown;
0150 #endif
0151 };
0152
0153 static_assert(sizeof(QTypeRevision) == 2);
0154 Q_DECLARE_TYPEINFO(QTypeRevision, Q_RELOCATABLE_TYPE);
0155
0156 #ifndef QT_NO_DEBUG_STREAM
0157 Q_CORE_EXPORT QDebug operator<<(QDebug, const QTypeRevision &revision);
0158 #endif
0159
0160 QT_END_NAMESPACE
0161
0162 QT_DECL_METATYPE_EXTERN(QTypeRevision, Q_CORE_EXPORT)
0163
0164 #endif
0165
0166 #if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 2
0167
0168 #include <QtCore/qversionnumber.h>
0169 #endif