diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-06-02 15:51:15 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2020-06-09 16:51:16 +0200 |
commit | d2833a3ce5af725d66ef9338f2a61b766dd3cb2d (patch) | |
tree | 3b74823b5f2da7cfd179e4faeed1697c4ff14d09 /src/corelib/text | |
parent | fd856532d7472ccc6daf6a95d5c28264d9e6adca (diff) |
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>
Diffstat (limited to 'src/corelib/text')
-rw-r--r-- | src/corelib/text/qbytearray.cpp | 23 | ||||
-rw-r--r-- | src/corelib/text/qstring.cpp | 53 | ||||
-rw-r--r-- | src/corelib/text/qstring.h | 28 | ||||
-rw-r--r-- | src/corelib/text/qstringview.cpp | 37 | ||||
-rw-r--r-- | src/corelib/text/qstringview.h | 26 |
5 files changed, 99 insertions, 68 deletions
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp index 008ce7298b..3f83e36d90 100644 --- a/src/corelib/text/qbytearray.cpp +++ b/src/corelib/text/qbytearray.cpp @@ -2914,13 +2914,17 @@ bool QByteArray::isLower() const Returns a byte array that contains the first \a len bytes of this byte array. + \obsolete Use first() instead in new code. + The entire byte array is returned if \a len is greater than size(). + Returns an empty QByteArray if \a len is smaller than 0. + Example: \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 @@ -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. + \obsolete Use last() instead in new code. + The entire byte array is returned if \a len is greater than size(). + Returns an empty QByteArray if \a len is smaller than 0. + Example: \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 { 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, 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(), returns a byte array containing all bytes starting at position \a pos until the end of the byte array. @@ -2964,13 +2973,15 @@ QByteArray QByteArray::right(int len) const Example: \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 { + qsizetype p = pos; + qsizetype l = len; using namespace QtPrivate; - switch (QContainerImplHelper::mid(size(), &pos, &len)) { + switch (QContainerImplHelper::mid(size(), &p, &l)) { case QContainerImplHelper::Null: return QByteArray(); case QContainerImplHelper::Empty: @@ -2982,7 +2993,7 @@ QByteArray QByteArray::mid(int pos, int len) const case QContainerImplHelper::Full: return *this; case QContainerImplHelper::Subset: - return QByteArray(d.data() + pos, len); + return QByteArray(d.data() + p, l); } Q_UNREACHABLE(); return QByteArray(); diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 6707cc580e..5e3debcc34 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -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 of the string. + \obsolete Use first() instead in new code. + The entire string is returned if \a n is greater than or equal to size(), or less than zero. \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 { @@ -4548,12 +4550,14 @@ QString QString::left(int n) const Returns a substring that contains the \a n rightmost characters of the string. + \obsolete Use last() instead in new code. + The entire string is returned if \a n is greater than or equal to size(), or less than zero. \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 { @@ -4566,6 +4570,8 @@ QString QString::right(int n) const Returns a string that contains \a n characters of this string, 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 length of the string. If there are less than \a n characters 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 - \sa left(), right(), chopped(), chop(), truncate() + \sa first(), last(), slice(), chopped(), chop(), truncate() */ QString QString::mid(int position, int n) const { + qsizetype p = position; + qsizetype l = n; using namespace QtPrivate; - switch (QContainerImplHelper::mid(size(), &position, &n)) { + switch (QContainerImplHelper::mid(size(), &p, &l)) { case QContainerImplHelper::Null: return QString(); case QContainerImplHelper::Empty: @@ -4594,7 +4602,7 @@ QString QString::mid(int position, int n) const case QContainerImplHelper::Full: return *this; case QContainerImplHelper::Subset: - return QString(constData() + position, n); + return QString(constData() + p, l); } Q_UNREACHABLE(); return QString(); @@ -9375,28 +9383,17 @@ QString &QString::setRawData(const QChar *unicode, int size) \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 \since 5.8 - \overload Returns the substring of length \a length starting at position \a start in this object. - \note This function performs no error checking. - The behavior is undefined when \a start < 0, \a length < 0, - or \a start + \a length > size(). + 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. \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 0 in this object. - \note This function performs no error checking. - 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() */ @@ -9419,8 +9416,8 @@ QString &QString::setRawData(const QChar *unicode, int size) Returns the substring of length \a length starting at position size() - \a length in this object. - \note This function performs no error checking. - 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() */ @@ -10777,8 +10774,10 @@ QStringRef QString::rightRef(int n) const */ QStringRef QStringRef::mid(int pos, int n) const { + qsizetype p = pos; + qsizetype l = n; using namespace QtPrivate; - switch (QContainerImplHelper::mid(m_size, &pos, &n)) { + switch (QContainerImplHelper::mid(m_size, &p, &l)) { case QContainerImplHelper::Null: return QStringRef(); case QContainerImplHelper::Empty: @@ -10786,7 +10785,7 @@ QStringRef QStringRef::mid(int pos, int n) const case QContainerImplHelper::Full: return *this; case QContainerImplHelper::Subset: - return QStringRef(m_string, pos + m_position, n); + return QStringRef(m_string, p + m_position, l); } Q_UNREACHABLE(); return QStringRef(); diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h index c0b23c9733..efd57328bb 100644 --- a/src/corelib/text/qstring.h +++ b/src/corelib/text/qstring.h @@ -179,14 +179,26 @@ public: const_reverse_iterator rend() 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 - { 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 - { return Q_ASSERT(pos >= 0), Q_ASSERT(n >= 0), Q_ASSERT(pos + n <= size()), QLatin1String(m_data + pos, n); } - Q_DECL_CONSTEXPR QLatin1String left(int n) const - { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QLatin1String(m_data, n); } - Q_DECL_CONSTEXPR QLatin1String right(int n) const - { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QLatin1String(m_data + m_size - n, n); } + constexpr QLatin1String mid(int pos, int 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); + } + 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 { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QLatin1String(m_data, m_size - n); } diff --git a/src/corelib/text/qstringview.cpp b/src/corelib/text/qstringview.cpp index b9dc9d2d41..42d18851c7 100644 --- a/src/corelib/text/qstringview.cpp +++ b/src/corelib/text/qstringview.cpp @@ -611,49 +611,48 @@ QT_BEGIN_NAMESPACE */ /*! - \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 - \overload Returns the substring of length \a length starting at position \a start in this object. - \note The behavior is undefined when \a start < 0, \a length < 0, - or \a start + \a length > size(). + \obsolete Use slice() instead in new code. - \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 + \obsolete Use first() instead in new code. + Returns the substring of length \a length starting at position 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 + \obsolete Use last() instead in new code. + Returns the substring of length \a length starting at position 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() */ /*! diff --git a/src/corelib/text/qstringview.h b/src/corelib/text/qstringview.h index 2b085c769d..6dbec21165 100644 --- a/src/corelib/text/qstringview.h +++ b/src/corelib/text/qstringview.h @@ -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 QStringView mid(qsizetype pos) 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 - { return Q_ASSERT(pos >= 0), Q_ASSERT(n >= 0), Q_ASSERT(pos + n <= size()), QStringView(m_data + pos, n); } - Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QStringView left(qsizetype n) const - { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QStringView(m_data, n); } - Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QStringView right(qsizetype n) const - { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QStringView(m_data + m_size - n, n); } + Q_REQUIRED_RESULT constexpr QStringView mid(qsizetype pos, qsizetype n = -1) const + { + using namespace QtPrivate; + auto result = QContainerImplHelper::mid(size(), &pos, &n); + return result == QContainerImplHelper::Null ? QStringView() : QStringView(m_data + pos, n); + } + Q_REQUIRED_RESULT constexpr QStringView left(qsizetype n) const + { + 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_ASSERT(n >= 0); Q_ASSERT(n <= size()); return QStringView(m_data, int(n)); } |