QStringView: add some QRegularExpression-related overloads

[ChangeLog][QtCore][QStringView] Added the indexOf(), contains(),
lastIndexOf() and count() methods taking a QRegularExpression.

Fixes: QTBUG-89050
Change-Id: Ic726754f67e06b3764302d2fad252e0378a77afc
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Giuseppe D'Angelo 2020-12-02 12:31:41 +01:00
parent be83ff65c4
commit ce0b767310
5 changed files with 383 additions and 0 deletions

View File

@ -10259,6 +10259,84 @@ qsizetype QtPrivate::lastIndexOf(QLatin1String haystack, qsizetype from, QLatin1
return qLastIndexOf(haystack, from, needle, cs);
}
#if QT_CONFIG(regularexpression)
qsizetype QtPrivate::indexOf(QStringView haystack, const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch)
{
if (!re.isValid()) {
qWarning("QStringView::indexOf: invalid QRegularExpression object");
return -1;
}
QRegularExpressionMatch match = re.match(haystack, from);
if (match.hasMatch()) {
const qsizetype ret = match.capturedStart();
if (rmatch)
*rmatch = std::move(match);
return ret;
}
return -1;
}
qsizetype QtPrivate::lastIndexOf(QStringView haystack, const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch)
{
if (!re.isValid()) {
qWarning("QStringView::lastIndexOf: invalid QRegularExpression object");
return -1;
}
qsizetype endpos = (from < 0) ? (haystack.size() + from + 1) : (from);
QRegularExpressionMatchIterator iterator = re.globalMatch(haystack);
qsizetype lastIndex = -1;
while (iterator.hasNext()) {
QRegularExpressionMatch match = iterator.next();
qsizetype start = match.capturedStart();
if (start <= endpos) {
lastIndex = start;
if (rmatch)
*rmatch = std::move(match);
} else {
break;
}
}
return lastIndex;
}
bool QtPrivate::contains(QStringView haystack, const QRegularExpression &re, QRegularExpressionMatch *rmatch)
{
if (!re.isValid()) {
qWarning("QStringView::contains: invalid QRegularExpression object");
return false;
}
QRegularExpressionMatch m = re.match(haystack);
bool hasMatch = m.hasMatch();
if (hasMatch && rmatch)
*rmatch = std::move(m);
return hasMatch;
}
qsizetype QtPrivate::count(QStringView haystack, const QRegularExpression &re)
{
if (!re.isValid()) {
qWarning("QStringView::count: invalid QRegularExpression object");
return 0;
}
qsizetype count = 0;
qsizetype index = -1;
qsizetype len = haystack.length();
while (index <= len - 1) {
QRegularExpressionMatch match = re.match(haystack, index + 1);
if (!match.hasMatch())
break;
index = match.capturedStart();
count++;
}
return count;
}
#endif // QT_CONFIG(regularexpression)
/*!
\since 5.0

View File

@ -70,6 +70,8 @@ class QStringView;
template <bool> class QBasicUtf8StringView;
class QAnyStringView;
class QChar;
class QRegularExpression;
class QRegularExpressionMatch;
namespace QtPrivate {
@ -122,6 +124,21 @@ namespace QtPrivate {
[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype count(QStringView haystack, QChar needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
[[nodiscard]] Q_CORE_EXPORT Q_DECL_PURE_FUNCTION qsizetype count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept;
#if QT_CONFIG(regularexpression)
[[nodiscard]] Q_CORE_EXPORT qsizetype indexOf(QStringView haystack,
const QRegularExpression &re,
qsizetype from = 0,
QRegularExpressionMatch *rmatch = nullptr);
[[nodiscard]] Q_CORE_EXPORT qsizetype lastIndexOf(QStringView haystack,
const QRegularExpression &re,
qsizetype from = -1,
QRegularExpressionMatch *rmatch = nullptr);
[[nodiscard]] Q_CORE_EXPORT bool contains(QStringView haystack,
const QRegularExpression &re,
QRegularExpressionMatch *rmatch = nullptr);
[[nodiscard]] Q_CORE_EXPORT qsizetype count(QStringView haystack, const QRegularExpression &re);
#endif
[[nodiscard]] Q_CORE_EXPORT QString convertToQString(QAnyStringView s);
[[nodiscard]] Q_CORE_EXPORT QByteArray convertToLatin1(QStringView str);

View File

@ -881,6 +881,67 @@ QT_BEGIN_NAMESPACE
\sa QString::lastIndexOf()
*/
#if QT_CONFIG(regularexpression)
/*!
\fn qsizetype QStringView::indexOf(const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch) const
\since 6.1
Returns the index position of the first match of the regular
expression \a re in the string view, searching forward from index
position \a from. Returns -1 if \a re didn't match anywhere.
If the match is successful and \a rmatch is not \nullptr, it also
writes the results of the match into the QRegularExpressionMatch object
pointed to by \a rmatch.
\note Due to how the regular expression matching algorithm works,
this function will actually match repeatedly from the beginning of
the string view until the position \a from is reached.
*/
/*!
\fn qsizetype QStringView::lastIndexOf(const QRegularExpression &re, qsizetype from, QRegularExpressionMatch *rmatch) const
\since 6.1
Returns the index position of the last match of the regular
expression \a re in the string view, which starts before the index
position \a from. Returns -1 if \a re didn't match anywhere.
If the match is successful and \a rmatch is not \nullptr, it also
writes the results of the match into the QRegularExpressionMatch object
pointed to by \a rmatch.
*/
/*!
\fn bool QStringView::contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch) const
\since 6.1
Returns \c true if the regular expression \a re matches somewhere in this
string view; otherwise returns \c false.
If the match is successful and \a rmatch is not \nullptr, it also
writes the results of the match into the QRegularExpressionMatch object
pointed to by \a rmatch.
\sa QRegularExpression::match()
*/
/*!
\fn qsizetype QStringView::count(const QRegularExpression &re) const
\since 6.1
Returns the number of times the regular expression \a re matches
in the string view.
For historical reasons, this function counts overlapping matches.
This behavior is different from simply iterating over the matches
in the string using QRegularExpressionMatchIterator.
\sa QRegularExpression::globalMatch()
*/
#endif // QT_CONFIG(regularexpression)
/*!
\fn QByteArray QStringView::toLatin1() const

View File

@ -71,6 +71,7 @@ QT_BEGIN_NAMESPACE
class QString;
class QStringView;
class QRegularExpression;
class QRegularExpressionMatch;
namespace QtPrivate {
template <typename Char>
@ -347,6 +348,25 @@ public:
{ return QtPrivate::lastIndexOf(*this, from, s, cs); }
[[nodiscard]] inline qsizetype lastIndexOf(QLatin1String s, qsizetype from = -1, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
#if QT_CONFIG(regularexpression)
[[nodiscard]] qsizetype indexOf(const QRegularExpression &re, qsizetype from = 0, QRegularExpressionMatch *rmatch = nullptr) const
{
return QtPrivate::indexOf(*this, re, from, rmatch);
}
[[nodiscard]] qsizetype lastIndexOf(const QRegularExpression &re, qsizetype from = -1, QRegularExpressionMatch *rmatch = nullptr) const
{
return QtPrivate::lastIndexOf(*this, re, from, rmatch);
}
[[nodiscard]] bool contains(const QRegularExpression &re, QRegularExpressionMatch *rmatch = nullptr) const
{
return QtPrivate::contains(*this, re, rmatch);
}
[[nodiscard]] qsizetype count(const QRegularExpression &re) const
{
return QtPrivate::count(*this, re);
}
#endif
[[nodiscard]] bool isRightToLeft() const noexcept
{ return QtPrivate::isRightToLeft(*this); }
[[nodiscard]] bool isValidUtf16() const noexcept

View File

@ -830,6 +830,16 @@ private Q_SLOTS:
void lastIndexOf_QStringView_QChar() { lastIndexOf_impl<QStringView, QChar>(); }
void lastIndexOf_QStringView_char16_t_data() { lastIndexOf_data(false); }
void lastIndexOf_QStringView_char16_t() { lastIndexOf_impl<QStringView, char16_t>(); }
private:
void indexOf_contains_lastIndexOf_count_regexp_data();
template <typename String> void indexOf_contains_lastIndexOf_count_regexp_impl() const;
private Q_SLOTS:
void indexOf_regexp_QString_data() { indexOf_contains_lastIndexOf_count_regexp_data(); }
void indexOf_regexp_QString() { indexOf_contains_lastIndexOf_count_regexp_impl<QString>(); }
void indexOf_regexp_QStringView_data() { indexOf_contains_lastIndexOf_count_regexp_data(); }
void indexOf_regexp_QStringView() { indexOf_contains_lastIndexOf_count_regexp_impl<QStringView>(); }
};
void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty)
@ -2496,6 +2506,203 @@ void tst_QStringApiSymmetry::lastIndexOf_impl() const
}
void tst_QStringApiSymmetry::indexOf_contains_lastIndexOf_count_regexp_data()
{
QTest::addColumn<QString>("subject");
QTest::addColumn<QRegularExpression>("regexp");
QTest::addColumn<qsizetype>("leftFrom");
QTest::addColumn<qsizetype>("indexOf");
QTest::addColumn<qsizetype>("count");
QTest::addColumn<qsizetype>("rightFrom");
QTest::addColumn<qsizetype>("lastIndexOf");
const auto ROW = [](const char *subject,
const char *pattern,
QRegularExpression::PatternOptions options,
qsizetype leftFrom, qsizetype indexOf, qsizetype count,
qsizetype rightFrom, qsizetype lastIndexOf)
{
QTest::addRow("subject \"%s\" pattern \"%s\" options %d leftFrom %d rightFrom %d",
subject, pattern, (int)options, (int)leftFrom, (int)rightFrom)
<< subject
<< QRegularExpression(pattern, options)
<< leftFrom
<< indexOf
<< count
<< rightFrom
<< lastIndexOf;
};
ROW("", "", QRegularExpression::NoPatternOption, 0, 0, 1, -1, 0);
ROW("test", "", QRegularExpression::NoPatternOption, 0, 0, 5, -1, 4);
ROW("", "^", QRegularExpression::NoPatternOption, 0, 0, 1, -1, 0);
ROW("", "$", QRegularExpression::NoPatternOption, 0, 0, 1, -1, 0);
ROW("", "^$", QRegularExpression::NoPatternOption, 0, 0, 1, -1, 0);
ROW("", "x", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
ROW("", "^x", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
ROW("", "x$", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
ROW("", "^x$", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
ROW("test", "e", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "e", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
ROW("test", "es", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "es", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
ROW("test", "es?", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "es?", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
ROW("test", "es+", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "es+", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
ROW("test", "e.", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "e.", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
ROW("test", "e.*", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "e.*", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
ROW("test", "e(?=s)", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "e(?!x)", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "ex?s", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "(?<=t)e", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "(?<!x)e", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "t", QRegularExpression::NoPatternOption, 0, 0, 2, 0, 0);
ROW("test", "t", QRegularExpression::NoPatternOption, 0, 0, 2, 1, 0);
ROW("test", "t", QRegularExpression::NoPatternOption, 0, 0, 2, -1, 3);
ROW("test", "t", QRegularExpression::NoPatternOption, 0, 0, 2, -2, 3);
ROW("test", "t", QRegularExpression::NoPatternOption, 0, 0, 2, -3, 0);
ROW("test", "^es", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
ROW("test", "^es", QRegularExpression::NoPatternOption, 0, -1, 0, -2, -1);
ROW("test", "es$", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
ROW("test", "ex", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
ROW("test", "ex?", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "ex+", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
ROW("test", "e(?=x)", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
ROW("test", "e(?!s)", QRegularExpression::NoPatternOption, 0, -1, 0, -1, -1);
ROW("test", "e.*t", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "e.*t", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
ROW("test", "e.*t", QRegularExpression::NoPatternOption, 0, 1, 1, -3, 1);
ROW("test", "e.*t", QRegularExpression::NoPatternOption, 0, 1, 1, -4, 1);
ROW("test", "e.*t", QRegularExpression::NoPatternOption, 0, 1, 1, -5, -1);
ROW("test", "e.*t$", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "e.*t$", QRegularExpression::NoPatternOption, 0, 1, 1, -2, 1);
ROW("test", "e.*st", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "e.*st$", QRegularExpression::NoPatternOption, 0, 1, 1, -1, 1);
ROW("test", "t.*t", QRegularExpression::NoPatternOption, 0, 0, 1, -1, 0);
ROW("test", "t.*t", QRegularExpression::NoPatternOption, 0, 0, 1, -2, 0);
ROW("test", "st", QRegularExpression::NoPatternOption, 0, 2, 1, -1, 2);
ROW("test", "st", QRegularExpression::NoPatternOption, 0, 2, 1, -2, 2);
ROW("test", "st", QRegularExpression::NoPatternOption, 0, 2, 1, -3, 2);
ROW("test", "st", QRegularExpression::NoPatternOption, 0, 2, 1, -4, -1);
ROW("", "", QRegularExpression::CaseInsensitiveOption, 0, 0, 1, -1, 0);
ROW("test", "", QRegularExpression::CaseInsensitiveOption, 0, 0, 5, -1, 4);
ROW("test", "^", QRegularExpression::CaseInsensitiveOption, 0, 0, 1, -1, 0);
ROW("test", "^t", QRegularExpression::CaseInsensitiveOption, 0, 0, 1, -1, 0);
ROW("TEST", "^t", QRegularExpression::CaseInsensitiveOption, 0, 0, 1, -1, 0);
ROW("test", "e", QRegularExpression::CaseInsensitiveOption, 0, 1, 1, -1, 1);
ROW("TEST", "e", QRegularExpression::CaseInsensitiveOption, 0, 1, 1, -1, 1);
ROW("TEST", "es", QRegularExpression::CaseInsensitiveOption, 0, 1, 1, -1, 1);
ROW("test", "ES", QRegularExpression::CaseInsensitiveOption, 0, 1, 1, -1, 1);
ROW("TEST", "ex?s", QRegularExpression::CaseInsensitiveOption, 0, 1, 1, -1, 1);
ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -1, 5);
ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -2, 5);
ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -3, 5);
ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -4, 5);
ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -5, 1);
ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -6, 1);
ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -7, 1);
ROW("testtest", "e", QRegularExpression::NoPatternOption, 0, 1, 2, -8, 1);
ROW("testtest", "es", QRegularExpression::NoPatternOption, 0, 1, 2, -1, 5);
ROW("testtest", "e.*s", QRegularExpression::NoPatternOption, 0, 1, 2, -1, 1);
ROW("testtest", "e", QRegularExpression::NoPatternOption, 1, 1, 2, -1, 5);
ROW("testtest", "es", QRegularExpression::NoPatternOption, 1, 1, 2, -1, 5);
ROW("testtest", "e.*s", QRegularExpression::NoPatternOption, 1, 1, 2, -1, 1);
ROW("testtest", "e", QRegularExpression::NoPatternOption, 2, 5, 1, -1, 5);
ROW("testtest", "es", QRegularExpression::NoPatternOption, 2, 5, 1, -1, 5);
ROW("testtest", "es", QRegularExpression::NoPatternOption, 2, 5, 1, -2, 5);
ROW("testtest", "es", QRegularExpression::NoPatternOption, 2, 5, 1, -3, 5);
ROW("testtest", "es", QRegularExpression::NoPatternOption, 2, 5, 1, -4, 5);
ROW("testtest", "es", QRegularExpression::NoPatternOption, 2, 5, 1, -5, 1);
ROW("testtest", "e.*s", QRegularExpression::NoPatternOption, 2, 5, 1, -1, 1);
ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 0, -1);
ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 1, 1);
ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 2, 1);
ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 3, 1);
ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 4, 1);
ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 5, 5);
ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 6, 5);
ROW("testtest", "e", QRegularExpression::NoPatternOption, -1, -1, 0, 7, 5);
ROW("testtest", "e", QRegularExpression::NoPatternOption, -2, -1, 0, -1, 5);
ROW("testtest", "e", QRegularExpression::NoPatternOption, -3, 5, 1, -1, 5);
ROW("testtest", "e", QRegularExpression::NoPatternOption, -4, 5, 1, -1, 5);
ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 0, 0);
ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 1, 0);
ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 2, 0);
ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 3, 3);
ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 4, 4);
ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 5, 4);
ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 6, 4);
ROW("testtest", "t", QRegularExpression::NoPatternOption, 0, 0, 4, 7, 7);
ROW("testtest", "t(?!e)", QRegularExpression::NoPatternOption, 0, 3, 2, 0, -1);
ROW("testtest", "t(?!e)", QRegularExpression::NoPatternOption, 0, 3, 2, 1, -1);
ROW("testtest", "t(?!e)", QRegularExpression::NoPatternOption, 0, 3, 2, 2, -1);
ROW("testtest", "t(?!e)", QRegularExpression::NoPatternOption, 0, 3, 2, 3, 3);
ROW("testtest", "t(?!e)", QRegularExpression::NoPatternOption, 0, 3, 2, 4, 3);
ROW("testtest", "t(?!e)", QRegularExpression::NoPatternOption, 0, 3, 2, -1, 7);
ROW("testtest", "tt", QRegularExpression::NoPatternOption, -1, -1, 0, 0, -1);
ROW("testtest", "tt", QRegularExpression::NoPatternOption, -1, -1, 0, 1, -1);
ROW("testtest", "tt", QRegularExpression::NoPatternOption, -1, -1, 0, 2, -1);
ROW("testtest", "tt", QRegularExpression::NoPatternOption, -1, -1, 0, 3, 3);
ROW("testtest", "tt", QRegularExpression::NoPatternOption, -1, -1, 0, 4, 3);
ROW("testtest", "tt", QRegularExpression::NoPatternOption, -2, -1, 0, 0, -1);
ROW("testtest", "tt", QRegularExpression::NoPatternOption, -3, -1, 0, 0, -1);
ROW("testtest", "tt", QRegularExpression::NoPatternOption, -4, -1, 0, 0, -1);
ROW("testtest", "tt", QRegularExpression::NoPatternOption, -5, 3, 1, -1, 3);
ROW("testtest", "(?<=t)e", QRegularExpression::NoPatternOption, 1, 1, 1, -1, 5); // the count is 1 because in the test we _cut_ the string before the lookbehind
ROW("testtest", "(?<=t)e", QRegularExpression::NoPatternOption, 2, 5, 1, -1, 5);
ROW("testtest", "(?<=t)e", QRegularExpression::NoPatternOption, 3, 5, 1, -1, 5);
ROW("testtest", "(?<=t)e", QRegularExpression::NoPatternOption, 4, 5, 1, -1, 5);
ROW("testtest", "(?<=t)e", QRegularExpression::NoPatternOption, 5, 5, 0, -1, 5); // the count is 0 because in the test we _cut_ the string before the lookbehind
ROW("testtest", "(?<=t)e", QRegularExpression::NoPatternOption, 6, -1, 0, -1, 5);
#undef ROW
}
template <typename String>
void tst_QStringApiSymmetry::indexOf_contains_lastIndexOf_count_regexp_impl() const
{
QFETCH(QString, subject);
QFETCH(QRegularExpression, regexp);
QFETCH(qsizetype, leftFrom);
QFETCH(qsizetype, indexOf);
QFETCH(qsizetype, count);
QFETCH(qsizetype, rightFrom);
QFETCH(qsizetype, lastIndexOf);
// indexOf
String s = subject;
qsizetype result = s.indexOf(regexp, leftFrom);
QCOMPARE(result, indexOf);
// contains
if (result >= 0)
QVERIFY(s.contains(regexp));
else if (leftFrom == 0)
QVERIFY(!s.contains(regexp));
// count
if (leftFrom >= 0)
QCOMPARE(s.mid(leftFrom).count(regexp), count);
else
QCOMPARE(s.mid(leftFrom + s.size()).count(regexp), count);
// lastIndexOf
result = s.lastIndexOf(regexp, rightFrom);
QCOMPARE(result, lastIndexOf);
}
QTEST_APPLESS_MAIN(tst_QStringApiSymmetry)
#include "tst_qstringapisymmetry.moc"