Port QLatin1String to qsizetype and add narrow-contract substring functions

QLatin1String::mid() etc were changed from narrow to wide contract,
but the narrow-contract replacements weren't added. This blocks using
the narrow-contract functions in QStringTokenizer.

As a drive-by, Q_REQUIRED_RESULT -> [[nodiscard]] and Q_DECL_CONSTEXPR
-> constexpr. Also centralize most Q_ASSERT()s in a single function,
verify(), in an attempt to reduce the amount of string data generated
from the asserts in assertive builds.

[ChangeLog][QtCore][QLatin1String] Added from(), sliced(), first(n),
last(n) functions.

[ChangeLog][QtCore][QLatin1String] size_type/size() is now qsizetype
(was: int). This makes QLatin1String(ptr, 0) ambiguous now between the
(ptr, ptr) and (ptr, qsizetype) constructors.

Change-Id: Ie195f66ae1974eb0752c058aa9f3b0853ed92477
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Marc Mutz 2020-06-25 14:28:57 +02:00
parent ba2b644213
commit 60dd5451a2
5 changed files with 169 additions and 83 deletions

View File

@ -1275,7 +1275,7 @@ static int qt_compare_strings(QLatin1String lhs, QStringView rhs, Qt::CaseSensit
static int qt_compare_strings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs) noexcept
{
if (lhs.isEmpty())
return lencmp(0, rhs.size());
return lencmp(qsizetype(0), rhs.size());
if (cs == Qt::CaseInsensitive)
return latin1nicmp(lhs.data(), lhs.size(), rhs.data(), rhs.size());
const auto l = std::min(lhs.size(), rhs.size());
@ -8641,6 +8641,10 @@ QString &QString::setRawData(const QChar *unicode, qsizetype size)
\since 5.10
Alias for \c{qsizetype}. Provided for compatibility with the STL.
\note In version prior to Qt 6, this was an alias for \c{int},
restricting the amount of data that could be held in a QLatin1String
on 64-bit architectures.
*/
/*!
@ -8708,7 +8712,7 @@ QString &QString::setRawData(const QChar *unicode, qsizetype size)
\sa latin1()
*/
/*! \fn QLatin1String::QLatin1String(const char *str, int size)
/*! \fn QLatin1String::QLatin1String(const char *str, qsizetype size)
Constructs a QLatin1String object that stores \a str with \a size.
@ -8768,9 +8772,13 @@ QString &QString::setRawData(const QChar *unicode, qsizetype size)
Returns the Latin-1 string stored in this object.
*/
/*! \fn int QLatin1String::size() const
/*! \fn QLatin1String::size() const
Returns the size of the Latin-1 string stored in this object.
\note In version prior to Qt 6, this function returned \c{int},
restricting the amount of data that could be held in a QLatin1String
on 64-bit architectures.
*/
/*! \fn bool QLatin1String::isNull() const
@ -8791,7 +8799,7 @@ QString &QString::setRawData(const QChar *unicode, qsizetype size)
\sa isNull(), size()
*/
/*! \fn QLatin1Char QLatin1String::at(int pos) const
/*! \fn QLatin1Char QLatin1String::at(qsizetype pos) const
\since 5.8
Returns the character at position \a pos in this object.
@ -8802,7 +8810,7 @@ QString &QString::setRawData(const QChar *unicode, qsizetype size)
\sa operator[]()
*/
/*! \fn QLatin1Char QLatin1String::operator[](int pos) const
/*! \fn QLatin1Char QLatin1String::operator[](qsizetype pos) const
\since 5.8
Returns the character at position \a pos in this object.
@ -8901,9 +8909,9 @@ QString &QString::setRawData(const QChar *unicode, qsizetype size)
*/
/*!
\fn int QLatin1String::indexOf(QStringView str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\fn int QLatin1String::indexOf(QLatin1String l1, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\fn int QLatin1String::indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\fn int QLatin1String::indexOf(QStringView str, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\fn int QLatin1String::indexOf(QLatin1String l1, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\fn int QLatin1String::indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\since 5.14
Returns the index position of the first occurrence of the string-view \a str,
@ -8935,9 +8943,9 @@ QString &QString::setRawData(const QChar *unicode, qsizetype size)
*/
/*!
\fn int QLatin1String::lastIndexOf(QStringView str, int from, Qt::CaseSensitivity cs) const
\fn int QLatin1String::lastIndexOf(QLatin1String l1, int from, Qt::CaseSensitivity cs) const
\fn int QLatin1String::lastIndexOf(QChar c, int from, Qt::CaseSensitivity cs) const
\fn int QLatin1String::lastIndexOf(QStringView str, qsizetype from, Qt::CaseSensitivity cs) const
\fn int QLatin1String::lastIndexOf(QLatin1String l1, qsizetype from, Qt::CaseSensitivity cs) const
\fn int QLatin1String::lastIndexOf(QChar c, qsizetype from, Qt::CaseSensitivity cs) const
\since 5.14
Returns the index position of the last occurrence of the string-view \a str,
@ -9043,47 +9051,105 @@ QString &QString::setRawData(const QChar *unicode, qsizetype size)
\sa crbegin(), rend(), cend()
*/
/*! \fn QLatin1String QLatin1String::mid(int start, int length) const
/*!
\fn QLatin1String::mid(qsizetype start, qsizetype length) const
\since 5.8
Returns the substring of length \a length starting at position
\a start in this object.
\a start in this Latin-1 string.
Returns a null string if the \a start index exceeds the
length of the string. If there are less than \a length characters
available in the string starting at \a start, or if
\a length is negative (default), the function returns all characters
that are available from \a start.
\obsolete Use sliced() instead in new code.
\sa left(), right(), chopped(), chop(), truncate()
*/
Returns an empty Latin-1 string if \a start exceeds the
length of this Latin-1 string. If there are less than \a length characters
available in this Latin-1 string starting at \a start, or if
\a length is negative (default), the function returns all characters that
are available from \a start.
/*! \fn QLatin1String QLatin1String::left(int length) const
\since 5.8
Returns the substring of length \a length starting at position
0 in this object.
The entire string is returned if \a length is greater than or equal
to size(), or less than zero.
\sa mid(), right(), chopped(), chop(), truncate()
*/
/*! \fn QLatin1String QLatin1String::right(int length) const
\since 5.8
Returns the substring of length \a length starting at position
size() - \a length in this object.
The entire string is returned if \a length is greater than or equal
to size(), or less than zero.
\sa mid(), left(), chopped(), chop(), truncate()
\sa first(), last(), sliced(), chopped(), chop(), truncate()
*/
/*!
\fn QLatin1String QLatin1String::chopped(int length) const
\fn QLatin1String::left(qsizetype length) const
\since 5.8
\obsolete Use first() instead in new code.
Returns the substring of length \a length starting at position
0 in this Latin-1 string.
The entire Latin-1 string is returned if \a length is greater than or equal
to size(), or less than zero.
\sa first(), last(), sliced(), startsWith(), chopped(), chop(), truncate()
*/
/*!
\fn QLatin1String::right(qsizetype length) const
\since 5.8
\obsolete Use last() instead in new code.
Returns the substring of length \a length starting at position
size() - \a length in this Latin-1 string.
The entire Latin-1 string is returned if \a length is greater than or equal
to size(), or less than zero.
\sa first(), last(), sliced(), endsWith(), chopped(), chop(), truncate()
*/
/*!
\fn QLatin1String::first(qsizetype n) const
\since 6.0
Returns a Latin-1 string that contains the first \a n characters
of this Latin-1 string.
\note The behavior is undefined when \a n < 0 or \a n > size().
\sa last(), subString(), startsWith(), chopped(), chop(), truncate()
*/
/*!
\fn QLatin1String::last(qsizetype n) const
\since 6.0
Returns a Latin-1 string that contains the last \a n characters
of this Latin-1 string.
\note The behavior is undefined when \a n < 0 or \a n > size().
\sa first(), subString(), endsWith(), chopped(), chop(), truncate()
*/
/*!
\fn QLatin1String::sliced(qsizetype pos, qsizetype n) const
\since 6.0
Returns a Latin-1 string that points to \a n characters of this
Latin-1 string, starting at position \a pos.
\note The behavior is undefined when \a pos < 0, \a n < 0,
or \c{pos + n > size()}.
\sa first(), last(), chopped(), chop(), truncate()
*/
/*!
\fn QLatin1String::sliced(qsizetype pos) const
\since 6.0
Returns a Latin-1 string starting at position \a pos in this
Latin-1 string, 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 QLatin1String QLatin1String::chopped(qsizetype length) const
\since 5.10
Returns the substring of length size() - \a length starting at the
@ -9097,7 +9163,7 @@ QString &QString::setRawData(const QChar *unicode, qsizetype size)
*/
/*!
\fn void QLatin1String::truncate(int length)
\fn void QLatin1String::truncate(qsizetype length)
\since 5.10
Truncates this string to length \a length.
@ -9110,7 +9176,7 @@ QString &QString::setRawData(const QChar *unicode, qsizetype size)
*/
/*!
\fn void QLatin1String::chop(int length)
\fn void QLatin1String::chop(qsizetype length)
\since 5.10
Truncates this string by \a length characters.

View File

@ -85,16 +85,16 @@ class QLatin1String
{
public:
constexpr inline QLatin1String() noexcept : m_size(0), m_data(nullptr) {}
constexpr inline explicit QLatin1String(const char *s) noexcept : m_size(s ? int(strlen(s)) : 0), m_data(s) {}
constexpr inline explicit QLatin1String(const char *s) noexcept : m_size(s ? qsizetype(strlen(s)) : 0), m_data(s) {}
constexpr explicit QLatin1String(const char *f, const char *l)
: QLatin1String(f, int(l - f)) {}
constexpr inline explicit QLatin1String(const char *s, int sz) noexcept : m_size(sz), m_data(s) {}
inline explicit QLatin1String(const QByteArray &s) noexcept : m_size(int(qstrnlen(s.constData(), s.size()))), m_data(s.constData()) {}
: QLatin1String(f, qsizetype(l - f)) {}
constexpr inline explicit QLatin1String(const char *s, qsizetype sz) noexcept : m_size(sz), m_data(s) {}
explicit QLatin1String(const QByteArray &s) noexcept : m_size(qsizetype(qstrnlen(s.constData(), s.size()))), m_data(s.constData()) {}
inline QString toString() const;
constexpr const char *latin1() const noexcept { return m_data; }
constexpr int size() const noexcept { return m_size; }
constexpr qsizetype size() const noexcept { return m_size; }
constexpr const char *data() const noexcept { return m_data; }
constexpr bool isNull() const noexcept { return !data(); }
@ -103,9 +103,9 @@ public:
template <typename...Args>
Q_REQUIRED_RESULT inline QString arg(Args &&...args) const;
constexpr QLatin1Char at(int i) const
[[nodiscard]] constexpr QLatin1Char at(qsizetype i) const
{ return Q_ASSERT(i >= 0), Q_ASSERT(i < size()), QLatin1Char(m_data[i]); }
constexpr QLatin1Char operator[](int i) const { return at(i); }
[[nodiscard]] constexpr QLatin1Char operator[](qsizetype i) const { return at(i); }
Q_REQUIRED_RESULT constexpr QLatin1Char front() const { return at(0); }
Q_REQUIRED_RESULT constexpr QLatin1Char back() const { return at(size() - 1); }
@ -137,12 +137,12 @@ public:
Q_REQUIRED_RESULT inline bool endsWith(QChar c, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::endsWith(*this, QStringView(&c, 1), cs); }
Q_REQUIRED_RESULT int indexOf(QStringView s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsizetype
Q_REQUIRED_RESULT int indexOf(QLatin1String s, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return int(QtPrivate::findString(*this, from, s, cs)); } // ### Qt6: qsizetype
Q_REQUIRED_RESULT inline int indexOf(QChar c, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return int(QtPrivate::findString(*this, from, QStringView(&c, 1), cs)); } // ### Qt6: qsizetype
[[nodiscard]] qsizetype indexOf(QStringView s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::findString(*this, from, s, cs); }
[[nodiscard]] qsizetype indexOf(QLatin1String s, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::findString(*this, from, s, cs); }
[[nodiscard]] qsizetype indexOf(QChar c, qsizetype from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::findString(*this, from, QStringView(&c, 1), cs); }
Q_REQUIRED_RESULT bool contains(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return indexOf(s, 0, cs) != -1; }
@ -151,20 +151,20 @@ public:
Q_REQUIRED_RESULT inline bool contains(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return indexOf(QStringView(&c, 1), 0, cs) != -1; }
Q_REQUIRED_RESULT int lastIndexOf(QStringView s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return int(QtPrivate::lastIndexOf(*this, from, s, cs)); } // ### Qt6: qsizetype
Q_REQUIRED_RESULT int lastIndexOf(QLatin1String s, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return int(QtPrivate::lastIndexOf(*this, from, s, cs)); } // ### Qt6: qsizetype
Q_REQUIRED_RESULT inline int lastIndexOf(QChar c, int from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return int(QtPrivate::lastIndexOf(*this, from, QStringView(&c, 1), cs)); } // ### Qt6: qsizetype
[[nodiscard]] qsizetype lastIndexOf(QStringView s, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::lastIndexOf(*this, from, s, cs); }
[[nodiscard]] qsizetype lastIndexOf(QLatin1String s, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::lastIndexOf(*this, from, s, cs); }
[[nodiscard]] qsizetype lastIndexOf(QChar c, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::lastIndexOf(*this, from, QStringView(&c, 1), cs); }
using value_type = const char;
using reference = value_type&;
using const_reference = reference;
using iterator = value_type*;
using const_iterator = iterator;
using difference_type = int; // violates Container concept requirements
using size_type = int; // violates Container concept requirements
using difference_type = qsizetype; // violates Container concept requirements
using size_type = qsizetype; // violates Container concept requirements
constexpr const_iterator begin() const noexcept { return data(); }
constexpr const_iterator cbegin() const noexcept { return data(); }
@ -179,33 +179,40 @@ public:
const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
constexpr QLatin1String mid(int pos, int n = -1) const
[[nodiscard]] constexpr QLatin1String mid(qsizetype pos, qsizetype n = -1) const
{
qsizetype p = pos;
qsizetype l = n;
using namespace QtPrivate;
auto result = QContainerImplHelper::mid(size(), &p, &l);
return result == QContainerImplHelper::Null ? QLatin1String() : QLatin1String(m_data + p, l);
auto result = QContainerImplHelper::mid(size(), &pos, &n);
return result == QContainerImplHelper::Null ? QLatin1String() : QLatin1String(m_data + pos, n);
}
constexpr QLatin1String left(int n) const
[[nodiscard]] constexpr QLatin1String left(qsizetype n) const
{
if (size_t(n) >= size_t(size()))
n = size();
return QLatin1String(m_data, n);
}
constexpr QLatin1String right(int n) const
[[nodiscard]] constexpr QLatin1String right(qsizetype n) const
{
if (size_t(n) >= size_t(size()))
n = size();
return QLatin1String(m_data + m_size - n, n);
}
Q_REQUIRED_RESULT constexpr QLatin1String chopped(int n) const
{ return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QLatin1String(m_data, m_size - n); }
constexpr void chop(int n)
{ Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size -= n; }
constexpr void truncate(int n)
{ Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size = n; }
[[nodiscard]] constexpr QLatin1String sliced(qsizetype pos) const
{ verify(pos); return QLatin1String(m_data + pos, m_size - pos); }
[[nodiscard]] constexpr QLatin1String sliced(qsizetype pos, qsizetype n) const
{ verify(pos, n); return QLatin1String(m_data + pos, n); }
[[nodiscard]] constexpr QLatin1String first(qsizetype n) const
{ verify(n); return QLatin1String(m_data, n); }
[[nodiscard]] constexpr QLatin1String last(qsizetype n) const
{ verify(n); return QLatin1String(m_data + size() - n, n); }
[[nodiscard]] constexpr QLatin1String chopped(qsizetype n) const
{ verify(n); return QLatin1String(m_data, size() - n); }
constexpr void chop(qsizetype n)
{ verify(n); m_size -= n; }
constexpr void truncate(qsizetype n)
{ verify(n); m_size = n; }
Q_REQUIRED_RESULT QLatin1String trimmed() const noexcept { return QtPrivate::trimmed(*this); }
@ -239,7 +246,14 @@ public:
#endif // !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
private:
int m_size;
Q_ALWAYS_INLINE constexpr void verify(qsizetype pos, qsizetype n = 0) const
{
Q_ASSERT(pos >= 0);
Q_ASSERT(pos <= size());
Q_ASSERT(n >= 0);
Q_ASSERT(n <= size() - pos);
}
qsizetype m_size;
const char *m_data;
};
Q_DECLARE_TYPEINFO(QLatin1String, Q_MOVABLE_TYPE);
@ -1142,7 +1156,7 @@ inline bool operator!=(QLatin1String s1, QLatin1String s2) noexcept
{ return !operator==(s1, s2); }
inline bool operator<(QLatin1String s1, QLatin1String s2) noexcept
{
const int len = qMin(s1.size(), s2.size());
const qsizetype len = qMin(s1.size(), s2.size());
const int r = len ? memcmp(s1.latin1(), s2.latin1(), len) : 0;
return r < 0 || (r == 0 && s1.size() < s2.size());
}

View File

@ -236,7 +236,7 @@ template <> struct QConcatenable<QLatin1String> : private QAbstractConcatenable
typedef QLatin1String type;
typedef QString ConvertTo;
enum { ExactSize = true };
static int size(const QLatin1String a) { return a.size(); }
static int size(const QLatin1String a) { return int(a.size()); } // ### Qt 6: qsizetype
static inline void appendTo(const QLatin1String a, QChar *&out)
{
appendLatin1To(a.latin1(), a.size(), out);

View File

@ -177,7 +177,7 @@ void tst_QLatin1String::emptyString()
{
const char *notEmpty = "foo";
QLatin1String l1(notEmpty, 0);
QLatin1String l1(notEmpty, qsizetype(0));
QCOMPARE(static_cast<const void*>(l1.data()), static_cast<const void*>(notEmpty));
QCOMPARE(l1.size(), 0);

View File

@ -536,6 +536,8 @@ private Q_SLOTS:
void sliced_QString() { sliced_impl<QString>(); }
void sliced_QStringView_data() { sliced_data(); }
void sliced_QStringView() { sliced_impl<QStringView>(); }
void sliced_QLatin1String_data() { sliced_data(); }
void sliced_QLatin1String() { sliced_impl<QLatin1String>(); }
void sliced_QByteArray_data() { sliced_data(); }
void sliced_QByteArray() { sliced_impl<QByteArray>(); }
@ -543,6 +545,8 @@ private Q_SLOTS:
void first_truncate_QString() { first_impl<QString>(); }
void first_truncate_QStringView_data() { first_data(); }
void first_truncate_QStringView() { first_impl<QStringView>(); }
void first_truncate_QLatin1String_data() { first_data(); }
void first_truncate_QLatin1String() { first_impl<QLatin1String>(); }
void first_truncate_QByteArray_data() { first_data(); }
void first_truncate_QByteArray() { first_impl<QByteArray>(); }
@ -550,6 +554,8 @@ private Q_SLOTS:
void last_QString() { last_impl<QString>(); }
void last_QStringView_data() { last_data(); }
void last_QStringView() { last_impl<QStringView>(); }
void last_QLatin1String_data() { last_data(); }
void last_QLatin1String() { last_impl<QLatin1String>(); }
void last_QByteArray_data() { last_data(); }
void last_QByteArray() { last_impl<QByteArray>(); }