summaryrefslogtreecommitdiffstats
path: root/src/corelib/tools/qtyperevision.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/tools/qtyperevision.h')
-rw-r--r--src/corelib/tools/qtyperevision.h167
1 files changed, 167 insertions, 0 deletions
diff --git a/src/corelib/tools/qtyperevision.h b/src/corelib/tools/qtyperevision.h
new file mode 100644
index 0000000000..8f255a77e8
--- /dev/null
+++ b/src/corelib/tools/qtyperevision.h
@@ -0,0 +1,167 @@
+// 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/qcompare.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);
+ }
+
+private:
+ friend constexpr bool
+ comparesEqual(const QTypeRevision &lhs, const QTypeRevision &rhs) noexcept
+ { return lhs.toEncodedVersion<quint16>() == rhs.toEncodedVersion<quint16>(); }
+ friend constexpr Qt::strong_ordering
+ compareThreeWay(const QTypeRevision &lhs, const QTypeRevision &rhs) noexcept
+ {
+ // For both major and minor the following rule applies:
+ // non-0 ver > unspecified ver > 0 ver
+ auto cmpUnspecified = [](quint8 leftVer, quint8 rightVer) {
+ Q_ASSERT(leftVer != rightVer
+ && (leftVer == QTypeRevision::SegmentUnknown
+ || rightVer == QTypeRevision::SegmentUnknown));
+ if (leftVer != QTypeRevision::SegmentUnknown)
+ return leftVer > 0 ? Qt::strong_ordering::greater : Qt::strong_ordering::less;
+ return rightVer > 0 ? Qt::strong_ordering::less : Qt::strong_ordering::greater;
+ };
+
+ if (lhs.hasMajorVersion() != rhs.hasMajorVersion()) {
+ return cmpUnspecified(lhs.majorVersion(), rhs.majorVersion());
+ } else {
+ const auto majorRes = Qt::compareThreeWay(lhs.majorVersion(), rhs.majorVersion());
+ if (is_eq(majorRes)) {
+ if (lhs.hasMinorVersion() != rhs.hasMinorVersion())
+ return cmpUnspecified(lhs.minorVersion(), rhs.minorVersion());
+ return Qt::compareThreeWay(lhs.minorVersion(), rhs.minorVersion());
+ }
+ return majorRes;
+ }
+ }
+ Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(QTypeRevision)
+
+ 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