From 9e5e30fa130e43524d9ff26493023ac966a878cc Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sun, 5 Feb 2017 14:55:01 +0100 Subject: [PATCH] QStringMatcher: fix setCaseSensitivity() on a non-QString-backed matcher When a non-QString-backed mode (via the (QChar*, int) ctor) was added for Qt 4.5, the author forgot to adjust the setCaseSensitivity() function. It still uses q_pattern instead of (p.uc, p.len) as the pattern for which to create the skip-table. Since there is no setPattern() overload for this mode, the correctness of the matcher is not harmed by this, but its performance degrades to that of a linear scan: the skip-table, being filled from an empty pattern, will be all-zeros, sending bm_find() into the 'possible match' case at every character. Since matching is still correct, but slow, it's not possible to write a test for this. I did, however, leave my attempts in the auto-test, for when we add QStringView overloads of setPattern() which will then be able to expose the bug. Change-Id: I7b803e8624b0352a0a974900affbbfc0c260d93b Reviewed-by: Giuseppe D'Angelo Reviewed-by: Edward Welbourne --- src/corelib/tools/qstringmatcher.cpp | 2 +- .../tools/qstringmatcher/tst_qstringmatcher.cpp | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/corelib/tools/qstringmatcher.cpp b/src/corelib/tools/qstringmatcher.cpp index 67e7ad3825c..67d3f0ebc84 100644 --- a/src/corelib/tools/qstringmatcher.cpp +++ b/src/corelib/tools/qstringmatcher.cpp @@ -252,7 +252,7 @@ void QStringMatcher::setCaseSensitivity(Qt::CaseSensitivity cs) { if (cs == q_cs) return; - bm_init_skiptable((const ushort *)q_pattern.unicode(), q_pattern.size(), p.q_skiptable, cs); + bm_init_skiptable((const ushort *)p.uc, p.len, p.q_skiptable, cs); q_cs = cs; } diff --git a/tests/auto/corelib/tools/qstringmatcher/tst_qstringmatcher.cpp b/tests/auto/corelib/tools/qstringmatcher/tst_qstringmatcher.cpp index 0c098cb1c39..8a55f544491 100644 --- a/tests/auto/corelib/tools/qstringmatcher/tst_qstringmatcher.cpp +++ b/tests/auto/corelib/tools/qstringmatcher/tst_qstringmatcher.cpp @@ -54,12 +54,21 @@ void tst_QStringMatcher::qstringmatcher() // public Qt::CaseSensitivity caseSensitivity() const void tst_QStringMatcher::caseSensitivity() { - QStringMatcher matcher; + const QString haystack = QStringLiteral("foobarFoo"); + const QStringRef needle = haystack.rightRef(3); // "Foo" + QStringMatcher matcher(needle.data(), needle.size()); + + QCOMPARE(matcher.caseSensitivity(), Qt::CaseSensitive); + QCOMPARE(matcher.indexIn(haystack), 6); + + matcher.setCaseSensitivity(Qt::CaseInsensitive); + + QCOMPARE(matcher.caseSensitivity(), Qt::CaseInsensitive); + QCOMPARE(matcher.indexIn(haystack), 0); matcher.setCaseSensitivity(Qt::CaseSensitive); QCOMPARE(matcher.caseSensitivity(), Qt::CaseSensitive); - matcher.setCaseSensitivity(Qt::CaseInsensitive); - QCOMPARE(matcher.caseSensitivity(), Qt::CaseInsensitive); + QCOMPARE(matcher.indexIn(haystack), 6); } void tst_QStringMatcher::indexIn_data()