diff options
Diffstat (limited to 'src/corelib/tools/qversionnumber.h')
-rw-r--r-- | src/corelib/tools/qversionnumber.h | 333 |
1 files changed, 203 insertions, 130 deletions
diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber.h index d43b86ba51..e7ae107226 100644 --- a/src/corelib/tools/qversionnumber.h +++ b/src/corelib/tools/qversionnumber.h @@ -1,61 +1,31 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. -** Copyright (C) 2014 Keith Gardner <kreios4004@gmail.com> -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// 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 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/qvector.h> -#include <QtCore/qmetatype.h> #include <QtCore/qtypeinfo.h> +#if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 2 +#include <QtCore/qtyperevision.h> +#endif // lean headers level 2 QT_BEGIN_NAMESPACE class QVersionNumber; -Q_CORE_EXPORT uint qHash(const QVersionNumber &key, uint seed = 0); +Q_CORE_EXPORT size_t qHash(const QVersionNumber &key, size_t seed = 0); #ifndef QT_NO_DATASTREAM -Q_CORE_EXPORT QDataStream& operator<<(QDataStream &out, const QVersionNumber &version); -Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version); +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &out, const QVersionNumber &version); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &in, QVersionNumber &version); #endif class QVersionNumber @@ -70,37 +40,40 @@ class QVersionNumber enum { // in little-endian, inline_segments[0] is shared with the pointer's LSB, while // in big-endian, it's inline_segments[7] - InlineSegmentMarker = Q_BYTE_ORDER == Q_LITTLE_ENDIAN ? 0 : sizeof(void*) - 1, + InlineSegmentMarker = Q_BYTE_ORDER == Q_LITTLE_ENDIAN ? 0 : sizeof(void *) - 1, InlineSegmentStartIdx = !InlineSegmentMarker, // 0 for BE, 1 for LE - InlineSegmentCount = sizeof(void*) - 1 + InlineSegmentCount = sizeof(void *) - 1 }; - Q_STATIC_ASSERT(InlineSegmentCount >= 3); // at least major, minor, micro + static_assert(InlineSegmentCount >= 3); // at least major, minor, micro - struct SegmentStorage { + struct SegmentStorage + { // Note: we alias the use of dummy and inline_segments in the use of the // union below. This is undefined behavior in C++98, but most compilers implement // the C++11 behavior. The one known exception is older versions of Sun Studio. union { quintptr dummy; - qint8 inline_segments[sizeof(void*)]; - QVector<int> *pointer_segments; + qint8 inline_segments[sizeof(void *)]; + QList<int> *pointer_segments; }; // set the InlineSegmentMarker and set length to zero SegmentStorage() noexcept : dummy(1) {} - SegmentStorage(const QVector<int> &seg) + SegmentStorage(const QList<int> &seg) { - if (dataFitsInline(seg.begin(), seg.size())) - setInlineData(seg.begin(), seg.size()); + if (dataFitsInline(seg.data(), seg.size())) + setInlineData(seg.data(), seg.size()); else - pointer_segments = new QVector<int>(seg); + setListData(seg); } + Q_CORE_EXPORT void setListData(const QList<int> &seg); + SegmentStorage(const SegmentStorage &other) { if (other.isUsingPointer()) - pointer_segments = new QVector<int>(*other.pointer_segments); + setListData(*other.pointer_segments); else dummy = other.dummy; } @@ -110,7 +83,7 @@ class QVersionNumber if (isUsingPointer() && other.isUsingPointer()) { *pointer_segments = *other.pointer_segments; } else if (other.isUsingPointer()) { - pointer_segments = new QVector<int>(*other.pointer_segments); + setListData(*other.pointer_segments); } else { if (isUsingPointer()) delete pointer_segments; @@ -125,48 +98,54 @@ class QVersionNumber other.dummy = 1; } - SegmentStorage &operator=(SegmentStorage &&other) noexcept + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(SegmentStorage) + + void swap(SegmentStorage &other) noexcept { - qSwap(dummy, other.dummy); - return *this; + std::swap(dummy, other.dummy); } - explicit SegmentStorage(QVector<int> &&seg) + explicit SegmentStorage(QList<int> &&seg) { - if (dataFitsInline(seg.begin(), seg.size())) - setInlineData(seg.begin(), seg.size()); + if (dataFitsInline(std::as_const(seg).data(), seg.size())) + setInlineData(std::as_const(seg).data(), seg.size()); else - pointer_segments = new QVector<int>(std::move(seg)); + setListData(std::move(seg)); } - SegmentStorage(std::initializer_list<int> args) + + Q_CORE_EXPORT void setListData(QList<int> &&seg); + + explicit SegmentStorage(QSpan<const int> args) + : SegmentStorage(args.begin(), args.end()) {} + + explicit SegmentStorage(const int *first, const int *last) { - if (dataFitsInline(args.begin(), int(args.size()))) { - setInlineData(args.begin(), int(args.size())); + if (dataFitsInline(first, last - first)) { + setInlineData(first, last - first); } else { - pointer_segments = new QVector<int>(args); + setListData(first, last); } } + Q_CORE_EXPORT void setListData(const int *first, const int *last); + ~SegmentStorage() { if (isUsingPointer()) delete pointer_segments; } bool isUsingPointer() const noexcept { return (inline_segments[InlineSegmentMarker] & 1) == 0; } - int size() const noexcept + qsizetype size() const noexcept { return isUsingPointer() ? pointer_segments->size() : (inline_segments[InlineSegmentMarker] >> 1); } - void setInlineSize(int len) - { inline_segments[InlineSegmentMarker] = 1 + 2 * len; } - - void resize(int len) + void setInlineSize(qsizetype len) { - if (isUsingPointer()) - pointer_segments->resize(len); - else - setInlineSize(len); + Q_ASSERT(len <= InlineSegmentCount); + inline_segments[InlineSegmentMarker] = qint8(1 + 2 * len); } - int at(int index) const + Q_CORE_EXPORT void resize(qsizetype len); + + int at(qsizetype index) const { return isUsingPointer() ? pointer_segments->at(index) : @@ -184,28 +163,29 @@ class QVersionNumber } private: - static bool dataFitsInline(const int *data, int len) + static bool dataFitsInline(const int *data, qsizetype len) { if (len > InlineSegmentCount) return false; - for (int i = 0; i < len; ++i) + for (qsizetype i = 0; i < len; ++i) if (data[i] != qint8(data[i])) return false; return true; } - void setInlineData(const int *data, int len) + void setInlineData(const int *data, qsizetype len) { + Q_ASSERT(len <= InlineSegmentCount); dummy = 1 + len * 2; #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN - for (int i = 0; i < len; ++i) + for (qsizetype i = 0; i < len; ++i) dummy |= quintptr(data[i] & 0xFF) << (8 * (i + 1)); #elif Q_BYTE_ORDER == Q_BIG_ENDIAN - for (int i = 0; i < len; ++i) + for (qsizetype i = 0; i < len; ++i) dummy |= quintptr(data[i] & 0xFF) << (8 * (sizeof(void *) - i - 1)); #else // the code above is equivalent to: setInlineSize(len); - for (int i = 0; i < len; ++i) + for (qsizetype i = 0; i < len; ++i) inline_segments[InlineSegmentStartIdx + i] = data[i] & 0xFF; #endif } @@ -213,21 +193,84 @@ 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() {} - inline explicit QVersionNumber(const QVector<int> &seg) - : m_segments(seg) - {} + 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 - explicit QVersionNumber(QVector<int> &&seg) - : m_segments(std::move(seg)) - {} + Q_WEAK_OVERLOAD + explicit QVersionNumber(QList<int> &&seg) : m_segments(std::move(seg)) { } inline QVersionNumber(std::initializer_list<int> args) + : m_segments(QSpan{args}) + {} + + explicit QVersionNumber(QSpan<const int> args) : m_segments(args) {} @@ -240,77 +283,107 @@ public: inline explicit QVersionNumber(int maj, int min, int mic) { m_segments.setSegments(3, maj, min, mic); } - Q_REQUIRED_RESULT inline bool isNull() const noexcept + [[nodiscard]] inline bool isNull() const noexcept { return segmentCount() == 0; } - Q_REQUIRED_RESULT inline bool isNormalized() const noexcept + [[nodiscard]] inline bool isNormalized() const noexcept { return isNull() || segmentAt(segmentCount() - 1) != 0; } - Q_REQUIRED_RESULT inline int majorVersion() const noexcept + [[nodiscard]] inline int majorVersion() const noexcept { return segmentAt(0); } - Q_REQUIRED_RESULT inline int minorVersion() const noexcept + [[nodiscard]] inline int minorVersion() const noexcept { return segmentAt(1); } - Q_REQUIRED_RESULT inline int microVersion() const noexcept + [[nodiscard]] inline int microVersion() const noexcept { return segmentAt(2); } - Q_REQUIRED_RESULT Q_CORE_EXPORT QVersionNumber normalized() const; + [[nodiscard]] Q_CORE_EXPORT QVersionNumber normalized() const; - Q_REQUIRED_RESULT Q_CORE_EXPORT QVector<int> segments() const; + [[nodiscard]] Q_CORE_EXPORT QList<int> segments() const; - Q_REQUIRED_RESULT inline int segmentAt(int index) const noexcept + [[nodiscard]] inline int segmentAt(qsizetype index) const noexcept { return (m_segments.size() > index) ? m_segments.at(index) : 0; } - Q_REQUIRED_RESULT inline int segmentCount() const noexcept + [[nodiscard]] inline qsizetype segmentCount() const noexcept { return m_segments.size(); } - Q_REQUIRED_RESULT Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const noexcept; - - Q_REQUIRED_RESULT Q_CORE_EXPORT static int compare(const QVersionNumber &v1, const QVersionNumber &v2) noexcept; + [[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; + + [[nodiscard]] Q_CORE_EXPORT static QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2); + + [[nodiscard]] Q_CORE_EXPORT QString toString() const; + [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(QAnyStringView string, qsizetype *suffixIndex = nullptr); + +#if QT_DEPRECATED_SINCE(6, 4) && QT_POINTER_SIZE != 4 + Q_WEAK_OVERLOAD + QT_DEPRECATED_VERSION_X_6_4("Use the 'qsizetype *suffixIndex' overload.") + [[nodiscard]] static QVersionNumber fromString(QAnyStringView string, int *suffixIndex) + { + QT_WARNING_PUSH + // fromString() writes to *n unconditionally, but GCC can't know that + QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") + qsizetype n; + auto r = fromString(string, &n); + if (suffixIndex) { + Q_ASSERT(int(n) == n); + *suffixIndex = int(n); + } + return r; + QT_WARNING_POP + } +#endif - Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2); - Q_REQUIRED_RESULT Q_CORE_EXPORT QString toString() const; -#if QT_STRINGVIEW_LEVEL < 2 - Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(const QString &string, int *suffixIndex = nullptr); +#if QT_CORE_REMOVED_SINCE(6, 4) + [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(const QString &string, int *suffixIndex); + [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(QLatin1StringView string, int *suffixIndex); + [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(QStringView string, int *suffixIndex); #endif - Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(QLatin1String string, int *suffixIndex = nullptr); - Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(QStringView string, int *suffixIndex = nullptr); private: + [[nodiscard]] friend bool comparesEqual(const QVersionNumber &lhs, + const QVersionNumber &rhs) noexcept + { + return compare(lhs, rhs) == 0; + } + [[nodiscard]] friend Qt::strong_ordering compareThreeWay(const QVersionNumber &lhs, + const QVersionNumber &rhs) noexcept + { + int c = compare(lhs, rhs); + return Qt::compareThreeWay(c, 0); + } + Q_DECLARE_STRONGLY_ORDERED(QVersionNumber) + #ifndef QT_NO_DATASTREAM friend Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version); #endif - friend Q_CORE_EXPORT uint qHash(const QVersionNumber &key, uint seed); + friend Q_CORE_EXPORT size_t qHash(const QVersionNumber &key, size_t seed); }; -Q_DECLARE_TYPEINFO(QVersionNumber, Q_MOVABLE_TYPE); +Q_DECLARE_TYPEINFO(QVersionNumber, Q_RELOCATABLE_TYPE); #ifndef QT_NO_DEBUG_STREAM Q_CORE_EXPORT QDebug operator<<(QDebug, const QVersionNumber &version); #endif -Q_REQUIRED_RESULT inline bool operator> (const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept -{ return QVersionNumber::compare(lhs, rhs) > 0; } - -Q_REQUIRED_RESULT inline bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept -{ return QVersionNumber::compare(lhs, rhs) >= 0; } - -Q_REQUIRED_RESULT inline bool operator< (const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept -{ return QVersionNumber::compare(lhs, rhs) < 0; } - -Q_REQUIRED_RESULT inline bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept -{ return QVersionNumber::compare(lhs, rhs) <= 0; } - -Q_REQUIRED_RESULT inline bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept -{ return QVersionNumber::compare(lhs, rhs) == 0; } - -Q_REQUIRED_RESULT inline bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept -{ return QVersionNumber::compare(lhs, rhs) != 0; } - QT_END_NAMESPACE -Q_DECLARE_METATYPE(QVersionNumber) +QT_DECL_METATYPE_EXTERN(QVersionNumber, Q_CORE_EXPORT) -#endif //QVERSIONNUMBER_H +#endif // QVERSIONNUMBER_H |