Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 09:26:20

0001 // Copyright (C) 2021 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 #ifndef QBYTEARRAYVIEW_H
0004 #define QBYTEARRAYVIEW_H
0005 
0006 #include <QtCore/qbytearrayalgorithms.h>
0007 #include <QtCore/qcompare.h>
0008 #include <QtCore/qcontainerfwd.h>
0009 #include <QtCore/qstringfwd.h>
0010 #include <QtCore/qarraydata.h>
0011 
0012 #include <string>
0013 #include <string_view>
0014 #include <QtCore/q20type_traits.h>
0015 
0016 QT_BEGIN_NAMESPACE
0017 
0018 namespace QtPrivate {
0019 
0020 template <typename Byte>
0021 struct IsCompatibleByteTypeHelper : std::false_type {};
0022 template <> struct IsCompatibleByteTypeHelper<char> : std::true_type {};
0023 template <> struct IsCompatibleByteTypeHelper<signed char> : std::true_type {};
0024 template <> struct IsCompatibleByteTypeHelper<unsigned char> : std::true_type {};
0025 template <> struct IsCompatibleByteTypeHelper<std::byte> : std::true_type {};
0026 
0027 template <typename Byte>
0028 struct IsCompatibleByteType
0029     : IsCompatibleByteTypeHelper<q20::remove_cvref_t<Byte>> {};
0030 
0031 template <typename Pointer>
0032 struct IsCompatibleByteArrayPointerHelper : std::false_type {};
0033 template <typename Byte>
0034 struct IsCompatibleByteArrayPointerHelper<Byte *>
0035     : IsCompatibleByteType<Byte> {};
0036 template<typename Pointer>
0037 struct IsCompatibleByteArrayPointer
0038     : IsCompatibleByteArrayPointerHelper<q20::remove_cvref_t<Pointer>> {};
0039 
0040 template <typename T, typename Enable = void>
0041 struct IsContainerCompatibleWithQByteArrayView : std::false_type {};
0042 
0043 template <typename T>
0044 struct IsContainerCompatibleWithQByteArrayView<T, std::enable_if_t<
0045         std::conjunction_v<
0046                 // lacking concepts and ranges, we accept any T whose std::data yields a suitable
0047                 // pointer ...
0048                 IsCompatibleByteArrayPointer<decltype(std::data(std::declval<const T &>()))>,
0049                 // ... and that has a suitable size ...
0050                 std::is_convertible<decltype(std::size(std::declval<const T &>())), qsizetype>,
0051                 // ... and it's a range as it defines an iterator-like API
0052                 IsCompatibleByteType<typename std::iterator_traits<decltype(
0053                         std::begin(std::declval<const T &>()))>::value_type>,
0054                 std::is_convertible<decltype(std::begin(std::declval<const T &>())
0055                                              != std::end(std::declval<const T &>())),
0056                                     bool>,
0057 
0058                 // This needs to be treated specially due to the empty vs null distinction
0059                 std::negation<std::is_same<std::decay_t<T>, QByteArray>>,
0060 
0061                 // We handle array literals specially for source compat reasons
0062                 std::negation<std::is_array<T>>,
0063 
0064                 // Don't make an accidental copy constructor
0065                 std::negation<std::is_same<std::decay_t<T>, QByteArrayView>>>>> : std::true_type {};
0066 
0067 // Used by QLatin1StringView too
0068 template <typename Char>
0069 static constexpr qsizetype lengthHelperPointer(const Char *data) noexcept
0070 {
0071     // std::char_traits can only be used with one of the regular char types
0072     // (char, char16_t, wchar_t, but not uchar or QChar), so we roll the loop
0073     // out by ourselves.
0074     qsizetype i = 0;
0075     if (!data)
0076         return i;
0077     while (data[i] != Char(0))
0078         ++i;
0079     return i;
0080 }
0081 
0082 } // namespace QtPrivate
0083 
0084 class Q_CORE_EXPORT QByteArrayView
0085 {
0086 public:
0087     typedef char storage_type;
0088     typedef const char value_type;
0089     typedef qptrdiff difference_type;
0090     typedef qsizetype size_type;
0091     typedef value_type &reference;
0092     typedef value_type &const_reference;
0093     typedef value_type *pointer;
0094     typedef value_type *const_pointer;
0095 
0096     typedef pointer iterator;
0097     typedef const_pointer const_iterator;
0098     typedef std::reverse_iterator<iterator> reverse_iterator;
0099     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
0100 
0101 private:
0102     template <typename Byte>
0103     using if_compatible_byte =
0104             typename std::enable_if_t<QtPrivate::IsCompatibleByteType<Byte>::value, bool>;
0105 
0106     template <typename Pointer>
0107     using if_compatible_pointer =
0108             typename std::enable_if_t<QtPrivate::IsCompatibleByteArrayPointer<Pointer>::value,
0109                                       bool>;
0110 
0111     template <typename T>
0112     using if_compatible_qbytearray_like =
0113             typename std::enable_if_t<std::is_same_v<T, QByteArray>, bool>;
0114 
0115     template <typename T>
0116     using if_compatible_container =
0117             typename std::enable_if_t<QtPrivate::IsContainerCompatibleWithQByteArrayView<T>::value,
0118                                       bool>;
0119 
0120     template <typename Container>
0121     static constexpr qsizetype lengthHelperContainer(const Container &c) noexcept
0122     {
0123         return qsizetype(std::size(c));
0124     }
0125 
0126     static constexpr qsizetype lengthHelperCharArray(const char *data, size_t size) noexcept
0127     {
0128         const auto it = std::char_traits<char>::find(data, size, '\0');
0129         const auto end = it ? it : std::next(data, size);
0130         return qsizetype(std::distance(data, end));
0131     }
0132 
0133     template <typename Byte>
0134     static const storage_type *castHelper(const Byte *data) noexcept
0135     { return reinterpret_cast<const storage_type*>(data); }
0136     static constexpr const storage_type *castHelper(const storage_type *data) noexcept
0137     { return data; }
0138 
0139 public:
0140     constexpr QByteArrayView() noexcept
0141         : m_size(0), m_data(nullptr) {}
0142     constexpr QByteArrayView(std::nullptr_t) noexcept
0143         : QByteArrayView() {}
0144 
0145     template <typename Byte, if_compatible_byte<Byte> = true>
0146     constexpr QByteArrayView(const Byte *data, qsizetype len)
0147         : m_size((Q_ASSERT(len >= 0), Q_ASSERT(data || !len), len)),
0148           m_data(castHelper(data)) {}
0149 
0150     template <typename Byte, if_compatible_byte<Byte> = true>
0151     constexpr QByteArrayView(const Byte *first, const Byte *last)
0152         : QByteArrayView(first, last - first) {}
0153 
0154 #ifdef Q_QDOC
0155     template <typename Byte>
0156     constexpr QByteArrayView(const Byte *data) noexcept;
0157 #else
0158     template <typename Pointer, if_compatible_pointer<Pointer> = true>
0159     constexpr QByteArrayView(const Pointer &data) noexcept
0160         : QByteArrayView(
0161               data, data ? QtPrivate::lengthHelperPointer(data) : 0) {}
0162 #endif
0163 
0164 #ifdef Q_QDOC
0165     QByteArrayView(const QByteArray &data) noexcept;
0166 #else
0167     template <typename ByteArray, if_compatible_qbytearray_like<ByteArray> = true>
0168     QByteArrayView(const ByteArray &ba) noexcept
0169         : QByteArrayView{ba.begin(), ba.size()} {}
0170 #endif
0171 
0172     template <typename Container, if_compatible_container<Container> = true>
0173     constexpr QByteArrayView(const Container &c) noexcept
0174         : QByteArrayView(std::data(c), lengthHelperContainer(c)) {}
0175     template <size_t Size>
0176     constexpr QByteArrayView(const char (&data)[Size]) noexcept
0177         : QByteArrayView(data, lengthHelperCharArray(data, Size)) {}
0178 
0179     template <typename Byte, if_compatible_byte<Byte> = true>
0180     constexpr QByteArrayView(const Byte (&data)[]) noexcept
0181         : QByteArrayView(&*data) {} // decay to pointer
0182 
0183 #ifdef Q_QDOC
0184     template <typename Byte, size_t Size>
0185 #else
0186     template <typename Byte, size_t Size, if_compatible_byte<Byte> = true>
0187 #endif
0188     [[nodiscard]] constexpr static QByteArrayView fromArray(const Byte (&data)[Size]) noexcept
0189     { return QByteArrayView(data, Size); }
0190     [[nodiscard]] inline QByteArray toByteArray() const; // defined in qbytearray.h
0191 
0192     [[nodiscard]] constexpr qsizetype size() const noexcept { return m_size; }
0193     [[nodiscard]] constexpr const_pointer data() const noexcept { return m_data; }
0194     [[nodiscard]] constexpr const_pointer constData() const noexcept { return data(); }
0195 
0196     [[nodiscard]] constexpr char operator[](qsizetype n) const
0197     { verify(n, 1); return m_data[n]; }
0198 
0199     //
0200     // QByteArray API
0201     //
0202     [[nodiscard]] constexpr char at(qsizetype n) const { return (*this)[n]; }
0203 
0204     [[nodiscard]] constexpr QByteArrayView first(qsizetype n) const
0205     { verify(0, n); return sliced(0, n); }
0206     [[nodiscard]] constexpr QByteArrayView last(qsizetype n) const
0207     { verify(0, n); return sliced(size() - n, n); }
0208     [[nodiscard]] constexpr QByteArrayView sliced(qsizetype pos) const
0209     { verify(pos, 0); return QByteArrayView(data() + pos, size() - pos); }
0210     [[nodiscard]] constexpr QByteArrayView sliced(qsizetype pos, qsizetype n) const
0211     { verify(pos, n); return QByteArrayView(data() + pos, n); }
0212 
0213      constexpr QByteArrayView &slice(qsizetype pos)
0214     { *this = sliced(pos); return *this; }
0215      constexpr QByteArrayView &slice(qsizetype pos, qsizetype n)
0216     { *this = sliced(pos, n); return *this; }
0217 
0218     [[nodiscard]] constexpr QByteArrayView chopped(qsizetype len) const
0219     { verify(0, len); return sliced(0, size() - len); }
0220 
0221     [[nodiscard]] constexpr QByteArrayView left(qsizetype n) const
0222     { if (n < 0 || n > size()) n = size(); return QByteArrayView(data(), n); }
0223     [[nodiscard]] constexpr QByteArrayView right(qsizetype n) const
0224     { if (n < 0 || n > size()) n = size(); if (n < 0) n = 0; return QByteArrayView(data() + size() - n, n); }
0225     [[nodiscard]] constexpr QByteArrayView mid(qsizetype pos, qsizetype n = -1) const
0226     {
0227         using namespace QtPrivate;
0228         auto result = QContainerImplHelper::mid(size(), &pos, &n);
0229         return result == QContainerImplHelper::Null ? QByteArrayView()
0230                                                     : QByteArrayView(m_data + pos, n);
0231     }
0232 
0233     constexpr void truncate(qsizetype n)
0234     { verify(0, n); m_size = n; }
0235     constexpr void chop(qsizetype n)
0236     { verify(0, n); m_size -= n; }
0237 
0238     // Defined in qbytearray.cpp:
0239     [[nodiscard]] QByteArrayView trimmed() const noexcept
0240     { return QtPrivate::trimmed(*this); }
0241     [[nodiscard]] short toShort(bool *ok = nullptr, int base = 10) const
0242     { return QtPrivate::toIntegral<short>(*this, ok, base); }
0243     [[nodiscard]] ushort toUShort(bool *ok = nullptr, int base = 10) const
0244     { return QtPrivate::toIntegral<ushort>(*this, ok, base); }
0245     [[nodiscard]] int toInt(bool *ok = nullptr, int base = 10) const
0246     { return QtPrivate::toIntegral<int>(*this, ok, base); }
0247     [[nodiscard]] uint toUInt(bool *ok = nullptr, int base = 10) const
0248     { return QtPrivate::toIntegral<uint>(*this, ok, base); }
0249     [[nodiscard]] long toLong(bool *ok = nullptr, int base = 10) const
0250     { return QtPrivate::toIntegral<long>(*this, ok, base); }
0251     [[nodiscard]] ulong toULong(bool *ok = nullptr, int base = 10) const
0252     { return QtPrivate::toIntegral<ulong>(*this, ok, base); }
0253     [[nodiscard]] qlonglong toLongLong(bool *ok = nullptr, int base = 10) const
0254     { return QtPrivate::toIntegral<qlonglong>(*this, ok, base); }
0255     [[nodiscard]] qulonglong toULongLong(bool *ok = nullptr, int base = 10) const
0256     { return QtPrivate::toIntegral<qulonglong>(*this, ok, base); }
0257     [[nodiscard]] float toFloat(bool *ok = nullptr) const
0258     {
0259         const auto r = QtPrivate::toFloat(*this);
0260         if (ok)
0261             *ok = bool(r);
0262         return r.value_or(0.0f);
0263     }
0264     [[nodiscard]] double toDouble(bool *ok = nullptr) const
0265     {
0266         const auto r = QtPrivate::toDouble(*this);
0267         if (ok)
0268             *ok = bool(r);
0269         return r.value_or(0.0);
0270     }
0271 
0272     [[nodiscard]] bool startsWith(QByteArrayView other) const noexcept
0273     { return QtPrivate::startsWith(*this, other); }
0274     [[nodiscard]] constexpr bool startsWith(char c) const noexcept
0275     { return !empty() && front() == c; }
0276 
0277     [[nodiscard]] bool endsWith(QByteArrayView other) const noexcept
0278     { return QtPrivate::endsWith(*this, other); }
0279     [[nodiscard]] constexpr bool endsWith(char c) const noexcept
0280     { return !empty() && back() == c; }
0281 
0282     [[nodiscard]] qsizetype indexOf(QByteArrayView a, qsizetype from = 0) const noexcept
0283     { return QtPrivate::findByteArray(*this, from, a); }
0284     [[nodiscard]] qsizetype indexOf(char ch, qsizetype from = 0) const noexcept
0285     { return QtPrivate::findByteArray(*this, from, ch); }
0286 
0287     [[nodiscard]] bool contains(QByteArrayView a) const noexcept
0288     { return indexOf(a) != qsizetype(-1); }
0289     [[nodiscard]] bool contains(char c) const noexcept
0290     { return indexOf(c) != qsizetype(-1); }
0291 
0292     [[nodiscard]] qsizetype lastIndexOf(QByteArrayView a) const noexcept
0293     { return lastIndexOf(a, size()); }
0294     [[nodiscard]] qsizetype lastIndexOf(QByteArrayView a, qsizetype from) const noexcept
0295     { return QtPrivate::lastIndexOf(*this, from, a); }
0296     [[nodiscard]] qsizetype lastIndexOf(char ch, qsizetype from = -1) const noexcept
0297     { return QtPrivate::lastIndexOf(*this, from, ch); }
0298 
0299     [[nodiscard]] qsizetype count(QByteArrayView a) const noexcept
0300     { return QtPrivate::count(*this, a); }
0301     [[nodiscard]] qsizetype count(char ch) const noexcept
0302     { return QtPrivate::count(*this, QByteArrayView(&ch, 1)); }
0303 
0304     inline int compare(QByteArrayView a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0305 
0306     [[nodiscard]] inline bool isValidUtf8() const noexcept { return QtPrivate::isValidUtf8(*this); }
0307 
0308     //
0309     // STL compatibility API:
0310     //
0311     [[nodiscard]] constexpr const_iterator begin()   const noexcept { return data(); }
0312     [[nodiscard]] constexpr const_iterator end()     const noexcept { return data() + size(); }
0313     [[nodiscard]] constexpr const_iterator cbegin()  const noexcept { return begin(); }
0314     [[nodiscard]] constexpr const_iterator cend()    const noexcept { return end(); }
0315     [[nodiscard]] constexpr const_reverse_iterator rbegin()  const noexcept { return const_reverse_iterator(end()); }
0316     [[nodiscard]] constexpr const_reverse_iterator rend()    const noexcept { return const_reverse_iterator(begin()); }
0317     [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
0318     [[nodiscard]] constexpr const_reverse_iterator crend()   const noexcept { return rend(); }
0319 
0320     [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
0321     [[nodiscard]] constexpr char front() const { Q_ASSERT(!empty()); return m_data[0]; }
0322     [[nodiscard]] constexpr char back()  const { Q_ASSERT(!empty()); return m_data[m_size - 1]; }
0323 
0324     [[nodiscard]] constexpr Q_IMPLICIT operator std::string_view() const noexcept
0325     { return std::string_view(m_data, size_t(m_size)); }
0326 
0327     [[nodiscard]] constexpr qsizetype max_size() const noexcept { return maxSize(); }
0328 
0329     //
0330     // Qt compatibility API:
0331     //
0332     [[nodiscard]] constexpr bool isNull() const noexcept { return !m_data; }
0333     [[nodiscard]] constexpr bool isEmpty() const noexcept { return empty(); }
0334     [[nodiscard]] constexpr qsizetype length() const noexcept
0335     { return size(); }
0336     [[nodiscard]] constexpr char first() const { return front(); }
0337     [[nodiscard]] constexpr char last()  const { return back(); }
0338 
0339     [[nodiscard]] static constexpr qsizetype maxSize() noexcept
0340     {
0341         // -1 to deal with the pointer one-past-the-end;
0342         return QtPrivate::MaxAllocSize - 1;
0343     }
0344 
0345 private:
0346     Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
0347                                           [[maybe_unused]] qsizetype n = 1) const
0348     {
0349         Q_ASSERT(pos >= 0);
0350         Q_ASSERT(pos <= size());
0351         Q_ASSERT(n >= 0);
0352         Q_ASSERT(n <= size() - pos);
0353     }
0354 
0355     friend bool
0356     comparesEqual(const QByteArrayView &lhs, const QByteArrayView &rhs) noexcept
0357     {
0358         return lhs.size() == rhs.size()
0359                 && (!lhs.size() || memcmp(lhs.data(), rhs.data(), lhs.size()) == 0);
0360     }
0361     friend Qt::strong_ordering
0362     compareThreeWay(const QByteArrayView &lhs, const QByteArrayView &rhs) noexcept
0363     {
0364         const int res = QtPrivate::compareMemory(lhs, rhs);
0365         return Qt::compareThreeWay(res, 0);
0366     }
0367     Q_DECLARE_STRONGLY_ORDERED(QByteArrayView)
0368 
0369     friend bool comparesEqual(const QByteArrayView &lhs, const char *rhs) noexcept
0370     { return comparesEqual(lhs, QByteArrayView(rhs)); }
0371     friend Qt::strong_ordering
0372     compareThreeWay(const QByteArrayView &lhs, const char *rhs) noexcept
0373     { return compareThreeWay(lhs, QByteArrayView(rhs)); }
0374     Q_DECLARE_STRONGLY_ORDERED(QByteArrayView, const char *)
0375 
0376     // defined in qstring.cpp
0377     friend Q_CORE_EXPORT bool
0378     comparesEqual(const QByteArrayView &lhs, const QChar &rhs) noexcept;
0379     friend Q_CORE_EXPORT Qt::strong_ordering
0380     compareThreeWay(const QByteArrayView &lhs, const QChar &rhs) noexcept;
0381     friend Q_CORE_EXPORT bool
0382     comparesEqual(const QByteArrayView &lhs, char16_t rhs) noexcept;
0383     friend Q_CORE_EXPORT Qt::strong_ordering
0384     compareThreeWay(const QByteArrayView &lhs, char16_t rhs) noexcept;
0385 #if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
0386     Q_DECLARE_STRONGLY_ORDERED(QByteArrayView, QChar, QT_ASCII_CAST_WARN)
0387     Q_DECLARE_STRONGLY_ORDERED(QByteArrayView, char16_t, QT_ASCII_CAST_WARN)
0388 #endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
0389 
0390     qsizetype m_size;
0391     const storage_type *m_data;
0392 };
0393 Q_DECLARE_TYPEINFO(QByteArrayView, Q_PRIMITIVE_TYPE);
0394 
0395 template<typename QByteArrayLike,
0396          std::enable_if_t<std::is_same_v<QByteArrayLike, QByteArray>, bool> = true>
0397 [[nodiscard]] inline QByteArrayView qToByteArrayViewIgnoringNull(const QByteArrayLike &b) noexcept
0398 { return QByteArrayView(b.begin(), b.size()); }
0399 
0400 inline int QByteArrayView::compare(QByteArrayView a, Qt::CaseSensitivity cs) const noexcept
0401 {
0402     return cs == Qt::CaseSensitive ? QtPrivate::compareMemory(*this, a) :
0403                                      qstrnicmp(data(), size(), a.data(), a.size());
0404 }
0405 
0406 #if QT_DEPRECATED_SINCE(6, 0)
0407 QT_DEPRECATED_VERSION_X_6_0("Use the QByteArrayView overload.")
0408 inline quint16 qChecksum(const char *s, qsizetype len,
0409                          Qt::ChecksumType standard = Qt::ChecksumIso3309)
0410 { return qChecksum(QByteArrayView(s, len), standard); }
0411 #endif
0412 
0413 qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, char needle) noexcept
0414 {
0415     if (from < 0)
0416         from = qMax(from + haystack.size(), qsizetype(0));
0417     if (from < haystack.size()) {
0418         const char *const b = haystack.data();
0419         if (const auto n = static_cast<const char *>(
0420                     memchr(b + from, needle, static_cast<size_t>(haystack.size() - from)))) {
0421             return n - b;
0422         }
0423     }
0424     return -1;
0425 }
0426 
0427 qsizetype QtPrivate::lastIndexOf(QByteArrayView haystack, qsizetype from, uchar needle) noexcept
0428 {
0429     if (from < 0)
0430         from = qMax(from + haystack.size(), qsizetype(0));
0431     else
0432         from = qMin(from, haystack.size() - 1);
0433 
0434     const char *const b = haystack.data();
0435     const void *n = b ? qmemrchr(b, needle, from + 1) : nullptr;
0436     return n ? static_cast<const char *>(n) - b : -1;
0437 }
0438 
0439 QT_END_NAMESPACE
0440 
0441 #endif // QBYTEARRAYVIEW_H