Ensure left/right/mid behave in a compatible way
QString and QStringRef did bounds checking for left/right/mid, whereas QStringView was asserting on out of bounds. Relax the behavior for QStringView and do bounds checking on pos/n as well. This removes a source of potentially hidden errors when porting from QStringRef (or QString) to QStringView. Unfortunately, one difference remains, where QByteArray::left/right() behaves differently (and somewhat more sane) than QString and QStringRef. We're keeping the difference here, as it has been around for many years. Mark left/right/mid as obsolete and to be replaced with the new first/last/slice methods. Change-Id: I18c203799ba78c928a4610a6038089f27696c22e Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
parent
fd856532d7
commit
d2833a3ce5
@ -2914,13 +2914,17 @@ bool QByteArray::isLower() const
|
|||||||
Returns a byte array that contains the first \a len bytes of this byte
|
Returns a byte array that contains the first \a len bytes of this byte
|
||||||
array.
|
array.
|
||||||
|
|
||||||
|
\obsolete Use first() instead in new code.
|
||||||
|
|
||||||
The entire byte array is returned if \a len is greater than
|
The entire byte array is returned if \a len is greater than
|
||||||
size().
|
size().
|
||||||
|
|
||||||
|
Returns an empty QByteArray if \a len is smaller than 0.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
\snippet code/src_corelib_text_qbytearray.cpp 27
|
\snippet code/src_corelib_text_qbytearray.cpp 27
|
||||||
|
|
||||||
\sa startsWith(), right(), mid(), chopped(), chop(), truncate()
|
\sa first(), last(), startsWith(), chopped(), chop(), truncate()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
QByteArray QByteArray::left(int len) const
|
QByteArray QByteArray::left(int len) const
|
||||||
@ -2935,15 +2939,18 @@ QByteArray QByteArray::left(int len) const
|
|||||||
/*!
|
/*!
|
||||||
Returns a byte array that contains the last \a len bytes of this byte array.
|
Returns a byte array that contains the last \a len bytes of this byte array.
|
||||||
|
|
||||||
|
\obsolete Use last() instead in new code.
|
||||||
|
|
||||||
The entire byte array is returned if \a len is greater than
|
The entire byte array is returned if \a len is greater than
|
||||||
size().
|
size().
|
||||||
|
|
||||||
|
Returns an empty QByteArray if \a len is smaller than 0.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
\snippet code/src_corelib_text_qbytearray.cpp 28
|
\snippet code/src_corelib_text_qbytearray.cpp 28
|
||||||
|
|
||||||
\sa endsWith(), left(), mid(), chopped(), chop(), truncate()
|
\sa endsWith(), last(), first(), slice(), chopped(), chop(), truncate()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
QByteArray QByteArray::right(int len) const
|
QByteArray QByteArray::right(int len) const
|
||||||
{
|
{
|
||||||
if (len >= size())
|
if (len >= size())
|
||||||
@ -2957,6 +2964,8 @@ QByteArray QByteArray::right(int len) const
|
|||||||
Returns a byte array containing \a len bytes from this byte array,
|
Returns a byte array containing \a len bytes from this byte array,
|
||||||
starting at position \a pos.
|
starting at position \a pos.
|
||||||
|
|
||||||
|
\obsolete Use slice() instead in new code.
|
||||||
|
|
||||||
If \a len is -1 (the default), or \a pos + \a len >= size(),
|
If \a len is -1 (the default), or \a pos + \a len >= size(),
|
||||||
returns a byte array containing all bytes starting at position \a
|
returns a byte array containing all bytes starting at position \a
|
||||||
pos until the end of the byte array.
|
pos until the end of the byte array.
|
||||||
@ -2964,13 +2973,15 @@ QByteArray QByteArray::right(int len) const
|
|||||||
Example:
|
Example:
|
||||||
\snippet code/src_corelib_text_qbytearray.cpp 29
|
\snippet code/src_corelib_text_qbytearray.cpp 29
|
||||||
|
|
||||||
\sa left(), right(), chopped(), chop(), truncate()
|
\sa first(), last(), slice(), chopped(), chop(), truncate()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
QByteArray QByteArray::mid(int pos, int len) const
|
QByteArray QByteArray::mid(int pos, int len) const
|
||||||
{
|
{
|
||||||
|
qsizetype p = pos;
|
||||||
|
qsizetype l = len;
|
||||||
using namespace QtPrivate;
|
using namespace QtPrivate;
|
||||||
switch (QContainerImplHelper::mid(size(), &pos, &len)) {
|
switch (QContainerImplHelper::mid(size(), &p, &l)) {
|
||||||
case QContainerImplHelper::Null:
|
case QContainerImplHelper::Null:
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
case QContainerImplHelper::Empty:
|
case QContainerImplHelper::Empty:
|
||||||
@ -2982,7 +2993,7 @@ QByteArray QByteArray::mid(int pos, int len) const
|
|||||||
case QContainerImplHelper::Full:
|
case QContainerImplHelper::Full:
|
||||||
return *this;
|
return *this;
|
||||||
case QContainerImplHelper::Subset:
|
case QContainerImplHelper::Subset:
|
||||||
return QByteArray(d.data() + pos, len);
|
return QByteArray(d.data() + p, l);
|
||||||
}
|
}
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
|
@ -4530,12 +4530,14 @@ QString QString::section(const QRegularExpression &re, int start, int end, Secti
|
|||||||
Returns a substring that contains the \a n leftmost characters
|
Returns a substring that contains the \a n leftmost characters
|
||||||
of the string.
|
of the string.
|
||||||
|
|
||||||
|
\obsolete Use first() instead in new code.
|
||||||
|
|
||||||
The entire string is returned if \a n is greater than or equal
|
The entire string is returned if \a n is greater than or equal
|
||||||
to size(), or less than zero.
|
to size(), or less than zero.
|
||||||
|
|
||||||
\snippet qstring/main.cpp 31
|
\snippet qstring/main.cpp 31
|
||||||
|
|
||||||
\sa right(), mid(), startsWith(), chopped(), chop(), truncate()
|
\sa first(), last(), startsWith(), chopped(), chop(), truncate()
|
||||||
*/
|
*/
|
||||||
QString QString::left(int n) const
|
QString QString::left(int n) const
|
||||||
{
|
{
|
||||||
@ -4548,12 +4550,14 @@ QString QString::left(int n) const
|
|||||||
Returns a substring that contains the \a n rightmost characters
|
Returns a substring that contains the \a n rightmost characters
|
||||||
of the string.
|
of the string.
|
||||||
|
|
||||||
|
\obsolete Use last() instead in new code.
|
||||||
|
|
||||||
The entire string is returned if \a n is greater than or equal
|
The entire string is returned if \a n is greater than or equal
|
||||||
to size(), or less than zero.
|
to size(), or less than zero.
|
||||||
|
|
||||||
\snippet qstring/main.cpp 48
|
\snippet qstring/main.cpp 48
|
||||||
|
|
||||||
\sa left(), mid(), endsWith(), chopped(), chop(), truncate()
|
\sa endsWith(), last(), first(), slice(), chopped(), chop(), truncate()
|
||||||
*/
|
*/
|
||||||
QString QString::right(int n) const
|
QString QString::right(int n) const
|
||||||
{
|
{
|
||||||
@ -4566,6 +4570,8 @@ QString QString::right(int n) const
|
|||||||
Returns a string that contains \a n characters of this string,
|
Returns a string that contains \a n characters of this string,
|
||||||
starting at the specified \a position index.
|
starting at the specified \a position index.
|
||||||
|
|
||||||
|
\obsolete Use slice() instead in new code.
|
||||||
|
|
||||||
Returns a null string if the \a position index exceeds the
|
Returns a null string if the \a position index exceeds the
|
||||||
length of the string. If there are less than \a n characters
|
length of the string. If there are less than \a n characters
|
||||||
available in the string starting at the given \a position, or if
|
available in the string starting at the given \a position, or if
|
||||||
@ -4576,13 +4582,15 @@ QString QString::right(int n) const
|
|||||||
|
|
||||||
\snippet qstring/main.cpp 34
|
\snippet qstring/main.cpp 34
|
||||||
|
|
||||||
\sa left(), right(), chopped(), chop(), truncate()
|
\sa first(), last(), slice(), chopped(), chop(), truncate()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
QString QString::mid(int position, int n) const
|
QString QString::mid(int position, int n) const
|
||||||
{
|
{
|
||||||
|
qsizetype p = position;
|
||||||
|
qsizetype l = n;
|
||||||
using namespace QtPrivate;
|
using namespace QtPrivate;
|
||||||
switch (QContainerImplHelper::mid(size(), &position, &n)) {
|
switch (QContainerImplHelper::mid(size(), &p, &l)) {
|
||||||
case QContainerImplHelper::Null:
|
case QContainerImplHelper::Null:
|
||||||
return QString();
|
return QString();
|
||||||
case QContainerImplHelper::Empty:
|
case QContainerImplHelper::Empty:
|
||||||
@ -4594,7 +4602,7 @@ QString QString::mid(int position, int n) const
|
|||||||
case QContainerImplHelper::Full:
|
case QContainerImplHelper::Full:
|
||||||
return *this;
|
return *this;
|
||||||
case QContainerImplHelper::Subset:
|
case QContainerImplHelper::Subset:
|
||||||
return QString(constData() + position, n);
|
return QString(constData() + p, l);
|
||||||
}
|
}
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
return QString();
|
return QString();
|
||||||
@ -9375,28 +9383,17 @@ QString &QString::setRawData(const QChar *unicode, int size)
|
|||||||
\sa crbegin(), rend(), cend()
|
\sa crbegin(), rend(), cend()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*! \fn QLatin1String QLatin1String::mid(int start) const
|
|
||||||
\since 5.8
|
|
||||||
|
|
||||||
Returns the substring starting at position \a start in this object,
|
|
||||||
and extending to the end of the string.
|
|
||||||
|
|
||||||
\note This function performs no error checking.
|
|
||||||
The behavior is undefined when \a start < 0 or \a start > size().
|
|
||||||
|
|
||||||
\sa left(), right(), chopped(), chop(), truncate()
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*! \fn QLatin1String QLatin1String::mid(int start, int length) const
|
/*! \fn QLatin1String QLatin1String::mid(int start, int length) const
|
||||||
\since 5.8
|
\since 5.8
|
||||||
\overload
|
|
||||||
|
|
||||||
Returns the substring of length \a length starting at position
|
Returns the substring of length \a length starting at position
|
||||||
\a start in this object.
|
\a start in this object.
|
||||||
|
|
||||||
\note This function performs no error checking.
|
Returns a null string if the \a start index exceeds the
|
||||||
The behavior is undefined when \a start < 0, \a length < 0,
|
length of the string. If there are less than \a length characters
|
||||||
or \a start + \a length > size().
|
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.
|
||||||
|
|
||||||
\sa left(), right(), chopped(), chop(), truncate()
|
\sa left(), right(), chopped(), chop(), truncate()
|
||||||
*/
|
*/
|
||||||
@ -9407,8 +9404,8 @@ QString &QString::setRawData(const QChar *unicode, int size)
|
|||||||
Returns the substring of length \a length starting at position
|
Returns the substring of length \a length starting at position
|
||||||
0 in this object.
|
0 in this object.
|
||||||
|
|
||||||
\note This function performs no error checking.
|
The entire string is returned if \a length is greater than or equal
|
||||||
The behavior is undefined when \a length < 0 or \a length > size().
|
to size(), or less than zero.
|
||||||
|
|
||||||
\sa mid(), right(), chopped(), chop(), truncate()
|
\sa mid(), right(), chopped(), chop(), truncate()
|
||||||
*/
|
*/
|
||||||
@ -9419,8 +9416,8 @@ QString &QString::setRawData(const QChar *unicode, int size)
|
|||||||
Returns the substring of length \a length starting at position
|
Returns the substring of length \a length starting at position
|
||||||
size() - \a length in this object.
|
size() - \a length in this object.
|
||||||
|
|
||||||
\note This function performs no error checking.
|
The entire string is returned if \a length is greater than or equal
|
||||||
The behavior is undefined when \a length < 0 or \a length > size().
|
to size(), or less than zero.
|
||||||
|
|
||||||
\sa mid(), left(), chopped(), chop(), truncate()
|
\sa mid(), left(), chopped(), chop(), truncate()
|
||||||
*/
|
*/
|
||||||
@ -10777,8 +10774,10 @@ QStringRef QString::rightRef(int n) const
|
|||||||
*/
|
*/
|
||||||
QStringRef QStringRef::mid(int pos, int n) const
|
QStringRef QStringRef::mid(int pos, int n) const
|
||||||
{
|
{
|
||||||
|
qsizetype p = pos;
|
||||||
|
qsizetype l = n;
|
||||||
using namespace QtPrivate;
|
using namespace QtPrivate;
|
||||||
switch (QContainerImplHelper::mid(m_size, &pos, &n)) {
|
switch (QContainerImplHelper::mid(m_size, &p, &l)) {
|
||||||
case QContainerImplHelper::Null:
|
case QContainerImplHelper::Null:
|
||||||
return QStringRef();
|
return QStringRef();
|
||||||
case QContainerImplHelper::Empty:
|
case QContainerImplHelper::Empty:
|
||||||
@ -10786,7 +10785,7 @@ QStringRef QStringRef::mid(int pos, int n) const
|
|||||||
case QContainerImplHelper::Full:
|
case QContainerImplHelper::Full:
|
||||||
return *this;
|
return *this;
|
||||||
case QContainerImplHelper::Subset:
|
case QContainerImplHelper::Subset:
|
||||||
return QStringRef(m_string, pos + m_position, n);
|
return QStringRef(m_string, p + m_position, l);
|
||||||
}
|
}
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
return QStringRef();
|
return QStringRef();
|
||||||
|
@ -179,14 +179,26 @@ public:
|
|||||||
const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
|
const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
|
||||||
const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
|
const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
|
||||||
|
|
||||||
Q_DECL_CONSTEXPR QLatin1String mid(int pos) const
|
constexpr QLatin1String mid(int pos, int n = -1) const
|
||||||
{ return Q_ASSERT(pos >= 0), Q_ASSERT(pos <= size()), QLatin1String(m_data + pos, m_size - pos); }
|
{
|
||||||
Q_DECL_CONSTEXPR QLatin1String mid(int pos, int n) const
|
qsizetype p = pos;
|
||||||
{ return Q_ASSERT(pos >= 0), Q_ASSERT(n >= 0), Q_ASSERT(pos + n <= size()), QLatin1String(m_data + pos, n); }
|
qsizetype l = n;
|
||||||
Q_DECL_CONSTEXPR QLatin1String left(int n) const
|
using namespace QtPrivate;
|
||||||
{ return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QLatin1String(m_data, n); }
|
auto result = QContainerImplHelper::mid(size(), &p, &l);
|
||||||
Q_DECL_CONSTEXPR QLatin1String right(int n) const
|
return result == QContainerImplHelper::Null ? QLatin1String() : QLatin1String(m_data + p, l);
|
||||||
{ return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QLatin1String(m_data + m_size - n, n); }
|
}
|
||||||
|
constexpr QLatin1String left(int n) const
|
||||||
|
{
|
||||||
|
if (size_t(n) >= size_t(size()))
|
||||||
|
n = size();
|
||||||
|
return QLatin1String(m_data, n);
|
||||||
|
}
|
||||||
|
constexpr QLatin1String right(int n) const
|
||||||
|
{
|
||||||
|
if (size_t(n) >= size_t(size()))
|
||||||
|
n = size();
|
||||||
|
return QLatin1String(m_data + m_size - n, n);
|
||||||
|
}
|
||||||
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1String chopped(int n) const
|
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1String chopped(int n) const
|
||||||
{ return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QLatin1String(m_data, m_size - n); }
|
{ return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QLatin1String(m_data, m_size - n); }
|
||||||
|
|
||||||
|
@ -610,50 +610,49 @@ QT_BEGIN_NAMESPACE
|
|||||||
\sa back(), front(), first()
|
\sa back(), front(), first()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
|
||||||
\fn QStringView QStringView::mid(qsizetype start) const
|
|
||||||
|
|
||||||
Returns the substring starting at position \a start in this object,
|
|
||||||
and extending to the end of the string.
|
|
||||||
|
|
||||||
\note The behavior is undefined when \a start < 0 or \a start > size().
|
|
||||||
|
|
||||||
\sa left(), right(), chopped(), chop(), truncate()
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn QStringView QStringView::mid(qsizetype start, qsizetype length) const
|
\fn QStringView QStringView::mid(qsizetype start, qsizetype length) const
|
||||||
\overload
|
|
||||||
|
|
||||||
Returns the substring of length \a length starting at position
|
Returns the substring of length \a length starting at position
|
||||||
\a start in this object.
|
\a start in this object.
|
||||||
|
|
||||||
\note The behavior is undefined when \a start < 0, \a length < 0,
|
\obsolete Use slice() instead in new code.
|
||||||
or \a start + \a length > size().
|
|
||||||
|
|
||||||
\sa left(), right(), chopped(), chop(), truncate()
|
Returns an empty string view if \a start 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.
|
||||||
|
|
||||||
|
\sa first(), last(), slice(), chopped(), chop(), truncate()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn QStringView QStringView::left(qsizetype length) const
|
\fn QStringView QStringView::left(qsizetype length) const
|
||||||
|
|
||||||
|
\obsolete Use first() instead in new code.
|
||||||
|
|
||||||
Returns the substring of length \a length starting at position
|
Returns the substring of length \a length starting at position
|
||||||
0 in this object.
|
0 in this object.
|
||||||
|
|
||||||
\note The behavior is undefined when \a length < 0 or \a length > size().
|
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()
|
\sa first(), last(), slice(), startsWith(), chopped(), chop(), truncate()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn QStringView QStringView::right(qsizetype length) const
|
\fn QStringView QStringView::right(qsizetype length) const
|
||||||
|
|
||||||
|
\obsolete Use last() instead in new code.
|
||||||
|
|
||||||
Returns the substring of length \a length starting at position
|
Returns the substring of length \a length starting at position
|
||||||
size() - \a length in this object.
|
size() - \a length in this object.
|
||||||
|
|
||||||
\note The behavior is undefined when \a length < 0 or \a length > size().
|
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(), slice(), endsWith(), chopped(), chop(), truncate()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -257,14 +257,24 @@ public:
|
|||||||
|
|
||||||
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar at(qsizetype n) const { return (*this)[n]; }
|
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar at(qsizetype n) const { return (*this)[n]; }
|
||||||
|
|
||||||
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QStringView mid(qsizetype pos) const
|
Q_REQUIRED_RESULT constexpr QStringView mid(qsizetype pos, qsizetype n = -1) const
|
||||||
{ return Q_ASSERT(pos >= 0), Q_ASSERT(pos <= size()), QStringView(m_data + pos, m_size - pos); }
|
{
|
||||||
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QStringView mid(qsizetype pos, qsizetype n) const
|
using namespace QtPrivate;
|
||||||
{ return Q_ASSERT(pos >= 0), Q_ASSERT(n >= 0), Q_ASSERT(pos + n <= size()), QStringView(m_data + pos, n); }
|
auto result = QContainerImplHelper::mid(size(), &pos, &n);
|
||||||
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QStringView left(qsizetype n) const
|
return result == QContainerImplHelper::Null ? QStringView() : QStringView(m_data + pos, n);
|
||||||
{ return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QStringView(m_data, n); }
|
}
|
||||||
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QStringView right(qsizetype n) const
|
Q_REQUIRED_RESULT constexpr QStringView left(qsizetype n) const
|
||||||
{ return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QStringView(m_data + m_size - n, n); }
|
{
|
||||||
|
if (size_t(n) >= size_t(size()))
|
||||||
|
n = size();
|
||||||
|
return QStringView(m_data, n);
|
||||||
|
}
|
||||||
|
Q_REQUIRED_RESULT constexpr QStringView right(qsizetype n) const
|
||||||
|
{
|
||||||
|
if (size_t(n) >= size_t(size()))
|
||||||
|
n = size();
|
||||||
|
return QStringView(m_data + m_size - n, n);
|
||||||
|
}
|
||||||
|
|
||||||
Q_REQUIRED_RESULT constexpr QStringView first(qsizetype n) const
|
Q_REQUIRED_RESULT constexpr QStringView first(qsizetype n) const
|
||||||
{ Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QStringView(m_data, int(n)); }
|
{ Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QStringView(m_data, int(n)); }
|
||||||
|
@ -281,33 +281,4 @@ void QArrayData::deallocate(QArrayData *data, size_t objectSize,
|
|||||||
::free(data);
|
::free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace QtPrivate {
|
|
||||||
/*!
|
|
||||||
\internal
|
|
||||||
*/
|
|
||||||
QContainerImplHelper::CutResult QContainerImplHelper::mid(int originalLength, int *_position, int *_length)
|
|
||||||
{
|
|
||||||
int &position = *_position;
|
|
||||||
int &length = *_length;
|
|
||||||
if (position > originalLength)
|
|
||||||
return Null;
|
|
||||||
|
|
||||||
if (position < 0) {
|
|
||||||
if (length < 0 || length + position >= originalLength)
|
|
||||||
return Full;
|
|
||||||
if (length + position <= 0)
|
|
||||||
return Null;
|
|
||||||
length += position;
|
|
||||||
position = 0;
|
|
||||||
} else if (uint(length) > uint(originalLength - position)) {
|
|
||||||
length = originalLength - position;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (position == 0 && length == originalLength)
|
|
||||||
return Full;
|
|
||||||
|
|
||||||
return length > 0 ? Subset : Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -306,7 +306,37 @@ namespace QtPrivate {
|
|||||||
struct Q_CORE_EXPORT QContainerImplHelper
|
struct Q_CORE_EXPORT QContainerImplHelper
|
||||||
{
|
{
|
||||||
enum CutResult { Null, Empty, Full, Subset };
|
enum CutResult { Null, Empty, Full, Subset };
|
||||||
static CutResult mid(int originalLength, int *position, int *length);
|
static constexpr CutResult mid(qsizetype originalLength, qsizetype *_position, qsizetype *_length)
|
||||||
|
{
|
||||||
|
qsizetype &position = *_position;
|
||||||
|
qsizetype &length = *_length;
|
||||||
|
if (position > originalLength) {
|
||||||
|
position = 0;
|
||||||
|
length = 0;
|
||||||
|
return Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position < 0) {
|
||||||
|
if (length < 0 || length + position >= originalLength) {
|
||||||
|
position = 0;
|
||||||
|
length = originalLength;
|
||||||
|
return Full;
|
||||||
|
}
|
||||||
|
if (length + position <= 0) {
|
||||||
|
position = length = 0;
|
||||||
|
return Null;
|
||||||
|
}
|
||||||
|
length += position;
|
||||||
|
position = 0;
|
||||||
|
} else if (size_t(length) > size_t(originalLength - position)) {
|
||||||
|
length = originalLength - position;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position == 0 && length == originalLength)
|
||||||
|
return Full;
|
||||||
|
|
||||||
|
return length > 0 ? Subset : Empty;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,8 +710,10 @@ int QVector<T>::lastIndexOf(const T &t, int from) const noexcept
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline QVector<T> QVector<T>::mid(int pos, int len) const
|
inline QVector<T> QVector<T>::mid(int pos, int len) const
|
||||||
{
|
{
|
||||||
|
qsizetype p = pos;
|
||||||
|
qsizetype l = len;
|
||||||
using namespace QtPrivate;
|
using namespace QtPrivate;
|
||||||
switch (QContainerImplHelper::mid(d.size, &pos, &len)) {
|
switch (QContainerImplHelper::mid(d.size, &p, &l)) {
|
||||||
case QContainerImplHelper::Null:
|
case QContainerImplHelper::Null:
|
||||||
case QContainerImplHelper::Empty:
|
case QContainerImplHelper::Empty:
|
||||||
return QVector();
|
return QVector();
|
||||||
@ -722,8 +724,8 @@ inline QVector<T> QVector<T>::mid(int pos, int len) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate memory
|
// Allocate memory
|
||||||
DataPointer copied(Data::allocate(len));
|
DataPointer copied(Data::allocate(l));
|
||||||
copied->copyAppend(constBegin() + pos, constBegin() + pos + len);
|
copied->copyAppend(constBegin() + p, constBegin() + p + l);
|
||||||
return copied;
|
return copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,9 +644,6 @@ private:
|
|||||||
void chop_data();
|
void chop_data();
|
||||||
template <typename String> void chop_impl();
|
template <typename String> void chop_impl();
|
||||||
|
|
||||||
void truncate_data() { left_data(); }
|
|
||||||
template <typename String> void truncate_impl();
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
|
|
||||||
void mid_QString_data() { mid_data(); }
|
void mid_QString_data() { mid_data(); }
|
||||||
@ -660,16 +657,16 @@ private Q_SLOTS:
|
|||||||
void mid_QByteArray_data() { mid_data(); }
|
void mid_QByteArray_data() { mid_data(); }
|
||||||
void mid_QByteArray() { mid_impl<QByteArray>(); }
|
void mid_QByteArray() { mid_impl<QByteArray>(); }
|
||||||
|
|
||||||
void left_truncate_QString_data() { left_data(); }
|
void left_QString_data() { left_data(); }
|
||||||
void left_truncate_QString() { left_impl<QString>(); }
|
void left_QString() { left_impl<QString>(); }
|
||||||
void left_truncate_QStringRef_data() { left_data(); }
|
void left_QStringRef_data() { left_data(); }
|
||||||
void left_truncate_QStringRef() { left_impl<QStringRef>(); }
|
void left_QStringRef() { left_impl<QStringRef>(); }
|
||||||
void left_truncate_QStringView_data() { left_data(); }
|
void left_QStringView_data() { left_data(); }
|
||||||
void left_truncate_QStringView() { left_impl<QStringView>(); }
|
void left_QStringView() { left_impl<QStringView>(); }
|
||||||
void left_truncate_QLatin1String_data() { left_data(); }
|
void left_QLatin1String_data() { left_data(); }
|
||||||
void left_truncate_QLatin1String() { left_impl<QLatin1String>(); }
|
void left_QLatin1String() { left_impl<QLatin1String>(); }
|
||||||
void left_truncate_QByteArray_data() { left_data(); }
|
void left_QByteArray_data();
|
||||||
void left_truncate_QByteArray() { left_impl<QByteArray>(); }
|
void left_QByteArray() { left_impl<QByteArray>(); }
|
||||||
|
|
||||||
void right_QString_data() { right_data(); }
|
void right_QString_data() { right_data(); }
|
||||||
void right_QString() { right_impl<QString>(); }
|
void right_QString() { right_impl<QString>(); }
|
||||||
@ -679,7 +676,7 @@ private Q_SLOTS:
|
|||||||
void right_QStringView() { right_impl<QStringView>(); }
|
void right_QStringView() { right_impl<QStringView>(); }
|
||||||
void right_QLatin1String_data() { right_data(); }
|
void right_QLatin1String_data() { right_data(); }
|
||||||
void right_QLatin1String() { right_impl<QLatin1String>(); }
|
void right_QLatin1String() { right_impl<QLatin1String>(); }
|
||||||
void right_QByteArray_data() { right_data(); }
|
void right_QByteArray_data();
|
||||||
void right_QByteArray() { right_impl<QByteArray>(); }
|
void right_QByteArray() { right_impl<QByteArray>(); }
|
||||||
|
|
||||||
void slice_QString_data() { slice_data(); }
|
void slice_QString_data() { slice_data(); }
|
||||||
@ -1533,6 +1530,37 @@ void tst_QStringApiSymmetry::tok_impl() const
|
|||||||
void tst_QStringApiSymmetry::mid_data()
|
void tst_QStringApiSymmetry::mid_data()
|
||||||
{
|
{
|
||||||
slice_data();
|
slice_data();
|
||||||
|
|
||||||
|
// mid() has a wider contract compared to slize(), so test those cases here:
|
||||||
|
#define ROW(base, p, n, r1, r2) \
|
||||||
|
QTest::addRow("%s %d %d", #base, p, n) << QStringRef(&base) << QLatin1String(#base) << p << n << QStringRef(&r1) << QStringRef(&r2)
|
||||||
|
|
||||||
|
ROW(a, -1, 0, a, null);
|
||||||
|
ROW(a, -1, 2, a, a);
|
||||||
|
ROW(a, -1, 3, a, a);
|
||||||
|
ROW(a, 0, -1, a, a);
|
||||||
|
ROW(a, 0, 2, a, a);
|
||||||
|
ROW(a, -1, -1, a, a);
|
||||||
|
ROW(a, 1, -1, empty, empty);
|
||||||
|
ROW(a, 1, 1, empty, empty);
|
||||||
|
ROW(a, 2, -1, null, null);
|
||||||
|
ROW(a, 2, 1, null, null);
|
||||||
|
|
||||||
|
ROW(abc, -1, -1, abc, abc);
|
||||||
|
ROW(abc, -1, 0, abc, null);
|
||||||
|
ROW(abc, -1, 2, abc, a);
|
||||||
|
ROW(abc, -1, 3, abc, ab);
|
||||||
|
ROW(abc, -1, 5, abc, abc);
|
||||||
|
ROW(abc, 0, -1, abc, abc);
|
||||||
|
ROW(abc, 0, 5, abc, abc);
|
||||||
|
ROW(abc, -1, 1, abc, null);
|
||||||
|
ROW(abc, -1, 2, abc, a);
|
||||||
|
ROW(abc, -1, 4, abc, abc);
|
||||||
|
ROW(abc, 1, -1, bc, bc);
|
||||||
|
ROW(abc, 1, 1, bc, b);
|
||||||
|
ROW(abc, 3, -1, empty, empty);
|
||||||
|
ROW(abc, 3, 1, empty, empty);
|
||||||
|
#undef ROW
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename String>
|
template <typename String>
|
||||||
@ -1578,6 +1606,35 @@ void tst_QStringApiSymmetry::mid_impl()
|
|||||||
void tst_QStringApiSymmetry::left_data()
|
void tst_QStringApiSymmetry::left_data()
|
||||||
{
|
{
|
||||||
first_data();
|
first_data();
|
||||||
|
|
||||||
|
// specific data testing out of bounds cases
|
||||||
|
#define ROW(base, n, res) \
|
||||||
|
QTest::addRow("%s%d", #base, n) << QStringRef(&base) << QLatin1String(#base) << n << QStringRef(&res);
|
||||||
|
|
||||||
|
ROW(a, -1, a);
|
||||||
|
ROW(a, 2, a);
|
||||||
|
|
||||||
|
ROW(ab, -100, ab);
|
||||||
|
ROW(ab, 100, ab);
|
||||||
|
#undef ROW
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is different from the rest for historical reasons. As we're replacing
|
||||||
|
// left() with first() as the recommended API, there's no point fixing this anymore
|
||||||
|
void tst_QStringApiSymmetry::left_QByteArray_data()
|
||||||
|
{
|
||||||
|
first_data();
|
||||||
|
|
||||||
|
// specific data testing out of bounds cases
|
||||||
|
#define ROW(base, n, res) \
|
||||||
|
QTest::addRow("%s%d", #base, n) << QStringRef(&base) << QLatin1String(#base) << n << QStringRef(&res);
|
||||||
|
|
||||||
|
ROW(a, -1, empty);
|
||||||
|
ROW(a, 2, a);
|
||||||
|
|
||||||
|
ROW(ab, -100, empty);
|
||||||
|
ROW(ab, 100, ab);
|
||||||
|
#undef ROW
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename String>
|
template <typename String>
|
||||||
@ -1602,14 +1659,6 @@ void tst_QStringApiSymmetry::left_impl()
|
|||||||
{
|
{
|
||||||
const auto left = detached(s).left(n);
|
const auto left = detached(s).left(n);
|
||||||
|
|
||||||
QCOMPARE(left, result);
|
|
||||||
QCOMPARE(left.isNull(), result.isNull());
|
|
||||||
QCOMPARE(left.isEmpty(), result.isEmpty());
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto left = s;
|
|
||||||
left.truncate(n);
|
|
||||||
|
|
||||||
QCOMPARE(left, result);
|
QCOMPARE(left, result);
|
||||||
QCOMPARE(left.isNull(), result.isNull());
|
QCOMPARE(left.isNull(), result.isNull());
|
||||||
QCOMPARE(left.isEmpty(), result.isEmpty());
|
QCOMPARE(left.isEmpty(), result.isEmpty());
|
||||||
@ -1619,6 +1668,35 @@ void tst_QStringApiSymmetry::left_impl()
|
|||||||
void tst_QStringApiSymmetry::right_data()
|
void tst_QStringApiSymmetry::right_data()
|
||||||
{
|
{
|
||||||
last_data();
|
last_data();
|
||||||
|
|
||||||
|
// specific data testing out of bounds cases
|
||||||
|
#define ROW(base, n, res) \
|
||||||
|
QTest::addRow("%s%d", #base, n) << QStringRef(&base) << QLatin1String(#base) << n << QStringRef(&res);
|
||||||
|
|
||||||
|
ROW(a, -1, a);
|
||||||
|
ROW(a, 2, a);
|
||||||
|
|
||||||
|
ROW(ab, -100, ab);
|
||||||
|
ROW(ab, 100, ab);
|
||||||
|
#undef ROW
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is different from the rest for historical reasons. As we're replacing
|
||||||
|
// left() with first() as the recommended API, there's no point fixing this anymore
|
||||||
|
void tst_QStringApiSymmetry::right_QByteArray_data()
|
||||||
|
{
|
||||||
|
last_data();
|
||||||
|
|
||||||
|
// specific data testing out of bounds cases
|
||||||
|
#define ROW(base, n, res) \
|
||||||
|
QTest::addRow("%s%d", #base, n) << QStringRef(&base) << QLatin1String(#base) << n << QStringRef(&res);
|
||||||
|
|
||||||
|
ROW(a, -1, empty);
|
||||||
|
ROW(a, 2, a);
|
||||||
|
|
||||||
|
ROW(ab, -100, empty);
|
||||||
|
ROW(ab, 100, ab);
|
||||||
|
#undef ROW
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename String>
|
template <typename String>
|
||||||
@ -1661,8 +1739,6 @@ void tst_QStringApiSymmetry::slice_data()
|
|||||||
// QTest::addRow("null") << QStringRef() << QLatin1String() << 0 << 0 << QStringRef() << QStringRef();
|
// QTest::addRow("null") << QStringRef() << QLatin1String() << 0 << 0 << QStringRef() << QStringRef();
|
||||||
QTest::addRow("empty") << QStringRef(&empty) << QLatin1String("") << 0 << 0 << QStringRef(&empty) << QStringRef(&empty);
|
QTest::addRow("empty") << QStringRef(&empty) << QLatin1String("") << 0 << 0 << QStringRef(&empty) << QStringRef(&empty);
|
||||||
|
|
||||||
// Some classes' mid() implementations have a wide contract, others a narrow one
|
|
||||||
// so only test valid arguents here:
|
|
||||||
#define ROW(base, p, n, r1, r2) \
|
#define ROW(base, p, n, r1, r2) \
|
||||||
QTest::addRow("%s%d%d", #base, p, n) << QStringRef(&base) << QLatin1String(#base) << p << n << QStringRef(&r1) << QStringRef(&r2)
|
QTest::addRow("%s%d%d", #base, p, n) << QStringRef(&base) << QLatin1String(#base) << p << n << QStringRef(&r1) << QStringRef(&r2)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user