diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2020-04-01 15:28:29 +0200 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2020-06-06 02:07:28 +0000 |
commit | ee635571122e1dd9b77276afb0f642e7ac9a015a (patch) | |
tree | 0ce36e65579428711dde617a8caeb7fdf2822862 /tests/auto/corelib/text | |
parent | 832d3b482ece878ee0ded823f0a8fa23523cdc17 (diff) |
QString/View: add tokenize() member functions
[ChangeLog][QtCore][QString, QStringView, QLatin1String] Added tokenize().
Change-Id: I5fbeab0ac1809ff2974e565129b61a6bdfb398bc
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'tests/auto/corelib/text')
3 files changed, 190 insertions, 1 deletions
diff --git a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp index f3a7e93be2..aeaf317d75 100644 --- a/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp +++ b/tests/auto/corelib/text/qstringapisymmetry/tst_qstringapisymmetry.cpp @@ -1429,6 +1429,14 @@ void tst_QStringApiSymmetry::tok_data(bool rhsHasVariableLength) split_data(rhsHasVariableLength); } +template <typename T> struct has_tokenize_method : std::false_type {}; +template <> struct has_tokenize_method<QString> : std::true_type {}; +template <> struct has_tokenize_method<QStringView> : std::true_type {}; +template <> struct has_tokenize_method<QLatin1String> : std::true_type {}; + +template <typename T> +constexpr inline bool has_tokenize_method_v = has_tokenize_method<std::decay_t<T>>::value; + template <typename Haystack, typename Needle> void tst_QStringApiSymmetry::tok_impl() const { @@ -1475,6 +1483,21 @@ void tst_QStringApiSymmetry::tok_impl() const QCOMPARE(toQStringList(tok), resultCS); } #endif // __cpp_deduction_guides + + if constexpr (has_tokenize_method_v<Haystack>) { + QCOMPARE(toQStringList(haystack.tokenize(needle)), resultCS); + QCOMPARE(toQStringList(haystack.tokenize(needle, Qt::KeepEmptyParts, Qt::CaseSensitive)), resultCS); + QCOMPARE(toQStringList(haystack.tokenize(needle, Qt::CaseInsensitive, Qt::KeepEmptyParts)), resultCIS); + QCOMPARE(toQStringList(haystack.tokenize(needle, Qt::SkipEmptyParts, Qt::CaseSensitive)), skippedResultCS); + QCOMPARE(toQStringList(haystack.tokenize(needle, Qt::CaseInsensitive, Qt::SkipEmptyParts)), skippedResultCIS); + + { + const auto tok = deepCopied(haystack).tokenize(deepCopied(needle)); + // here, the temporaries returned from deepCopied() have already been destroyed, + // yet `tok` should have kept a copy alive as needed: + QCOMPARE(toQStringList(tok), resultCS); + } + } } void tst_QStringApiSymmetry::mid_data() diff --git a/tests/auto/corelib/text/qstringview/qstringview.pro b/tests/auto/corelib/text/qstringview/qstringview.pro index e0e9973c91..e6d610e980 100644 --- a/tests/auto/corelib/text/qstringview/qstringview.pro +++ b/tests/auto/corelib/text/qstringview/qstringview.pro @@ -3,4 +3,5 @@ TARGET = tst_qstringview QT = core testlib contains(QT_CONFIG, c++14):CONFIG *= c++14 contains(QT_CONFIG, c++1z):CONFIG *= c++1z +contains(QT_CONFIG, c++2a):CONFIG *= c++2a SOURCES += tst_qstringview.cpp diff --git a/tests/auto/corelib/text/qstringview/tst_qstringview.cpp b/tests/auto/corelib/text/qstringview/tst_qstringview.cpp index b2288f0785..69702a14b3 100644 --- a/tests/auto/corelib/text/qstringview/tst_qstringview.cpp +++ b/tests/auto/corelib/text/qstringview/tst_qstringview.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> +** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com> ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -27,6 +27,7 @@ ****************************************************************************/ #include <QStringView> +#include <QStringTokenizer> #include <QString> #include <QChar> #include <QStringRef> @@ -39,6 +40,8 @@ #include <string_view> #include <array> #include <vector> +#include <algorithm> +#include <memory> // for negative testing (can't convert from) #include <deque> @@ -264,6 +267,9 @@ private Q_SLOTS: void overloadResolution(); + void tokenize_data() const; + void tokenize() const; + private: template <typename String> void conversion_tests(String arg) const; @@ -502,6 +508,165 @@ void tst_QStringView::fromQStringRef() const conversion_tests(QString("Hello World!").midRef(6)); } +void tst_QStringView::tokenize_data() const +{ + // copied from tst_QString + QTest::addColumn<QString>("str"); + QTest::addColumn<QString>("sep"); + QTest::addColumn<QStringList>("result"); + + QTest::newRow("1") << "a,b,c" << "," << (QStringList() << "a" << "b" << "c"); + QTest::newRow("2") << QString("-rw-r--r-- 1 0 0 519240 Jul 9 2002 bigfile") + << " " + << (QStringList() << "-rw-r--r--" << "" << "1" << "0" << "" << "0" << "" + << "519240" << "Jul" << "" << "9" << "" << "2002" + << "bigfile"); + QTest::newRow("one-empty") << "" << " " << (QStringList() << ""); + QTest::newRow("two-empty") << " " << " " << (QStringList() << "" << ""); + QTest::newRow("three-empty") << " " << " " << (QStringList() << "" << "" << ""); + + QTest::newRow("all-empty") << "" << "" << (QStringList() << "" << ""); + QTest::newRow("sep-empty") << "abc" << "" << (QStringList() << "" << "a" << "b" << "c" << ""); +} + +void tst_QStringView::tokenize() const +{ + QFETCH(const QString, str); + QFETCH(const QString, sep); + QFETCH(const QStringList, result); + + // lvalue QString +#ifdef __cpp_deduction_guides + { + auto rit = result.cbegin(); + for (auto sv : QStringTokenizer{str, sep}) + QCOMPARE(sv, *rit++); + } +#endif + { + auto rit = result.cbegin(); + for (auto sv : QStringView{str}.tokenize(sep)) + QCOMPARE(sv, *rit++); + } + + // rvalue QString +#ifdef __cpp_deduction_guides + { + auto rit = result.cbegin(); + for (auto sv : QStringTokenizer{str, QString{sep}}) + QCOMPARE(sv, *rit++); + } +#endif + { + auto rit = result.cbegin(); + for (auto sv : QStringView{str}.tokenize(QString{sep})) + QCOMPARE(sv, *rit++); + } + + // (rvalue) QStringRef +#ifdef __cpp_deduction_guides + { + auto rit = result.cbegin(); + for (auto sv : QStringTokenizer{str, sep.midRef(0)}) + QCOMPARE(sv, *rit++); + } +#endif + { + auto rit = result.cbegin(); + for (auto sv : QStringView{str}.tokenize(sep.midRef(0))) + QCOMPARE(sv, *rit++); + } + + // (rvalue) QChar +#ifdef __cpp_deduction_guides + if (sep.size() == 1) { + auto rit = result.cbegin(); + for (auto sv : QStringTokenizer{str, sep.front()}) + QCOMPARE(sv, *rit++); + } +#endif + if (sep.size() == 1) { + auto rit = result.cbegin(); + for (auto sv : QStringView{str}.tokenize(sep.front())) + QCOMPARE(sv, *rit++); + } + + // (rvalue) char16_t +#ifdef __cpp_deduction_guides + if (sep.size() == 1) { + auto rit = result.cbegin(); + for (auto sv : QStringTokenizer{str, *qToStringViewIgnoringNull(sep).utf16()}) + QCOMPARE(sv, *rit++); + } +#endif + if (sep.size() == 1) { + auto rit = result.cbegin(); + for (auto sv : QStringView{str}.tokenize(*qToStringViewIgnoringNull(sep).utf16())) + QCOMPARE(sv, *rit++); + } + + // char16_t literal + const auto make_literal = [](const QString &sep) { + auto literal = std::make_unique<char16_t[]>(sep.size() + 1); + const auto to_char16_t = [](QChar c) { return char16_t{c.unicode()}; }; + std::transform(sep.cbegin(), sep.cend(), literal.get(), to_char16_t); + return literal; + }; + const std::unique_ptr<const char16_t[]> literal = make_literal(sep); +#ifdef __cpp_deduction_guides + { + auto rit = result.cbegin(); + for (auto sv : QStringTokenizer{str, literal.get()}) + QCOMPARE(sv, *rit++); + } +#endif + { + auto rit = result.cbegin(); + for (auto sv : QStringView{str}.tokenize(literal.get())) + QCOMPARE(sv, *rit++); + } + +#ifdef __cpp_deduction_guides +#ifdef __cpp_lib_ranges + // lvalue QString + { + QStringList actual; + const QStringTokenizer tok{str, sep}; + std::ranges::transform(tok, std::back_inserter(actual), + [](auto sv) { return sv.toString(); }); + QCOMPARE(result, actual); + } + + // rvalue QString + { + QStringList actual; + const QStringTokenizer tok{str, QString{sep}}; + std::ranges::transform(tok, std::back_inserter(actual), + [](auto sv) { return sv.toString(); }); + QCOMPARE(result, actual); + } + + // (rvalue) QStringRef + { + QStringList actual; + const QStringTokenizer tok{str, sep.midRef(0)}; + std::ranges::transform(tok, std::back_inserter(actual), + [](auto sv) { return sv.toString(); }); + QCOMPARE(result, actual); + } + + // (rvalue) QChar + if (sep.size() == 1) { + QStringList actual; + const QStringTokenizer tok{str, sep.front()}; + std::ranges::transform(tok, std::back_inserter(actual), + [](auto sv) { return sv.toString(); }); + QCOMPARE(result, actual); + } +#endif // __cpp_lib_ranges +#endif // __cpp_deduction_guides +} + template <typename Char> void tst_QStringView::fromLiteral(const Char *arg) const { |