Add QString::splitRef functions.

The functions can be used to optimize code that do not need to use
the split results as QString directly.

[ChangeLog][QtCore] QString can now split a string to a list of
QStringRef.

Change-Id: Ic2dc929e1fba82f9a060e37c51068a301cb5b866
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
This commit is contained in:
Jędrzej Nowacki 2014-05-14 10:56:44 +02:00
parent b80c449c2d
commit f5c3126201
3 changed files with 198 additions and 15 deletions

View File

@ -6668,6 +6668,28 @@ QStringList QString::split(const QString &sep, SplitBehavior behavior, Qt::CaseS
return splitString<QStringList>(*this, &QString::mid, sep, behavior, cs, sep.size());
}
/*!
Splits the string into substring references wherever \a sep occurs, and
returns the list of those strings. If \a sep does not match
anywhere in the string, splitRef() returns a single-element vector
containing this string reference.
\a cs specifies whether \a sep should be matched case
sensitively or case insensitively.
If \a behavior is QString::SkipEmptyParts, empty entries don't
appear in the result. By default, empty entries are kept.
\note All references are valid as long this string is alive. Destroying this
string will cause all references be dangling pointers.
\since 5.4
\sa QStringRef split()
*/
QVector<QStringRef> QString::splitRef(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
{
return splitString<QVector<QStringRef> >(*this, &QString::midRef, sep, behavior, cs, sep.size());
}
/*!
\overload
*/
@ -6676,6 +6698,15 @@ QStringList QString::split(QChar sep, SplitBehavior behavior, Qt::CaseSensitivit
return splitString<QStringList>(*this, &QString::mid, sep, behavior, cs, 1);
}
/*!
\overload
\since 5.4
*/
QVector<QStringRef> QString::splitRef(QChar sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
{
return splitString<QVector<QStringRef> >(*this, &QString::midRef, sep, behavior, cs, 1);
}
#ifndef QT_NO_REGEXP
namespace {
template<class ResultList, typename MidMethod>
@ -6729,6 +6760,25 @@ QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const
{
return splitString<QStringList>(*this, &QString::mid, rx, behavior);
}
/*!
\overload
\since 5.4
Splits the string into substring references wherever the regular expression
\a rx matches, and returns the list of those strings. If \a rx
does not match anywhere in the string, splitRef() returns a
single-element vector containing this string reference.
\note All references are valid as long this string is alive. Destroying this
string will cause all references be dangling pointers.
\sa QStringRef split()
*/
QVector<QStringRef> QString::splitRef(const QRegExp &rx, SplitBehavior behavior) const
{
return splitString<QVector<QStringRef> >(*this, &QString::midRef, rx, behavior);
}
#endif
#ifndef QT_NO_REGULAREXPRESSION
@ -6793,6 +6843,25 @@ QStringList QString::split(const QRegularExpression &re, SplitBehavior behavior)
{
return splitString<QStringList>(*this, &QString::mid, re, behavior);
}
/*!
\overload
\since 5.4
Splits the string into substring references wherever the regular expression
\a re matches, and returns the list of those strings. If \a re
does not match anywhere in the string, splitRef() returns a
single-element vector containing this string reference.
\note All references are valid as long this string is alive. Destroying this
string will cause all references be dangling pointers.
\sa split() QStringRef
*/
QVector<QStringRef> QString::splitRef(const QRegularExpression &re, SplitBehavior behavior) const
{
return splitString<QVector<QStringRef> >(*this, &QString::midRef, re, behavior);
}
#endif // QT_BOOTSTRAPPED
#endif // QT_NO_REGULAREXPRESSION

View File

@ -441,13 +441,19 @@ public:
QStringList split(const QString &sep, SplitBehavior behavior = KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
QVector<QStringRef> splitRef(const QString &sep, SplitBehavior behavior = KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
QStringList split(QChar sep, SplitBehavior behavior = KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
QVector<QStringRef> splitRef(QChar sep, SplitBehavior behavior = KeepEmptyParts,
Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_REQUIRED_RESULT;
#ifndef QT_NO_REGEXP
QStringList split(const QRegExp &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
QVector<QStringRef> splitRef(const QRegExp &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
#endif
#ifndef QT_NO_REGULAREXPRESSION
QStringList split(const QRegularExpression &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
QVector<QStringRef> splitRef(const QRegularExpression &sep, SplitBehavior behavior = KeepEmptyParts) const Q_REQUIRED_RESULT;
#endif
enum NormalizationForm {
NormalizationForm_D,

View File

@ -76,6 +76,10 @@ class tst_QString : public QObject
{
Q_OBJECT
template<typename List, class RegExp>
void split_regexp(const QString &string, const QString &pattern, QStringList result);
template<typename List>
void split(const QString &string, const QString &separator, QStringList result);
public:
tst_QString();
public slots:
@ -221,6 +225,14 @@ private slots:
void split();
void split_regexp_data();
void split_regexp();
void split_regularexpression_data();
void split_regularexpression();
void splitRef_data();
void splitRef();
void splitRef_regexp_data();
void splitRef_regexp();
void splitRef_regularexpression_data();
void splitRef_regularexpression();
void fromUtf16_data();
void fromUtf16();
void fromUtf16_char16_data();
@ -4989,16 +5001,49 @@ void tst_QString::split_data()
QTest::newRow("sep-empty") << "abc" << "" << (QStringList() << "" << "a" << "b" << "c" << "");
}
void tst_QString::split()
template<class> struct StringSplitWrapper;
template<> struct StringSplitWrapper<QString>
{
QFETCH(QString, str);
QFETCH(QString, sep);
QFETCH(QStringList, result);
const QString &string;
QStringList split(const QString &sep, QString::SplitBehavior behavior = QString::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return string.split(sep, behavior, cs); }
QStringList split(QChar sep, QString::SplitBehavior behavior = QString::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return string.split(sep, behavior, cs); }
QStringList split(const QRegExp &sep, QString::SplitBehavior behavior = QString::KeepEmptyParts) const { return string.split(sep, behavior); }
QStringList split(const QRegularExpression &sep, QString::SplitBehavior behavior = QString::KeepEmptyParts) const { return string.split(sep, behavior); }
};
template<> struct StringSplitWrapper<QStringRef>
{
const QString &string;
QVector<QStringRef> split(const QString &sep, QString::SplitBehavior behavior = QString::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return string.splitRef(sep, behavior, cs); }
QVector<QStringRef> split(QChar sep, QString::SplitBehavior behavior = QString::KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { return string.splitRef(sep, behavior, cs); }
QVector<QStringRef> split(const QRegExp &sep, QString::SplitBehavior behavior = QString::KeepEmptyParts) const { return string.splitRef(sep, behavior); }
QVector<QStringRef> split(const QRegularExpression &sep, QString::SplitBehavior behavior = QString::KeepEmptyParts) const { return string.splitRef(sep, behavior); }
};
static bool operator ==(const QStringList &left, const QVector<QStringRef> &right)
{
if (left.size() != right.size())
return false;
QStringList::const_iterator iLeft = left.constBegin();
QVector<QStringRef>::const_iterator iRight = right.constBegin();
for (; iLeft != left.end(); ++iLeft, ++iRight) {
if (*iLeft != *iRight)
return false;
}
return true;
}
static inline bool operator ==(const QVector<QStringRef> &left, const QStringList &right) { return right == left; }
template<class List>
void tst_QString::split(const QString &string, const QString &sep, QStringList result)
{
QRegExp rx = QRegExp(QRegExp::escape(sep));
QRegularExpression re(QRegularExpression::escape(sep));
QStringList list;
List list;
StringSplitWrapper<typename List::value_type> str = {string};
list = str.split(sep);
QVERIFY(list == result);
@ -5035,6 +5080,27 @@ void tst_QString::split()
}
}
void tst_QString::split()
{
QFETCH(QString, str);
QFETCH(QString, sep);
QFETCH(QStringList, result);
split<QStringList>(str, sep, result);
}
void tst_QString::splitRef_data()
{
split_data();
}
void tst_QString::splitRef()
{
QFETCH(QString, str);
QFETCH(QString, sep);
QFETCH(QStringList, result);
split<QVector<QStringRef> >(str, sep, result);
}
void tst_QString::split_regexp_data()
{
QTest::addColumn<QString>("string");
@ -5054,24 +5120,66 @@ void tst_QString::split_regexp_data()
<< (QStringList() << "" << "Now" << ": " << "this" << " " << "sentence" << " " << "fragment" << ".");
}
template<class List, class RegExp>
void tst_QString::split_regexp(const QString &_string, const QString &pattern, QStringList result)
{
List list;
StringSplitWrapper<typename List::value_type> string = {_string};
list = string.split(RegExp(pattern));
QVERIFY(list == result);
result.removeAll(QString());
list = string.split(RegExp(pattern), QString::SkipEmptyParts);
QVERIFY(list == result);
}
void tst_QString::split_regexp()
{
QFETCH(QString, string);
QFETCH(QString, pattern);
QFETCH(QStringList, result);
split_regexp<QStringList, QRegExp>(string, pattern, result);
}
QStringList list;
list = string.split(QRegExp(pattern));
QCOMPARE(list, result);
list = string.split(QRegularExpression(pattern));
QCOMPARE(list, result);
void tst_QString::split_regularexpression_data()
{
split_regexp_data();
}
result.removeAll(QString());
void tst_QString::split_regularexpression()
{
QFETCH(QString, string);
QFETCH(QString, pattern);
QFETCH(QStringList, result);
split_regexp<QStringList, QRegularExpression>(string, pattern, result);
}
list = string.split(QRegExp(pattern), QString::SkipEmptyParts);
QCOMPARE(list, result);
list = string.split(QRegularExpression(pattern), QString::SkipEmptyParts);
QCOMPARE(list, result);
void tst_QString::splitRef_regularexpression_data()
{
split_regexp_data();
}
void tst_QString::splitRef_regularexpression()
{
QFETCH(QString, string);
QFETCH(QString, pattern);
QFETCH(QStringList, result);
split_regexp<QVector<QStringRef>, QRegularExpression>(string, pattern, result);
}
void tst_QString::splitRef_regexp_data()
{
split_regexp_data();
}
void tst_QString::splitRef_regexp()
{
QFETCH(QString, string);
QFETCH(QString, pattern);
QFETCH(QStringList, result);
split_regexp<QVector<QStringRef>, QRegExp>(string, pattern, result);
}
void tst_QString::fromUtf16_data()