diff options
Diffstat (limited to 'src/corelib/text/qstringlist.cpp')
-rw-r--r-- | src/corelib/text/qstringlist.cpp | 313 |
1 files changed, 207 insertions, 106 deletions
diff --git a/src/corelib/text/qstringlist.cpp b/src/corelib/text/qstringlist.cpp index 687c83b8ab..61923e0b3f 100644 --- a/src/corelib/text/qstringlist.cpp +++ b/src/corelib/text/qstringlist.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <qstringlist.h> #include <qset.h> @@ -120,25 +84,7 @@ QT_BEGIN_NAMESPACE \section1 Iterating Over the Strings - To iterate over a list, you can either use index positions or - QList's Java-style and STL-style iterator types: - - Indexing: - - \snippet qstringlist/main.cpp 1 - - Java-style iterator: - - \snippet qstringlist/main.cpp 2 - - STL-style iterator: - - \snippet qstringlist/main.cpp 3 - - The QStringListIterator class is simply a type definition for - QListIterator<QString>. QStringList also provide the - QMutableStringListIterator class which is a type definition for - QMutableListIterator<QString>. + See \l {Iterating over Containers}. \section1 Manipulating the Strings @@ -243,8 +189,11 @@ QT_BEGIN_NAMESPACE \fn void QStringList::sort(Qt::CaseSensitivity cs) Sorts the list of strings in ascending order. + +//! [comparison-case-sensitivity] If \a cs is \l Qt::CaseSensitive (the default), the string comparison is case sensitive; otherwise the comparison is case insensitive. +//! [comparison-case-sensitivity] Sorting is performed using the STL's std::sort() algorithm, which averages \l{linear-logarithmic time}, i.e. O(\e{n} log \e{n}). @@ -257,34 +206,25 @@ QT_BEGIN_NAMESPACE integer index. */ -namespace { -struct CaseInsensitiveLessThan { - typedef bool result_type; - result_type operator()(const QString &s1, const QString &s2) const - { - return s1.compare(s2, Qt::CaseInsensitive) < 0; - } -}; -} - void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs) { - if (cs == Qt::CaseSensitive) + if (cs == Qt::CaseSensitive) { std::sort(that->begin(), that->end()); - else - std::sort(that->begin(), that->end(), CaseInsensitiveLessThan()); + } else { + auto CISCompare = [](const auto &s1, const auto &s2) { + return s1.compare(s2, Qt::CaseInsensitive) < 0; + }; + std::sort(that->begin(), that->end(), CISCompare); + } } -#if QT_STRINGVIEW_LEVEL < 2 /*! \fn QStringList QStringList::filter(const QString &str, Qt::CaseSensitivity cs) const Returns a list of all the strings containing the substring \a str. - If \a cs is \l Qt::CaseSensitive (the default), the string - comparison is case sensitive; otherwise the comparison is case - insensitive. + \include qstringlist.cpp comparison-case-sensitivity \snippet qstringlist/main.cpp 5 \snippet qstringlist/main.cpp 10 @@ -296,7 +236,17 @@ void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs) \sa contains() */ -#endif + +template <typename String> +static QStringList filter_helper(const QStringList &that, const String &needle, Qt::CaseSensitivity cs) +{ + QStringList res; + for (const auto &s : that) { + if (s.contains(needle, cs)) + res.append(s); + } + return res; +} /*! \fn QStringList QStringList::filter(QStringView str, Qt::CaseSensitivity cs) const @@ -306,14 +256,48 @@ void QtPrivate::QStringList_sort(QStringList *that, Qt::CaseSensitivity cs) QStringList QtPrivate::QStringList_filter(const QStringList *that, QStringView str, Qt::CaseSensitivity cs) { - QStringMatcher matcher(str, cs); + return filter_helper(*that, str, cs); +} + +/*! + \fn QStringList QStringList::filter(const QStringMatcher &matcher) const + \since 6.7 + \overload + + Returns a list of all the strings matched by \a matcher (i.e. for which + \c matcher.indexIn() returns an index >= 0). + + Using a QStringMatcher may be faster when searching in large lists and/or + in lists with long strings (the best way to find out is benchmarking). + + For example: + \snippet qstringlist/main.cpp 18 + + \sa contains() +*/ + +QStringList QtPrivate::QStringList_filter(const QStringList &that, const QStringMatcher &matcher) +{ QStringList res; - for (qsizetype i = 0; i < that->size(); ++i) - if (matcher.indexIn(that->at(i)) != -1) - res << that->at(i); + for (const auto &s : that) { + if (matcher.indexIn(s) != -1) + res.append(s); + } return res; } +/*! + \fn QStringList QStringList::filter(QLatin1StringView str, Qt::CaseSensitivity cs) const + \since 6.7 + \overload +*/ + +QStringList QtPrivate::QStringList_filter(const QStringList &that, QLatin1StringView needle, + Qt::CaseSensitivity cs) +{ + return filter_helper(that, needle, cs); +} + template<typename T> static bool stringList_contains(const QStringList &stringList, const T &str, Qt::CaseSensitivity cs) { @@ -325,17 +309,16 @@ static bool stringList_contains(const QStringList &stringList, const T &str, Qt: } -#if QT_STRINGVIEW_LEVEL < 2 /*! \fn bool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) const Returns \c true if the list contains the string \a str; otherwise - returns \c false. The search is case insensitive if \a cs is - Qt::CaseInsensitive; the search is case sensitive by default. + returns \c false. + + \include qstringlist.cpp comparison-case-sensitivity \sa indexOf(), lastIndexOf(), QString::contains() */ -#endif /*! \fn bool QStringList::contains(QStringView str, Qt::CaseSensitivity cs) const @@ -343,8 +326,9 @@ static bool stringList_contains(const QStringList &stringList, const T &str, Qt: \since 5.12 Returns \c true if the list contains the string \a str; otherwise - returns \c false. The search is case insensitive if \a cs is - Qt::CaseInsensitive; the search is case sensitive by default. + returns \c false. + + \include qstringlist.cpp comparison-case-sensitivity */ bool QtPrivate::QStringList_contains(const QStringList *that, QStringView str, Qt::CaseSensitivity cs) @@ -353,17 +337,18 @@ bool QtPrivate::QStringList_contains(const QStringList *that, QStringView str, } /*! - \fn bool QStringList::contains(QLatin1String str, Qt::CaseSensitivity cs) const + \fn bool QStringList::contains(QLatin1StringView str, Qt::CaseSensitivity cs) const \overload \since 5.10 - Returns \c true if the list contains the string \a str; otherwise - returns \c false. The search is case insensitive if \a cs is - Qt::CaseInsensitive; the search is case sensitive by default. + Returns \c true if the list contains the Latin-1 string viewed by \a str; otherwise + returns \c false. + + \include qstringlist.cpp comparison-case-sensitivity \sa indexOf(), lastIndexOf(), QString::contains() */ -bool QtPrivate::QStringList_contains(const QStringList *that, QLatin1String str, +bool QtPrivate::QStringList_contains(const QStringList *that, QLatin1StringView str, Qt::CaseSensitivity cs) { return stringList_contains(*that, str, cs); @@ -382,22 +367,22 @@ bool QtPrivate::QStringList_contains(const QStringList *that, QLatin1String str, QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegularExpression &re) { QStringList res; - for (qsizetype i = 0; i < that->size(); ++i) { - if (that->at(i).contains(re)) - res << that->at(i); + for (const auto &str : *that) { + if (str.contains(re)) + res.append(str); } return res; } #endif // QT_CONFIG(regularexpression) -#if QT_STRINGVIEW_LEVEL < 2 /*! \fn QStringList &QStringList::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs) Returns a string list where every string has had the \a before text replaced with the \a after text wherever the \a before text - is found. The \a before text is matched case-sensitively or not - depending on the \a cs flag. + is found. + + \include qstringlist.cpp comparison-case-sensitivity For example: @@ -418,7 +403,6 @@ QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegula \overload \since 5.14 */ -#endif /*! \fn QStringList &QStringList::replaceInStrings(QStringView before, QStringView after, Qt::CaseSensitivity cs) @@ -428,8 +412,19 @@ QStringList QtPrivate::QStringList_filter(const QStringList *that, const QRegula void QtPrivate::QStringList_replaceInStrings(QStringList *that, QStringView before, QStringView after, Qt::CaseSensitivity cs) { - for (qsizetype i = 0; i < that->size(); ++i) - (*that)[i].replace(before.data(), before.length(), after.data(), after.length(), cs); + // Before potentially detaching "that" list, check if any string contains "before" + qsizetype i = -1; + for (qsizetype j = 0; j < that->size(); ++j) { + if (that->at(j).contains(before, cs)) { + i = j; + break; + } + } + if (i == -1) + return; + + for (; i < that->size(); ++i) + (*that)[i].replace(before.data(), before.size(), after.data(), after.size(), cs); } #if QT_CONFIG(regularexpression) @@ -456,9 +451,21 @@ void QtPrivate::QStringList_replaceInStrings(QStringList *that, QStringView befo \snippet qstringlist/main.cpp 5 \snippet qstringlist/main.cpp 17 */ -void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegularExpression &re, const QString &after) +void QtPrivate::QStringList_replaceInStrings(QStringList *that, const QRegularExpression &re, + const QString &after) { - for (qsizetype i = 0; i < that->size(); ++i) + // Before potentially detaching "that" list, check if any string contains "before" + qsizetype i = -1; + for (qsizetype j = 0; j < that->size(); ++j) { + if (that->at(j).contains(re)) { + i = j; + break; + } + } + if (i == -1) + return; + + for (; i < that->size(); ++i) (*that)[i].replace(re, after); } #endif // QT_CONFIG(regularexpression) @@ -474,7 +481,6 @@ static qsizetype accumulatedSize(const QStringList &list, qsizetype seplen) return result; } -#if QT_STRINGVIEW_LEVEL < 2 /*! \fn QString QStringList::join(const QString &separator) const @@ -484,7 +490,6 @@ static qsizetype accumulatedSize(const QStringList &list, qsizetype seplen) \sa QString::split() */ -#endif /*! \fn QString QStringList::join(QChar separator) const @@ -509,11 +514,11 @@ QString QtPrivate::QStringList_join(const QStringList *that, const QChar *sep, q } /*! - \fn QString QStringList::join(QLatin1String separator) const + \fn QString QStringList::join(QLatin1StringView separator) const \since 5.8 \overload join() */ -QString QtPrivate::QStringList_join(const QStringList &list, QLatin1String sep) +QString QtPrivate::QStringList_join(const QStringList &list, QLatin1StringView sep) { QString result; if (!list.isEmpty()) { @@ -536,7 +541,7 @@ QString QtPrivate::QStringList_join(const QStringList &list, QLatin1String sep) */ QString QtPrivate::QStringList_join(const QStringList *that, QStringView sep) { - return QStringList_join(that, sep.data(), sep.length()); + return QStringList_join(that, sep.data(), sep.size()); } /*! @@ -576,6 +581,102 @@ QString QtPrivate::QStringList_join(const QStringList *that, QStringView sep) the latter string list. */ +/*! + \fn qsizetype QStringList::indexOf(const QString &str, qsizetype from, Qt::CaseSensitivity cs) const + \fn qsizetype QStringList::indexOf(QStringView str, qsizetype from, Qt::CaseSensitivity cs) const + \fn qsizetype QStringList::indexOf(QLatin1StringView str, qsizetype from, Qt::CaseSensitivity cs) const + + Returns the index position of the first match of \a str in the list, + searching forward from index position \a from. Returns -1 if no item + matched. + + \include qstringlist.cpp comparison-case-sensitivity + +//! [overloading-base-class-methods] + \note The \a cs parameter was added in Qt 6.7, i.e. these methods now overload + the methods inherited from the base class. Prior to that these methods only + had two parameters. This change is source compatible and existing code should + continue to work. +//! [overloading-base-class-methods] + + \sa lastIndexOf() +*/ + +template <typename String> +qsizetype indexOf_helper(const QStringList &that, String needle, qsizetype from, + Qt::CaseSensitivity cs) +{ + if (from < 0) // Historical behavior + from = qMax(from + that.size(), 0); + + if (from >= that.size()) + return -1; + + for (qsizetype i = from; i < that.size(); ++i) { + if (needle.compare(that.at(i), cs) == 0) + return i; + } + return -1; +} + +qsizetype QtPrivate::QStringList_indexOf(const QStringList &that, QStringView needle, + qsizetype from, Qt::CaseSensitivity cs) +{ + return indexOf_helper(that, needle, from, cs); +} + +qsizetype QtPrivate::QStringList_indexOf(const QStringList &that, QLatin1StringView needle, + qsizetype from, Qt::CaseSensitivity cs) +{ + return indexOf_helper(that, needle, from, cs); +} + +/*! + \fn qsizetype QStringList::lastIndexOf(const QString &str, qsizetype from, Qt::CaseSensitivity cs) const + \fn qsizetype QStringList::lastIndexOf(QStringView str, qsizetype from, Qt::CaseSensitivity cs) const + \fn qsizetype QStringList::lastIndexOf(QLatin1StringView str, qsizetype from, Qt::CaseSensitivity cs) const + + Returns the index position of the last match of \a str in the list, + searching backward from index position \a from. If \a from is -1 (the + default), the search starts at the last item. Returns -1 if no item + matched. + + \include qstringlist.cpp comparison-case-sensitivity + + \include qstringlist.cpp overloading-base-class-methods + + \sa indexOf() +*/ + +template <typename String> +qsizetype lastIndexof_helper(const QStringList &that, String needle, qsizetype from, + Qt::CaseSensitivity cs) +{ + if (from < 0) + from += that.size(); + else if (from >= that.size()) + from = that.size() - 1; + + for (qsizetype i = from; i >= 0; --i) { + if (needle.compare(that.at(i), cs) == 0) + return i; + } + + return -1; +} + +qsizetype QtPrivate::QStringList_lastIndexOf(const QStringList &that, QLatin1StringView needle, + qsizetype from, Qt::CaseSensitivity cs) +{ + return lastIndexof_helper(that, needle, from, cs); +} + +qsizetype QtPrivate::QStringList_lastIndexOf(const QStringList &that, QStringView needle, + qsizetype from, Qt::CaseSensitivity cs) +{ + return lastIndexof_helper(that, needle, from, cs); +} + #if QT_CONFIG(regularexpression) /*! \fn qsizetype QStringList::indexOf(const QRegularExpression &re, qsizetype from) const |