diff options
Diffstat (limited to 'src/corelib/tools/qversionnumber.h')
-rw-r--r-- | src/corelib/tools/qversionnumber.h | 275 |
1 files changed, 99 insertions, 176 deletions
diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber.h index a7c2b44a7e..e7ae107226 100644 --- a/src/corelib/tools/qversionnumber.h +++ b/src/corelib/tools/qversionnumber.h @@ -6,12 +6,17 @@ #ifndef QVERSIONNUMBER_H #define QVERSIONNUMBER_H +#include <QtCore/qcompare.h> +#include <QtCore/qcontainertools_impl.h> #include <QtCore/qlist.h> #include <QtCore/qmetatype.h> #include <QtCore/qnamespace.h> +#include <QtCore/qspan.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 @@ -110,7 +115,7 @@ class QVersionNumber Q_CORE_EXPORT void setListData(QList<int> &&seg); - explicit SegmentStorage(std::initializer_list<int> args) + explicit SegmentStorage(QSpan<const int> args) : SegmentStorage(args.begin(), args.end()) {} explicit SegmentStorage(const int *first, const int *last) @@ -188,23 +193,85 @@ class QVersionNumber Q_CORE_EXPORT void setVector(int len, int maj, int min, int mic); } m_segments; + class It + { + const QVersionNumber *v; + qsizetype i; + + friend class QVersionNumber; + explicit constexpr It(const QVersionNumber *vn, qsizetype idx) noexcept : v(vn), i(idx) {} + + friend constexpr bool comparesEqual(const It &lhs, const It &rhs) + { Q_ASSERT(lhs.v == rhs.v); return lhs.i == rhs.i; } + friend constexpr Qt::strong_ordering compareThreeWay(const It &lhs, const It &rhs) + { Q_ASSERT(lhs.v == rhs.v); return Qt::compareThreeWay(lhs.i, rhs.i); } + Q_DECLARE_STRONGLY_ORDERED_LITERAL_TYPE(It) + + public: + // Rule Of Zero applies + It() = default; + + using iterator_category = std::random_access_iterator_tag; + using value_type = int; +#ifdef QT_COMPILER_HAS_LWG3346 + using element_type = const int; +#endif + using difference_type = qptrdiff; // difference to container requirements + using size_type = qsizetype; // difference to container requirements + using reference = value_type; // difference to container requirements + using pointer = QtPrivate::ArrowProxy<reference>; + + reference operator*() const { return v->segmentAt(i); } + pointer operator->() const { return {**this}; } + + It &operator++() { ++i; return *this; } + It operator++(int) { auto copy = *this; ++*this; return copy; } + + It &operator--() { --i; return *this; } + It operator--(int) { auto copy = *this; --*this; return copy; } + + It &operator+=(difference_type n) { i += n; return *this; } + friend It operator+(It it, difference_type n) { it += n; return it; } + friend It operator+(difference_type n, It it) { return it + n; } + + It &operator-=(difference_type n) { i -= n; return *this; } + friend It operator-(It it, difference_type n) { it -= n; return it; } + + friend difference_type operator-(It lhs, It rhs) + { Q_ASSERT(lhs.v == rhs.v); return lhs.i - rhs.i; } + + reference operator[](difference_type n) const { return *(*this + n); } + }; + public: + using const_iterator = It; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + + using value_type = It::value_type; + using difference_type = It::difference_type; + using size_type = It::size_type; + using reference = It::reference; + using const_reference = reference; + using pointer = It::pointer; + using const_pointer = pointer; + inline QVersionNumber() noexcept : m_segments() {} + Q_WEAK_OVERLOAD inline explicit QVersionNumber(const QList<int> &seg) : m_segments(seg) { } // compiler-generated copy/move ctor/assignment operators and the destructor are ok + Q_WEAK_OVERLOAD explicit QVersionNumber(QList<int> &&seg) : m_segments(std::move(seg)) { } inline QVersionNumber(std::initializer_list<int> args) - : m_segments(args) + : m_segments(QSpan{args}) {} - template <qsizetype N> - explicit QVersionNumber(const QVarLengthArray<int, N> &sec) - : m_segments(sec.begin(), sec.end()) + explicit QVersionNumber(QSpan<const int> args) + : m_segments(args) {} inline explicit QVersionNumber(int maj) @@ -241,6 +308,19 @@ public: [[nodiscard]] inline qsizetype segmentCount() const noexcept { return m_segments.size(); } + [[nodiscard]] const_iterator begin() const noexcept { return const_iterator{this, 0}; } + [[nodiscard]] const_iterator end() const noexcept { return begin() + segmentCount(); } + [[nodiscard]] const_iterator cbegin() const noexcept { return begin(); } + [[nodiscard]] const_iterator cend() const noexcept { return end(); } + + [[nodiscard]] const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator{end()}; } + [[nodiscard]] const_reverse_iterator rend() const noexcept { return const_reverse_iterator{begin()}; } + [[nodiscard]] const_reverse_iterator crbegin() const noexcept { return rbegin(); } + [[nodiscard]] const_reverse_iterator crend() const noexcept { return rend(); } + + [[nodiscard]] const_iterator constBegin() const noexcept { return begin(); } + [[nodiscard]] const_iterator constEnd() const noexcept { return end(); } + [[nodiscard]] Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const noexcept; [[nodiscard]] Q_CORE_EXPORT static int compare(const QVersionNumber &v1, const QVersionNumber &v2) noexcept; @@ -276,191 +356,34 @@ public: [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(QStringView string, int *suffixIndex); #endif - [[nodiscard]] friend bool operator> (const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept - { return compare(lhs, rhs) > 0; } - - [[nodiscard]] friend bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept - { return compare(lhs, rhs) >= 0; } - - [[nodiscard]] friend bool operator< (const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept - { return compare(lhs, rhs) < 0; } - - [[nodiscard]] friend bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept - { return compare(lhs, rhs) <= 0; } - - [[nodiscard]] friend bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept - { return compare(lhs, rhs) == 0; } - - [[nodiscard]] friend bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept - { return compare(lhs, rhs) != 0; } - private: -#ifndef QT_NO_DATASTREAM - friend Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version); -#endif - friend Q_CORE_EXPORT size_t qHash(const QVersionNumber &key, size_t seed); -}; - -Q_DECLARE_TYPEINFO(QVersionNumber, Q_RELOCATABLE_TYPE); - -#ifndef QT_NO_DEBUG_STREAM -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) + [[nodiscard]] friend bool comparesEqual(const QVersionNumber &lhs, + const QVersionNumber &rhs) noexcept { - // 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)); + return compare(lhs, rhs) == 0; } - - 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) + [[nodiscard]] friend Qt::strong_ordering compareThreeWay(const QVersionNumber &lhs, + const QVersionNumber &rhs) noexcept { - return Q_ASSERT(isValidSegment(majorVersion)), - Q_ASSERT(isValidSegment(minorVersion)), - QTypeRevision(quint8(majorVersion), quint8(minorVersion)); + int c = compare(lhs, rhs); + return Qt::compareThreeWay(c, 0); } + Q_DECLARE_STRONGLY_ORDERED(QVersionNumber) - 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; +#ifndef QT_NO_DATASTREAM + friend Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version); #endif + friend Q_CORE_EXPORT size_t qHash(const QVersionNumber &key, size_t seed); }; -static_assert(sizeof(QTypeRevision) == 2); -Q_DECLARE_TYPEINFO(QTypeRevision, Q_RELOCATABLE_TYPE); +Q_DECLARE_TYPEINFO(QVersionNumber, Q_RELOCATABLE_TYPE); #ifndef QT_NO_DEBUG_STREAM -Q_CORE_EXPORT QDebug operator<<(QDebug, const QTypeRevision &revision); +Q_CORE_EXPORT QDebug operator<<(QDebug, const QVersionNumber &version); #endif QT_END_NAMESPACE QT_DECL_METATYPE_EXTERN(QVersionNumber, Q_CORE_EXPORT) -QT_DECL_METATYPE_EXTERN(QTypeRevision, Q_CORE_EXPORT) #endif // QVERSIONNUMBER_H |