Warning, file /include/QtCore/qbytearrayview.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 #ifndef QBYTEARRAYVIEW_H
0004 #define QBYTEARRAYVIEW_H
0005
0006 #include <QtCore/qbytearrayalgorithms.h>
0007 #include <QtCore/qstringfwd.h>
0008 #include <QtCore/qarraydata.h>
0009
0010 #include <string>
0011 #include <string_view>
0012 #include <QtCore/q20type_traits.h>
0013
0014 QT_BEGIN_NAMESPACE
0015
0016 namespace QtPrivate {
0017
0018 template <typename Byte>
0019 struct IsCompatibleByteTypeHelper
0020 : std::integral_constant<bool,
0021 std::is_same_v<Byte, char> ||
0022 std::is_same_v<Byte, uchar> ||
0023 std::is_same_v<Byte, signed char> ||
0024 std::is_same_v<Byte, std::byte>> {};
0025
0026 template <typename Byte>
0027 struct IsCompatibleByteType
0028 : IsCompatibleByteTypeHelper<q20::remove_cvref_t<Byte>> {};
0029
0030 template <typename Pointer>
0031 struct IsCompatibleByteArrayPointerHelper : std::false_type {};
0032 template <typename Byte>
0033 struct IsCompatibleByteArrayPointerHelper<Byte *>
0034 : IsCompatibleByteType<Byte> {};
0035 template<typename Pointer>
0036 struct IsCompatibleByteArrayPointer
0037 : IsCompatibleByteArrayPointerHelper<q20::remove_cvref_t<Pointer>> {};
0038
0039 template <typename T, typename Enable = void>
0040 struct IsContainerCompatibleWithQByteArrayView : std::false_type {};
0041
0042 template <typename T>
0043 struct IsContainerCompatibleWithQByteArrayView<T, std::enable_if_t<
0044 std::conjunction_v<
0045
0046
0047 IsCompatibleByteArrayPointer<decltype(std::data(std::declval<const T &>()))>,
0048
0049 std::is_convertible<decltype(std::size(std::declval<const T &>())), qsizetype>,
0050
0051 IsCompatibleByteType<typename std::iterator_traits<decltype(
0052 std::begin(std::declval<const T &>()))>::value_type>,
0053 std::is_convertible<decltype(std::begin(std::declval<const T &>())
0054 != std::end(std::declval<const T &>())),
0055 bool>,
0056
0057
0058 std::negation<std::is_same<std::decay_t<T>, QByteArray>>,
0059
0060
0061 std::negation<std::is_array<T>>,
0062
0063
0064 std::negation<std::is_same<std::decay_t<T>, QByteArrayView>>>>> : std::true_type {};
0065
0066
0067 template <typename Char>
0068 static constexpr qsizetype lengthHelperPointer(const Char *data) noexcept
0069 {
0070 return qsizetype(std::char_traits<Char>::length(data));
0071 }
0072
0073 }
0074
0075 class Q_CORE_EXPORT QByteArrayView
0076 {
0077 public:
0078 typedef char storage_type;
0079 typedef const char value_type;
0080 typedef qptrdiff difference_type;
0081 typedef qsizetype size_type;
0082 typedef value_type &reference;
0083 typedef value_type &const_reference;
0084 typedef value_type *pointer;
0085 typedef value_type *const_pointer;
0086
0087 typedef pointer iterator;
0088 typedef const_pointer const_iterator;
0089 typedef std::reverse_iterator<iterator> reverse_iterator;
0090 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
0091
0092 private:
0093 template <typename Byte>
0094 using if_compatible_byte =
0095 typename std::enable_if_t<QtPrivate::IsCompatibleByteType<Byte>::value, bool>;
0096
0097 template <typename Pointer>
0098 using if_compatible_pointer =
0099 typename std::enable_if_t<QtPrivate::IsCompatibleByteArrayPointer<Pointer>::value,
0100 bool>;
0101
0102 template <typename T>
0103 using if_compatible_qbytearray_like =
0104 typename std::enable_if_t<std::is_same_v<T, QByteArray>, bool>;
0105
0106 template <typename T>
0107 using if_compatible_container =
0108 typename std::enable_if_t<QtPrivate::IsContainerCompatibleWithQByteArrayView<T>::value,
0109 bool>;
0110
0111 template <typename Container>
0112 static constexpr qsizetype lengthHelperContainer(const Container &c) noexcept
0113 {
0114 return qsizetype(std::size(c));
0115 }
0116
0117 static constexpr qsizetype lengthHelperCharArray(const char *data, size_t size) noexcept
0118 {
0119 const auto it = std::char_traits<char>::find(data, size, '\0');
0120 const auto end = it ? it : std::next(data, size);
0121 return qsizetype(std::distance(data, end));
0122 }
0123
0124 template <typename Byte>
0125 static const storage_type *castHelper(const Byte *data) noexcept
0126 { return reinterpret_cast<const storage_type*>(data); }
0127 static constexpr const storage_type *castHelper(const storage_type *data) noexcept
0128 { return data; }
0129
0130 public:
0131 constexpr QByteArrayView() noexcept
0132 : m_size(0), m_data(nullptr) {}
0133 constexpr QByteArrayView(std::nullptr_t) noexcept
0134 : QByteArrayView() {}
0135
0136 template <typename Byte, if_compatible_byte<Byte> = true>
0137 constexpr QByteArrayView(const Byte *data, qsizetype len)
0138 : m_size((Q_ASSERT(len >= 0), Q_ASSERT(data || !len), len)),
0139 m_data(castHelper(data)) {}
0140
0141 template <typename Byte, if_compatible_byte<Byte> = true>
0142 constexpr QByteArrayView(const Byte *first, const Byte *last)
0143 : QByteArrayView(first, last - first) {}
0144
0145 #ifdef Q_QDOC
0146 template <typename Byte>
0147 constexpr QByteArrayView(const Byte *data) noexcept;
0148 #else
0149 template <typename Pointer, if_compatible_pointer<Pointer> = true>
0150 constexpr QByteArrayView(const Pointer &data) noexcept
0151 : QByteArrayView(
0152 data, data ? QtPrivate::lengthHelperPointer(data) : 0) {}
0153 #endif
0154
0155 #ifdef Q_QDOC
0156 QByteArrayView(const QByteArray &data) noexcept;
0157 #else
0158 template <typename ByteArray, if_compatible_qbytearray_like<ByteArray> = true>
0159 QByteArrayView(const ByteArray &ba) noexcept
0160 : QByteArrayView(ba.isNull() ? nullptr : ba.data(), qsizetype(ba.size())) {}
0161 #endif
0162
0163 template <typename Container, if_compatible_container<Container> = true>
0164 constexpr QByteArrayView(const Container &c) noexcept
0165 : QByteArrayView(std::data(c), lengthHelperContainer(c)) {}
0166 template <size_t Size>
0167 constexpr QByteArrayView(const char (&data)[Size]) noexcept
0168 : QByteArrayView(data, lengthHelperCharArray(data, Size)) {}
0169
0170 #ifdef Q_QDOC
0171 template <typename Byte, size_t Size>
0172 #else
0173 template <typename Byte, size_t Size, if_compatible_byte<Byte> = true>
0174 #endif
0175 [[nodiscard]] constexpr static QByteArrayView fromArray(const Byte (&data)[Size]) noexcept
0176 { return QByteArrayView(data, Size); }
0177 [[nodiscard]] inline QByteArray toByteArray() const;
0178
0179 [[nodiscard]] constexpr qsizetype size() const noexcept { return m_size; }
0180 [[nodiscard]] constexpr const_pointer data() const noexcept { return m_data; }
0181 [[nodiscard]] constexpr const_pointer constData() const noexcept { return data(); }
0182
0183 [[nodiscard]] constexpr char operator[](qsizetype n) const
0184 { verify(n, 1); return m_data[n]; }
0185
0186
0187
0188
0189 [[nodiscard]] constexpr char at(qsizetype n) const { return (*this)[n]; }
0190
0191 [[nodiscard]] constexpr QByteArrayView first(qsizetype n) const
0192 { verify(0, n); return sliced(0, n); }
0193 [[nodiscard]] constexpr QByteArrayView last(qsizetype n) const
0194 { verify(0, n); return sliced(size() - n, n); }
0195 [[nodiscard]] constexpr QByteArrayView sliced(qsizetype pos) const
0196 { verify(pos, 0); return QByteArrayView(data() + pos, size() - pos); }
0197 [[nodiscard]] constexpr QByteArrayView sliced(qsizetype pos, qsizetype n) const
0198 { verify(pos, n); return QByteArrayView(data() + pos, n); }
0199 [[nodiscard]] constexpr QByteArrayView chopped(qsizetype len) const
0200 { verify(0, len); return sliced(0, size() - len); }
0201
0202 [[nodiscard]] constexpr QByteArrayView left(qsizetype n) const
0203 { if (n < 0 || n > size()) n = size(); return QByteArrayView(data(), n); }
0204 [[nodiscard]] constexpr QByteArrayView right(qsizetype n) const
0205 { if (n < 0 || n > size()) n = size(); if (n < 0) n = 0; return QByteArrayView(data() + size() - n, n); }
0206 [[nodiscard]] constexpr QByteArrayView mid(qsizetype pos, qsizetype n = -1) const
0207 {
0208 using namespace QtPrivate;
0209 auto result = QContainerImplHelper::mid(size(), &pos, &n);
0210 return result == QContainerImplHelper::Null ? QByteArrayView()
0211 : QByteArrayView(m_data + pos, n);
0212 }
0213
0214 constexpr void truncate(qsizetype n)
0215 { verify(0, n); m_size = n; }
0216 constexpr void chop(qsizetype n)
0217 { verify(0, n); m_size -= n; }
0218
0219
0220 [[nodiscard]] QByteArrayView trimmed() const noexcept
0221 { return QtPrivate::trimmed(*this); }
0222 [[nodiscard]] short toShort(bool *ok = nullptr, int base = 10) const
0223 { return QtPrivate::toIntegral<short>(*this, ok, base); }
0224 [[nodiscard]] ushort toUShort(bool *ok = nullptr, int base = 10) const
0225 { return QtPrivate::toIntegral<ushort>(*this, ok, base); }
0226 [[nodiscard]] int toInt(bool *ok = nullptr, int base = 10) const
0227 { return QtPrivate::toIntegral<int>(*this, ok, base); }
0228 [[nodiscard]] uint toUInt(bool *ok = nullptr, int base = 10) const
0229 { return QtPrivate::toIntegral<uint>(*this, ok, base); }
0230 [[nodiscard]] long toLong(bool *ok = nullptr, int base = 10) const
0231 { return QtPrivate::toIntegral<long>(*this, ok, base); }
0232 [[nodiscard]] ulong toULong(bool *ok = nullptr, int base = 10) const
0233 { return QtPrivate::toIntegral<ulong>(*this, ok, base); }
0234 [[nodiscard]] qlonglong toLongLong(bool *ok = nullptr, int base = 10) const
0235 { return QtPrivate::toIntegral<qlonglong>(*this, ok, base); }
0236 [[nodiscard]] qulonglong toULongLong(bool *ok = nullptr, int base = 10) const
0237 { return QtPrivate::toIntegral<qulonglong>(*this, ok, base); }
0238 [[nodiscard]] float toFloat(bool *ok = nullptr) const
0239 {
0240 const auto r = QtPrivate::toFloat(*this);
0241 if (ok)
0242 *ok = bool(r);
0243 return r.value_or(0.0f);
0244 }
0245 [[nodiscard]] double toDouble(bool *ok = nullptr) const
0246 {
0247 const auto r = QtPrivate::toDouble(*this);
0248 if (ok)
0249 *ok = bool(r);
0250 return r.value_or(0.0);
0251 }
0252
0253 [[nodiscard]] bool startsWith(QByteArrayView other) const noexcept
0254 { return QtPrivate::startsWith(*this, other); }
0255 [[nodiscard]] bool startsWith(char c) const noexcept
0256 { return !empty() && front() == c; }
0257
0258 [[nodiscard]] bool endsWith(QByteArrayView other) const noexcept
0259 { return QtPrivate::endsWith(*this, other); }
0260 [[nodiscard]] bool endsWith(char c) const noexcept
0261 { return !empty() && back() == c; }
0262
0263 [[nodiscard]] qsizetype indexOf(QByteArrayView a, qsizetype from = 0) const noexcept
0264 { return QtPrivate::findByteArray(*this, from, a); }
0265 [[nodiscard]] qsizetype indexOf(char ch, qsizetype from = 0) const noexcept
0266 { return QtPrivate::findByteArray(*this, from, QByteArrayView(&ch, 1)); }
0267
0268 [[nodiscard]] bool contains(QByteArrayView a) const noexcept
0269 { return indexOf(a) != qsizetype(-1); }
0270 [[nodiscard]] bool contains(char c) const noexcept
0271 { return indexOf(c) != qsizetype(-1); }
0272
0273 [[nodiscard]] qsizetype lastIndexOf(QByteArrayView a) const noexcept
0274 { return lastIndexOf(a, size()); }
0275 [[nodiscard]] qsizetype lastIndexOf(QByteArrayView a, qsizetype from) const noexcept
0276 { return QtPrivate::lastIndexOf(*this, from, a); }
0277 [[nodiscard]] qsizetype lastIndexOf(char ch, qsizetype from = -1) const noexcept
0278 { return QtPrivate::lastIndexOf(*this, from, QByteArrayView(&ch, 1)); }
0279
0280 [[nodiscard]] qsizetype count(QByteArrayView a) const noexcept
0281 { return QtPrivate::count(*this, a); }
0282 [[nodiscard]] qsizetype count(char ch) const noexcept
0283 { return QtPrivate::count(*this, QByteArrayView(&ch, 1)); }
0284
0285 inline int compare(QByteArrayView a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
0286
0287 [[nodiscard]] inline bool isValidUtf8() const noexcept { return QtPrivate::isValidUtf8(*this); }
0288
0289
0290
0291
0292 [[nodiscard]] constexpr const_iterator begin() const noexcept { return data(); }
0293 [[nodiscard]] constexpr const_iterator end() const noexcept { return data() + size(); }
0294 [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return begin(); }
0295 [[nodiscard]] constexpr const_iterator cend() const noexcept { return end(); }
0296 [[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
0297 [[nodiscard]] constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
0298 [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
0299 [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return rend(); }
0300
0301 [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
0302 [[nodiscard]] constexpr char front() const { Q_ASSERT(!empty()); return m_data[0]; }
0303 [[nodiscard]] constexpr char back() const { Q_ASSERT(!empty()); return m_data[m_size - 1]; }
0304
0305 [[nodiscard]] constexpr Q_IMPLICIT operator std::string_view() const noexcept
0306 { return std::string_view(m_data, size_t(m_size)); }
0307
0308
0309
0310
0311 [[nodiscard]] constexpr bool isNull() const noexcept { return !m_data; }
0312 [[nodiscard]] constexpr bool isEmpty() const noexcept { return empty(); }
0313 [[nodiscard]] constexpr qsizetype length() const noexcept
0314 { return size(); }
0315 [[nodiscard]] constexpr char first() const { return front(); }
0316 [[nodiscard]] constexpr char last() const { return back(); }
0317
0318 friend inline bool operator==(QByteArrayView lhs, QByteArrayView rhs) noexcept
0319 { return lhs.size() == rhs.size() && (!lhs.size() || memcmp(lhs.data(), rhs.data(), lhs.size()) == 0); }
0320 friend inline bool operator!=(QByteArrayView lhs, QByteArrayView rhs) noexcept
0321 { return !(lhs == rhs); }
0322 friend inline bool operator< (QByteArrayView lhs, QByteArrayView rhs) noexcept
0323 { return QtPrivate::compareMemory(lhs, rhs) < 0; }
0324 friend inline bool operator<=(QByteArrayView lhs, QByteArrayView rhs) noexcept
0325 { return QtPrivate::compareMemory(lhs, rhs) <= 0; }
0326 friend inline bool operator> (QByteArrayView lhs, QByteArrayView rhs) noexcept
0327 { return !(lhs <= rhs); }
0328 friend inline bool operator>=(QByteArrayView lhs, QByteArrayView rhs) noexcept
0329 { return !(lhs < rhs); }
0330
0331 private:
0332 Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
0333 [[maybe_unused]] qsizetype n = 1) const
0334 {
0335 Q_ASSERT(pos >= 0);
0336 Q_ASSERT(pos <= size());
0337 Q_ASSERT(n >= 0);
0338 Q_ASSERT(n <= size() - pos);
0339 }
0340
0341 qsizetype m_size;
0342 const storage_type *m_data;
0343 };
0344 Q_DECLARE_TYPEINFO(QByteArrayView, Q_PRIMITIVE_TYPE);
0345
0346 template<typename QByteArrayLike,
0347 std::enable_if_t<std::is_same_v<QByteArrayLike, QByteArray>, bool> = true>
0348 [[nodiscard]] inline QByteArrayView qToByteArrayViewIgnoringNull(const QByteArrayLike &b) noexcept
0349 { return QByteArrayView(b.data(), b.size()); }
0350
0351 inline int QByteArrayView::compare(QByteArrayView a, Qt::CaseSensitivity cs) const noexcept
0352 {
0353 return cs == Qt::CaseSensitive ? QtPrivate::compareMemory(*this, a) :
0354 qstrnicmp(data(), size(), a.data(), a.size());
0355 }
0356
0357 #if QT_DEPRECATED_SINCE(6, 0)
0358 QT_DEPRECATED_VERSION_X_6_0("Use the QByteArrayView overload.")
0359 inline quint16 qChecksum(const char *s, qsizetype len,
0360 Qt::ChecksumType standard = Qt::ChecksumIso3309)
0361 { return qChecksum(QByteArrayView(s, len), standard); }
0362 #endif
0363
0364 QT_END_NAMESPACE
0365
0366 #endif