Warning, file /include/QtCore/qversionnumber.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006 #ifndef QVERSIONNUMBER_H
0007 #define QVERSIONNUMBER_H
0008
0009 #include <QtCore/qlist.h>
0010 #include <QtCore/qmetatype.h>
0011 #include <QtCore/qnamespace.h>
0012 #include <QtCore/qstring.h>
0013 #include <QtCore/qtypeinfo.h>
0014 #if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 2
0015 #include <QtCore/qtyperevision.h>
0016 #endif
0017
0018 QT_BEGIN_NAMESPACE
0019
0020 class QVersionNumber;
0021 Q_CORE_EXPORT size_t qHash(const QVersionNumber &key, size_t seed = 0);
0022
0023 #ifndef QT_NO_DATASTREAM
0024 Q_CORE_EXPORT QDataStream &operator<<(QDataStream &out, const QVersionNumber &version);
0025 Q_CORE_EXPORT QDataStream &operator>>(QDataStream &in, QVersionNumber &version);
0026 #endif
0027
0028 class QVersionNumber
0029 {
0030
0031
0032
0033
0034
0035
0036
0037 enum {
0038
0039
0040 InlineSegmentMarker = Q_BYTE_ORDER == Q_LITTLE_ENDIAN ? 0 : sizeof(void *) - 1,
0041 InlineSegmentStartIdx = !InlineSegmentMarker,
0042 InlineSegmentCount = sizeof(void *) - 1
0043 };
0044 static_assert(InlineSegmentCount >= 3);
0045
0046 struct SegmentStorage
0047 {
0048
0049
0050
0051 union {
0052 quintptr dummy;
0053 qint8 inline_segments[sizeof(void *)];
0054 QList<int> *pointer_segments;
0055 };
0056
0057
0058 SegmentStorage() noexcept : dummy(1) {}
0059
0060 SegmentStorage(const QList<int> &seg)
0061 {
0062 if (dataFitsInline(seg.data(), seg.size()))
0063 setInlineData(seg.data(), seg.size());
0064 else
0065 setListData(seg);
0066 }
0067
0068 Q_CORE_EXPORT void setListData(const QList<int> &seg);
0069
0070 SegmentStorage(const SegmentStorage &other)
0071 {
0072 if (other.isUsingPointer())
0073 setListData(*other.pointer_segments);
0074 else
0075 dummy = other.dummy;
0076 }
0077
0078 SegmentStorage &operator=(const SegmentStorage &other)
0079 {
0080 if (isUsingPointer() && other.isUsingPointer()) {
0081 *pointer_segments = *other.pointer_segments;
0082 } else if (other.isUsingPointer()) {
0083 setListData(*other.pointer_segments);
0084 } else {
0085 if (isUsingPointer())
0086 delete pointer_segments;
0087 dummy = other.dummy;
0088 }
0089 return *this;
0090 }
0091
0092 SegmentStorage(SegmentStorage &&other) noexcept
0093 : dummy(other.dummy)
0094 {
0095 other.dummy = 1;
0096 }
0097
0098 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(SegmentStorage)
0099
0100 void swap(SegmentStorage &other) noexcept
0101 {
0102 std::swap(dummy, other.dummy);
0103 }
0104
0105 explicit SegmentStorage(QList<int> &&seg)
0106 {
0107 if (dataFitsInline(std::as_const(seg).data(), seg.size()))
0108 setInlineData(std::as_const(seg).data(), seg.size());
0109 else
0110 setListData(std::move(seg));
0111 }
0112
0113 Q_CORE_EXPORT void setListData(QList<int> &&seg);
0114
0115 explicit SegmentStorage(std::initializer_list<int> args)
0116 : SegmentStorage(args.begin(), args.end()) {}
0117
0118 explicit SegmentStorage(const int *first, const int *last)
0119 {
0120 if (dataFitsInline(first, last - first)) {
0121 setInlineData(first, last - first);
0122 } else {
0123 setListData(first, last);
0124 }
0125 }
0126
0127 Q_CORE_EXPORT void setListData(const int *first, const int *last);
0128
0129 ~SegmentStorage() { if (isUsingPointer()) delete pointer_segments; }
0130
0131 bool isUsingPointer() const noexcept
0132 { return (inline_segments[InlineSegmentMarker] & 1) == 0; }
0133
0134 qsizetype size() const noexcept
0135 { return isUsingPointer() ? pointer_segments->size() : (inline_segments[InlineSegmentMarker] >> 1); }
0136
0137 void setInlineSize(qsizetype len)
0138 {
0139 Q_ASSERT(len <= InlineSegmentCount);
0140 inline_segments[InlineSegmentMarker] = qint8(1 + 2 * len);
0141 }
0142
0143 Q_CORE_EXPORT void resize(qsizetype len);
0144
0145 int at(qsizetype index) const
0146 {
0147 return isUsingPointer() ?
0148 pointer_segments->at(index) :
0149 inline_segments[InlineSegmentStartIdx + index];
0150 }
0151
0152 void setSegments(int len, int maj, int min = 0, int mic = 0)
0153 {
0154 if (maj == qint8(maj) && min == qint8(min) && mic == qint8(mic)) {
0155 int data[] = { maj, min, mic };
0156 setInlineData(data, len);
0157 } else {
0158 setVector(len, maj, min, mic);
0159 }
0160 }
0161
0162 private:
0163 static bool dataFitsInline(const int *data, qsizetype len)
0164 {
0165 if (len > InlineSegmentCount)
0166 return false;
0167 for (qsizetype i = 0; i < len; ++i)
0168 if (data[i] != qint8(data[i]))
0169 return false;
0170 return true;
0171 }
0172 void setInlineData(const int *data, qsizetype len)
0173 {
0174 Q_ASSERT(len <= InlineSegmentCount);
0175 dummy = 1 + len * 2;
0176 #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
0177 for (qsizetype i = 0; i < len; ++i)
0178 dummy |= quintptr(data[i] & 0xFF) << (8 * (i + 1));
0179 #elif Q_BYTE_ORDER == Q_BIG_ENDIAN
0180 for (qsizetype i = 0; i < len; ++i)
0181 dummy |= quintptr(data[i] & 0xFF) << (8 * (sizeof(void *) - i - 1));
0182 #else
0183
0184 setInlineSize(len);
0185 for (qsizetype i = 0; i < len; ++i)
0186 inline_segments[InlineSegmentStartIdx + i] = data[i] & 0xFF;
0187 #endif
0188 }
0189
0190 Q_CORE_EXPORT void setVector(int len, int maj, int min, int mic);
0191 } m_segments;
0192
0193 public:
0194 inline QVersionNumber() noexcept
0195 : m_segments()
0196 {}
0197 inline explicit QVersionNumber(const QList<int> &seg) : m_segments(seg) { }
0198
0199
0200
0201 explicit QVersionNumber(QList<int> &&seg) : m_segments(std::move(seg)) { }
0202
0203 inline QVersionNumber(std::initializer_list<int> args)
0204 : m_segments(args)
0205 {}
0206
0207 template <qsizetype N>
0208 explicit QVersionNumber(const QVarLengthArray<int, N> &sec)
0209 : m_segments(sec.begin(), sec.end())
0210 {}
0211
0212 inline explicit QVersionNumber(int maj)
0213 { m_segments.setSegments(1, maj); }
0214
0215 inline explicit QVersionNumber(int maj, int min)
0216 { m_segments.setSegments(2, maj, min); }
0217
0218 inline explicit QVersionNumber(int maj, int min, int mic)
0219 { m_segments.setSegments(3, maj, min, mic); }
0220
0221 [[nodiscard]] inline bool isNull() const noexcept
0222 { return segmentCount() == 0; }
0223
0224 [[nodiscard]] inline bool isNormalized() const noexcept
0225 { return isNull() || segmentAt(segmentCount() - 1) != 0; }
0226
0227 [[nodiscard]] inline int majorVersion() const noexcept
0228 { return segmentAt(0); }
0229
0230 [[nodiscard]] inline int minorVersion() const noexcept
0231 { return segmentAt(1); }
0232
0233 [[nodiscard]] inline int microVersion() const noexcept
0234 { return segmentAt(2); }
0235
0236 [[nodiscard]] Q_CORE_EXPORT QVersionNumber normalized() const;
0237
0238 [[nodiscard]] Q_CORE_EXPORT QList<int> segments() const;
0239
0240 [[nodiscard]] inline int segmentAt(qsizetype index) const noexcept
0241 { return (m_segments.size() > index) ? m_segments.at(index) : 0; }
0242
0243 [[nodiscard]] inline qsizetype segmentCount() const noexcept
0244 { return m_segments.size(); }
0245
0246 [[nodiscard]] Q_CORE_EXPORT bool isPrefixOf(const QVersionNumber &other) const noexcept;
0247
0248 [[nodiscard]] Q_CORE_EXPORT static int compare(const QVersionNumber &v1, const QVersionNumber &v2) noexcept;
0249
0250 [[nodiscard]] Q_CORE_EXPORT static QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2);
0251
0252 [[nodiscard]] Q_CORE_EXPORT QString toString() const;
0253 [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(QAnyStringView string, qsizetype *suffixIndex = nullptr);
0254
0255 #if QT_DEPRECATED_SINCE(6, 4) && QT_POINTER_SIZE != 4
0256 Q_WEAK_OVERLOAD
0257 QT_DEPRECATED_VERSION_X_6_4("Use the 'qsizetype *suffixIndex' overload.")
0258 [[nodiscard]] static QVersionNumber fromString(QAnyStringView string, int *suffixIndex)
0259 {
0260 QT_WARNING_PUSH
0261
0262 QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized")
0263 qsizetype n;
0264 auto r = fromString(string, &n);
0265 if (suffixIndex) {
0266 Q_ASSERT(int(n) == n);
0267 *suffixIndex = int(n);
0268 }
0269 return r;
0270 QT_WARNING_POP
0271 }
0272 #endif
0273
0274
0275 #if QT_CORE_REMOVED_SINCE(6, 4)
0276 [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(const QString &string, int *suffixIndex);
0277 [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(QLatin1StringView string, int *suffixIndex);
0278 [[nodiscard]] Q_CORE_EXPORT static QVersionNumber fromString(QStringView string, int *suffixIndex);
0279 #endif
0280
0281 [[nodiscard]] friend bool operator> (const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
0282 { return compare(lhs, rhs) > 0; }
0283
0284 [[nodiscard]] friend bool operator>=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
0285 { return compare(lhs, rhs) >= 0; }
0286
0287 [[nodiscard]] friend bool operator< (const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
0288 { return compare(lhs, rhs) < 0; }
0289
0290 [[nodiscard]] friend bool operator<=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
0291 { return compare(lhs, rhs) <= 0; }
0292
0293 [[nodiscard]] friend bool operator==(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
0294 { return compare(lhs, rhs) == 0; }
0295
0296 [[nodiscard]] friend bool operator!=(const QVersionNumber &lhs, const QVersionNumber &rhs) noexcept
0297 { return compare(lhs, rhs) != 0; }
0298
0299 private:
0300 #ifndef QT_NO_DATASTREAM
0301 friend Q_CORE_EXPORT QDataStream& operator>>(QDataStream &in, QVersionNumber &version);
0302 #endif
0303 friend Q_CORE_EXPORT size_t qHash(const QVersionNumber &key, size_t seed);
0304 };
0305
0306 Q_DECLARE_TYPEINFO(QVersionNumber, Q_RELOCATABLE_TYPE);
0307
0308 #ifndef QT_NO_DEBUG_STREAM
0309 Q_CORE_EXPORT QDebug operator<<(QDebug, const QVersionNumber &version);
0310 #endif
0311
0312 QT_END_NAMESPACE
0313
0314 QT_DECL_METATYPE_EXTERN(QVersionNumber, Q_CORE_EXPORT)
0315
0316 #endif