summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/CMakeLists.txt2
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qbytearray.cpp4
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_text_qbytearrayview.cpp67
-rw-r--r--src/corelib/global/qglobal.h2
-rw-r--r--src/corelib/text/qbytearray.cpp388
-rw-r--r--src/corelib/text/qbytearray.h82
-rw-r--r--src/corelib/text/qbytearrayalgorithms.h76
-rw-r--r--src/corelib/text/qbytearrayview.h313
-rw-r--r--src/corelib/text/qbytearrayview.qdoc692
-rw-r--r--src/corelib/text/text.pri2
-rw-r--r--src/corelib/tools/qhash.cpp12
-rw-r--r--src/corelib/tools/qhashfunctions.h1
-rw-r--r--src/tools/moc/generator.cpp6
-rw-r--r--src/tools/uic/qclass_lib_map.h1
-rw-r--r--tests/auto/corelib/text/CMakeLists.txt1
-rw-r--r--tests/auto/corelib/text/qbytearrayview/CMakeLists.txt10
-rw-r--r--tests/auto/corelib/text/qbytearrayview/qbytearrayview.pro4
-rw-r--r--tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp595
-rw-r--r--tests/auto/corelib/text/text.pro1
19 files changed, 1960 insertions, 299 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index 9d6eb3d908..bb697f23f4 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -154,8 +154,10 @@ qt_add_module(Core
statemachine/qstate.cpp statemachine/qstate.h statemachine/qstate_p.h
statemachine/qstatemachine.cpp statemachine/qstatemachine.h statemachine/qstatemachine_p.h
text/qbytearray.cpp text/qbytearray.h text/qbytearray_p.h
+ text/qbytearrayalgorithms.h
text/qbytearraylist.cpp text/qbytearraylist.h
text/qbytearraymatcher.cpp text/qbytearraymatcher.h
+ text/qbytearrayview.h
text/qbytedata_p.h
text/qchar.h
text/qcollator.cpp text/qcollator.h text/qcollator_p.h
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qbytearray.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qbytearray.cpp
index 9c07a2e92c..74f14f2a4b 100644
--- a/src/corelib/doc/snippets/code/src_corelib_text_qbytearray.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qbytearray.cpp
@@ -224,7 +224,7 @@ ba.replace(QByteArray("ou"), QByteArray("o"));
//! [21]
QByteArray x("sticky question");
-QByteArray y("sti");
+QByteArrayView y("sti");
x.indexOf(y); // returns 0
x.indexOf(y, 1); // returns 10
x.indexOf(y, 10); // returns 10
@@ -243,7 +243,7 @@ ba.indexOf("X"); // returns -1
//! [23]
QByteArray x("crazy azimuths");
-QByteArray y("az");
+QByteArrayView y("az");
x.lastIndexOf(y); // returns 6
x.lastIndexOf(y, 6); // returns 6
x.lastIndexOf(y, 5); // returns 2
diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qbytearrayview.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qbytearrayview.cpp
new file mode 100644
index 0000000000..31a2107c62
--- /dev/null
+++ b/src/corelib/doc/snippets/code/src_corelib_text_qbytearrayview.cpp
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtCore/qbytearrayview.h>
+
+//! [0]
+ void myfun1(QByteArrayView bv); // preferred
+ void myfun2(const QByteArrayView &bv); // compiles and works, but slower
+//! [0]
+
+//! [1]
+ void fun(QByteArrayView bv);
+ void fun(char ch) { fun(QByteArrayView(&ch, 1)); }
+//! [1]
+
+void wrapper() {
+ const char array[1] = { 0 };
+//! [2]
+ auto bv = QByteArrayView(array, std::size(array)); // using C++17 std::size()
+//! [2]
+}
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 5065a2716f..539e3e7cda 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -598,8 +598,6 @@ using qsizetype = QIntegerForSizeof<std::size_t>::Signed;
# define QT_WIN_CALLBACK CALLBACK QT_ENSURE_STACK_ALIGNED_FOR_SSE
#endif
-typedef int QNoImplicitBoolCast;
-
/*
Utility macros and inline functions
*/
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp
index 375c64a90c..c498aa30a6 100644
--- a/src/corelib/text/qbytearray.cpp
+++ b/src/corelib/text/qbytearray.cpp
@@ -408,47 +408,16 @@ int qstrnicmp(const char *str1, qsizetype len1, const char *str2, qsizetype len2
/*!
\internal
- ### Qt6: replace the QByteArray parameter with [pointer,len] pair
*/
-int qstrcmp(const QByteArray &str1, const char *str2)
-{
- if (!str2)
- return str1.isEmpty() ? 0 : +1;
-
- const char *str1data = str1.constData();
- const char *str1end = str1data + str1.length();
- for ( ; str1data < str1end && *str2; ++str1data, ++str2) {
- int diff = int(uchar(*str1data)) - uchar(*str2);
- if (diff)
- // found a difference
- return diff;
- }
-
- // Why did we stop?
- if (*str2 != '\0')
- // not the null, so we stopped because str1 is shorter
- return -1;
- if (str1data < str1end)
- // we haven't reached the end, so str1 must be longer
- return +1;
- return 0;
-}
-
-/*!
- \internal
- ### Qt6: replace the QByteArray parameter with [pointer,len] pair
- */
-int qstrcmp(const QByteArray &str1, const QByteArray &str2)
+int QtPrivate::compareMemory(QByteArrayView lhs, QByteArrayView rhs)
{
- int l1 = str1.length();
- int l2 = str2.length();
- int ret = memcmp(str1.constData(), str2.constData(), qMin(l1, l2));
+ int ret = memcmp(lhs.data(), rhs.data(), qMin(lhs.size(), rhs.size()));
if (ret != 0)
return ret;
// they matched qMin(l1, l2) bytes
// so the longer one is lexically after the shorter one
- return l1 - l2;
+ return lhs.size() == rhs.size() ? 0 : lhs.size() > rhs.size() ? 1 : -1;
}
// the CRC table below is created by the following piece of code
@@ -911,7 +880,7 @@ QByteArray qUncompress(const uchar* data, int nbytes)
This issue does not apply to \l{QString}s since they represent characters
using Unicode.
- \sa QString, QBitArray
+ \sa QByteArrayView, QString, QBitArray
*/
/*!
@@ -1446,22 +1415,15 @@ QByteArray &QByteArray::operator=(const char *str)
\sa front(), at(), operator[]()
*/
-/*! \fn bool QByteArray::contains(const QByteArray &ba) const
+/*! \fn bool QByteArray::contains(QByteArrayView bv) const
+ \since 6.0
- Returns \c true if the byte array contains an occurrence of the byte
- array \a ba; otherwise returns \c false.
+ Returns \c true if this byte array contains an occurrence of the
+ sequence of bytes viewed by \a bv; otherwise returns \c false.
\sa indexOf(), count()
*/
-/*! \fn bool QByteArray::contains(const char *str) const
-
- \overload
-
- Returns \c true if the byte array contains the '\\0'-terminated string \a
- str; otherwise returns \c false.
-*/
-
/*! \fn bool QByteArray::contains(char ch) const
\overload
@@ -2388,61 +2350,54 @@ QByteArray QByteArray::repeated(int times) const
hashHaystack -= (a) << ol_minus_1; \
hashHaystack <<= 1
-/*!
- Returns the index position of the first occurrence of the byte
- array \a ba in this byte array, searching forward from index
- position \a from. Returns -1 if \a ba could not be found.
-
- Example:
- \snippet code/src_corelib_text_qbytearray.cpp 21
-
- \sa lastIndexOf(), contains(), count()
-*/
+static inline qsizetype findCharHelper(QByteArrayView haystack, qsizetype from, char needle) noexcept
+{
+ if (from < 0)
+ from = qMax(from + haystack.size(), qsizetype(0));
+ if (from < haystack.size()) {
+ const char *const b = haystack.data();
+ if (const auto n = static_cast<const char *>(
+ memchr(b + from, needle, static_cast<size_t>(haystack.size() - from)))) {
+ return n - b;
+ }
+ }
+ return -1;
+}
-int QByteArray::indexOf(const QByteArray &ba, int from) const
+qsizetype QtPrivate::findByteArray(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept
{
- const int ol = ba.size();
+ const auto ol = needle.size();
if (ol == 0)
return from;
if (ol == 1)
- return indexOf(ba[0], from);
+ return findCharHelper(haystack, from, needle.front());
- const int l = size();
+ const auto l = haystack.size();
if (from > l || ol + from > l)
return -1;
- return static_cast<int>(qFindByteArray(data(), size(), from, ba.data(), ol));
+ return qFindByteArray(haystack.data(), haystack.size(), from, needle.data(), ol);
}
-/*! \fn int QByteArray::indexOf(const char *str, int from) const
-
- \overload
+/*! \fn int QByteArray::indexOf(QByteArrayView bv, int from) const
+ \since 6.0
- Returns the index position of the first occurrence of the '\\0'-terminated
- string \a str in the byte array, searching forward from index position \a
- from. Returns -1 if \a str could not be found.
-*/
-int QByteArray::indexOf(const char *c, int from) const
-{
- const int ol = qstrlen(c);
- if (ol == 1)
- return indexOf(*c, from);
+ Returns the index position of the start of the first occurrence of the
+ sequence of bytes viewed by \a bv in this byte array, searching forward
+ from index position \a from. Returns -1 if no match is found.
- const int l = size();
- if (from > l || ol + from > l)
- return -1;
- if (ol == 0)
- return from;
+ Example:
+ \snippet code/src_corelib_text_qbytearray.cpp 21
- return static_cast<int>(qFindByteArray(data(), size(), from, c, ol));
-}
+ \sa lastIndexOf(), contains(), count()
+*/
/*!
\overload
- Returns the index position of the first occurrence of the byte \a ch in the
- byte array, searching forward from index position \a from. Returns -1 if \a
- ch could not be found.
+ Returns the index position of the start of the first occurrence of the
+ byte \a ch in this byte array, searching forward from index position \a from.
+ Returns -1 if no match is found.
Example:
\snippet code/src_corelib_text_qbytearray.cpp 22
@@ -2452,16 +2407,7 @@ int QByteArray::indexOf(const char *c, int from) const
int QByteArray::indexOf(char ch, int from) const
{
- if (from < 0)
- from = qMax(from + size(), 0);
- if (from < size()) {
- const char *n = data() + from - 1;
- const char *e = end();
- while (++n != e)
- if (*n == ch)
- return n - data();
- }
- return -1;
+ return static_cast<int>(findCharHelper(*this, from, ch));
}
static qsizetype lastIndexOfHelper(const char *haystack, qsizetype l, const char *needle,
@@ -2498,57 +2444,55 @@ static qsizetype lastIndexOfHelper(const char *haystack, qsizetype l, const char
}
-/*!
- \fn int QByteArray::lastIndexOf(const QByteArray &ba, int from) const
-
- Returns the index position of the last occurrence of the byte array \a ba in
- this byte array, searching backward from index position \a from. If \a from
- is -1 (the default), the search starts at the last byte (at index size() -
- 1). Returns -1 if \a ba could not be found.
-
- Example:
- \snippet code/src_corelib_text_qbytearray.cpp 23
-
- \sa indexOf(), contains(), count()
-*/
+static inline qsizetype lastIndexOfCharHelper(QByteArrayView haystack, qsizetype from, char needle) noexcept
+{
+ if (from < 0)
+ from += haystack.size();
+ else if (from > haystack.size())
+ from = haystack.size() - 1;
+ if (from >= 0) {
+ const char *b = haystack.data();
+ const char *n = b + from + 1;
+ while (n-- != b) {
+ if (*n == needle)
+ return n - b;
+ }
+ }
+ return -1;
+}
-int QByteArray::lastIndexOf(const QByteArray &ba, int from) const
+qsizetype QtPrivate::lastIndexOf(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept
{
- if (isEmpty())
- return !ba.size() ? 0 : -1;
- const int ol = ba.size();
+ if (haystack.isEmpty())
+ return !needle.size() ? 0 : -1;
+ const auto ol = needle.size();
if (ol == 1)
- return lastIndexOf(ba[0], from);
+ return lastIndexOfCharHelper(haystack, from, needle.front());
- return lastIndexOfHelper(data(), size(), ba.data(), ol, from);
+ return lastIndexOfHelper(haystack.data(), haystack.size(), needle.data(), ol, from);
}
-/*! \fn int QByteArray::lastIndexOf(const char *str, int from) const
- \overload
+/*! \fn int QByteArray::lastIndexOf(QByteArrayView bv, int from) const
+ \since 6.0
- Returns the index position of the last occurrence of the '\\0'-terminated
- string \a str in the byte array, searching backward from index position \a
- from. If \a from is -1 (the default), the search starts at the last byte (at
- index size() - 1). Returns -1 if \a str could not be found.
-*/
-int QByteArray::lastIndexOf(const char *str, int from) const
-{
- if (isEmpty())
- return (str && *str) ? -1 : 0;
- const int ol = qstrlen(str);
- if (ol == 1)
- return lastIndexOf(*str, from);
+ Returns the index position of the start of the last occurrence of the sequence
+ of bytes viewed by \a bv in this byte array, searching backward from index
+ position \a from. If \a from is -1 (the default), the search starts from the
+ end of the byte array. Returns -1 if no match is found.
- return lastIndexOfHelper(data(), size(), str, ol, from);
-}
+ Example:
+ \snippet code/src_corelib_text_qbytearray.cpp 23
+
+ \sa indexOf(), contains(), count()
+*/
/*!
\overload
- Returns the index position of the last occurrence of byte \a ch in the byte
- array, searching backward from index position \a from. If \a from is -1 (the
- default), the search starts at the last byte (at index size() - 1). Returns
- -1 if \a ch could not be found.
+ Returns the index position of the start of the last occurrence of byte \a ch in
+ this byte array, searching backward from index position \a from. If \a from is -1
+ (the default), the search starts at the last byte (at index size() - 1). Returns
+ -1 if no match is found.
Example:
\snippet code/src_corelib_text_qbytearray.cpp 24
@@ -2558,53 +2502,45 @@ int QByteArray::lastIndexOf(const char *str, int from) const
int QByteArray::lastIndexOf(char ch, int from) const
{
- if (from < 0)
- from += size();
- else if (from > size())
- from = size()-1;
- if (from >= 0) {
- const char *b = data();
- const char *n = b + from + 1;
- while (n-- != b)
- if (*n == ch)
- return n - b;
- }
- return -1;
+ return static_cast<int>(lastIndexOfCharHelper(*this, from, ch));
}
-/*!
- Returns the number of (potentially overlapping) occurrences of
- byte array \a ba in this byte array.
-
- \sa contains(), indexOf()
-*/
+static inline qsizetype countCharHelper(QByteArrayView haystack, char needle) noexcept
+{
+ qsizetype num = 0;
+ for (char ch : haystack) {
+ if (ch == needle)
+ ++num;
+ }
+ return num;
+}
-int QByteArray::count(const QByteArray &ba) const
+qsizetype QtPrivate::count(QByteArrayView haystack, QByteArrayView needle) noexcept
{
- int num = 0;
- int i = -1;
- if (size() > 500 && ba.size() > 5) {
- QByteArrayMatcher matcher(ba);
- while ((i = matcher.indexIn(*this, i + 1)) != -1)
+ if (needle.size() == 1)
+ return countCharHelper(haystack, needle[0]);
+
+ qsizetype num = 0;
+ qsizetype i = -1;
+ if (haystack.size() > 500 && needle.size() > 5) {
+ QByteArrayMatcher matcher(needle.data());
+ while ((i = matcher.indexIn(haystack.data(), i + 1)) != -1)
++num;
} else {
- while ((i = indexOf(ba, i + 1)) != -1)
+ while ((i = haystack.indexOf(needle, i + 1)) != -1)
++num;
}
return num;
}
-/*!
- \overload
+/*! \fn int QByteArray::count(QByteArrayView &bv) const
+ \since 6.0
- Returns the number of (potentially overlapping) occurrences of
- '\\0'-terminated string \a str in the byte array.
-*/
+ Returns the number of (potentially overlapping) occurrences of the
+ sequence of bytes viewed by \a bv in this byte array.
-int QByteArray::count(const char *str) const
-{
- return count(fromRawData(str, qstrlen(str)));
-}
+ \sa contains(), indexOf()
+*/
/*!
\overload
@@ -2616,13 +2552,7 @@ int QByteArray::count(const char *str) const
int QByteArray::count(char ch) const
{
- int num = 0;
- const char *i = end();
- const char *b = begin();
- while (i != b)
- if (*--i == ch)
- ++num;
- return num;
+ return static_cast<int>(countCharHelper(*this, ch));
}
/*! \fn int QByteArray::count() const
@@ -2633,119 +2563,75 @@ int QByteArray::count(char ch) const
*/
/*!
- \fn int QByteArray::compare(const char *c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \since 5.12
-
- Returns an integer less than, equal to, or greater than zero depending on
- whether this QByteArray sorts before, at the same position as, or after the
- '\\0'-terminated string \a c. The comparison is performed according to case
- sensitivity \a cs.
-
- \sa operator==
-*/
-
-/*!
- \fn int QByteArray::compare(const QByteArray &a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
- \overload
- \since 5.12
+ \fn int QByteArray::compare(const QByteArrayView &bv, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
+ \since 6.0
Returns an integer less than, equal to, or greater than zero depending on
whether this QByteArray sorts before, at the same position as, or after the
- QByteArray \a a. The comparison is performed according to case sensitivity
+ QByteArrayView \a bv. The comparison is performed according to case sensitivity
\a cs.
- \sa operator==
+ \sa operator==, {Character Case}
*/
-/*!
- Returns \c true if this byte array starts with byte array \a ba;
- otherwise returns \c false.
-
- Example:
- \snippet code/src_corelib_text_qbytearray.cpp 25
-
- \sa endsWith(), left()
-*/
-bool QByteArray::startsWith(const QByteArray &ba) const
+bool QtPrivate::startsWith(QByteArrayView haystack, QByteArrayView needle) noexcept
{
- if (size() < ba.size())
+ if (haystack.size() < needle.size())
return false;
- if (data() == ba.data() || ba.size() == 0)
+ if (haystack.data() == needle.data() || needle.size() == 0)
return true;
- return memcmp(data(), ba.data(), ba.size()) == 0;
+ return memcmp(haystack.data(), needle.data(), needle.size()) == 0;
}
-/*! \overload
+/*! \fn bool QByteArray::startsWith(QByteArrayView bv) const
+ \since 6.0
+
+ Returns \c true if this byte array starts with the sequence of bytes
+ viewed by \a bv; otherwise returns \c false.
- Returns \c true if this byte array starts with '\\0'-terminated string \a
- str; otherwise returns \c false.
+ Example:
+ \snippet code/src_corelib_text_qbytearray.cpp 25
+
+ \sa endsWith(), left()
*/
-bool QByteArray::startsWith(const char *str) const
-{
- if (!str || !*str)
- return true;
- const int len = int(strlen(str));
- if (size() < len)
- return false;
- return qstrncmp(data(), str, len) == 0;
-}
-/*! \overload
+/*!
+ \fn bool QByteArray::startsWith(char ch) const
+ \overload
Returns \c true if this byte array starts with byte \a ch; otherwise returns
\c false.
*/
-bool QByteArray::startsWith(char ch) const
+
+bool QtPrivate::endsWith(QByteArrayView haystack, QByteArrayView needle) noexcept
{
- if (size() == 0)
+ if (haystack.size() < needle.size())
return false;
- return data()[0] == ch;
+ if (haystack.end() == needle.end() || needle.size() == 0)
+ return true;
+ return memcmp(haystack.end() - needle.size(), needle.data(), needle.size()) == 0;
}
/*!
- Returns \c true if this byte array ends with byte array \a ba;
- otherwise returns \c false.
+ \fn bool QByteArray::endsWith(QByteArrayView bv) const
+ \since 6.0
+
+ Returns \c true if this byte array ends with the sequence of bytes
+ viewed by \a bv; otherwise returns \c false.
Example:
\snippet code/src_corelib_text_qbytearray.cpp 26
\sa startsWith(), right()
*/
-bool QByteArray::endsWith(const QByteArray &ba) const
-{
- if (size() < ba.size())
- return false;
- if (end() == ba.end() || ba.size() == 0)
- return true;
- return memcmp(end() - ba.size(), ba.data(), ba.size()) == 0;
-}
-
-/*! \overload
- Returns \c true if this byte array ends with '\\0'-terminated string \a str;
- otherwise returns \c false.
-*/
-bool QByteArray::endsWith(const char *str) const
-{
- if (!str || !*str)
- return true;
- const int len = int(strlen(str));
- if (size() < len)
- return false;
- return qstrncmp(end() - len, str, len) == 0;
-}
-
-/*! \overload
+/*!
+ \fn bool QByteArray::endsWith(char ch) const
+ \overload
Returns \c true if this byte array ends with byte \a ch;
otherwise returns \c false.
*/
-bool QByteArray::endsWith(char ch) const
-{
- if (size() == 0)
- return false;
- return data()[size() - 1] == ch;
-}
/*
Returns true if \a c is an uppercase ASCII letter.
diff --git a/src/corelib/text/qbytearray.h b/src/corelib/text/qbytearray.h
index 1e0a671981..c7101716c4 100644
--- a/src/corelib/text/qbytearray.h
+++ b/src/corelib/text/qbytearray.h
@@ -46,6 +46,8 @@
#include <QtCore/qarraydata.h>
#include <QtCore/qarraydatapointer.h>
#include <QtCore/qcontainerfwd.h>
+#include <QtCore/qbytearrayalgorithms.h>
+#include <QtCore/qbytearrayview.h>
#include <stdlib.h>
#include <string.h>
@@ -94,10 +96,8 @@ Q_CORE_EXPORT char *qstrcpy(char *dst, const char *src);
Q_CORE_EXPORT char *qstrncpy(char *dst, const char *src, uint len);
Q_CORE_EXPORT int qstrcmp(const char *str1, const char *str2);
-Q_CORE_EXPORT int qstrcmp(const QByteArray &str1, const QByteArray &str2);
-Q_CORE_EXPORT int qstrcmp(const QByteArray &str1, const char *str2);
static inline int qstrcmp(const char *str1, const QByteArray &str2)
-{ return -qstrcmp(str2, str1); }
+{ return -QtPrivate::compareMemory(str2, str1); }
inline int qstrncmp(const char *str1, const char *str2, uint len)
{
@@ -202,21 +202,20 @@ public:
Q_REQUIRED_RESULT inline char &back();
int indexOf(char c, int from = 0) const;
- int indexOf(const char *c, int from = 0) const;
- int indexOf(const QByteArray &a, int from = 0) const;
+ int indexOf(QByteArrayView bv, int from = 0) const
+ { return int(QtPrivate::findByteArray(qToByteArrayViewIgnoringNull(*this), from, bv)); }
+
int lastIndexOf(char c, int from = -1) const;
- int lastIndexOf(const char *c, int from = -1) const;
- int lastIndexOf(const QByteArray &a, int from = -1) const;
+ int lastIndexOf(QByteArrayView bv, int from = -1) const
+ { return int(QtPrivate::lastIndexOf(qToByteArrayViewIgnoringNull(*this), from, bv)); }
inline bool contains(char c) const;
- inline bool contains(const char *a) const;
- inline bool contains(const QByteArray &a) const;
+ inline bool contains(QByteArrayView bv) const;
int count(char c) const;
- int count(const char *a) const;
- int count(const QByteArray &a) const;
+ int count(const QByteArrayView &bv) const
+ { return int(QtPrivate::count(qToByteArrayViewIgnoringNull(*this), bv)); }
- inline int compare(const char *c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
- inline int compare(const QByteArray &a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
+ inline int compare(const QByteArrayView &a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
Q_REQUIRED_RESULT QByteArray left(int len) const;
Q_REQUIRED_RESULT QByteArray right(int len) const;
@@ -233,13 +232,13 @@ public:
Q_REQUIRED_RESULT QByteArray chopped(int len) const
{ Q_ASSERT(len >= 0); Q_ASSERT(len <= size()); return first(size() - len); }
- bool startsWith(const QByteArray &a) const;
- bool startsWith(char c) const;
- bool startsWith(const char *c) const;
+ bool startsWith(QByteArrayView bv) const
+ { return QtPrivate::startsWith(qToByteArrayViewIgnoringNull(*this), bv); }
+ bool startsWith(char c) const { return size() > 0 && front() == c; }
- bool endsWith(const QByteArray &a) const;
- bool endsWith(char c) const;
- bool endsWith(const char *c) const;
+ bool endsWith(char c) const { return size() > 0 && back() == c; }
+ bool endsWith(QByteArrayView bv) const
+ { return QtPrivate::endsWith(qToByteArrayViewIgnoringNull(*this), bv); }
bool isUpper() const;
bool isLower() const;
@@ -429,7 +428,6 @@ public:
}
private:
- operator QNoImplicitBoolCast() const;
void reallocData(uint alloc, Data::ArrayOptions options);
void expand(int i);
QByteArray nulTerminated() const;
@@ -553,53 +551,48 @@ inline void QByteArray::push_front(const char *c)
{ prepend(c); }
inline void QByteArray::push_front(const QByteArray &a)
{ prepend(a); }
-inline bool QByteArray::contains(const QByteArray &a) const
-{ return indexOf(a) != -1; }
inline bool QByteArray::contains(char c) const
{ return indexOf(c) != -1; }
-inline int QByteArray::compare(const char *c, Qt::CaseSensitivity cs) const noexcept
-{
- return cs == Qt::CaseSensitive ? qstrcmp(*this, c) :
- qstrnicmp(data(), size(), c, -1);
-}
-inline int QByteArray::compare(const QByteArray &a, Qt::CaseSensitivity cs) const noexcept
+inline bool QByteArray::contains(QByteArrayView bv) const
+{ return indexOf(bv) != -1; }
+inline int QByteArray::compare(const QByteArrayView &a, Qt::CaseSensitivity cs) const noexcept
{
- return cs == Qt::CaseSensitive ? qstrcmp(*this, a) :
+ return cs == Qt::CaseSensitive ? QtPrivate::compareMemory(*this, a) :
qstrnicmp(data(), size(), a.data(), a.size());
}
Q_CORE_EXPORT bool operator==(const QByteArray &a1, const QByteArray &a2) noexcept;
inline bool operator==(const QByteArray &a1, const char *a2) noexcept
-{ return a2 ? qstrcmp(a1,a2) == 0 : a1.isEmpty(); }
+{ return a2 ? QtPrivate::compareMemory(a1, a2) == 0 : a1.isEmpty(); }
inline bool operator==(const char *a1, const QByteArray &a2) noexcept
{ return a1 ? qstrcmp(a1,a2) == 0 : a2.isEmpty(); }
inline bool operator!=(const QByteArray &a1, const QByteArray &a2) noexcept
{ return !(a1==a2); }
inline bool operator!=(const QByteArray &a1, const char *a2) noexcept
-{ return a2 ? qstrcmp(a1,a2) != 0 : !a1.isEmpty(); }
+{ return a2 ? QtPrivate::compareMemory(a1, a2) != 0 : !a1.isEmpty(); }
inline bool operator!=(const char *a1, const QByteArray &a2) noexcept
{ return a1 ? qstrcmp(a1,a2) != 0 : !a2.isEmpty(); }
inline bool operator<(const QByteArray &a1, const QByteArray &a2) noexcept
-{ return qstrcmp(a1, a2) < 0; }
+{ return QtPrivate::compareMemory(QByteArrayView(a1), QByteArrayView(a2)) < 0; }
inline bool operator<(const QByteArray &a1, const char *a2) noexcept
-{ return qstrcmp(a1, a2) < 0; }
+{ return QtPrivate::compareMemory(a1, a2) < 0; }
inline bool operator<(const char *a1, const QByteArray &a2) noexcept
{ return qstrcmp(a1, a2) < 0; }
inline bool operator<=(const QByteArray &a1, const QByteArray &a2) noexcept
-{ return qstrcmp(a1, a2) <= 0; }
+{ return QtPrivate::compareMemory(QByteArrayView(a1), QByteArrayView(a2)) <= 0; }
inline bool operator<=(const QByteArray &a1, const char *a2) noexcept
-{ return qstrcmp(a1, a2) <= 0; }
+{ return QtPrivate::compareMemory(a1, a2) <= 0; }
inline bool operator<=(const char *a1, const QByteArray &a2) noexcept
{ return qstrcmp(a1, a2) <= 0; }
inline bool operator>(const QByteArray &a1, const QByteArray &a2) noexcept
-{ return qstrcmp(a1, a2) > 0; }
+{ return QtPrivate::compareMemory(QByteArrayView(a1), QByteArrayView(a2)) > 0; }
inline bool operator>(const QByteArray &a1, const char *a2) noexcept
-{ return qstrcmp(a1, a2) > 0; }
+{ return QtPrivate::compareMemory(a1, a2) > 0; }
inline bool operator>(const char *a1, const QByteArray &a2) noexcept
{ return qstrcmp(a1, a2) > 0; }
inline bool operator>=(const QByteArray &a1, const QByteArray &a2) noexcept
-{ return qstrcmp(a1, a2) >= 0; }
+{ return QtPrivate::compareMemory(QByteArrayView(a1), QByteArrayView(a2)) >= 0; }
inline bool operator>=(const QByteArray &a1, const char *a2) noexcept
-{ return qstrcmp(a1, a2) >= 0; }
+{ return QtPrivate::compareMemory(a1, a2) >= 0; }
inline bool operator>=(const char *a1, const QByteArray &a2) noexcept
{ return qstrcmp(a1, a2) >= 0; }
#if !defined(QT_USE_QSTRINGBUILDER)
@@ -614,8 +607,6 @@ inline const QByteArray operator+(const char *a1, const QByteArray &a2)
inline const QByteArray operator+(char a1, const QByteArray &a2)
{ return QByteArray(&a1, 1) += a2; }
#endif // QT_USE_QSTRINGBUILDER
-inline bool QByteArray::contains(const char *c) const
-{ return indexOf(c) != -1; }
inline QByteArray &QByteArray::replace(char before, const char *c)
{ return replace(&before, 1, c, qstrlen(c)); }
inline QByteArray &QByteArray::replace(const QByteArray &before, const char *c)
@@ -704,6 +695,15 @@ inline bool operator!=(const QByteArray::FromBase64Result &lhs, const QByteArray
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QByteArray::FromBase64Result &key, size_t seed = 0) noexcept;
+//
+// QByteArrayView members that require QByteArray:
+//
+QByteArray QByteArrayView::toByteArray() const
+{
+ Q_ASSERT(size() == int(size()));
+ return QByteArray(data(), int(size()));
+}
+
QT_END_NAMESPACE
#endif // QBYTEARRAY_H
diff --git a/src/corelib/text/qbytearrayalgorithms.h b/src/corelib/text/qbytearrayalgorithms.h
new file mode 100644
index 0000000000..fdcd00a8c1
--- /dev/null
+++ b/src/corelib/text/qbytearrayalgorithms.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** 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$
+**
+****************************************************************************/
+
+#ifndef QBYTEARRAYALGORITHMS_H
+#define QBYTEARRAYALGORITHMS_H
+
+#include <QtCore/qnamespace.h>
+
+#if 0
+#pragma qt_class(QByteArrayAlgorithms)
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QByteArrayView;
+
+namespace QtPrivate {
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+bool startsWith(QByteArrayView haystack, QByteArrayView needle) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+bool endsWith(QByteArrayView haystack, QByteArrayView needle) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+qsizetype findByteArray(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+qsizetype lastIndexOf(QByteArrayView haystack, qsizetype from, QByteArrayView needle) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION
+qsizetype count(QByteArrayView haystack, QByteArrayView needle) noexcept;
+
+[[nodiscard]] Q_CORE_EXPORT int compareMemory(QByteArrayView lhs, QByteArrayView rhs);
+
+} // namespace QtPrivate
+
+QT_END_NAMESPACE
+
+#endif // QBYTEARRAYALGORITHMS_H
diff --git a/src/corelib/text/qbytearrayview.h b/src/corelib/text/qbytearrayview.h
new file mode 100644
index 0000000000..36764abfb4
--- /dev/null
+++ b/src/corelib/text/qbytearrayview.h
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** 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$
+**
+****************************************************************************/
+#ifndef QBYTEARRAYVIEW_H
+#define QBYTEARRAYVIEW_H
+
+#include <QtCore/qbytearrayalgorithms.h>
+
+#include <string>
+
+QT_BEGIN_NAMESPACE
+
+class QByteArray;
+class QLatin1String;
+
+namespace QtPrivate {
+
+template <typename Byte>
+struct IsCompatibleByteTypeHelper
+ : std::integral_constant<bool,
+ std::is_same_v<Byte, char> ||
+ std::is_same_v<Byte, uchar> ||
+ std::is_same_v<Byte, signed char> ||
+ std::is_same_v<Byte, std::byte>> {};
+
+template <typename Byte>
+struct IsCompatibleByteType
+ : IsCompatibleByteTypeHelper<
+ typename std::remove_cv_t<typename std::remove_reference_t<Byte>>> {};
+
+template <typename Pointer>
+struct IsCompatibleByteArrayPointerHelper : std::false_type {};
+template <typename Byte>
+struct IsCompatibleByteArrayPointerHelper<Byte *>
+ : IsCompatibleByteType<Byte> {};
+template<typename Pointer>
+struct IsCompatibleByteArrayPointer
+ : IsCompatibleByteArrayPointerHelper<
+ typename std::remove_cv_t<typename std::remove_reference_t<Pointer>>> {};
+
+template <typename T, typename Enable = void>
+struct IsContainerCompatibleWithQByteArrayView : std::false_type {};
+
+template <typename T>
+struct IsContainerCompatibleWithQByteArrayView<T, std::enable_if_t<
+ std::conjunction_v<
+ // lacking concepts and ranges, we accept any T whose std::data yields a suitable
+ // pointer ...
+ IsCompatibleByteArrayPointer<decltype(std::data(std::declval<const T &>()))>,
+ // ... and that has a suitable size ...
+ std::is_convertible<decltype(std::size(std::declval<const T &>())), qsizetype>,
+ // ... and it's a range as it defines an iterator-like API
+ IsCompatibleByteType<typename std::iterator_traits<decltype(
+ std::begin(std::declval<const T &>()))>::value_type>,
+ std::is_convertible<decltype(std::begin(std::declval<const T &>())
+ != std::end(std::declval<const T &>())),
+ bool>,
+
+ // This needs to be treated specially due to the empty vs null distinction
+ std::negation<std::is_same<std::decay_t<T>, QByteArray>>,
+
+ // Don't make an accidental copy constructor
+ std::negation<std::is_same<std::decay_t<T>, QByteArrayView>>>>> : std::true_type {};
+
+} // namespace QtPrivate
+
+class Q_CORE_EXPORT QByteArrayView
+{
+public:
+ typedef char storage_type;
+ typedef const char value_type;
+ typedef qptrdiff difference_type;
+ typedef qsizetype size_type;
+ typedef value_type &reference;
+ typedef value_type &const_reference;
+ typedef value_type *pointer;
+ typedef value_type *const_pointer;
+
+ typedef pointer iterator;
+ typedef const_pointer const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+private:
+ template <typename Byte>
+ using if_compatible_byte =
+ typename std::enable_if_t<QtPrivate::IsCompatibleByteType<Byte>::value, bool>;
+
+ template <typename Pointer>
+ using if_compatible_pointer =
+ typename std::enable_if_t<QtPrivate::IsCompatibleByteArrayPointer<Pointer>::value,
+ bool>;
+
+ template <typename T>
+ using if_compatible_qbytearray_like =
+ typename std::enable_if_t<std::is_same_v<T, QByteArray>, bool>;
+
+ template <typename T>
+ using if_compatible_container =
+ typename std::enable_if_t<QtPrivate::IsContainerCompatibleWithQByteArrayView<T>::value,
+ bool>;
+
+ template <typename Char>
+ static constexpr qsizetype lengthHelperPointer(const Char *data) noexcept
+ {
+ return qsizetype(std::char_traits<Char>::length(data));
+ }
+
+ template <typename Container>
+ static constexpr qsizetype lengthHelperContainer(const Container &c) noexcept
+ {
+ return qsizetype(std::size(c));
+ }
+
+ template <typename Char, size_t N>
+ static constexpr qsizetype lengthHelperContainer(const Char (&)[N]) noexcept
+ {
+ return qsizetype(N - 1);
+ }
+
+ template <typename Byte>
+ static const storage_type *castHelper(const Byte *data) noexcept
+ { return reinterpret_cast<const storage_type*>(data); }
+ static Q_DECL_CONSTEXPR const storage_type *castHelper(const storage_type *data) noexcept
+ { return data; }
+
+public:
+ constexpr QByteArrayView() noexcept
+ : m_size(0), m_data(nullptr) {}
+ constexpr QByteArrayView(std::nullptr_t) noexcept
+ : QByteArrayView() {}
+
+ template <typename Byte, if_compatible_byte<Byte> = true>
+ constexpr QByteArrayView(const Byte *data, qsizetype len)
+ : m_size((Q_ASSERT(len >= 0), Q_ASSERT(data || !len), len)),
+ m_data(castHelper(data)) {}
+
+ template <typename Byte, if_compatible_byte<Byte> = true>
+ constexpr QByteArrayView(const Byte *first, const Byte *last)
+ : QByteArrayView(first, last - first) {}
+
+#ifdef Q_QDOC
+ template <typename Byte, size_t N>
+ constexpr QByteArrayView(const Byte (&array)[N]) noexcept;
+
+ template <typename Byte>
+ constexpr QByteArrayView(const Byte *data) noexcept;
+#else
+ template <typename Pointer, if_compatible_pointer<Pointer> = true>
+ constexpr QByteArrayView(const Pointer &data) noexcept
+ : QByteArrayView(
+ data, data ? lengthHelperPointer(data) : 0) {}
+#endif
+
+#ifdef Q_QDOC
+ QByteArrayView(const QByteArray &data) noexcept;
+#else
+ template <typename ByteArray, if_compatible_qbytearray_like<ByteArray> = true>
+ QByteArrayView(const ByteArray &ba) noexcept
+ : QByteArrayView(ba.isNull() ? nullptr : ba.data(), qsizetype(ba.size())) {}
+#endif
+
+ template <typename Container, if_compatible_container<Container> = true>
+ constexpr QByteArrayView(const Container &c) noexcept
+ : QByteArrayView(std::data(c), lengthHelperContainer(c)) {}
+
+ [[nodiscard]] inline QByteArray toByteArray() const; // defined in qbytearray.h
+
+ [[nodiscard]] constexpr qsizetype size() const noexcept { return m_size; }
+ [[nodiscard]] constexpr const_pointer data() const noexcept { return m_data; }
+ [[nodiscard]] constexpr const_pointer constData() const noexcept { return data(); }
+
+ [[nodiscard]] constexpr char operator[](qsizetype n) const
+ { Q_ASSERT(n >= 0); Q_ASSERT(n < size()); return m_data[n]; }
+
+ //
+ // QByteArray API
+ //
+ [[nodiscard]] constexpr char at(qsizetype n) const { return (*this)[n]; }
+
+ [[nodiscard]] constexpr QByteArrayView first(qsizetype n) const
+ { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QByteArrayView(data(), n); }
+ [[nodiscard]] constexpr QByteArrayView last(qsizetype n) const
+ { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QByteArrayView(data() + size() - n, n); }
+ [[nodiscard]] constexpr QByteArrayView sliced(qsizetype pos) const
+ { Q_ASSERT(pos >= 0); Q_ASSERT(pos <= size()); return QByteArrayView(data() + pos, size() - pos); }
+ [[nodiscard]] constexpr QByteArrayView sliced(qsizetype pos, qsizetype n) const
+ { Q_ASSERT(pos >= 0); Q_ASSERT(n >= 0); Q_ASSERT(size_t(pos) + size_t(n) <= size_t(size())); return QByteArrayView(data() + pos, n); }
+ [[nodiscard]] constexpr QByteArrayView chopped(qsizetype len) const
+ { Q_ASSERT(len >= 0); Q_ASSERT(len <= size()); return first(size() - len); }
+
+ constexpr void truncate(qsizetype n)
+ { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size = n; }
+ constexpr void chop(qsizetype n)
+ { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size -= n; }
+
+ [[nodiscard]] bool startsWith(QByteArrayView other) const noexcept
+ { return QtPrivate::startsWith(*this, other); }
+ [[nodiscard]] bool startsWith(char c) const noexcept
+ { return !empty() && front() == c; }
+
+ [[nodiscard]] bool endsWith(QByteArrayView other) const noexcept
+ { return QtPrivate::endsWith(*this, other); }
+ [[nodiscard]] bool endsWith(char c) const noexcept
+ { return !empty() && back() == c; }
+
+ [[nodiscard]] qsizetype indexOf(QByteArrayView a, qsizetype from = 0) const noexcept
+ { return QtPrivate::findByteArray(*this, from, a); }
+ [[nodiscard]] qsizetype indexOf(char ch, qsizetype from = 0) const noexcept
+ { return QtPrivate::findByteArray(*this, from, QByteArrayView(&ch, 1)); }
+
+ [[nodiscard]] bool contains(QByteArrayView a) const noexcept
+ { return indexOf(a) != qsizetype(-1); }
+ [[nodiscard]] bool contains(char c) const noexcept
+ { return indexOf(c) != qsizetype(-1); }
+
+ [[nodiscard]] qsizetype lastIndexOf(QByteArrayView a, qsizetype from = -1) const noexcept
+ { return QtPrivate::lastIndexOf(*this, from, a); }
+ [[nodiscard]] qsizetype lastIndexOf(char ch, qsizetype from = -1) const noexcept
+ { return QtPrivate::lastIndexOf(*this, from, QByteArrayView(&ch, 1)); }
+
+ [[nodiscard]] qsizetype count(QByteArrayView a) const noexcept
+ { return QtPrivate::count(*this, a); }
+ [[nodiscard]] qsizetype count(char ch) const noexcept
+ { return QtPrivate::count(*this, QByteArrayView(&ch, 1)); }
+
+ //
+ // STL compatibility API:
+ //
+ [[nodiscard]] constexpr const_iterator begin() const noexcept { return data(); }
+ [[nodiscard]] constexpr const_iterator end() const noexcept { return data() + size(); }
+ [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return begin(); }
+ [[nodiscard]] constexpr const_iterator cend() const noexcept { return end(); }
+ [[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
+ [[nodiscard]] constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
+ [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
+ [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return rend(); }
+
+ [[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
+ [[nodiscard]] constexpr char front() const { Q_ASSERT(!empty()); return m_data[0]; }
+ [[nodiscard]] constexpr char back() const { Q_ASSERT(!empty()); return m_data[m_size - 1]; }
+
+ //
+ // Qt compatibility API:
+ //
+ [[nodiscard]] constexpr bool isNull() const noexcept { return !m_data; }
+ [[nodiscard]] constexpr bool isEmpty() const noexcept { return empty(); }
+#if QT_DEPRECATED_SINCE(6, 0)
+ [[nodiscard]]
+ Q_DECL_DEPRECATED_X("Use size() and port callers to qsizetype.")
+ constexpr int length() const /* not nothrow! */
+ { Q_ASSERT(int(size()) == size()); return int(size()); }
+#endif
+ [[nodiscard]] constexpr char first() const { return front(); }
+ [[nodiscard]] constexpr char last() const { return back(); }
+
+private:
+ qsizetype m_size;
+ const storage_type *m_data;
+};
+Q_DECLARE_TYPEINFO(QByteArrayView, Q_PRIMITIVE_TYPE);
+
+// QByteArrayView <> QByteArrayView
+inline bool operator==(QByteArrayView lhs, QByteArrayView rhs) noexcept { return lhs.size() == rhs.size() && QtPrivate::compareMemory(lhs, rhs) == 0; }
+inline bool operator!=(QByteArrayView lhs, QByteArrayView rhs) noexcept { return !(lhs == rhs); }
+inline bool operator< (QByteArrayView lhs, QByteArrayView rhs) noexcept { return QtPrivate::compareMemory(lhs, rhs) < 0; }
+inline bool operator<=(QByteArrayView lhs, QByteArrayView rhs) noexcept { return QtPrivate::compareMemory(lhs, rhs) <= 0; }
+inline bool operator> (QByteArrayView lhs, QByteArrayView rhs) noexcept { return !(lhs <= rhs); }
+inline bool operator>=(QByteArrayView lhs, QByteArrayView rhs) noexcept { return !(lhs < rhs); }
+
+template<typename QByteArrayLike,
+ std::enable_if_t<std::is_same_v<QByteArrayLike, QByteArray>, bool> = true>
+[[nodiscard]] inline QByteArrayView qToByteArrayViewIgnoringNull(const QByteArrayLike &b) noexcept
+{ return QByteArrayView(b.data(), b.size()); }
+
+QT_END_NAMESPACE
+
+#endif // QBYTEARRAYVIEW_H
diff --git a/src/corelib/text/qbytearrayview.qdoc b/src/corelib/text/qbytearrayview.qdoc
new file mode 100644
index 0000000000..d1a9df6a1c
--- /dev/null
+++ b/src/corelib/text/qbytearrayview.qdoc
@@ -0,0 +1,692 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QByteArrayView
+ \inmodule QtCore
+ \brief The QByteArrayView class provides a view on an array of bytes with a read-only
+ subset of the QByteArray API.
+ \since 6.0
+
+ \ingroup tools
+ \ingroup shared
+ \ingroup string-processing
+
+ \reentrant
+
+ A QByteArrayView references a contiguous portion of raw bytes it does
+ not own. It acts as an interface type to all kinds of byte-array-like data,
+ without the need to construct a QByteArray first.
+
+ The byte array data may be represented as an array (or an array-compatible
+ data-structure such as QByteArray, std::basic_string, etc.) of \c char,
+ \c{signed char}, \c{unsigned char} or \c std::byte.
+
+ QByteArrayView is designed as an interface type; its main use-case is
+ as a function parameter type. When QByteArrayViews are used as automatic
+ variables or data members, care must be taken to ensure that the referenced
+ data (for example, owned by a QByteArray) outlives the QByteArrayView on all
+ code paths, lest the byte array view ends up referencing deleted data.
+
+ When used as an interface type, QByteArrayView allows a single function to accept
+ a wide variety of byte-array-like data sources. One function accepting QByteArrayView
+ thus replaces several function overloads (taking, for example, QByteArray, const char *,
+ etc.) while at the same time enabling even more byte array data sources to be passed
+ to the function.
+
+ QByteArrayView should be passed by value, not by reference-to-const:
+ \snippet code/src_corelib_text_qbytearrayview.cpp 0
+
+ If you want to give your users maximum freedom in what type of data they
+ can pass to your function, accompany the QByteArrayView overload with
+ overloads for
+
+ \list
+ \li \e char: this overload can delegate to the QByteArrayView version:
+ \snippet code/src_corelib_text_qbytearrayview.cpp 1
+ even though, for technical reasons, QByteArrayView cannot provide a
+ char constructor by itself.
+ \li \e QByteArray: if you store an unmodified copy of the byte array and
+ thus would like to take advantage of QByteArray's implicit sharing.
+ \endlist
+
+ QByteArrayView can also be used as the return value of a function. If you call a
+ function returning QByteArrayView, take extra care to not keep the QByteArrayView
+ around longer than the function promises to keep the referenced data alive.
+ If in doubt, obtain a strong reference to the data by calling toByteArray() to convert
+ the QByteArrayView into a QByteArray.
+
+ \section1 Compatible Byte Types
+
+ QByteArrayView can be constructed on any container of bytes, where the byte type
+ is one of:
+
+ \list
+ \li \c char (both signed and unsigned)
+ \li \c std::byte
+ \endlist
+
+ \sa QByteArray, QStringView
+*/
+
+/*!
+ \typedef QByteArrayView::storage_type
+
+ Alias for \c char.
+*/
+
+/*!
+ \typedef QByteArrayView::value_type
+
+ Alias for \c{const char}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QByteArrayView::difference_type
+
+ Alias for \c{std::ptrdiff_t}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QByteArrayView::size_type
+
+ Alias for qsizetype. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QByteArrayView::reference
+
+ Alias for \c{value_type &}. Provided for compatibility with the STL.
+
+ QByteArrayView does not support mutable references, so this is the same
+ as const_reference.
+*/
+
+/*!
+ \typedef QByteArrayView::const_reference
+
+ Alias for \c{value_type &}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QByteArrayView::pointer
+
+ Alias for \c{value_type *}. Provided for compatibility with the STL.
+
+ QByteArrayView does not support mutable pointers, so this is the same
+ as const_pointer.
+*/
+
+/*!
+ \typedef QByteArrayView::const_pointer
+
+ Alias for \c{value_type *}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QByteArrayView::iterator
+
+ This typedef provides an STL-style const iterator for QByteArrayView.
+
+ QByteArrayView does not support mutable iterators, so this is the same
+ as const_iterator.
+
+ \sa const_iterator, reverse_iterator
+*/
+
+/*!
+ \typedef QByteArrayView::const_iterator
+
+ This typedef provides an STL-style const iterator for QByteArrayView.
+
+ \sa iterator, const_reverse_iterator
+*/
+
+/*!
+ \typedef QByteArrayView::reverse_iterator
+
+ This typedef provides an STL-style const reverse iterator for QByteArrayView.
+
+ QByteArrayView does not support mutable reverse iterators, so this is the
+ same as const_reverse_iterator.
+
+ \sa const_reverse_iterator, iterator
+*/
+
+/*!
+ \typedef QByteArrayView::const_reverse_iterator
+
+ This typedef provides an STL-style const reverse iterator for QByteArrayView.
+
+ \sa reverse_iterator, const_iterator
+*/
+
+/*!
+ \fn QByteArrayView::QByteArrayView()
+
+ Constructs a null byte array view.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QByteArrayView::QByteArrayView(std::nullptr_t)
+
+ Constructs a null byte array view.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn template <typename Byte> QByteArrayView::QByteArrayView(const Byte *data, qsizetype len)
+
+ Constructs a byte array view on \a data with length \a len.
+
+ The range \c{[data,len)} must remain valid for the lifetime of this QByteArrayView.
+
+ Passing \nullptr as \a data is safe if \a len is 0, too, and results in a null
+ byte array view.
+
+ The behavior is undefined if \a len is negative or, when positive, if \a data is \nullptr.
+
+ This constructor only participates in overload resolution if \c Byte is a compatible
+ byte type.
+
+ \sa {Compatible Byte Types}
+*/
+
+/*!
+ \fn template <typename Byte> QByteArrayView::QByteArrayView(const Byte *first, const Byte *last)
+
+ Constructs a byte array view on \a first with length (\a last - \a first).
+
+ The range \c{[first,last)} must remain valid for the lifetime of
+ this QByteArrayView.
+
+ Passing \c \nullptr as \a first is safe if \a last is \nullptr, too,
+ and results in a null byte array view.
+
+ The behavior is undefined if \a last precedes \a first, or \a first
+ is \nullptr and \a last is not.
+
+ This constructor only participates in overload resolution if \c Byte is
+ a compatible byte type.
+
+ \sa {Compatible Byte Types}
+*/
+
+/*!
+ \fn template <typename Byte> QByteArrayView::QByteArrayView(const Byte *data)
+
+ Constructs a byte array view on \a data. The length is determined
+ by scanning for the first \c{Byte(0)}.
+
+ \a data must remain valid for the lifetime of this byte array view object.
+
+ Passing \nullptr as \a data is safe and results in a null byte array view.
+
+ This constructor only participates in overload resolution if \a data is not
+ an array and if \c Byte is a compatible byte type.
+
+ \sa {Compatible Byte Types}
+*/
+
+/*!
+ \fn template <typename Byte, size_t N> QByteArrayView::QByteArrayView(const Byte (&data)[N])
+
+ Constructs a byte array view on the array of bytes \a data.
+ The length is set to \c{N-1}, excluding the trailing \{Byte(0)}.
+ If you need the full array, use the constructor from pointer and
+ size instead:
+
+ \snippet code/src_corelib_text_qbytearrayview.cpp 2
+
+ \a data must remain valid for the lifetime of this byte array view
+ object.
+
+ This constructor only participates in overload resolution if \a
+ data is an actual array and \c Byte is a compatible byte
+ type.
+
+ \sa {Compatible Byte Types}
+*/
+
+/*!
+ \fn QByteArrayView::QByteArrayView(const QByteArray &byteArray)
+
+ Constructs a byte array view on \a byteArray.
+
+ \c{byteArray.data()} must remain valid for the lifetime of this byte array view object.
+
+ The byte array view will be null if and only if \c{byteArray.isNull()}.
+*/
+
+/*!
+ \fn template <typename Container> QByteArrayView::QByteArrayView(const Container &c)
+
+ Constructs a byte array view on the array-like container \a c. The length and data
+ are set via \c{std::size(c)} and \c{std::data(c)} respectively.
+
+ The container's data must remain valid for the lifetime of this byte array view object.
+
+ This constructor participates in overload resolution if \a c is any contiguous
+ container container with elements of a compatible byte type.
+
+ \sa {Compatible Byte Types}
+*/
+
+/*!
+ \fn QByteArray QByteArrayView::toByteArray() const
+
+ Returns a deep copy of this byte array view's data as a QByteArray.
+
+ The return value will be a null QByteArray if and only if this byte array
+ view is null.
+
+ \warning QByteArrayView can store data with more than 2\sup{31} bytes while
+ QByteArray cannot. Calling this function on a byte array view for which size()
+ returns a value greater than \c{INT_MAX / 2} constitutes undefined behavior.
+*/
+
+/*!
+ \fn const char *QByteArrayView::data() const
+
+ Returns a const \c char pointer to the first byte in the byte array.
+
+ \note The character array represented by the return value is \e not guaranteed
+ to be null-terminated. The returned pointer is only safe to use for accessing
+ bytes at indices that are less than this byte array view's size().
+
+ \sa begin(), end()
+*/
+
+/*!
+ \fn const char *QByteArrayView::constData() const
+
+ Returns a const \c char pointer to the first byte in the byte array.
+
+ \note The character array represented by the return value is \e not guaranteed
+ to be null-terminated. The returned pointer is only safe to use for accessing
+ bytes at indices that are less than this byte array view's size().
+
+ \sa data(), begin(), end()
+*/
+
+/*!
+ \fn QByteArrayView::const_iterator QByteArrayView::begin() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the
+ first byte in the byte array.
+
+ This function is provided for STL compatibility.
+
+ \sa end(), cbegin(), rbegin(), data()
+*/
+
+/*!
+ \fn QByteArrayView::const_iterator QByteArrayView::cbegin() const
+
+ Same as begin().
+
+ This function is provided for STL compatibility.
+
+ \sa cend(), begin(), crbegin(), data()
+*/
+
+/*!
+ \fn QByteArrayView::const_iterator QByteArrayView::end() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing
+ just after the last byte in the byte array.
+
+ This function is provided for STL compatibility.
+
+ \sa begin(), cend(), rend()
+*/
+
+/*! \fn QByteArrayView::const_iterator QByteArrayView::cend() const
+
+ Same as end().
+
+ This function is provided for STL compatibility.
+
+ \sa cbegin(), end(), crend()
+*/
+
+/*!
+ \fn QByteArrayView::const_reverse_iterator QByteArrayView::rbegin() const
+
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing
+ to the first byte in the byte array, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rend(), crbegin(), begin()
+*/
+
+/*!
+ \fn QByteArrayView::const_reverse_iterator QByteArrayView::crbegin() const
+
+ Same as rbegin().
+
+ This function is provided for STL compatibility.
+
+ \sa crend(), rbegin(), cbegin()
+*/
+
+/*!
+ \fn QByteArrayView::const_reverse_iterator QByteArrayView::rend() const
+
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
+ the last byte in the byte array, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rbegin(), crend(), end()
+*/
+
+/*!
+ \fn QByteArrayView::const_reverse_iterator QByteArrayView::crend() const
+
+ Same as rend().
+
+ This function is provided for STL compatibility.
+
+ \sa crbegin(), rend(), cend()
+*/
+
+/*!
+ \fn bool QByteArrayView::empty() const
+
+ Returns \c true if this byte array view is empty - that is, \c{size() == 0}.
+
+ This function is provided for STL compatibility.
+
+ \sa isEmpty(), isNull(), size()
+*/
+
+/*!
+ \fn bool QByteArrayView::isEmpty() const
+
+ Returns \c true if this byte array view is empty - that is, \c{size() == 0}.
+
+ \sa empty(), isNull(), size()
+*/
+
+/*!
+ \fn bool QByteArrayView::isNull() const
+
+ Returns \c true if this byte array view is null - that is, \c{data() == nullptr}.
+
+ \sa empty(), isEmpty(), size()
+*/
+
+/*!
+ \fn qsizetype QByteArrayView::size() const
+
+ Returns the number of bytes in this byte array view.
+
+ \sa empty(), isEmpty(), isNull()
+*/
+
+#if QT_DEPRECATED_SINCE(6, 0)
+/*!
+ \fn int QByteArrayView::length() const
+ \obsolete
+ Use size() and port callers to qsizetype.
+
+ Same as size(), but returns the result as an \c int.
+
+ This function is provided for compatibility with other Qt containers.
+
+ \warning QByteArrayView can represent data with more than 2\sup{31} bytes.
+ Calling this function on a byte array view for which size() returns a value greater
+ than \c{INT_MAX} constitutes undefined behavior.
+
+ \sa empty(), isEmpty(), isNull(), size()
+*/
+#endif
+
+/*!
+ \fn char QByteArrayView::operator[](qsizetype n) const
+
+ Returns the character at position \a n in this byte array view.
+
+ The behavior is undefined if \a n is negative or not less than size().
+
+ \sa at(), front(), back()
+*/
+
+/*!
+ \fn char QByteArrayView::at(qsizetype n) const
+
+ Returns the character at position \a n in this byte array view.
+
+ The behavior is undefined if \a n is negative or not less than size().
+
+ \sa operator[](), front(), back()
+*/
+
+/*!
+ \fn char QByteArrayView::front() const
+
+ Returns the first byte in the byte array.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty byte array view constitutes
+ undefined behavior.
+
+ \sa back()
+*/
+
+/*!
+ \fn char QByteArrayView::back() const
+
+ Returns the last byte in the byte array.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty byte array view constitutes
+ undefined behavior.
+
+ \sa front()
+*/
+
+/*!
+ \fn QByteArrayView QByteArrayView::first(qsizetype n) const
+
+ Returns a byte array view that points to the first \a n bytes
+ of this byte array view. Equivalent to \c{sliced(0, n)}.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa last(), startsWith(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QByteArrayView QByteArrayView::last(qsizetype n) const
+
+ Returns a byte array view that points to the last \a n bytes
+ of this byte array view.
+
+ \note The behavior is undefined when \a n < 0 or \a n > size().
+
+ \sa first(), endsWith(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QByteArrayView QByteArrayView::sliced(qsizetype pos, qsizetype n) const
+
+ Returns a byte array view that points to \a n bytes of this byte array
+ view, starting at position \a pos.
+
+ \note The behavior is undefined when \a pos < 0, \a n < 0,
+ or \a pos + \a n > size().
+
+ \sa first(), last(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QByteArrayView QByteArrayView::sliced(qsizetype pos) const
+
+ Returns a byte array view starting at position \a pos in this object,
+ and extending to its end.
+
+ \note The behavior is undefined when \a pos < 0 or \a pos > size().
+
+ \sa first(), last(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QByteArrayView QByteArrayView::chopped(qsizetype length) const
+
+ Returns a copy of this byte array view that omits its last \a length bytes.
+ In other words, returns a byte array view of length size() - \a length starting
+ at the beginning of this object.
+
+ Same as \c{first(size() - length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa first(), last(), sliced(), chop(), truncate()
+*/
+
+/*!
+ \fn void QByteArrayView::truncate(qsizetype length)
+
+ Truncates this byte array view to length \a length.
+
+ Same as \c{*this = first(length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa first(), last(), sliced(), right(), chopped(), chop()
+*/
+
+/*!
+ \fn void QByteArrayView::chop(qsizetype length)
+
+ Truncates this byte array view by \a length characters.
+
+ Same as \c{*this = first(size() - length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa sliced(), first(), last(), chopped(), truncate()
+*/
+
+/*!
+ \fn bool QByteArrayView::startsWith(QByteArrayView bv) const
+ \fn bool QByteArrayView::startsWith(char ch) const
+
+ Returns \c true if this byte array view starts with byte array view \a bv
+ or character \a ch, respectively; otherwise returns \c false.
+
+ \sa endsWith()
+*/
+
+/*!
+ \fn bool QByteArrayView::endsWith(QByteArrayView bv) const
+ \fn bool QByteArrayView::endsWith(char ch) const
+
+ Returns \c true if this byte array view ends with byte array view \a bv
+ or character \a ch, respectively; otherwise returns \c false.
+
+ \sa startsWith()
+*/
+
+/*!
+ \fn qsizetype QByteArrayView::indexOf(QByteArrayView bv, qsizetype from = 0) const
+ \fn qsizetype QByteArrayView::indexOf(char ch, qsizetype from = 0) const
+
+ Returns the index position of either the start of the first occurrence of
+ the sequence of bytes viewed by \a bv or the first occurrence of byte \a ch,
+ respectively, in this byte array view, searching forward from index position
+ \a from.Returns -1 if no match is found.
+
+ If \a from is -1, the search starts at the last character; if it is
+ -2, at the next to last character and so on.
+
+ \sa lastIndexOf(), contains()
+*/
+
+/*!
+ \fn bool QByteArrayView::contains(QByteArrayView bv) const
+ \fn bool QByteArrayView::contains(char ch) const
+
+ Returns \c true if this byte array view contains an occurrence of the sequence
+ of bytes viewed by \a bv or character \a ch, respectively; otherwise returns
+ \c false.
+
+ \sa indexOf(), lastIndexOf()
+*/
+
+/*!
+ \fn qsizetype QByteArrayView::lastIndexOf(QByteArrayView bv, qsizetype from = -1) const
+ \fn qsizetype QByteArrayView::lastIndexOf(char ch, qsizetype from = -1) const
+
+ Returns the index position of either the start of the last occurrence of
+ the sequence of bytes viewed by \a bv or the last occurrence of byte \a ch,
+ respectively, in this byte array view, searching forward from index position
+ \a from. If \a from is -1 (the default), the search starts from the end of the
+ byte array view. Returns -1 if no match is found.
+
+ \sa indexOf(), contains()
+*/
+
+/*!
+ \fn int QByteArrayView::count(QByteArrayView &bv) const
+
+ Returns the number of (potentially overlapping) occurrences of the
+ sequence of bytes viewed by \a bv in this byte array view.
+
+ \sa contains(), indexOf()
+*/
+
+/*!
+ \fn bool QByteArrayView::count(char ch) const
+ \overload
+
+ Returns the number of occurrences of byte \a ch in this byte array view.
+
+ \sa contains(), indexOf()
+*/
+
+/*!
+ \fn QByteArrayView qToByteArrayViewIgnoringNull(const QByteArray &b);
+ \internal
+
+ Convert \a b to a QByteArrayView ignoring \c{b.isNull()}.
+
+ Returns a byte array view that references \a{b}'s data, but is never null.
+
+ This is a faster way to convert a QByteArray to a QByteArrayView,
+ if null QByteArray can legitimately be treated as empty ones.
+
+ \sa QByteArray::isNull(), QByteArrayView
+*/
diff --git a/src/corelib/text/text.pri b/src/corelib/text/text.pri
index 1d83bc151b..89fbdddd83 100644
--- a/src/corelib/text/text.pri
+++ b/src/corelib/text/text.pri
@@ -3,8 +3,10 @@
HEADERS += \
text/qbytearray.h \
text/qbytearray_p.h \
+ text/qbytearrayalgorithms.h \
text/qbytearraylist.h \
text/qbytearraymatcher.h \
+ text/qbytearrayview.h \
text/qbytedata_p.h \
text/qchar.h \
text/qcollator.h \
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index f52d46a9e8..0f46e7f113 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -400,6 +400,11 @@ size_t qHash(const QByteArray &key, size_t seed) noexcept
return qHashBits(key.constData(), size_t(key.size()), seed);
}
+size_t qHash(const QByteArrayView &key, size_t seed) noexcept
+{
+ return qHashBits(key.constData(), size_t(key.size()), seed);
+}
+
size_t qHash(QStringView key, size_t seed) noexcept
{
return qHashBits(key.data(), key.size()*sizeof(QChar), seed);
@@ -886,6 +891,13 @@ size_t qHash(long double key, size_t seed) noexcept
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
+/*! \fn size_t qHash(const QByteArrayView &key, size_t seed = 0)
+ \relates QHash
+ \since 6.0
+
+ Returns the hash value for the \a key, using \a seed to seed the calculation.
+*/
+
/*! \fn size_t qHash(const QBitArray &key, size_t seed = 0)
\relates QHash
\since 5.0
diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h
index b48a665383..e8e93206ce 100644
--- a/src/corelib/tools/qhashfunctions.h
+++ b/src/corelib/tools/qhashfunctions.h
@@ -155,6 +155,7 @@ Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(std::nullptr_t, size_t seed
// (some) Qt types
Q_DECL_CONST_FUNCTION constexpr inline size_t qHash(const QChar key, size_t seed = 0) noexcept { return qHash(key.unicode(), seed); }
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QByteArray &key, size_t seed = 0) noexcept;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(const QByteArrayView &key, size_t seed = 0) noexcept;
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION size_t qHash(QStringView key, size_t seed = 0) noexcept;
#if QT_STRINGVIEW_LEVEL < 2
inline Q_DECL_PURE_FUNCTION size_t qHash(const QString &key, size_t seed = 0) noexcept
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 5178e90471..39640b6f68 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -164,7 +164,8 @@ bool Generator::registerableMetaType(const QByteArray &propertyType)
;
for (const QByteArray &smartPointer : smartPointers) {
- if (propertyType.startsWith(smartPointer + "<") && !propertyType.endsWith("&"))
+ QByteArray ba = smartPointer + "<";
+ if (propertyType.startsWith(ba) && !propertyType.endsWith("&"))
return knownQObjectClasses.contains(propertyType.mid(smartPointer.size() + 1, propertyType.size() - smartPointer.size() - 1 - 1));
}
@@ -174,7 +175,8 @@ bool Generator::registerableMetaType(const QByteArray &propertyType)
#undef STREAM_1ARG_TEMPLATE
;
for (const QByteArray &oneArgTemplateType : oneArgTemplates) {
- if (propertyType.startsWith(oneArgTemplateType + "<") && propertyType.endsWith(">")) {
+ QByteArray ba = oneArgTemplateType + "<";
+ if (propertyType.startsWith(ba) && propertyType.endsWith(">")) {
const int argumentSize = propertyType.size() - oneArgTemplateType.size() - 1
// The closing '>'
- 1
diff --git a/src/tools/uic/qclass_lib_map.h b/src/tools/uic/qclass_lib_map.h
index ae6fa911c5..b63b05107b 100644
--- a/src/tools/uic/qclass_lib_map.h
+++ b/src/tools/uic/qclass_lib_map.h
@@ -29,7 +29,6 @@ QT_CLASS_LIB(QIntegerForSize, QtCore, qglobal.h)
QT_CLASS_LIB(QIntegerForSize, QtCore, qglobal.h)
QT_CLASS_LIB(QIntegerForSize, QtCore, qglobal.h)
QT_CLASS_LIB(QIntegerForSize, QtCore, qglobal.h)
-QT_CLASS_LIB(QNoImplicitBoolCast, QtCore, qglobal.h)
QT_CLASS_LIB(Q_INT64, QtCore, qglobal.h)
QT_CLASS_LIB(Q_UINT64, QtCore, qglobal.h)
QT_CLASS_LIB(QSysInfo, QtCore, qglobal.h)
diff --git a/tests/auto/corelib/text/CMakeLists.txt b/tests/auto/corelib/text/CMakeLists.txt
index 1988bcc28d..0c36f1e088 100644
--- a/tests/auto/corelib/text/CMakeLists.txt
+++ b/tests/auto/corelib/text/CMakeLists.txt
@@ -4,6 +4,7 @@ add_subdirectory(qbytearray)
add_subdirectory(qbytearrayapisymmetry)
add_subdirectory(qbytearraylist)
add_subdirectory(qbytearraymatcher)
+add_subdirectory(qbytearrayview)
add_subdirectory(qbytedatabuffer)
add_subdirectory(qchar)
add_subdirectory(qcollator)
diff --git a/tests/auto/corelib/text/qbytearrayview/CMakeLists.txt b/tests/auto/corelib/text/qbytearrayview/CMakeLists.txt
new file mode 100644
index 0000000000..34476b8246
--- /dev/null
+++ b/tests/auto/corelib/text/qbytearrayview/CMakeLists.txt
@@ -0,0 +1,10 @@
+# Generated from qbytearrayview.pro.
+
+#####################################################################
+## tst_qbytearrayview Test:
+#####################################################################
+
+qt_add_test(tst_qbytearrayview
+ SOURCES
+ tst_qbytearrayview.cpp
+)
diff --git a/tests/auto/corelib/text/qbytearrayview/qbytearrayview.pro b/tests/auto/corelib/text/qbytearrayview/qbytearrayview.pro
new file mode 100644
index 0000000000..23d0aed959
--- /dev/null
+++ b/tests/auto/corelib/text/qbytearrayview/qbytearrayview.pro
@@ -0,0 +1,4 @@
+CONFIG += testcase
+TARGET = tst_qbytearrayview
+QT = core testlib
+SOURCES += tst_qbytearrayview.cpp
diff --git a/tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp b/tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp
new file mode 100644
index 0000000000..c1d80b47dc
--- /dev/null
+++ b/tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp
@@ -0,0 +1,595 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** 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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QByteArrayView>
+
+#include <QTest>
+
+// for negative testing (can't convert from)
+#include <deque>
+#include <list>
+
+template <typename T>
+constexpr bool CanConvert = std::is_convertible_v<T, QByteArrayView>;
+
+static_assert(!CanConvert<QString>);
+static_assert(!CanConvert<QStringView>);
+static_assert(!CanConvert<const char16_t*>);
+
+static_assert(!CanConvert<char>);
+static_assert(CanConvert<char[1]>);
+static_assert(CanConvert<const char[1]>);
+static_assert(CanConvert<char*>);
+static_assert(CanConvert<const char*>);
+
+static_assert(!CanConvert<uchar>);
+static_assert(CanConvert<uchar[1]>);
+static_assert(CanConvert<const uchar[1]>);
+static_assert(CanConvert<uchar*>);
+static_assert(CanConvert<const uchar*>);
+
+static_assert(!CanConvert<signed char>);
+static_assert(CanConvert<signed char[1]>);
+static_assert(CanConvert<const signed char[1]>);
+static_assert(CanConvert<signed char*>);
+static_assert(CanConvert<const signed char*>);
+
+static_assert(!CanConvert<std::byte>);
+static_assert(CanConvert<std::byte[1]>);
+static_assert(CanConvert<const std::byte[1]>);
+static_assert(CanConvert<std::byte*>);
+static_assert(CanConvert<const std::byte*>);
+
+static_assert(CanConvert< QByteArray >);
+static_assert(CanConvert<const QByteArray >);
+static_assert(CanConvert< QByteArray&>);
+static_assert(CanConvert<const QByteArray&>);
+
+static_assert(CanConvert< std::string >);
+static_assert(CanConvert<const std::string >);
+static_assert(CanConvert< std::string&>);
+static_assert(CanConvert<const std::string&>);
+
+static_assert(CanConvert< std::string_view >);
+static_assert(CanConvert<const std::string_view >);
+static_assert(CanConvert< std::string_view&>);
+static_assert(CanConvert<const std::string_view&>);
+
+static_assert(CanConvert< QVector<char> >);
+static_assert(CanConvert<const QVector<char> >);
+static_assert(CanConvert< QVector<char>&>);
+static_assert(CanConvert<const QVector<char>&>);
+
+static_assert(CanConvert< QVarLengthArray<char> >);
+static_assert(CanConvert<const QVarLengthArray<char> >);
+static_assert(CanConvert< QVarLengthArray<char>&>);
+static_assert(CanConvert<const QVarLengthArray<char>&>);
+
+static_assert(CanConvert< std::vector<char> >);
+static_assert(CanConvert<const std::vector<char> >);
+static_assert(CanConvert< std::vector<char>&>);
+static_assert(CanConvert<const std::vector<char>&>);
+
+static_assert(CanConvert< std::array<char, 1> >);
+static_assert(CanConvert<const std::array<char, 1> >);
+static_assert(CanConvert< std::array<char, 1>&>);
+static_assert(CanConvert<const std::array<char, 1>&>);
+
+static_assert(!CanConvert<std::deque<char>>);
+static_assert(!CanConvert<std::list<char>>);
+
+class tst_QByteArrayView : public QObject
+{
+ Q_OBJECT
+private slots:
+ void constExpr() const;
+ void basics() const;
+ void literals() const;
+ void literalsWithInternalNulls() const;
+ void at() const;
+
+ void fromQByteArray() const;
+
+ void fromCharStar() const
+ {
+ fromEmptyLiteral<char>();
+ conversionTests("Hello, World!");
+ }
+
+ void fromUCharStar() const
+ {
+ fromEmptyLiteral<uchar>();
+
+ const uchar data[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
+ conversionTests(data);
+ }
+
+ void fromSignedCharStar() const
+ {
+ fromEmptyLiteral<signed char>();
+
+ const signed char data[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
+ conversionTests(data);
+ }
+
+ void fromStdByteArray() const
+ {
+ fromEmptyLiteral<std::byte>();
+
+ const std::byte data[] = {std::byte{'H'}, std::byte{'e'}, std::byte{'l'}, std::byte{'l'},
+ std::byte{'o'}, std::byte{0}};
+ conversionTests(data);
+ }
+
+ void fromCharRange() const
+ {
+ const char data[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
+ fromRange(std::begin(data), std::end(data));
+ }
+
+ void fromUCharRange() const
+ {
+ const uchar data[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
+ fromRange(std::begin(data), std::end(data));
+ }
+
+ void fromSignedCharRange() const
+ {
+ const signed char data[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
+ fromRange(std::begin(data), std::end(data));
+ }
+
+ void fromStdByteRange() const
+ {
+ const std::byte data[] = {std::byte{'H'}, std::byte{'e'}, std::byte{'l'}, std::byte{'l'},
+ std::byte{'o'}, std::byte{0}};
+ fromRange(std::begin(data), std::end(data));
+ }
+
+ void fromCharContainers() const
+ {
+ fromContainers<char>();
+ }
+
+ void fromUCharContainers() const
+ {
+ fromContainers<uchar>();
+ }
+
+ void fromSignedCharContainers() const
+ {
+ fromContainers<signed char>();
+ }
+
+ void fromStdByteContainers() const
+ {
+ fromContainers<std::byte>();
+ }
+
+ void comparison() const;
+
+private:
+ template <typename Data>
+ void conversionTests(Data arg) const;
+ template <typename Char>
+ void fromEmptyLiteral() const;
+ template <typename Char>
+ void fromRange(const Char *first, const Char *last) const;
+ template <typename Char, typename Container>
+ void fromContainer() const;
+ template <typename Char>
+ void fromContainers() const;
+};
+
+void tst_QByteArrayView::constExpr() const
+{
+ // compile-time checks
+ {
+ constexpr QByteArrayView bv;
+ static_assert(bv.size() == 0);
+ static_assert(bv.isNull());
+ static_assert(bv.empty());
+ static_assert(bv.isEmpty());
+ static_assert(bv.data() == nullptr);
+
+ constexpr QByteArrayView bv2(bv.data(), bv.data() + bv.size());
+ static_assert(bv2.isNull());
+ static_assert(bv2.empty());
+ }
+ {
+ constexpr QByteArrayView bv = "";
+ static_assert(bv.size() == 0);
+ static_assert(!bv.isNull());
+ static_assert(bv.empty());
+ static_assert(bv.isEmpty());
+ static_assert(bv.data() != nullptr);
+
+ constexpr QByteArrayView bv2(bv.data(), bv.data() + bv.size());
+ static_assert(!bv2.isNull());
+ static_assert(bv2.empty());
+ }
+ {
+ static_assert(QByteArrayView("Hello").size() == 5);
+ constexpr QByteArrayView bv = "Hello";
+ static_assert(bv.size() == 5);
+ static_assert(!bv.empty());
+ static_assert(!bv.isEmpty());
+ static_assert(!bv.isNull());
+ static_assert(*bv.data() == 'H');
+ static_assert(bv[0] == 'H');
+ static_assert(bv.at(0) == 'H');
+ static_assert(bv.front() == 'H');
+ static_assert(bv.first() == 'H');
+ static_assert(bv[4] == 'o');
+ static_assert(bv.at(4) == 'o');
+ static_assert(bv.back() == 'o');
+ static_assert(bv.last() == 'o');
+
+ static_assert(*bv.begin() == 'H' );
+ static_assert(*(bv.end() - 1) == 'o' );
+ static_assert(*bv.cbegin() == 'H' );
+ static_assert(*(bv.cend() - 1) == 'o' );
+ static_assert(*bv.rbegin() == 'o' );
+ static_assert(*bv.crbegin() == 'o' );
+
+ // This is just to test that rend()/crend() are constexpr.
+ static_assert(bv.rbegin() != bv.rend());
+ static_assert(bv.crbegin() != bv.crend());
+
+ constexpr QByteArrayView bv2(bv.data(), bv.data() + bv.size());
+ static_assert(!bv2.isNull());
+ static_assert(!bv2.empty());
+ static_assert(bv2.size() == 5);
+ }
+ {
+ static constexpr char hello[] = "Hello";
+ constexpr QByteArrayView bv(hello);
+ static_assert(bv.size() == 5);
+ static_assert(!bv.empty());
+ static_assert(!bv.isEmpty());
+ static_assert(!bv.isNull());
+ static_assert(*bv.data() == 'H');
+ static_assert(bv[0] == 'H');
+ static_assert(bv.at(0) == 'H');
+ static_assert(bv.front() == 'H');
+ static_assert(bv.first() == 'H');
+ static_assert(bv[4] == 'o');
+ static_assert(bv.at(4) == 'o');
+ static_assert(bv.back() == 'o');
+ static_assert(bv.last() == 'o');
+ }
+ {
+ static constexpr char hello[] = { 'H', 'e', 'l', 'l', 'o' };
+ constexpr QByteArrayView bv(hello, std::size(hello));
+ static_assert(bv.size() == 5);
+ static_assert(!bv.empty());
+ static_assert(!bv.isEmpty());
+ static_assert(!bv.isNull());
+ static_assert(*bv.data() == 'H');
+ static_assert(bv[0] == 'H');
+ static_assert(bv.at(0) == 'H');
+ static_assert(bv.front() == 'H');
+ static_assert(bv.first() == 'H');
+ static_assert(bv[4] == 'o');
+ static_assert(bv.at(4) == 'o');
+ static_assert(bv.back() == 'o');
+ static_assert(bv.last() == 'o');
+ }
+ {
+ constexpr char *null = nullptr;
+ constexpr QByteArrayView bv(null);
+ static_assert(bv.isNull());
+ static_assert(bv.isEmpty());
+ static_assert(bv.size() == 0);
+ }
+}
+
+void tst_QByteArrayView::basics() const
+{
+ QByteArrayView bv1;
+
+ // a default-constructed QByteArrayView is null:
+ QVERIFY(bv1.isNull());
+ // which implies it's empty();
+ QVERIFY(bv1.isEmpty());
+
+ QByteArrayView bv2;
+
+ QVERIFY(bv2 == bv1);
+ QVERIFY(!(bv2 != bv1));
+}
+
+void tst_QByteArrayView::literals() const
+{
+ const char hello[] = "Hello";
+
+ QCOMPARE(QByteArrayView(hello).size(), 5);
+ QCOMPARE(QByteArrayView(hello + 0).size(), 5); // forces decay to pointer
+ QByteArrayView bv = hello;
+ QCOMPARE(bv.size(), 5);
+ QVERIFY(!bv.empty());
+ QVERIFY(!bv.isEmpty());
+ QVERIFY(!bv.isNull());
+ QCOMPARE(*bv.data(), 'H');
+ QCOMPARE(bv[0], 'H');
+ QCOMPARE(bv.at(0), 'H');
+ QCOMPARE(bv.front(), 'H');
+ QCOMPARE(bv.first(), 'H');
+ QCOMPARE(bv[4], 'o');
+ QCOMPARE(bv.at(4), 'o');
+ QCOMPARE(bv.back(), 'o');
+ QCOMPARE(bv.last(), 'o');
+
+ QByteArrayView bv2(bv.data(), bv.data() + bv.size());
+ QVERIFY(!bv2.isNull());
+ QVERIFY(!bv2.empty());
+ QCOMPARE(bv2.size(), 5);
+}
+
+void tst_QByteArrayView::literalsWithInternalNulls() const
+{
+ const char withnull[] = "a\0zzz";
+
+ // these are different results
+ QCOMPARE(size_t(QByteArrayView(withnull).size()), sizeof(withnull)/sizeof(withnull[0]) - 1);
+ QCOMPARE(QByteArrayView(withnull + 0).size(), 1);
+
+ QByteArrayView nulled(withnull);
+ QCOMPARE(nulled[1], '\0');
+ QCOMPARE(nulled.indexOf('\0'), 1);
+ QCOMPARE(nulled.indexOf('z'), 2);
+ QCOMPARE(nulled.lastIndexOf('z'), 4);
+ QCOMPARE(nulled.lastIndexOf('a'), 0);
+ QVERIFY(nulled.startsWith("a\0z"));
+ QVERIFY(!nulled.startsWith("a\0y"));
+ QVERIFY(nulled.endsWith("zz"));
+ QVERIFY(nulled.contains("z"));
+ QVERIFY(nulled.contains("\0z"));
+ QVERIFY(!nulled.contains("\0y"));
+ QCOMPARE(nulled.first(5), withnull);
+ QCOMPARE(nulled.last(5), withnull);
+ QCOMPARE(nulled.sliced(0), withnull);
+ QCOMPARE(nulled.sliced(2, 2), "zz");
+ QCOMPARE(nulled.chopped(2), "a\0z");
+ QVERIFY(nulled.chopped(2) != "a\0y");
+ QCOMPARE(nulled.count('z'), 3);
+
+ const char nullfirst[] = "\0buzz";
+ QByteArrayView fromnull(nullfirst);
+ QVERIFY(!fromnull.isEmpty());
+
+ const char nullNotEnd[] = { 'b', 'o', 'w', '\0', 'a', 'f', 't', 'z' };
+ QByteArrayView midNull(nullNotEnd);
+ QCOMPARE(midNull.back(), 't');
+}
+
+void tst_QByteArrayView::at() const
+{
+ QByteArray hello("Hello");
+ QByteArrayView bv(hello);
+ QCOMPARE(bv.at(0), 'H'); QCOMPARE(bv[0], 'H');
+ QCOMPARE(bv.at(1), 'e'); QCOMPARE(bv[1], 'e');
+ QCOMPARE(bv.at(2), 'l'); QCOMPARE(bv[2], 'l');
+ QCOMPARE(bv.at(3), 'l'); QCOMPARE(bv[3], 'l');
+ QCOMPARE(bv.at(4), 'o'); QCOMPARE(bv[4], 'o');
+}
+
+void tst_QByteArrayView::fromQByteArray() const
+{
+ QByteArray null;
+ QByteArray empty = "";
+
+ QVERIFY(QByteArrayView(null).isNull());
+ QVERIFY(!qToByteArrayViewIgnoringNull(null).isNull());
+
+ QVERIFY(QByteArrayView(null).isEmpty());
+ QVERIFY(qToByteArrayViewIgnoringNull(null).isEmpty());
+
+ QVERIFY(QByteArrayView(empty).isEmpty());
+ QVERIFY(qToByteArrayViewIgnoringNull(empty).isEmpty());
+
+ QVERIFY(!QByteArrayView(empty).isNull());
+ QVERIFY(!qToByteArrayViewIgnoringNull(empty).isNull());
+
+ conversionTests(QByteArray("Hello World!"));
+}
+
+namespace help {
+template <typename T>
+size_t size(const T &t) { return size_t(t.size()); }
+template <typename T>
+size_t size(const T *t) { return std::char_traits<T>::length(t); }
+
+template <typename T>
+decltype(auto) cbegin(const T &t) { return t.begin(); }
+template <typename T>
+const T * cbegin(const T *t) { return t; }
+
+template <typename T>
+decltype(auto) cend(const T &t) { return t.end(); }
+template <typename T>
+const T * cend(const T *t) { return t + size(t); }
+
+template <typename T>
+decltype(auto) crbegin(const T &t) { return t.rbegin(); }
+template <typename T>
+std::reverse_iterator<const T*> crbegin(const T *t) { return std::reverse_iterator<const T*>(cend(t)); }
+
+template <typename T>
+decltype(auto) crend(const T &t) { return t.rend(); }
+template <typename T>
+std::reverse_iterator<const T*> crend(const T *t) { return std::reverse_iterator<const T*>(cbegin(t)); }
+
+} // namespace help
+
+template <typename Data>
+void tst_QByteArrayView::conversionTests(Data data) const
+{
+ // copy-construct:
+ {
+ QByteArrayView bv = data;
+
+ QCOMPARE(help::size(bv), help::size(data));
+
+ const auto compare = [](auto v1, auto v2) {
+ if constexpr (std::is_same_v<decltype(v1), std::byte>)
+ return std::to_integer<char>(v1) == v2;
+ else
+ return v1 == v2;
+ };
+ QVERIFY(std::equal(help::cbegin(data), help::cend(data),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(bv.cbegin(), bv.size()), compare));
+ QVERIFY(std::equal(help::cbegin(data), help::cend(data),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(bv.begin(), bv.size()), compare));
+ QVERIFY(std::equal(help::crbegin(data), help::crend(data), bv.crbegin(), compare));
+ QVERIFY(std::equal(help::crbegin(data), help::crend(data), bv.rbegin(), compare));
+ QCOMPARE(bv, data);
+ }
+
+ QByteArrayView bv;
+
+ // copy-assign:
+ {
+ bv = data;
+
+ QCOMPARE(help::size(bv), help::size(data));
+
+ // check relational operators:
+
+ QCOMPARE(bv, data);
+ QCOMPARE(data, bv);
+
+ QVERIFY(!(bv != data));
+ QVERIFY(!(data != bv));
+
+ QVERIFY(!(bv < data));
+ QVERIFY(bv <= data);
+ QVERIFY(!(bv > data));
+ QVERIFY(bv >= data);
+
+ QVERIFY(!(data < bv));
+ QVERIFY(data <= bv);
+ QVERIFY(!(data > bv));
+ QVERIFY(data >= bv);
+ }
+
+ // copy-construct from rvalue (QByteArrayView never assumes ownership):
+ {
+ QByteArrayView bv2 = std::move(data);
+ QCOMPARE(bv2, bv);
+ QCOMPARE(bv2, data);
+ }
+
+ // copy-assign from rvalue (QByteArrayView never assumes ownership):
+ {
+ QByteArrayView bv2;
+ bv2 = std::move(data);
+ QCOMPARE(bv2, bv);
+ QCOMPARE(bv2, data);
+ }
+}
+
+template <typename Char>
+void tst_QByteArrayView::fromEmptyLiteral() const
+{
+ const Char *null = nullptr;
+ const Char empty[] = { Char{0} };
+
+ QCOMPARE(QByteArrayView(null).size(), 0);
+ QCOMPARE(QByteArrayView(null).data(), nullptr);
+ QCOMPARE(QByteArrayView(empty).size(), 0);
+ QCOMPARE(static_cast<const void*>(QByteArrayView(empty).data()),
+ static_cast<const void*>(empty));
+
+ QVERIFY(QByteArrayView(null).isNull());
+ QVERIFY(QByteArrayView(null).isEmpty());
+ QVERIFY(QByteArrayView(empty).isEmpty());
+ QVERIFY(!QByteArrayView(empty).isNull());
+}
+
+template <typename Char>
+void tst_QByteArrayView::fromRange(const Char *first, const Char *last) const
+{
+ const Char *null = nullptr;
+ QCOMPARE(QByteArrayView(null, null).size(), 0);
+ QCOMPARE(QByteArrayView(null, null).data(), nullptr);
+ QCOMPARE(QByteArrayView(first, first).size(), 0);
+ QCOMPARE(static_cast<const void*>(QByteArrayView(first, first).data()),
+ static_cast<const void*>(first));
+
+ const auto bv = QByteArrayView(first, last);
+ QCOMPARE(bv.size(), last - first);
+ QCOMPARE(static_cast<const void*>(bv.data()),
+ static_cast<const void*>(first));
+
+ QCOMPARE(static_cast<const void*>(bv.last(0).data()),
+ static_cast<const void*>(last));
+ QCOMPARE(static_cast<const void*>(bv.sliced(bv.size()).data()),
+ static_cast<const void*>(last));
+
+ // can't call conversionTests() here, as it requires a single object
+}
+
+template <typename Char, typename Container>
+void tst_QByteArrayView::fromContainer() const
+{
+ const QByteArray s = "Hello World!";
+
+ Container c;
+ // unspecified whether empty containers make null QByteArrayView
+ QVERIFY(QByteArrayView(c).isEmpty());
+
+ QCOMPARE(sizeof(Char), sizeof(char));
+
+ const auto *data = reinterpret_cast<const Char *>(s.data());
+ std::copy(data, data + s.size(), std::back_inserter(c));
+ conversionTests(std::move(c));
+}
+
+template <typename Char>
+void tst_QByteArrayView::fromContainers() const
+{
+ fromContainer<Char, QVector<Char>>();
+ fromContainer<Char, QVarLengthArray<Char>>();
+ fromContainer<Char, std::vector<Char>>();
+ fromContainer<Char, std::basic_string<Char>>();
+}
+
+void tst_QByteArrayView::comparison() const
+{
+ const QByteArrayView aa = "aa";
+ const QByteArrayView bb = "bb";
+
+ QVERIFY(aa == aa);
+ QVERIFY(aa != bb);
+ QVERIFY(aa < bb);
+ QVERIFY(bb > aa);
+}
+
+QTEST_APPLESS_MAIN(tst_QByteArrayView)
+#include "tst_qbytearrayview.moc"
diff --git a/tests/auto/corelib/text/text.pro b/tests/auto/corelib/text/text.pro
index bad5f6d61a..272bcb1013 100644
--- a/tests/auto/corelib/text/text.pro
+++ b/tests/auto/corelib/text/text.pro
@@ -5,6 +5,7 @@ SUBDIRS = \
qbytearrayapisymmetry \
qbytearraylist \
qbytearraymatcher \
+ qbytearrayview \
qbytedatabuffer \
qchar \
qcollator \